这个程序是书中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


而且程序后面使用了命令行参数argc和argv,需要从命令行输入密码

且会提示密码正确/错误
但这种提示也不一定有,比如以下情况

只有一部分密码会给出提示。原因是代码并未进行如除数是否为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做验证,证明算法还原没问题
浙公网安备 33010602011771号