简体   繁体   English

IDA反汇编会为Visual Studio 2017中编译的exe生成与ASM文件完全不同的代码

[英]IDA disassembly produces completely different code to ASM file for exe compiled in Visual Studio 2017

I compiled a simple program using Visual Studio 2017 我使用Visual Studio 2017编译了一个简单程序

#include <stdio.h>
int main()  
{
    printf("hello, world\n"); 
    return 0; 
}

I compile it with command line 我用命令行编译

cl 1.cpp /Fa1.asm 

This gives me assembly code that (mostly) makes sense to me 这给了我大多数情况下有意义的汇编代码

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.14.26429.4 



INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

CONST   SEGMENT
$SG5542 DB  'hello, world', 0aH, 00H
CONST   ENDS
PUBLIC  ___local_stdio_printf_options
PUBLIC  __vfprintf_l
PUBLIC  _printf
PUBLIC  _main
PUBLIC  ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA ; `__local_stdio_printf_options'::`2'::_OptionsStorage
EXTRN   ___acrt_iob_func:PROC
EXTRN   ___stdio_common_vfprintf:PROC
;   COMDAT ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA
_BSS    SEGMENT
?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA DQ 01H DUP (?) ; `__local_stdio_printf_options'::`2'::_OptionsStorage
_BSS    ENDS
; Function compile flags: /Odtp
_TEXT   SEGMENT
_main   PROC
; File c:\users\mr dai\documents\michael\study\cybersecurity\reverseengineering4beg\random\random\random.cpp
; Line 3
    push    ebp
    mov ebp, esp
; Line 4
    push    OFFSET $SG5542
    call    _printf
    add esp, 4
; Line 5
    xor eax, eax
; Line 6
    pop ebp
    ret 0
_main   ENDP
_TEXT   ENDS
; Function compile flags: /Odtp
;   COMDAT _printf
_TEXT   SEGMENT
__Result$ = -8                      ; size = 4
__ArgList$ = -4                     ; size = 4
__Format$ = 8                       ; size = 4
_printf PROC                        ; COMDAT
; File c:\program files (x86)\windows kits\10\include\10.0.17134.0\ucrt\stdio.h
; Line 954
    push    ebp
    mov ebp, esp
    sub esp, 8
; Line 957
    lea eax, DWORD PTR __Format$[ebp+4]
    mov DWORD PTR __ArgList$[ebp], eax
; Line 958
    mov ecx, DWORD PTR __ArgList$[ebp]
    push    ecx
    push    0
    mov edx, DWORD PTR __Format$[ebp]
    push    edx
    push    1
    call    ___acrt_iob_func
    add esp, 4
    push    eax
    call    __vfprintf_l
    add esp, 16                 ; 00000010H
    mov DWORD PTR __Result$[ebp], eax
; Line 959
    mov DWORD PTR __ArgList$[ebp], 0
; Line 960
    mov eax, DWORD PTR __Result$[ebp]
; Line 961
    mov esp, ebp
    pop ebp
    ret 0
_printf ENDP
_TEXT   ENDS
; Function compile flags: /Odtp
;   COMDAT __vfprintf_l
_TEXT   SEGMENT
__Stream$ = 8                       ; size = 4
__Format$ = 12                      ; size = 4
__Locale$ = 16                      ; size = 4
__ArgList$ = 20                     ; size = 4
__vfprintf_l PROC                   ; COMDAT
; File c:\program files (x86)\windows kits\10\include\10.0.17134.0\ucrt\stdio.h
; Line 642
    push    ebp
    mov ebp, esp
; Line 643
    mov eax, DWORD PTR __ArgList$[ebp]
    push    eax
    mov ecx, DWORD PTR __Locale$[ebp]
    push    ecx
    mov edx, DWORD PTR __Format$[ebp]
    push    edx
    mov eax, DWORD PTR __Stream$[ebp]
    push    eax
    call    ___local_stdio_printf_options
    mov ecx, DWORD PTR [eax+4]
    push    ecx
    mov edx, DWORD PTR [eax]
    push    edx
    call    ___stdio_common_vfprintf
    add esp, 24                 ; 00000018H
; Line 644
    pop ebp
    ret 0
__vfprintf_l ENDP
_TEXT   ENDS
; Function compile flags: /Odtp
;   COMDAT ___local_stdio_printf_options
_TEXT   SEGMENT
___local_stdio_printf_options PROC          ; COMDAT
; File c:\program files (x86)\windows kits\10\include\10.0.17134.0\ucrt\corecrt_stdio_config.h
; Line 85
    push    ebp
    mov ebp, esp
; Line 87
    mov eax, OFFSET ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA ; `__local_stdio_printf_options'::`2'::_OptionsStorage
; Line 88
    pop ebp
    ret 0
___local_stdio_printf_options ENDP
_TEXT   ENDS
END

However I open the exe with IDA and the disassemble spits out something completely unintelligible. 但是,我用IDA打开了exe,反汇编却吐出了一些完全无法理解的东西。

ida_cap

Why is this the case? 为什么会这样呢? Does visual studio automatically obfuscate assembly code by default? 默认情况下,Visual Studio是否会自动混淆汇编代码? I googled but this doesn't seem to be the case. 我用谷歌搜索,但事实并非如此。 If so, how do I turn obfuscation off? 如果是这样,如何关闭混淆功能?

Thanks 谢谢

main is not the entry point of you program, at this level. 在这个级别上, main不是您程序的入口点。

The C language is an abstraction, before main can ran the runtime must be initialised . C语言是一种抽象,在main可以运行之前, 必须初始化运行时
C++ is even more complicated but the idea is the same: there is some code that is run before main (otherwise who would initialise cout for example?) C ++甚至更复杂,但是思想是相同的:在main之前运行一些代码(否则谁会初始化cout ?)

At the end of the day, all languages compile down to a binary PE, it's important to get familiar with that. 归根结底,所有语言都可以编译为二进制PE,熟悉这一点很重要。

I've compiled your program in order to show how to find main . 我已经编译了您的程序,以展示如何查找main
Note however that, based on your code, I assumed you were compiling a C file while looking at the disassembly it seems you compiled a C++ file. 但是请注意,根据您的代码,我假设您在查看反汇编时正在编译C文件,似乎您已编译了C ++文件。 C++ is notoriously more complex to reverse engineer. 众所周知,C ++对于逆向工程更为复杂。

The example below will differ from yours, mine is an x86 debug build. 下面的示例与您的示例不同,我的是x86调试版本。


First of all, IDA tells you where the PE entry point is in the Exports tab 首先,IDA会告诉您PE入口点在“ 导出”选项卡中的位置

“导出”选项卡中的PE入口点

If you double click it and follow the path the jmp and call instructions (there is only one path, you can't get lost) you arrive at a routine with two calls 如果双击它并遵循jmpcall说明的路径(只有一条路径,就不会迷路),您将通过两次调用到达例程

初始化和主体

VS generate a security cookie as the first thing and that's what the first function called does: VS首先生成一个安全cookie,这就是第一个调用的功能:

安全cookie

Note that this routine is pretty recognisable even without the IDA hints because it make very spot-on API calls, you can Google some of the function names in the picture to find the documentation. 请注意,即使没有IDA提示,该例程也非常容易识别,因为它可以进行非常即时的API调用,您可以在图片中使用Google的某些函数名称来查找文档。

Assessed that this is the security cookie generation routine we then get back to the previous one and enter the second call 评估这是安全性Cookie生成例程,然后我们返回上一个例程并输入第二个调用

身体

This is the body of your program, not main but where the CRT is initialised and finalised, including calling main . 这是程序的主体,不是main而是CRT初始化和完成的地方,包括调用main
Take a look at the flow-chart in the lower left corner and see that most of the work is in the left branch (meaning that the right branch is an error condition). 查看左下角的流程图,看看大部分工作在左分支中(这意味着右分支是错误情况)。

main is usually called a few call s before _exit or _cexit . main通常在_exit_cexit之前称为几次call We then move close to these calls: 然后,我们靠近这些调用:

候选人电话

If you hover over a function call IDA will show the function code. 如果将鼠标悬停在函数调用上,IDA将显示该函数代码。
Functions that are a single jmp are present in the the debug build to help the debugger and are more often than not runtime functions. 调试构建中提供了单个jmp功能来帮助调试器,并且通常不是运行时功能。
The first circled function, when hovered, show a call to an "enviroment" routine, this is good since main needs the program arguments (Windows don't pass the argument to the program, there is a specific API to get them). 当第一个带圆圈的函数悬停时,显示对“环境”例程的调用,这很好,因为main需要程序参数(Windows不会将参数传递给程序,有一个特定的API可以获取它们)。

前主

This looks like a call to main , the arguments match. 这看起来像是对main的调用,参数匹配。
In fact, if we enter the call we get to main : 实际上,如果我们输入呼叫,则会到达main

主要


Of course, you could have found main by simply looking for the "Hello, world!" 当然,您可以通过简单地查找“ Hello,world!”来找到main string in the "String view" ( Shift + F12 ) but in a real world scenario of reverse engineering this almost always not possible. 在“字符串视图”( Shift + F12 )中输入字符串,但是在现实世界中,进行逆向工程几乎总是不可能的。

Making program and then reverse engineering them is a very good approach, if you have VS installed, you may have the MS DIA SDK that allows IDA to read the pdb files. 制作程序然后进行反向工程是一个很好的方法,如果您安装了VS,则可能拥有MS DIA SDK,该软件允许IDA读取pdb文件。
This greatly help with the reverse engineering, you can load two IDAs, one with the PDB and one without and compare. 这对逆向工程有很大帮​​助,您可以加载两个IDA,一个加载PDB,另一个不加载并进行比较。
Unfortunately, getting the MS DIA SDK may not be so easy. 不幸的是,获得MS DIA SDK可能并不容易。

Also, IDA FLIRT is a must. 另外,IDA FLIRT是必须的。
It's a library of method signature, it allows IDA to recognise the runtime functions, making it very easy to focus on the application real code. 这是一个方法签名库,它使IDA能够识别运行时函数,从而使将重点放在应用程序实际代码上变得非常容易。 It's hard to find (and harder to generate) the signature though but they are totally worth it. 虽然很难找到(也很难生成)签名,但是它们完全值得。


Finally, note that debug build may be harder to reverse engineer due to the type of code generated. 最后,请注意,由于生成的代码类型不同,调试版本可能更难以逆向工程。
If you make a release build and reverse engineer it, you'll see it's easier to get to main . 如果您进行发布构建并对它进行反向工程,您会发现进入main更容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM