IDA逆アセンブリは、Visual Studio2017でコンパイルされたexeファイルのASMファイルとはまったく異なるコードを生成します

ackbar03

Visual Studio2017を使用して簡単なプログラムをコンパイルしました

#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を開くと、逆アセンブルすると完全に理解できないものが吐き出されます。

ida_cap

なぜそうなのですか?Visual Studioはデフォルトでアセンブリコードを自動的に難読化しますか?私はグーグルで検索しましたが、そうではないようです。もしそうなら、どうすれば難読化をオフにできますか?

ありがとう

マーガレットブルーム

main このレベルでは、はプログラムのエントリポイントではありません。

The C language is an abstraction, before main can ran the runtime must be initialised.
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?)

At the end of the day, all languages compile down to a binary PE, it's important to get familiar with that.

I've compiled your program in order to show how to find 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++ is notoriously more complex to reverse engineer.

The example below will differ from yours, mine is an x86 debug build.


First of all, IDA tells you where the PE entry point is in the Exports tab

[エクスポート]タブの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

初期化と本体

VS generate a security cookie as the first thing and that's what the first function called does:

セキュリティクッキー

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.

Assessed that this is the security cookie generation routine we then get back to the previous one and enter the second call

体

This is the body of your program, not main but where the CRT is initialised and finalised, including calling 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 calls before _exit or _cexit. We then move close to these calls:

候補者の呼び出し

If you hover over a function call IDA will show the function code.
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.
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).

プレメイン

This looks like a call to main, the arguments match.
In fact, if we enter the call we get to main:

メイン


Of course, you could have found main by simply looking for the "Hello, world!" string in the "String view" (Shift + F12) but in a real world scenario of reverse engineering this almost always not possible.

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.
This greatly help with the reverse engineering, you can load two IDAs, one with the PDB and one without and compare.
Unfortunately, getting the MS DIA SDK may not be so easy.

また、IDAFLIRTは必須です。
これはメソッドシグネチャのライブラリであり、IDAがランタイム関数を認識できるようにするため、アプリケーションの実際のコードに非常に簡単に集中できます。署名を見つけるのは難しい(そして生成するのは難しい)が、それだけの価値はある。


最後に、生成されるコードのタイプが原因で、デバッグビルドをリバースエンジニアリングするのが難しい場合があることに注意してください。
リリースビルドを作成してリバースエンジニアリングすると、にアクセスしやすくなりますmain

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ