解释汇编中的结构访问?

逆向工程 拆卸 部件 编译器优化
2021-06-22 09:55:26

我无法理解在反汇编中使用结构体。你能解释一下下面的代码吗?拆解如下:

反汇编片段

源代码:

源代码片段

3个回答

这称为内联。strcpy 被 mov 指令取代,因为编译器决定以这种方式代码运行得更快。

这是手动字符串分配。请注意所有 DWORD 是如何由可打印字符组成的?r在IDA的十六进制值转换为字符串中的字符。

这段代码似乎将字符串分配到不同的堆栈地址,一次分配 4 个字符。这是对调用逐字节迭代字符串的函数的常见优化。

正如其他人指出的那样,这种优化通常称为“循环展开”,因为它将循环的几次迭代展开到顺序汇编中,但是我经常发现直接字符串字符分配的类型更常见的是类似于以下代码的输出:

char str[] = "this is a string";

答案的优化咒语让我很感兴趣,所以我想我会检查正在对代码进行哪些实际优化(OP 似乎是初学者,我怀疑 OP 是否能够进行优化)

看来这是默认编译,没有在 gcc 中启用优化

gcc 版本 8.1.0 (i686-win32-dwarf-rev0, 由 MinGW-W64 项目构建)

无论是否优化,visual studio 2017 15.7.3根本不做这种代码

禁用优化 vs 调用 strcpy ()

:\>cl /nologo /Zi booky.cpp
booky.cpp

:\>cdb -c ".lines;uf booky!main;q" booky.exe | grep -E "  15|  16|  17"


   15 001c6b35 6850be2100      push    offset booky!__xt_z+0x108 (0021be50)
   15 001c6b3a 8d8530ffffff    lea     eax,[ebp-0D0h]
   15 001c6b40 50              push    eax
   15 001c6b41 e86bb2ffff      call    booky!ILT+3500(_strcpy) (001c1db1) <<<<
   15 001c6b46 83c408          add     esp,8
   16 001c6b49 685cbe2100      push    offset booky!__xt_z+0x114 (0021be5c)
   16 001c6b4e 8d8d62ffffff    lea     ecx,[ebp-9Eh]
   16 001c6b54 51              push    ecx
   16 001c6b55 e857b2ffff      call    booky!ILT+3500(_strcpy) (001c1db1) <<<<
   16 001c6b5a 83c408          add     esp,8
   17 001c6b5d 6868be2100      push    offset booky!__xt_z+0x120 (0021be68)
   17 001c6b62 8d5594          lea     edx,[ebp-6Ch]
   17 001c6b65 52              push    edx
   17 001c6b66 e846b2ffff      call    booky!ILT+3500(_strcpy) (001c1db1)  <<<<
   17 001c6b6b 83c408          add     esp,8

优化空间 (O2) 或完全优化 (Ox) vs2017 诉诸于使用 sse2 移动

:\>cl /Zi /O2 booky.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26430 for x86

:\>cdb -c ".lines;uf booky!main;q" booky.exe | grep -E "  15|  16|  17"
   15 00f7aae4 a158befc00      mov     eax,dword ptr [booky!`string'+0x8 (00fcbe58)]

:\>cdb -c ".lines;uf booky!main;q" booky.exe | grep -A 5 -E "  15|  16|  17"
   15 00f7aae4 a158befc00      mov     eax,dword ptr [booky!`string'+0x8 (00fcbe58)]
   19 00f7aae9 b933000000      mov     ecx,33h
   19 00f7aaee f30f7e0550befc00 movq    xmm0,mmword ptr [booky!`string' (00fcbe50)] <<<<<<<<
   19 00f7aaf6 89442408        mov     dword ptr [esp+8],eax
   19 00f7aafa 0fb60568befc00  movzx   eax,byte ptr [booky!`string'+0x8 (00fcbe68)] <<<<<<<
   19 00f7ab01 8844243a        mov     byte ptr [esp+3Ah],al

:\>cl /Zi /Ox booky.cpp

:\>cdb -c ".lines;uf booky!main;q" booky.exe | grep -A 5 -E "  15|  16|  17"
   15 0138ac74 a198e83d01      mov     eax,dword ptr [booky!__newctype+0x308 (013de898)]
   19 0138ac79 b933000000      mov     ecx,33h
   19 0138ac7e f30f7e0590e83d01 movq    xmm0,mmword ptr [booky!__newctype+0x300 (013de890)]
   19 0138ac86 89442408        mov     dword ptr [esp+8],eax
   19 0138ac8a 0fb605a4e83d01  movzx   eax,byte ptr [booky!__newctype+0x314 (013de8a4)]
   19 0138ac91 8844243a        mov     byte ptr [esp+3Ah],al

即使使用 O0 显式禁用优化,mingw gcc 8.10 似乎也将字符串分解为双字

:>e:\mingw\mingw-w64.bat
:>ls
booky.cpp
:>gcc -g -O0 booky.cpp

g++ -g -O0 也反汇编为如下相同的结构

:\>objdump -d --start-address 0x4015c0 --stop-address 0x401600 -M intel a.exe

a.exe:     file format pei-i386


Disassembly of section .text:

004015c0 <_main>:
  4015c0:       55                      push   ebp
  4015c1:       89 e5                   mov    ebp,esp
  4015c3:       57                      push   edi
  4015c4:       56                      push   esi
  4015c5:       53                      push   ebx
  4015c6:       83 e4 f0                and    esp,0xfffffff0
  4015c9:       81 ec 70 02 00 00       sub    esp,0x270
  4015cf:       e8 ec 01 00 00          call   4017c0 <___main>
  4015d4:       8d 84 24 a4 01 00 00    lea    eax,[esp+0x1a4]
  4015db:       c7 00 50 72 6f 67       mov    DWORD PTR [eax],0x676f7250
  4015e1:       c7 40 04 72 61 6d 6d    mov    DWORD PTR [eax+0x4],0x6d6d6172
  4015e8:       c7 40 08 69 6e 67 00    mov    DWORD PTR [eax+0x8],0x676e69
  4015ef:       8d 84 24 a4 01 00 00    lea    eax,[esp+0x1a4]
  4015f6:       83 c0 32                add    eax,0x32
  4015f9:       c7 00 4e 75 68 61       mov    DWORD PTR [eax],0x6168754e
  4015ff:       c7                      .byte 0xc7

禁用此-fno-builtin-strcpy需要在命令行中传递给 gcc 如果 -fno-builtin-strcpy 被传递 gcc 即使使用-O3 优化编译也不会分块字符串

汇编

:\>ls
booky.cpp

:\>g++ -O3 -g -fno-builtin-strcpy -o booky.exe booky.cpp

:\>ls
booky.cpp  booky.exe

执行

:\>booky.exe
ProgrammingTelecom Billing

拆卸

:\>objdump -d --start-address=0x402670 --stop-address=0x4026b0 -M intel booky.exe

booky.exe:     file format pei-i386


Disassembly of section .text:

00402670 <_main>:
  402670:       55                      push   ebp
  402671:       89 e5                   mov    ebp,esp
  402673:       57                      push   edi
  402674:       56                      push   esi
  402675:       53                      push   ebx
  402676:       83 e4 f0                and    esp,0xfffffff0
  402679:       81 ec 80 02 00 00       sub    esp,0x280
  40267f:       e8 ec ef ff ff          call   401670 <___main>
  402684:       8d 74 24 1c             lea    esi,[esp+0x1c]
  402688:       c7 44 24 04 44 40 40    mov    DWORD PTR [esp+0x4],0x404044
  40268f:       00
  402690:       8d bc 24 b4 01 00 00    lea    edi,[esp+0x1b4]
  402697:       89 34 24                mov    DWORD PTR [esp],esi
  40269a:       8d 9c 24 b4 01 00 00    lea    ebx,[esp+0x1b4]
  4026a1:       e8 ee fe ff ff          call   402594 <_strcpy>
  4026a6:       8d 44 24 4e             lea    eax,[esp+0x4e]
  4026aa:       c7                      .byte 0xc7
  4026ab:       44                      inc    esp
  4026ac:       24 04                   and    al,0x4
  4026ae:       50                      push   eax
  4026af:       40                      inc    eax

来自radare2的分析输出

|           ; JMP XREF from 0x0040262f (sym.___getmainargs)
|           0x00402671      89e5           mov ebp, esp
|           0x00402673      57             push edi
|           0x00402674      56             push esi
|           0x00402675      53             push ebx
|           0x00402676      83e4f0         and esp, 0xfffffff0
|           0x00402679      81ec80020000   sub esp, 0x280
|           0x0040267f      e8ecefffff     call sym.___main
|           0x00402684      8d74241c       lea esi, [local_1ch]        ; 0x1c ; 28
|           0x00402688      c74424044440.  mov dword [local_4h], str.Programming ; 
[0x404044:4]=0x676f7250 ; "Programming" ; const char * src
|           0x00402690      8dbc24b40100.  lea edi, [local_1b4h]       ; 0x1b4 ; 436
|           0x00402697      893424         mov dword [esp], esi        ; char * dest
|           0x0040269a      8d9c24b40100.  lea ebx, [local_1b4h]       ; 0x1b4 ; 436
|           0x004026a1      e8eefeffff     call sym._strcpy            ;
 char *strcpy(char *dest, const char *src)
|           0x004026a6      8d44244e       lea eax, [local_4eh]        ; 0x4e ; 'N' ; 78
|           0x004026aa      c74424045040.  mov dword [local_4h], str.Nuha_Ali ; 
[0x404050:4]=0x6168754e ; "Nuha Ali" ; const char * src
|           0x004026b2      890424         mov dword [esp], eax        ; char * dest
|           0x004026b5      e8dafeffff     call sym._strcpy            ;
 char *strcpy(char *dest, const char *src)