解释汇编中的结构访问?
逆向工程
拆卸
部件
编译器优化
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)
其它你可能感兴趣的问题

