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を開くと、逆アセンブルすると完全に理解できないものが吐き出されます。
なぜそうなのですか?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
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 call
s 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]
コメントを追加