zoukankan      html  css  js  c++  java
  • 【黑客免杀攻防】读书笔记12

    1、指针与数组

    C源码

    前两组printf()函数是以指针方式访问数组nArray中的数据的,而后两组printf()函数则是使用数组下标的方式访问数组nArray中的数据的。

    int _tmain(int argc, _TCHAR* argv[])
    {
        // 数组赋值
    	int  nArray[3] = {0x10,0x20,0x300};
    	// 数组地址赋值给指针
    	int *pPtr      = nArray;
    
        // 输出指针中地址
    	printf("%x %x %x
    ", pPtr+0, pPtr+1, pPtr+2);
    	// 输出指针指向的值
    	printf("%x %x %x
    ", *(pPtr+0), *(pPtr+1), *(pPtr+2));
        // 输出数组中的地址
    	printf("%x %x %x
    ", &nArray[0], &nArray[1], &nArray[2]);
    	// 输出数组中的值
    	printf("%x %x %x
    ", nArray[0], nArray[1], nArray[2]);
    
    	return 0;
    }
    
    

    Debug汇编

    对比指针访问和数组访问的汇编,发现用指针访问是向后移动长度为一个int大小的距离,也就是4字节。

    至于加8是因为指针的运算时以指针类型为依据的。

    003CC55E mov [local.4],0x10
    003CC565 mov [local.3],0x20
    003CC56C mov [local.2],0x300
    003CC573 lea eax,[local.4]
    003CC576 mov [local.7],eax
    003CC579 mov eax,[local.7]
    003CC57C add eax,0x8                              ;  pPtr+2   
    003CC57C                                          ;  C语言中,指针的运算是以指针类型为依据的
    003CC57C                                          ;  一个int型指针加1,就是将其指向的地址向后移动长度为一个
    003CC57C 										  ; int大小的距离,也就是4字节。如果是Word型,那就向后移动2字节。
    003CC57F push eax
    003CC580 mov ecx,[local.7]
    003CC583 add ecx,0x4                              ;  pPtr+1  
    003CC586 push ecx
    003CC587 mov edx,[local.7]
    003CC58A push edx                                 ;  pPtr+0  
    003CC58B push 9-44.00420C6C                       ;  ASCII "%x %x %x
    "
    003CC590 call 9-44.003CB0B3
    003CC595 add esp,0x10
    003CC598 mov eax,[local.7]                        ;  *(pPtr+2)  
    003CC59B mov ecx,dword ptr ds:[eax+0x8]
    003CC59E push ecx
    003CC59F mov edx,[local.7]                        ;  *(pPtr+1)  
    003CC5A2 mov eax,dword ptr ds:[edx+0x4]
    003CC5A5 push eax
    003CC5A6 mov ecx,[local.7]
    003CC5A9 mov edx,dword ptr ds:[ecx]
    003CC5AB push edx
    003CC5AC push 9-44.00420C6C                       ;  ASCII "%x %x %x
    "
    003CC5B1 call 9-44.003CB0B3
    003CC5B6 add esp,0x10
    003CC5B9 lea eax,[local.2]                        ;  &nArray[2]
    003CC5BC push eax
    003CC5BD lea ecx,[local.3]                        ;  &nArray[1]
    003CC5C0 push ecx
    003CC5C1 lea edx,[local.4]                        ;  &nArray[0]
    003CC5C4 push edx
    003CC5C5 push 9-44.00420C6C                       ;  ASCII "%x %x %x
    "
    003CC5CA call 9-44.003CB0B3
    003CC5CF add esp,0x10
    003CC5D2 mov eax,[local.2]                        ;  nArray[2]
    003CC5D5 push eax
    003CC5D6 mov ecx,[local.3]                        ;  nArray[1]
    003CC5D9 push ecx
    003CC5DA mov edx,[local.4]                        ;  nArray[0]
    003CC5DD push edx
    003CC5DE push 9-44.00420C6C                       ;  ASCII "%x %x %x
    "
    003CC5E3 call 9-44.003CB0B3
    003CC5E8 add esp,0x10
    003CC5EB xor eax,eax
    

    Release汇编

    发布版的的汇编指令和debug版本相比会做一些优化的操作。

    使用指针取数据和数组取数据的反汇编代码是完全相同的。

    011D1000 sub esp,0xC
    011D1003 lea eax,dword ptr ss:[esp+0x8]           ;  pPtr+2  
    011D1007 push eax
    011D1008 lea ecx,dword ptr ss:[esp+0x8]           ;  pPtr+1  
    011D100C push ecx
    011D100D lea edx,dword ptr ss:[esp+0x8]           ;  pPtr+0 
    011D1011 push edx
    011D1012 push 9-44.011DB384                       ;  ASCII 25,"x %x %x
    "
    011D1017 mov dword ptr ss:[esp+0x10],0x10         ;  存放值
    011D101F mov dword ptr ss:[esp+0x14],0x20
    011D1027 mov dword ptr ss:[esp+0x18],0x300
    011D102F call 9-44.printfc_crttProcess4lockonFilt>
    011D1034 mov eax,dword ptr ss:[esp+0x18]          ;  *(pPtr+2) 
    011D1038 mov ecx,dword ptr ss:[esp+0x14]          ;  *(pPtr+1) 
    011D103C mov edx,dword ptr ss:[esp+0x10]          ;  *(pPtr+0) 
    011D1040 push eax
    011D1041 push ecx
    011D1042 push edx
    011D1043 push 9-44.011DB384                       ;  ASCII 25,"x %x %x
    "
    011D1048 call 9-44.printfc_crttProcess4lockonFilt>
    011D104D lea eax,dword ptr ss:[esp+0x28]          ;  &nArray[2]
    011D1051 push eax
    011D1052 lea ecx,dword ptr ss:[esp+0x28]          ;  &nArray[1]
    011D1056 push ecx
    011D1057 lea edx,dword ptr ss:[esp+0x28]          ;  &nArray[0]
    011D105B push edx
    011D105C push 9-44.011DB384                       ;  ASCII 25,"x %x %x
    "
    011D1061 call 9-44.printfc_crttProcess4lockonFilt>
    011D1066 mov eax,dword ptr ss:[esp+0x38]          ;  nArray[2]
    011D106A mov ecx,dword ptr ss:[esp+0x34]          ;  nArray[1]
    011D106E mov edx,dword ptr ss:[esp+0x30]          ;  nArray[0]
    011D1072 push eax
    011D1073 push ecx
    011D1074 push edx
    011D1075 push 9-44.011DB384                       ;  ASCII 25,"x %x %x
    "
    011D107A call 9-44.printfc_crttProcess4lockonFilt>
    
    

    1.1 数组的不同表达方式

    数组在反汇编中的表达方式一般分为一维数组、二维数组、多维数组这三种,其中一维数组和多维数组是比较难以区分的,但是可以从代码结构和逻辑着手,进而分析出这是一个几维数组。

    在数组面对循环访问的情况下,负责控制访问数组成员偏移的功能由一个寄存器作为选择子来代替。

    数组的访问会遵循以下公式:

    数组成员地址 = 数组起始地址 + sizeof(数组类型) X 数组成员下标

    2 数组与结构体

    数组与结构体存放数据的原则都是一样的,它们都是在一段连续的空间中存放若干数据,唯一的不同之处在于数组存放的数据都是同一类型的,而结构体则有可能存放多种类型的数据。

    C源代码

    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	struct _TEST 
    	{
    		int    nNum;
    		double dFloat;
    		char   szStr[0x10];
    	}stcTEST;
    	stcTEST.nNum   = 0xAAAA;
    	stcTEST.dFloat = 12.345;
    	strcpy_s(stcTEST.szStr,"Hello World!");
    
    	printf("%X %f %s",stcTEST.nNum,stcTEST.dFloat,stcTEST.szStr);
    
    	return 0;
    }
    
    

    这里的代码没看明白

    movsd   xmm0, ds:qword_416490 ; 将12.345保存到浮点寄存器中
    lea     eax, [esp+44h+var_18]
    add     esp, 4
    mov     [esp+40h+var_28], 0AAAAh
    movsd   [esp+40h+var_20], xmm0
    push    offset aHelloWorld ; "Hello World!"
    push    10h
    push    eax
    call    sub_403A3F      ; strcpy函数
    movsd   xmm0, [esp+4Ch+var_20]
    lea     eax, [esp+4Ch+var_18]
    add     esp, 0Ch
    push    eax
    sub     esp, 8          ; 空出8字节空间保存double
    movsd   [esp+4Ch+var_4C], xmm0
    push    [esp+4Ch+var_28]
    push    offset aXFS     ; "%X %f %s"
    call    sub_401090
    

    数组是一组同类型的被连续保存的数据,而结构体也有可能与数组一样。结构体的反汇编特征与数组一致。我理解为两者都是内存里开辟了一串连续的存储空间,然后把数据根据数据类型大小存放。

  • 相关阅读:
    git使用教程指南
    关于px,分辨率,ppi的辨析
    js事件循环机制辨析
    promise基于reduce实现队列消息
    js 文件下载进度监控
    sql表与表之间的数据操作
    微信退款证书使用c#
    微信小程序支付C#后端源码
    微信小程序支付前端源码
    未能加载文件或程序集“System.Web.Http.WebHost, Version=4.0.0.0, ”或它的某一个依赖项。系统找不到指定的文件。
  • 原文地址:https://www.cnblogs.com/17bdw/p/8287542.html
Copyright © 2011-2022 走看看