본문 바로가기

개인 공부/리버싱

Reverse Engineering-003(구조체 & API)

 

구조체와 API Call

※ 구조체 : 사용자가 여러가지 타입을가지고 새롭게 정의하는 사용자 정의 타입!!

※ API(Application Programming Interface) :  프로그램들이 서로 상호작용한는 것을 도와주는 매개체

  • 구조체의 각 멤버 변수가 어떤식으로 사용되는지 확인
  • 리버스 엔지니어링 할 때는 스택 포인터만 보고 구조체 크기가 얼마인지 확인
  • API인자로는 어떤 것이 들어가는지 파악하는 것이 필수!!
#include<stdio.h>
#include <windows.h>

void RunProcess() {
	STARTUPINFO si;	// 생성화는 프로세스 속성을 지정할 때 사용
	PROCESS_INFORMATION pi;	// 새로 생성된 프로세스와 기본 스레드에 대한 정보가 있다

	// ZeroMemory() : 메모리 영역을 0x00으로 체우는 매크로!(함수X)
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);	// .cb : 구조체 변수의 크기를 전달
	ZeroMemory(&pi, sizeof(pi));
	
    // CreateProcess () : 새(자식) 프로세스를 만드는 함수
	if (!CreateProcess(NULL, "MyChildProcess", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
		printf("CreateProcess Failed \n");
		return;
	}
    
	//WaitForSingleObject() : 쓰레드 종료 지연시키는 함수
	WaitForSingleObject(pi.hProcess, INFINITE);

	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);	
}

int main() {
	RunProcess();
	return 0;
}

x32dbg - void RunProcess()
x32dbg - int main ()

구조체 2개 (STARTINFO & PROCESS_INFORMATION)

/* ===== STARTUPINFO =====*/
typedef struct _STARTUPINFO{
	DWORD	cb;
	LPSTR	lpReserved;
	LPSTR	lpDesktop;
	LPSTR	lpTitle;
	DWORD	dwX;    
	DWORD	dwY;
	DWORD	dwXSize;
	DWORD	dwYSize;
	DWORD	dwXCountChars;
	DWORD	dwYCountChars;
	DWORD	dwFileAttribute
	DWORD	dwFlags;
	WORD	wShowWindw;
	WORD	cbReserved2;
	LPBYTE	lpReserved2;
	HANDLE	hStdInput;
	HANDLE	hstdOutput;
	HANDLE	hStdError;
} STARTUPINFO, *LPSTARTUPINFO;

/* ===== PROCESS_INFORMATION ===== */
typdef struct _PROCESS_INFORMATION{
	HANDLE	hProcess;
	HANDLE	hThread;
	DWORD	dwProcessId;
	DWORD	dwThreadId;    
} PROCESS_INFORMATION;
  • STARTUPINFO 구조체의 크기는 0X44Byte(68Byte), PROCESS_INFORMATION 구조체는 0X10Byte(16Byte)
  • 구조체의 총 크기는 0x55Byte(78Byte)

ZeroMemory

  • ZeroMemory() 매크로이고 memset 함수를 사용하여 0x40108E에 memset함수를 불러오는 것을 확인
  • [ebp-54]에 0x44(68)을 넣는 것을 확인 --> STARTUPINFO  si의 길이를 전달
  • xor을 통해 ecx값을 0으로 초기화하는 것을 확인

CreateProcess

  • CreateProcess에 10개의 인자를 전달하는 것을 확인
  • PUSH (순서대로 :  &pi, &si, NULL, NULL, 0,  FALSE, NULL, NULL, "MyChildProcess" ,NULL ) 전달
  •  그리고 함수 호출하는 것을 확인!! 0x4010C6

  • test eax, eax(0x4010CC)로 eax에 데이터가 있는 지 확인 -> 프로세스가 새로 생겼는지 확인
  • 프로세스가 생기지 않았다면 pritnf문 호출(CreateProcess Failed \n)하고 리턴
  • 프로세스가 생겼다면  FFFFFFFF(INFINITE)와, [ebp-10] pi.hProcess를 전달하며 WaitForSingleObject 호출
    • 이것으로 [ebp-10]은 pi.hProcess인 것을 확인
  • [ebp-10] pi.hProcess를 CloseHandle 전달하며 호출
  • [ebp-C] pi.hTread를 CloseHandle 전달하며 호출
    • 이것으로 [ebp-C]는 pi.hTread인 것을 확인

  • push ebp와 RunProcess를 호출하는 것을 보고 main 함수라는 것을 추측
  • 그리고 0x4010DA에서 add esp 4로 스택을 정리하는 것을 봐서 __cdecl 호출 규약인것을 확인

'개인 공부 > 리버싱' 카테고리의 다른 글

Reverse Engineering-006 PE-01  (0) 2023.04.17
Reverse Engineering-005  (0) 2023.04.13
Reverse Engineering-004(C++)  (0) 2023.04.12
Reverse Engineering-002(문법)  (0) 2023.04.10
Reverse Engineering-001(Assembly)  (0) 2023.04.09