【问题标题】:IDA disassembly produces completely different code to ASM file for exe compiled in Visual Studio 2017IDA 反汇编生成与在 Visual Studio 2017 中编译的 exe 的 ASM 文件完全不同的代码
【发布时间】:2023-03-22 03:08:01
【问题描述】:

我使用 Visual Studio 2017 编译了一个简单的程序

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

我用命令行编译它

cl 1.cpp /Fa1.asm 

这给了我(大部分)对我有意义的汇编代码

; 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

但是,我用 IDA 打开 exe,反汇编程序吐出一些完全无法理解的东西。

为什么会这样? Visual Studio 默认会自动混淆汇编代码吗?我用谷歌搜索,但似乎并非如此。如果是这样,我该如何关闭混淆功能?

谢谢

【问题讨论】:

  • 您正在查看链接到程序中的运行时库。当然,C 和 C++ 程序员永远不必在混淆器上花钱。
  • 所以它没有被混淆?那么如何查看我的实际主要方法,以便我可以看到类似于 ASM 文件的内容?另外,当我打开其他一些用于练习的 exe 时,为什么我没有看到这种混乱,为什么它不会出现在 ASM 文件中?抱歉问了这么多问题,谢谢
  • 它在某个地方。但是由于您编写的代码很少,因此很难找到。图表演示文稿不是很有用找到它回来。 ASM 文件从不包含运行时库代码。我看不到那些“其他 exe”,但是您是否使用 /MT 与 /MD 构建程序很重要。 /MT 将运行时库包含在程序中,/MD 将其保留在另一个 DLL 中。然而,总是有一些运行时库支持链接,这是初始化和启动程序所必需的。
  • 我通过在 IDA 中搜索汇编代码找到了它,它被埋在那里的某个地方。通常如何在其他程序上实际完成?所有的图书馆链接都非常混乱
  • 通常不会这样做,没有人有时间。

标签: assembly visual-studio-2017 disassembly ida


【解决方案1】:

main 不是你程序的入口点,在这个级别。

C 语言是一种抽象,之前main 可以运行runtime must be initialised
C++ 更复杂,但思路是一样的:有一些代码在main 之前运行(否则谁会初始化cout?)

归根结底,所有语言都编译为二进制 PE,熟悉这一点很重要。

我已经编译了你的程序,以便展示如何找到main
但是请注意,根据您的代码,我假设您在查看反汇编时正在编译 C 文件,似乎您编译了 C++ 文件。 众所周知,C++ 的逆向工程更复杂。

下面的示例与您的不同,我的是 x86 调试版本。


首先,IDA 会告诉你 PE 入口点在 Exports 选项卡中的位置

如果您双击它并按照jmpcall 说明的路径(只有一个路径,您不会迷路),您将进入一个带有两个调用的例程

VS 首先生成一个安全 cookie,这就是第一个调用的函数的作用:

请注意,即使没有 IDA 提示,此例程也很容易识别,因为它会进行非常准确的 API 调用,您可以谷歌图片中的一些函数名称来查找文档。

评估这是安全cookie生成例程,然后我们回到上一个并进入第二个调用

这是程序的主体,不是 main,而是 CRT 初始化和完成的地方,包括调用 main
看一下左下角的流程图,发现大部分工作都在左分支中(意味着右分支是错误条件)。

main 通常在_exit_cexit 之前被称为几个calls。 然后我们接近这些调用:

如果您将鼠标悬停在函数调用上,IDA 将显示函数代码。
单个 jmp 的函数存在于调试版本中以帮助调试器,并且通常是运行时函数。
第一个带圆圈的函数,当悬停时,显示对“环境”例程的调用,这很好,因为main 需要程序参数(Windows 不将参数传递给程序,有一个特定的 API 来获取它们) .

这看起来像是对main 的调用,参数匹配。
事实上,如果我们输入电话,我们会得到main


当然,您可以通过简单地查找“Hello, world!”找到main。 “字符串视图”(Shift + F12)中的字符串,但在逆向工程的现实世界场景中,这几乎总是不可能的。

制作程序然后对其进行逆向工程是一个非常好的方法,如果您安装了 VS,您可能拥有允许 IDA 读取 pdb 文件的 MS DIA SDK。
这对逆向工程有很大帮​​助,您可以加载两个 IDA,一个带有 PDB,一个不带并进行比较。
不幸的是,获得 MS DIA SDK 可能并不那么容易。

此外,IDA FLIRT 是必须的。
它是一个方法签名库,它允许 IDA 识别运行时函数,从而非常容易专注于应用程序的真实代码。 虽然很难找到(也更难生成)签名,但它们完全值得。


最后,请注意,由于生成的代码类型,调试构建可能更难进行逆向工程。
如果您进行发布构建并对其进行逆向工程,您会发现访问main 会更容易。

【讨论】:

  • 非常感谢您花时间解释这一点!我希望得到一些这样的建议和指示。我一定会看看 FLIRT 和 Ms DIA sdk。你有什么好的资源可以推荐来学习这个吗?您上面提到的很多内容似乎都来自经验,我之前尝试过用谷歌搜索我的问题,但无法找到我需要的信息。我目前正在阅读一本汇编书和逆向工程介绍。我也有 Ida 专业书籍,但还没有时间阅读。
  • @ackbar03 我的建议是学习 C 语言的 Windows API 编程,如果需要,还可以学习 C++ 编程。每次查看生成的机器码。基本上,对您的程序进行逆向工程。使用的程序集通常是整个 ISA 的一小部分,因此您可以直接从 RE 中学习(需要时参考 Intel 手册)。 COM 技术是另一回事。检查其他编译器的输出(例如 Delphi、VB6、MinGW/DevC++)。基本上,您看到的程序越多,您就越容易识别它们。
  • @ackbar03 还有 DynamoRIO、Frida、rr、Time triver 调试器等工具。 Here's a very good article on how to use them to build an exploit,不同的主题但仿射。
  • @ackbar03 哦,慢慢来。花一周时间完全重新编译一个二进制文件是可以的。像 AnyRun 这样的网站有恶意软件样本,可以在现实世界场景中进行训练。
  • 你是神玛格丽特。我会按照你的形象建造一座神社
猜你喜欢
  • 1970-01-01
  • 2018-03-21
  • 2014-05-29
  • 2011-07-26
  • 2019-03-18
  • 2012-05-09
  • 1970-01-01
  • 2015-12-21
  • 2016-12-10
相关资源
最近更新 更多