二进制C-编码与if逆向
xiu裸函数实现加法运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
#include "stdafx.h"
int __declspec(naked) add(int x,int y,int z) { __asm { push ebp mov ebp,esp sub esp,0x40 push ebx push esi push edi mov eax,0xCCCCCCCC mov ecx,0x10 lea edi,dword ptr ds:[ebp-0x40] rep stosd mov dword ptr ds:[ebp-0x4],1 mov dword ptr ds:[ebp-0x8],2 mov dword ptr ds:[ebp-0xc],3 mov eax,dword ptr ds:[ebp+0x8] add eax,dword ptr ds:[ebp+0xc] add eax,dword ptr ds:[ebp+0x10] add eax,dword ptr ds:[ebp-0x4] add eax,dword ptr ds:[ebp-0x8] add eax,dword ptr ds:[ebp-0xc] pop edi pop esi pop ebx mov esp,ebp pop ebp ret }
}
int main(int argc, char* argv[]) { add(1,2,3); return 0;
}
|
编码
ASCII编码表
十进制的数值对应的字符,使用指定的七位或者八位二进制数组合来表示128或256钟字符,标准ASCII表用七位,最高位永远是0

扩展ASCII码表
八位全用上,但是仍然只适用在英文上
GB2312
为了显示中文,必须有一套编码规则用于将汉字转换为计算机可以接受的数字系统,为了区分中英文混合的文本,标准ASCII码表最高位都是0,我们汉字的编码最高位都是1,用于区分
GB2312采用双字节编码,每个字符占两个字节,其中第一个字节为0xA1-0xF7,第二个字节为0xA1-0xFE。
其中第一个字节表示这个字符在GB2312字符表中所处“区”的编号,第二个字节表示这个字符在这个区中的位置

内存图示

if语句逆向
if
看到影响标志位的汇编语句,紧跟着一句cmp指令和JCC,那么这几条语句很有可能就是if语句执行的内存区域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include "stdafx.h"
int g_n = 0;
void add(int x,int y) { if(x>y) { g_n=x; } }
int main(int argc, char* argv[]) { add(2,3); return 0;
}
|

if…else
判断if语句和if else语句的区别就在于,JCC指令跳转到的地方的上一句指令是不是jmp,jmp跳到了堆栈还原ESI,EDI等寄存器的pop指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include "stdafx.h"
int g_n = 0;
void add(int x,int y) { if(x>y) { g_n=x; } else { g_n=y; } }
int main(int argc, char* argv[]) { add(2,3); return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 00401020 push ebp 00401021 mov ebp,esp 00401023 sub esp,40h 00401026 push ebx 00401027 push esi 00401028 push edi 00401029 lea edi,[ebp-40h] 0040102C mov ecx,10h 00401031 mov eax,0CCCCCCCCh 00401036 rep stos dword ptr [edi] 00401038 mov eax,dword ptr [ebp+8] 0040103B cmp eax,dword ptr [ebp+0Ch] 0040103E jle add+2Bh (0040104b) 00401040 mov ecx,dword ptr [ebp+8] 00401043 mov dword ptr [g_n (004225c4)],ecx 00401049 jmp add+34h (00401054) 0040104B mov edx,dword ptr [ebp+0Ch] 0040104E mov dword ptr [g_n (004225c4)],edx 00401054 pop edi 00401055 pop esi 00401056 pop ebx 00401057 mov esp,ebp 00401059 pop ebp 0040105A ret
|
if…else if…else if…else
add esp,0Ch
根据外平栈的语句综合判断参数可能有三个
假设为a[ebp+8],b[ebp+0Ch],c[ebp+10h]
全局变量g_n[0x004225c4]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| 0040B500 push ebp 0040B501 mov ebp,esp 0040B503 sub esp,40h 0040B506 push ebx 0040B507 push esi 0040B508 push edi 0040B509 lea edi,[ebp-40h] 0040B50C mov ecx,10h 0040B511 mov eax,0CCCCCCCCh 0040B516 rep stos dword ptr [edi] 0040B518 mov eax,dword ptr [ebp+8] 0040B51B cmp eax,dword ptr [ebp+0Ch] 0040B51E jle add+2Bh (0040b52b) 0040B520 mov ecx,dword ptr [ebp+8] 0040B523 mov dword ptr [g_n (004225c4)],ecx 0040B529 jmp add+5Ah (0040b55a) 0040B52B mov edx,dword ptr [ebp+0Ch] 0040B52E cmp edx,dword ptr [ebp+10h] 0040B531 jle add+3Dh (0040b53d) 0040B533 mov eax,dword ptr [ebp+0Ch] 0040B536 mov [g_n (004225c4)],eax 0040B53B jmp add+5Ah (0040b55a) 0040B53D mov ecx,dword ptr [ebp+10h] 0040B540 cmp ecx,dword ptr [ebp+8] 0040B543 jle add+50h (0040b550) 0040B545 mov edx,dword ptr [ebp+10h] 0040B548 mov dword ptr [g_n (004225c4)],edx 0040B54E jmp add+5Ah (0040b55a) 0040B550 mov eax,[g_n (004225c4)] 0040B555 mov [g_n (004225c4)],eax 0040B55A pop edi 0040B55B pop esi 0040B55C pop ebx 0040B55D mov esp,ebp 0040B55F pop ebp 0040B560 ret
|
判断else if
1、没个条件跳转指令要跳去的地址前面都有jmp
2、这些jmp指令的地址都一样
3、没有条件判断的分支为else部分
源代码
,这些代码没有意义,单纯为了逆向乱写的逻辑,重点在于else if语句的逆向上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include "stdafx.h"
int g_n = 0;
void add(int x,int y,int z) { if(x>y) { g_n=x; } else if(y>z) { g_n=y; } else if(z>x) { g_n=z; } else { g_n=g_n; } }
int main(int argc, char* argv[]) { add(1,2,3); return 0;
}
|