본문 바로가기

개인 공부/리버싱

Reverse Engineering-002(문법)

함수의 기본 구조

  • 리버스 엔지니어링의 기본을 익히기 위해서는 함수에대해 잘 알아야한다!! (소스코들은 많은 함수로 구성)
  • 크게 함수가 하는 기능, 세세하게 파라미터 개수, 리턴값으로 어떤 값들이 전달되는 지 분석해야함

분석 시 주의할점 ! 

  • 빌드시에 컴파일러가 자동으로 생성해내는 코드를 필터링해야한다!!
/* ========== 함수의 기본구조(C) ========== */
int sum(int x, int y){
	int sum = x + y;
	return sum;
}

/* ========== 디스 어셈브링한 코드 ========== */
push	ebp			// 베이스 주소를 스택에 저장
mov 	ebp, esp		// 현재 스택포인터를 ebp로 바꾼다
push	ecx	
mov 	eax, [ebp+arg_0]	// eax에 파라미터(int x)를 넣는다
add 	eax, [ebp+arg_4]	// eax(x)에 파리미터(int y)를 더한다
mov 	[ebp+var_4], eax	// [ebp+var_4](int sum)에 eax(x+y)를 넣는다
mov 	eax, [ebp+var_4]	// eax에 [ebp+var_4](sum)을 넣는다
mov 	esp, ebp		// 함수가 종료되기 전 스택 위치를 원래대로 돌린다
pop 	ebp			// 함수를 종료 (eax를 리턴한다)
retn
  • 이 함수는 push ebp로 시작해서 pop ebp로 끝난다!
  • 간단한 함수의 경우에는 대부분 push ebp를 통해 함수시작한다

함수의 호출 규약  

  • __cdecl 
    • 호출 규약이 없을 경우 기본 값으로 사용!
    • add를 통해 스택을 정리한다
    • 메인 함수(0x401020)에서 add esp, 8을 통해 스택을 정리하는 것을 확인

__cdecl 호출 규약

  •  __stdcall
    • 많이 사용되는 방식
    • 함수 안에서 스택을 처리한다
    • 메인함수(0x4010020)에서 스택을 처리하지않고 함수(0x401000) 안에서 처리하는 것을 확인!

__stdcall 호출 규약

  • __fastcall
    • 함수의 파라미터가 2개 이하일 경우 인자를 push로 넣지 않고 레지스터(ecx, edx)를 이용한다
    • 레지스터를 이용해서 다른 호출규약보다 빠르다
    • 메인함수(0x401020)에서 push를 이용하지 않고 edx, ecx 레지스터리를 이용하는 것을 확인

__fastcall

  • __thiscall
    • 주로 C++의 클래스에서 이용되는 방식이다
    • 객체에 대한 포인터를 ecx에 전달한다
    • c++에서 ecx로 전달되는 값이 this 포인터가 된다

if 문 (조건문)

c언어 if문
X32dbg로  확인

위 사진은 visual stuido로 코딩한 것을 X32dbg로 역어셈블한 결과이다

  1.  0x401030이 main 함수인것을 추측할 수 있다
    • 0x401033에서 push 1을 하는 것을 확인하고 0x401035에서 Temp함수(0x401000)를 호출하는 것을 확인!! 
  2. 0x401000이 Temp()함수라는 것을 추측
    • 0x401004가 if문으로 (cmp dword ptr ss:[ebp+8], 1) if(a == 1)인것을 확인
    • ebp+4는 파라미터이며, dword(4Byte)인 것을  봐서 int a라고 추측 
  3. ebp - 4는 int b, ebp+8은 a라고 추측할 수있다
    • ebp - n 일 경우 보통 스택에서 변수를 의미한다
    • ebp + n일 경우 보통 파라미터로 사용된다
    • 0x401004의 조건문 ([ebp+8] == 1)에 따라 조건이 맞을 경우 0x40100F를 무시하고 0x401011로 가서 a를 1 증가하는 것을 확인
    • 조건문이 다를 경우 0x40100F 점프문을 통해 0x40101C로 가서 b를 1 증가하는 것을 확인
  4. 추측을 통해 0x401004가 조건문인 것을 확인하였고, 0x401030이 메인 함수, 0x401000이 Temp()함수 인것을 확인

for, while문 (반복문)

c언어 반복문
X32dbg

위 사진은 visual stuido로 코딩한 것을 X32dbg로 역어셈블한 결과이다

  1. 0x401003을 통해 int형(4Byte) 변수 2개가 선언되었다는 것을 추측할 수 있다
    1. 0x401006, 0x40100D에서 각각 mov dword ptr ss:[ebp-8], 0 / mov dword ptr ss:[ebp-4], 0이므로 변수 2개가 선언되고 초기화된것을 확인
  2. ebp-4 가 i, ebp-8이 a인 것을 추측
    1. 0x401016 ~ 0x40101F에서 확인 할 수 있는데 ebp-4가 100(0x64)보다 크거나 같을 경우 종료
    2. 크거나 같지 않을 경우 ebp-4를 더하고 또 ebp-4에 1씩 증가하는 것을  확인 할 수 있다
    3. ebp-8은 a, ebp-4는 i라는 것을 확인
  3. 0x40100D~ 0x40102E가 for문(반복문)이라는 것을 확인
    1. 위에 추측하고 확인 한것을 통해 for(int i = 0 ; i < 100; i++) a += i; 문법인 것을 확인
    2. 디버거에서 확인 한 코드는 함수가 따로 있는게 아니라 메인 함수에 for문이 있는 것을 확인했다

※ 어셈블(Assemble) : 컴파일러가 어셈블리코드를 바이너리 코드로 전환하는 과정을 의미 

※ 역어셈블(Disassemble) : 바이너리 코드를 어셈블리코드로 바꾸는 과정!!

* 실습을 하기위해서는 Visual studio의 보안 설정을 해제!!

  1. 프로젝트 설정(구성 : Release, 플랫폼 : 활성(win32))
    1. 구성속성 -> 고급 -> 멀티바이트 문자 집합 사용
    2. 구성속성 -> C/C++ -> 최적화 -> 최적화 : 사용안함
    3. 구성속성 -> C/C++ -> 코드 생성 -> 버퍼 보안 검사 : 아니요(/GS-) / 보안 검사 :보안검사 사용 안함 (/GS-) 
    4. 구성속성 -> C/C++ -> 전처리기 -> _CRT_SECURE_NO_WARNNIGS
    5. 구성속성 -> 링커 ->(고급->) DEP(데이터 실행 방지) : 이미지가 DEP와 호환되지 않습니다(/NXCOMPAT:NO)
    6. 구성속성 -> 링커 -> 명령줄 -> /SAFESEH:NO


 

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

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-003(구조체 & API)  (0) 2023.04.12
Reverse Engineering-001(Assembly)  (0) 2023.04.09