환경: Visual Studio 2019
빈 프로젝트 설정 ㄱㄱ >> 아무거나.c 파일 만들기
#include<stdio.h>
int main(int argc, char** argv)
{
__debugbreak();
printf("Hello Malware!\n");
return 0;
}
속성 >> c/c++ >> 코드 생성 >> 런타임 라이브러리 >> 다중 쓰레드 디버그 /MTd
>> 설정 끄고 ctrl+shift+b
>> 브레이크 포인트 걸고 f5 >> 디버그 >> 창 >> 디스어셈블리, 메모리, 레지스터
메모리창에 0x 주소입력하고 엔터
/ 디버그는 x64
1: #include <stdio.h>
2:
3: int main(int argc, char** argv)
4: {
00007FF74D539800 48 89 54 24 10 mov qword ptr [rsp+10h],rdx
00007FF74D539805 89 4C 24 08 mov dword ptr [rsp+8],ecx
00007FF74D539809 55 push rbp
00007FF74D53980A 57 push rdi
00007FF74D53980B 48 81 EC E8 00 00 00 sub rsp,0E8h
00007FF74D539812 48 8D 6C 24 20 lea rbp,[rsp+20h]
00007FF74D539817 48 8D 0D E5 A7 10 00 lea rcx,[__6B80F3E7_소스@c (07FF74D644003h)]
00007FF74D53981E E8 B3 C6 FF FF call __CheckForDebuggerJustMyCode (07FF74D535ED6h)
5: __debugbreak();
00007FF74D539823 CC int 3
6: printf("Hello Malware!\n");
00007FF74D539824 48 8D 0D 6D A7 0C 00 lea rcx,[string "a+b= %d" (07FF74D603F98h)]
00007FF74D53982B E8 5A AE FF FF call printf (07FF74D53468Ah)
7: return 0;
00007FF74D539830 33 C0 xor eax,eax
8: }
00007FF74D539832 48 8D A5 C8 00 00 00 lea rsp,[rbp+0C8h]
00007FF74D539839 5F pop rdi
00007FF74D53983A 5D pop rbp
00007FF74D53983B C3 ret
한줄 씩 알아보도록 하자.
mov qword ptr [rsp+10h], rdx : rdx 값을 rsp에서 16바이트(16진수로 10은 16이다 + h는 16진수를 뜻한다.) 떨어진 위치에 저장한다. 여기서 rsp + 10h는 스택의 상대적인 위치이다 = 로컬 변수나 함수 호출전에 넘겨진 인수를 저장하는 공간.
mov dword ptr [rsp+8], ecx : ecx 값을 rsp + 8(여기서 8은 10진수이다.)에 위치한 곳에 저장한다. ecx는 32비트이므로 dword를 쓴다.
push rbp: 베이스 포인터를 저장한다. 여기서부터 함수 시작
push rdi: 값을 스택에 저장한다. 함수 호출 시 첫번째 매개변수를 전달한다.
call은 함수 호출인 것을 기억하자.
c언어로 어셈블리가 돌아가는 방식을 알아 봤다. 어셈블리어를 보고 c언어로 구현하는 것도 혼자 공부해보자.
반응형