본문 바로가기

공부/리버싱 핵심원리

Hello World! 리버싱

#include <Windows.h>
#include <tchar.h>

int _tmain(int argc, TCHAR *argv[]) { //  Microsoft에서 확장된 형태의 main.
				      // _tmain함수는 유니코드를 지원하는 프로그램은 컴파일 시 main함수의 와이드 문자 버전인 wmain함수로 바뀌고
				      // 유니코드를 지원하지 않는 프로그램은 컴파일 시 main함수로 바뀜
				      // _tamin함수를 사용하기 위해서는 tchar.h 헤더파일을 포함시켜줘야 함
	MessageBox(
		NULL,
		L"Hello World!",		// L"" 와이드 문자열
		L"www.reversecore.com",		// MessageBox 함수는 유니코드 문자열을 받아들이는 경우가 있으므로, 
		MB_OK				// "Hello World!"를 사용하면 해당 함수가 문자열을 올바르게 처리하지 못할 수 있음
	);					// 따라서 유니코드 문자열을 전달할 때는 L을 붙여 와이드 문자열을 쓴다

	return 0;
}

HelloWorld.cpp

 

_tmain

Microsoft에서 확장된 형태의 main.
_tmain함수는 유니코드를 지원하는 프로그램은 컴파일 시 main함수의 와이드 문자 버전인 wmain함수로 바뀌고, 유니코드를 지원하지 않는 프로그램은 컴파일 시 main함수로 바뀜
_tamin함수를 사용하기 위해서는 tchar.h 헤더파일을 포함시켜줘야 함

 

L"Hello World!" / L" "

와이드 문자열
MessageBox 함수는 유니코드 문자열을 받아들이는 경우가 있으므로, "Hello World!"를 사용하면 해당 함수가 문자열을 올바르게 처리하지 못할 수 있음
따라서 유니코드 문자열을 전달할 때는 L을 붙여 와이드 문자열을 쓴다

 

Not a valid PE file: File 'exe파일 위치' is probably not a 32-bit Portable Executable. Try to load it
anywау?
Error: Unable to start file 'exe파일 위치'

필자는 exe 파일을 블리을 때 이 오류가 떠 제대로 진행을 못 했다. 32비트만 지원한다는 건 알겠는데 그래서 32비트를 어떻게 만드는 건데? 그걸 몰라 검색으로 시간을 허비했다.
비주얼 스튜디오 2022 버전 말고 2010 버전으로 빌드하니 해결됐다.


 

Helloworld.exe 디버깅 목표

>어셈블리 언어로 변환된 main() 함수 찾기
>> 기본적인 디버거 사용법 학습
>>어셈블리 명령어 학습


 

1. Code window

메모리 주소값 / 헥사코드(hex) / 어셈블리 언어 번역 / 주석창

> 기본적으로 disassembly code를 표시한다.

> 각종 comment, label을 보여준다.

> 코드를 분석하여 loop, jump 위치 등의 정보를 표시한다.

 

2. Register window

> CPU register 값을 실시간으로 표시한다.

> 특정 register 값은 수정도 가능하다.

 

3. Dump window

> 프로세스에서 원하는 memory 주소 위치의 값을 헥사코드/아스키코드/유니코드 값으로 표시한다.

> 수정도 가능

 

4. Stack window

> ESP register가 가리키는 프로세스 stack memory를 실시간으로 표시한다.

> 수정도 가능

 


디버깅 시작

 

1. Debug > Run 실행

EP(Entry Point) 코드에서 멈춘다

 

No 명령어 단축키 설명
  Run F9 디버깅 시작
  Restart Ctrl + F2 처음부터 다시 디버깅 시작 (디버깅하는 프로세스 종료 후 재실행)
  Step into F7 하나의 op code 실행 (CALL 명령을 만나면, 그 함수 코드 내부로 이동)
  Step over F8 하나의 op code 실행 (CALL 명령을 만나면, 그 함수의 내부로 이동하지 않고, 그 함수 자체를 실행하고 다음 명령을 수행)
  Execute till return Ctrl + F9 함수 코드 내에서 RETN 명령어까지 실행 (함수 종료)

F7을 누르면 CALL 명령을 만났을 때, 그 함수 코드 내부로 이동

 

돌아옴 > F8 눌러서 다음 JMP문 실행(함수 아니라 F7이든 F8이든 똑같다)
하나하나 함수 다 들어가서 메인함수인지 확인 (F7로 행별 실행 > 함수 들어가면 확인 후 Ctrl+F9 > F8 > 반복)

 

메인함수같이생긴애 발견
들어가보면 이렇다. PUSH 로 주소값 나타냄(유니코드로 주석에 있는 문자열 의미), 메시지박스 CALL

 


 

디버거 명령어

 


 

베이스 캠프

디버거를 재실행할 때마다 매번 EP 코드부터 새로 시작 >> 비효율적!!

코드 중간중간 분석을 원하는 중요 포인트(주소)를 지정하여 그 포인트로 빠르게 이동하여 분석 >> 오굿

 

 

베이스 캠프를 설치하는 4가지 방법 (1)

1. Ctrl + G 로 Go to 명령

821071 주소로 가보겠다. 주소는 컴퓨터마다 다르니 본인의 주소에 맞춰서 하기!

2. 821071 주소에 커서가 놓여져 있으면, [F4] Execute till cursor 명령으로, 커서까지 프로그램 실행

3. 분석

 

 

베이스 캠프를 설치하는 4가지 방법 (2)

1. Ctrl + G 로 Go to 명령 > 821071 주소로 이동

2. 주요 지점에 커서가 위치하면, BP를 설정 [F2]

설정되면 주소가 빨간색으로 변경됨

3. 실행 [F9] > BP가 설정된 곳에서 멈춤

4. 분석

 

BP 설정 > 검색

1. [View] > [Breakpoints] or [ALT+B]

2. Breakpoint 목록

3. 목록에서 breakpoint 를 선택 후, 더블클릭 > 해당 주소로 이동

 

 

베이스 캠프를 설치하는 4가지 방법 (3)

주석 삽입

1. Ctrl + G 로 Go to 명령 > 821071 주소로 이동

2. 주요 지점에 커서가 위치하면, 주석 삽입: 세미콜론(;)

주석이 생김

주석 검색

1. 오른쪽 마우스 > [Search for] > [User defined comment]

빨간 글씨(Initial어쩌구)는 현재 커서의 위치

2. 탐색하려는 주석을 더블클릭 > 커서 이동

3. [F4] Execute till cursor 실행

 

베이스 캠프를 설치하는 4가지 방법 (4)

레이블(Label): 원하는 주소에 특정 이름을 붙여 줌

1. 레이블 표시 설정

[Options] > [Debugging options] > [Disasm] > "Show symbolic addresses" 체크

2. 설정된 주소는 Label로 표시됨

 

레이블(Label) 설정

1. Ctrl + G 로 Go to 명령 > 821071 주소로 이동

2. 주요 지점에 커서가 위치하면, 레이블 삽입: 콜론(:)

3. 주소 821071이 사용된 코드로 이동/확인

레이블로 주소 표시

 

레이블(Label) 검색

1. 오른쪽 마우스 > [Search for] > [User defined label]

빨간 글씨(Initial어쩌구)는 현재 커서의 위치

2. 탐색하려는 레이블을 더블클릭 > 커서 이동

3. [F4] Execute till cursor 실행

 


 

 

원하는 코드를 빨리 찾아내는 4가지 노하우

1. 코드 실행 방법 << 우리가 확인할 수 있는 상황이 나올 때까지 실제로 실행시켜 본다

(Hello World 창이 뜰때까지 F8 돌림 > 메시지박스 출력 시점 확인 > Hellow.wmain 함수를 호출한 부분이 메인함수)

 

2. 문자열 검색 방법 << 프로그램 내에서 사용되는 "문자열"을 확인

우클릭 > [Search for] > [All referenced text strings]

더블 클릭하거나 Go to 명령을 사용하여 이동 / "덤프 창" > [Ctrl+G]: 주소값 > 문자열이 저장된 메모리로 이동 (코드와 문자열 저장 영역이 다름)

 

3. API 검색 방법 1 - 호출 코드에 BP << 사용된 API를 검색

우클릭 > [Search for] > [All intermodular calls]

메시지박스

 

4. API 검색 방법 2 - API 코드에 직접 BP

 


 

"Hello World!" 문자열 패치

패치 대상: 파일 or 메모리 / 코드 or 데이터

실습 목표: 메시지 박스의 "Hello World!"를 다른 문자로 변경

두 가지 방법이 있다(아래에선 1, 2 순서 바뀜)

1-1. 문자열 버퍼를 직접 수정

     1) 덤프 창에서 Go to 명령으로 주소로 이동

     2) 마우스로 변경할 메모리 전체 선택

     3) [Ctrl+E] : Edit Data at...

     4) 문자 변경

입력 시, 문자열 길이 주의. / 또, 유니코드 문자열은 2바이트의 NULL로 끝나야 함. 하지만 유니코드 항목에는 NULL을 입력할 수 없으므로 Hex 항목에다 NULL 입력 (자동으로 되더라)

     5) 실행

바뀐 내용

 

1-2. 문자열 버퍼를 직접 수정 > 변경된 문자열을 실행 파일에 저장하기

     1) 디버깅을 재실행하면 변경된 내용이 다시 처음 상태로 됨 (로딩된 메모리만 변경)

     2) 덤프 창에서 변경된 내용을 선택

     3) 우클릭 > [Copy to executable file]

     4) 우클릭 > [Save file]: 다른 이름으로 저장 (HelloWorld_2.exe)

     5) HelloWorld_2.exe 실행

 

 

2. 다른 메모리 영역에 새로운 문자열을 생성하여 전달

문자열의 주소값을 변경

하지만! 아무 주소나 마구 사용하면 xxx

실습에서는 Paging으로 전달되어 사용하지 않는 영역을 이용한다(덤프창에 0-NULL로 채워져있는 부분)

메모리 NULL Padding 영역

적당한 위치(823018)에 패치 문자열 저장

     1) 덤프 창에서 문자열을 저장할 영역 선택

     2) [Ctrl+E] : Edit Data at 823018

     3) 유니코드에 문자열 저장

     4) 코드창에서 커서를 821007 주소에 위치시킨 후, 더블 클릭 > Assemble 창

     5) 어셈블 창에 Push 823018 입력 후 [Assemble] > 실행 [F9]

하면...

"r"

이렇게 나온다.

응?

다른 영역에 문자열 저장하고 하니 잘 됐다. 위 스샷 주소명에 argc이라고 적힌 걸 보아 아마 다른거랑 겹친 듯.

 

'공부 > 리버싱 핵심원리' 카테고리의 다른 글

IAT 따라가기  (0) 2024.05.12
PE File Format  (0) 2024.05.11
Lena's Reversing for Newbies  (0) 2024.04.17
abex' crackme #2 분석  (0) 2024.04.17
abex' crackme #1 분석  (0) 2024.04.15