IDA逆向:数组的逆向
阅读《IDA Pro权威指南》第八章,整理的一些笔记,作为逆向的基础,可能有很多认识不足。
//全局分配数组
**********************************************************************
源程序:
int global_arrary[3]; int main() { int idx = 2; global_arrary[0] = 10; global_arrary[1] = 20; global_arrary[2] = 30; global_arrary[idx] = 40; return 0; }
逆向分析:
.text:0041136E mov [ebp+var_8], 2 ; var_8为idx .text:00411375 mov dword_417138, 0Ah ;global_arrary[0] = 10 .text:0041137F mov dword_41713C, 14h ;global_arrary[1] = 20 .text:00411389 mov dword_417140, 1Eh ;global_arrary[2] = 30 .text:00411393 mov eax, [ebp+var_8] ;eax=idx .text:00411396 mov dword_417138[eax*4], 28h ;global_arrary[idx] = 10 由此可见当索引为变量时,易分析出元素大小 这里为4 .text:004113A1 xor eax, eax .text:004113A3 pop edi .text:004113A4 pop esi .text:004113A5 pop ebx .text:004113A6 mov esp, ebp .text:004113A8 pop ebp .text:004113A9 retn .text:004113A9 sub_411350 endp
//栈分配数组
**********************************************************************
源程序:
int _tmain(int argc, _TCHAR* argv[]) { int a[5]; //int aa,bb,cc,dd,ee; int idx = 0; //int* p =a; a[0] = 10; a[1] = 20; a[2] = 30; a[3] = 40; a[4] = 50; a[idx]=100; print(a); return 0; }
逆向分析:
var_EC= byte ptr -0ECh idx= dword ptr -28h a= dword ptr -1Ch var_4= dword ptr -4 argc= dword ptr 8 argv= dword ptr 0Ch mov [ebp+var_4], eax mov [ebp+idx], 0 ;idx = 0 mov [ebp+a], 0Ah ;a[0] =10 mov [ebp+a+4], 14h mov [ebp+a+8], 1Eh mov [ebp+a+0Ch], 28h mov [ebp+a+10h], 32h mov eax, [ebp+idx] ;eax = idx mov [ebp+eax*4+a], 64h ;a[idx] = 100
可以从idx的在栈中的位置 大致判断出数组的大小,可以操纵数组溢出之类的
数组大小 = a+10h - idx = -1ch + 10h - -28h = 28(十进制) = (5*4 + 8(vs2010保护))
//char数组
*************************************************************************
int _tmain(int argc, _TCHAR* argv[]) { char* p = {"asdfgeg"}; char* q = "qwqre"; char b[3]= {"qw"}; printf("%s\r\n",p); printf("%s\r\n",q); printf("%s\r\n",b); return 0; }
mov [ebp+p], offset aAsdfgeg ; "asdfgeg" ;将字符串常量地址赋值给 [ebp+p] mov [ebp+q], offset aQwqre ; "qwqre" mov ax, word ptr ds:aQw ; "qw" ds是段寄存器,是用来存储段地址的,程序是通过段地址:偏移地址寻找数据地址的。 mov word ptr [ebp+b], ax //b[0] mov cl, ds:byte_415742 mov [ebp+b+2], cl //b[2]
vs2010反汇编:
char* p = {"asdfgeg"}; 00E5139E mov dword ptr [p],offset string "asdfgeg" (0E55750h) char* q = "qwqre"; 00E513A5 mov dword ptr [q],offset string "qwqre" (0E55748h) char b[3]= {"qw"}; 00E513AC mov ax,word ptr [string "qw" (0E55744h)] 00E513B2 mov word ptr [b],ax 00E513B6 mov cl,byte ptr ds:[0E55746h] 00E513BC mov byte ptr [ebp-1Eh],cl
//堆分配数组
*****************************************************************************************
int main() { int* heapArray = (int*)malloc(3 * sizeof(int)); int idx = 2; heapArray[0] = 10; heapArray[1] = 20; heapArray[2] = 30; heapArray[idx] =40; return 0; }
mov esi, esp push 0Ch ; Size //malloc的参数 即数组大小 call ds:__imp__malloc add esp, 4 cmp esi, esp call j___RTC_CheckEsp mov [ebp+heapArray], eax mov [ebp+idx], 2 mov eax, [ebp+heapArray] //数组起始位置储存在heaparray中 每次要先获得基址再加偏移 mov dword ptr [eax], 0Ah mov eax, [ebp+heapArray] mov dword ptr [eax+4], 14h mov eax, [ebp+heapArray] mov dword ptr [eax+8], 1Eh mov eax, [ebp+idx] mov ecx, [ebp+heapArray] mov dword ptr [ecx+eax*4], 28h
*************************************************************************************
总结:
只有当变量作为数组的索引时才最容易确定数组的存在