这个程序是书中4.5章节的内容,花了两个晚上才看完,在此写个文章用来记录

最开是是一个14个字节的数组

var_10= byte ptr -10h
var_F= byte ptr -0Fh
var_E= byte ptr -0Eh
var_D= byte ptr -0Dh
var_C= byte ptr -0Ch
var_B= byte ptr -0Bh
var_A= byte ptr -0Ah
var_9= byte ptr -9
var_8= byte ptr -8
var_7= byte ptr -7
var_6= byte ptr -6
var_5= byte ptr -5
var_4= byte ptr -4
var_3= byte ptr -3

使用快捷键N将其转化为数组的形式,并命名为charNumber14
image
image

而且程序后面使用了命令行参数argc和argv,需要从命令行输入密码
image
且会提示密码正确/错误
但这种提示也不一定有,比如以下情况
image
只有一部分密码会给出提示。原因是代码并未进行如除数是否为0,字符串长度等边界检查,导致程序中途崩溃。
以下是对汇编代码的注释

.text:00401000 charNumber14    = byte ptr -10h
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000
.text:00401000                 sub     esp, 10h
.text:00401003                 mov     ecx, [esp+10h+argv] ; ecx = argv[0]
.text:00401007                 mov     al, 1
.text:00401009                 mov     [esp+10h+charNumber14+6], al ; ch[6] = 1
.text:0040100D                 mov     [esp+10h+charNumber14+7], al ; ch[7] = 1
.text:00401011                 mov     edx, [ecx+4]    ; edx = argv[1]
.text:00401014                 mov     [esp+10h+charNumber14+0Ah], al ; ch[10] = 1
.text:00401018                 mov     al, byte ptr [esp+10h+argc] ; al = argc
.text:0040101C                 push    ebx
.text:0040101D                 mov     bl, al          ; bl = argc
.text:0040101F                 push    esi
.text:00401020                 dec     bl              ; bl = argc - 1
.text:00401022                 push    edi
.text:00401023                 or      [edx], bl       ; argv[1][0] |= argc - 1
.text:00401025                 mov     edx, [ecx+4]    ; edx = argv[1]
.text:00401028                 mov     [esp+1Ch+charNumber14], 77h ; 'w' ; ch[0] = 0x77
.text:0040102D                 mov     [esp+1Ch+charNumber14+1], 76h ; 'v' ; ch[1] = 0x76
.text:00401032                 xor     [edx+1], bl     ; argv[1][1] ^= argc - 1
.text:00401035                 mov     dl, 6
.text:00401037                 imul    dl              ; al = argc * 6
.text:00401039                 mov     esi, [ecx+4]    ; esi = argv[1]
.text:0040103C                 sub     al, dl          ; al = (argc - 1) * 6
.text:0040103E                 mov     [esp+1Ch+charNumber14+2], 0CAh ; ch[2] = 0xCA
.text:00401043                 mov     [esp+1Ch+charNumber14+3], 0F3h ; ch[3] = 0xF3
.text:00401048                 imul    byte ptr [esi+2] ; al = argv[1][2] * 6 * (argc - 1)
.text:0040104B                 mov     [esi+2], al     ; argv[1][2] = argv[1][2] * 6 * (argc - 1)
.text:0040104E                 mov     esi, [ecx+4]    ; esi = argv[1]
.text:00401051                 mov     [esp+1Ch+charNumber14+4], 0A8h ; ch[4] = 0xA8
.text:00401056                 mov     [esp+1Ch+charNumber14+5], 0Ch ; ch[5] = 0x0C
.text:0040105B                 movsx   eax, byte ptr [esi+2] ; eax = argv[1][2]
.text:0040105F                 cdq                     ; 扩展高位到edx,正数=0,负数=0xFFFFFFFF
.text:00401060                 and     edx, 3          ; 保留edx低2位,正数=0,负数=3
.text:00401063                 mov     [esp+1Ch+charNumber14+8], 0FEh ; ch[8] = 0xFE
.text:00401068                 add     eax, edx        ; eax = argv[1][2] + edx
.text:0040106A                 mov     [esp+1Ch+charNumber14+9], 0DBh ; ch[9] = 0xDB
.text:0040106F                 sar     eax, 2          ; eax = argv[1][2]/4
.text:00401072                 mov     [esi+3], al     ; argv[1][3] = argv[1][2]/4
.text:00401075                 mov     eax, [ecx+4]    ; eax = argv[1]
.text:00401078                 mov     [esp+1Ch+charNumber14+0Bh], 0E0h ; ch[11] = 0xE0
.text:0040107D                 mov     [esp+1Ch+charNumber14+0Ch], 0FBh ; ch[12] = 0xFB
.text:00401082                 mov     dl, [eax+4]     ; dl = argv[1][4]
.text:00401085                 mov     [esp+1Ch+charNumber14+0Dh], 0 ; ch[13] = 0
.text:0040108A                 shl     dl, 3           ; dl = argv[1][4] << 3
.text:0040108D                 mov     [eax+4], dl     ; argv[1][4] <<= 3
.text:00401090                 mov     eax, [ecx+4]    ; eax = argv[1]
.text:00401093                 mov     dl, [eax+5]     ; dl = argv[1][5]
.text:00401096                 sar     dl, 2
.text:00401099                 mov     [eax+5], dl     ; argv[1][5] >>= 2
.text:0040109C                 mov     esi, [ecx+4]    ; esi = argv[1]
.text:0040109F                 mov     al, bl          ; al = argc - 1
.text:004010A1                 mov     dl, [esi+6]     ; dl = argv[1][6]
.text:004010A4                 and     al, 7           ; al = (argc - 1) & 7
.text:004010A6                 and     dl, al          ; dl = argv[1][6] & [(argc - 1) & 7]
.text:004010A8                 mov     [esi+6], dl     ; argv[1][6] &= (argc - 1) & 7
.text:004010AB                 mov     esi, [ecx+4]    ; esi = argv[1]
.text:004010AE                 movsx   edx, byte ptr [esi+7] ; edx = argv[1][7]
.text:004010B2                 and     edx, 80000001h  ; 保留edx最高位和最低位
.text:004010B8                 jns     short loc_4010BF ; 负数不跳转,正数跳转
.text:004010BA                 dec     edx
.text:004010BB                 or      edx, 0FFFFFFFEh
.text:004010BE                 inc     edx             ; edx = 0xFFFFFFFF
.text:004010BF
.text:004010BF loc_4010BF:                             ; CODE XREF: _main+B8↑j
.text:004010BF                 mov     [esi+7], dl     ; argv[1][7] %= 2
.text:004010C2                 mov     eax, [ecx+4]    ; eax = argv[1]
.text:004010C5                 not     bl              ; ~(argc - 1)
.text:004010C7                 mov     [eax+8], bl     ; argv[1][8] = ~(argc - 1)
.text:004010CA                 mov     eax, [ecx+4]    ; eax = argv[1]
.text:004010CD                 mov     dl, [eax]       ; dl = argv[1][0]
.text:004010CF                 mov     bl, [eax+2]     ; bl = argv[1][2]
.text:004010D2                 lea     esi, [eax+9]    ; esi = &argv[1][9]
.text:004010D5                 sub     dl, bl          ; dl = argv[1][0] - argv[1][2]
.text:004010D7                 mov     bl, [esi]       ; bl = argv[1][9]
.text:004010D9                 add     bl, dl          ; bl = argv[1][9] + argv[1][0] - argv[1][2]
.text:004010DB                 mov     [esi], bl       ; argv[1][9] = argv[1][9] + argv[1][0] - argv[1][2]
.text:004010DD                 mov     eax, [ecx+4]    ; eax = argv[1]
.text:004010E0                 inc     esi             ; esi = argv[1][10]
.text:004010E1                 movsx   edi, byte ptr [eax+7] ; edi = argv[1][7]
.text:004010E5                 movsx   eax, byte ptr [eax+6] ; eax = argv[1][6]
.text:004010E9                 cdq                     ; eax扩展高位到edx
.text:004010EA                 idiv    edi             ; argv[1][6] / argv[1][7]
.text:004010EC                 inc     esi             ; esi = argv[1][11]
.text:004010ED                 mov     [esi-1], al     ; argv[1][10] = argv[1][6] / argv[1][7]
.text:004010F0                 mov     eax, [ecx+4]    ; eax = argv[1]
.text:004010F3                 mov     dl, [eax+3]     ; dl = argv[1][3]
.text:004010F6                 mov     bl, [eax+1]     ; bl = argv[1][1]
.text:004010F9                 mov     al, [esi]       ; al = argv[1][11]
.text:004010FB                 sub     dl, bl          ; dl = argv[1][3] - argv[1][1]
.text:004010FD                 add     al, dl          ; al = argv[1][11] + argv[1][3] - argv[1][1]
.text:004010FF                 mov     [esi], al       ; argv[1][11] = argv[1][11] + argv[1][3] - argv[1][1]
.text:00401101                 mov     eax, [ecx+4]    ; eax = argv[1]
.text:00401104                 movsx   dx, byte ptr [eax+5] ; dx = argv[1][5]
.text:00401109                 movsx   ax, byte ptr [eax+4] ; ax = argv[1][4]
.text:0040110E                 imul    edx, eax        ; edx = argv[1][5] * argv[1][4]
.text:00401111                 mov     [esi], dx       ; argv[1][11] = argv[1][5] * argv[1][4]
.text:00401114                 mov     ecx, [ecx+4]    ; ecx = argv[1]
.text:00401117                 lea     esi, [esp+1Ch+charNumber14]
.text:0040111B
.text:0040111B loc_40111B:                             ; CODE XREF: _main+13D↓j
.text:0040111B                 mov     dl, [ecx]
.text:0040111D                 mov     bl, [esi]
.text:0040111F                 mov     al, dl
.text:00401121                 cmp     dl, bl
.text:00401123                 jnz     short loc_401143
.text:00401125                 test    al, al
.text:00401127                 jz      short loc_40113F
.text:00401129                 mov     dl, [ecx+1]
.text:0040112C                 mov     bl, [esi+1]
.text:0040112F                 mov     al, dl
.text:00401131                 cmp     dl, bl
.text:00401133                 jnz     short loc_401143
.text:00401135                 add     ecx, 2
.text:00401138                 add     esi, 2
.text:0040113B                 test    al, al
.text:0040113D                 jnz     short loc_40111B
.text:0040113F
.text:0040113F loc_40113F:                             ; CODE XREF: _main+127↑j
.text:0040113F                 xor     eax, eax
.text:00401141                 jmp     short loc_401148
.text:00401143 ; ---------------------------------------------------------------------------
.text:00401143
.text:00401143 loc_401143:                             ; CODE XREF: _main+123↑j
.text:00401143                                         ; _main+133↑j
.text:00401143                 sbb     eax, eax
.text:00401145                 sbb     eax, 0FFFFFFFFh
.text:00401148
.text:00401148 loc_401148:                             ; CODE XREF: _main+141↑j
.text:00401148                 pop     edi
.text:00401149                 pop     esi
.text:0040114A                 test    eax, eax
.text:0040114C                 pop     ebx
.text:0040114D                 jnz     short loc_401167
.text:0040114F                 push    offset Right    ; "密码正确!"
.text:00401154                 push    offset Format   ; "%s \r\n"
.text:00401159                 call    _printf
.text:0040115E                 add     esp, 8
.text:00401161                 xor     eax, eax
.text:00401163                 add     esp, 10h
.text:00401166                 retn
.text:00401167 ; ---------------------------------------------------------------------------
.text:00401167
.text:00401167 loc_401167:                             ; CODE XREF: _main+14D↑j
.text:00401167                 push    offset False    ; "密码错误!"
.text:0040116C                 push    offset Format   ; "%s \r\n"
.text:00401171                 call    _printf
.text:00401176                 add     esp, 8
.text:00401179                 xor     eax, eax
.text:0040117B                 add     esp, 10h
.text:0040117E                 retn
.text:0040117E _main           endp

得到如下加密算法

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[], char **envp)
{
    argv[1][0] |= argc - 1;
    argv[1][1] ^= argc - 1;
    argv[1][2] *= (argc - 1) * 6;
    argv[1][3] = argv[1][2] / 4;
    argv[1][4] <<= 3;
    argv[1][5] >>= 2;
    argv[1][6] &= (argc - 1) & 7;
    argv[1][7] %= 2;
    argv[1][8] = ~(argc - 1);
    argv[1][9] += argv[1][0] - argv[1][2];
    argv[1][10] = argv[1][6] / argv[1][7];
    argv[1][11] += argv[1][3] - argv[1][1];
    argv[1][11] = argv[1][5] * argv[1][4];

    int enc[] = {0x77, 0x76, 0xCA, 0xF3, 0xA8, 0x0C, 0x01, 0x01, 0xFE, 0xDB, 0x01, 0xE0, 0xFB, 0x00};

    int ret = strcmp(argv[1], (char *)enc);

    printf("%d", ret);

    return 0;
}

最后由于位运算不可逆,通过加密后的数组还原出原始字符串,所以只能拿正确密码www.51asm.com做验证,证明算法还原没问题

posted on 2026-09-21 20:56  %HuTao%  阅读(6)  评论(0)    收藏  举报