#About


Author : Basse 2002


Korean :

Key를 구한 후 입력하게 되면 성공메시지를 볼 수 있다

이때 성공메시지 대신 Key 값이 MessageBox에 출력 되도록 하려면 파일을 HexEdit로 오픈 한 다음

0x???? ~ 0x???? 영역에 Key 값을 overwrite 하면 된다.


문제 : Key값과 + 주소영역을 찾으시오

Ex) 77777777????????


English :

You will see a success message after finding the key.

If you would want the Key itself to replace the success message in the MessageBox,

open up a Hex Editor and overwrite the key value in the offset range 0x???? ~ 0x????.


Q : find the key value and the offset range and write the solution in this format : key????????

(first ???? for the start and the next 4 ?s for the end).




#Contents


해당 문제는 안티리버싱 기법 중 하나인 더미코드의 이해와 Hex Editor에서의 바이너리를 이해하는 것을 목표로 한다




#Solution


[그림 1] - 실행화면


12.exe를 실행하게 되면 위와 같은 UI를 확인 가능하며, 임의의 값을 넣고 Check를 누르면 아무 반응이 없음을 알 수 있었다


분석을 위해 디버거로 열었을 때, 아래와 같은 에러 메시지를 확인할 수 있었다.


[그림 2] - 에러메시지


메시지의 내용과 문제를 연관지어 생각해보면, 12.exe 파일은 PE 구조중 코드 영역이 비어 있음을 알 수 있고 이를

이용해 코드영역에 overwrite 해야할 값은 Key 값이 위치하는 주소값이라는 가설을 세울 수 있다(혼자 일단 세워봄 ㅎ)



[그림 3] - Key 값


[그림 2]의 과정을 넘어, 디버거로 열고 조금만 내리다 보면 Congratulation, you fond the right key(이하 성공메시지)라는

문구를 확인할 수 있으며, 위 문구가 적힌 코드 위에서 아스키 문자로 적혀있는 키 값을 확인할 수 있다.


문제의 지문에서도 알 수 있듯, Key 값을 구해 입력하게 되면 성공메시지가 뜨는 것을 알 수 있으니, Key 값을 메시지로 출력시키기 위해서는

어떻게 할 수 있을까 생각하다가 메모리에 성공메시지가 담겨있는 주소가 아닌, 키 값이 담긴 주소로 바꿔 주면 가능할 것 같아

아래와 같이 코드를 수정해주었다 ( 0040106B 주소 또한 키 값을 출력하는 코드로 강제로 분기 하게 바꿔줌 )


[그림 4] - 코드 수정


수정을 진행 후, 임의의 값을 넣고 Check를 누르자 아래와 같이 키 값이 출력됨을 알 수 있다


[그림 5] - 키 값 출력


또한 이러한 방법이 아닌, Hex Editor로 수정도 가능함을 알게 되었다

 

1. 아래와 같이 강제로 성공 메시지를 출력하는 구문으로 분기하게 끔 만들어 준다

강제로 분기하게 만드는 방법은, 여러개의 코드가 될 수 있음


[그림 6] - 분기문 수정


2. [그림 6]과 같이 코드를 수정 후 패치 한 다음, 아래와 같이 성공메시지가 저장되어 있는 주소인 0040353B를 HexEditor에서 찾는다


[그림 7] - 성공 메시지가 저장 되어 있는 메모리 주소


3. 위 0040353B 부분을, 키 값이 적혀 있는 메모리 주소인 00403000으로 아래와 같이 바꿔준다


[그림 8] - 메모리 주소 값 변경


4. 위와 같이 수정해 준 뒤, 저장하고 프로그램을 실행하면 아래와 같이 키 값이 메시지창에 출력됨을 확인할 수 있다


[그림 9] - 메시지 창에 키 값 출력


그래서 여기까지가 제일 처음 문제 풀며 삽질 했던 것이며, 지금 부터 풀이를 진행 하겠습니다 ㅋ.ㅋ ... 고멘ㅎ




#Solution


[그림 10] - 실행화면


12.exe를 디버거상에 올렸을 때 화면이며, 어떻게 짜여진 프로그램인지 알기 위해 해당 프로그램에서 사용 된 함수들을 추출해 보았더니 아래와 같았다


[그림 11] - 함수 목록


해당 프로그램에 사용 된 함수들은 위와 같고, 문제 풀이에 가장 관련 있는 함수는 "GetDlgItemInt"다

해당 함수는, 컨트롤로부터 입력된 정수 값을 읽어들여 리턴하는 함수이며 아래와 같이 정의되어 있다


UNIT GetDlgItemInt(HWND hDlg, int nID, BOOL *IpTranslated, BOOL bSigned);


컨트롤로부터 정수형 값을 읽어들일 때는 항상 에러가 발생할 소지가 있으며, 그 예시로는 입력된 정수를 읽어들일 때

숫자 이외의 문자가 있거나 숫자가 너무 클 경우이다. 이 경우 GetDlgItemInt는 세 번째 인수로 지정된 BOOL형 포인터에

에러가 있었는지 없었는지를 대입하며, 에러 검사를 할 필요 없을 경우엔 NULL 값을 전달한다

(출처 : ymn2047.tistory.com/category/API)


[그림 12] - BreakPoint > DialogBoxParamA


0040101D부분에 bp를 걸고 실행했을 때, 아래의 DialogBox를 볼 수 있다


[그림 13] - DialogBox


Key 부분에 임의의 값을 넣고 체크해 봤지만 값을 검증하지 않는 듯 아무런 반응이 없었고, 다시 bp를 아래 사진과 같이  GetDlgItemInt에 걸고 진행을 했다


[그림 14] - BreakPoint > GetDlgItemInt


위와 같이 GetDlgItemInt 함수에 bp를 걸고 실행 시켰을 때에는 [그림 13]의 과정과 달리 아래 그림과 같이 임의의 값인 256을 넣고 체크한 뒤,

F8(Step Over)를 눌러 코드를 한줄 진행하게 되면, [그림 16]과 같이, GetDlgItemInt 함수의 리턴 값으로 EAX에 0x100으로 반환 됨을 알 수 있다


[그림 15] - 임의의 값 입력


[그림 16] - EAX = 0x100


[그림 17] - 반복 루틴 진행


위 그림은 GetDlgItemInt의 반환 값으로 0x100이 반환되고 난 후 바로 아래 코드들의 주석이다


00401068에서 ESI 값에서 4바이트를 읽어들인 후, 0과 비교를 하며 ESI 값은 바로 위 코드에 적힌 아스키 값이다

0040106B에서는 위의 ESI 값이 0이 아니라면 00401071로 분기해서 다음 4바이트를 읽어들이는 루틴이 반복 진행되며 이 반복되는 코드들은

성공메시지를 띄우기 위한 구문으로 넘어가는 JMP 0040107D가 실행되지 않는, 리버싱을 어렵게 하기위한 더미코드라고 볼 수 있다.


[그림 17]의 반복루틴은 더미코드기 때문에 문제해결과는 상관이 없기에, 0040107D로 넘어가 코드를 확인하면,

리턴값이 담기는 레지스터인 EAX에 담긴 값과 7A2896BF와 비교하며, 비교한 값이 같다면 성공메시지를 출력한다


따라서 7A2896BF를 의미하는 10진수 값을 Key 값으로 넣으면 성공메시지를 확인할 수 있으며 10진수 값은 2049480383이다


[그림 18] - 값 입력


[그림 18-1] - 성공 메시지 출력


문제에서 요구하는 것은 성공메시지를 출력하는 것이 아닌 키 값 출력을 요구하므로

해당 메시지가 저장되어 있는 곳으로 가서 키 값으로 바꿔주면 될 것이고, 그 과정은 아래와 같다


[그림 19] - Success Message on Hex Value


[그림 20] - Change Hex Value


[그림 21] - 2049480383


[그림 22] - 변경 된 값 출력



'Wargame' 카테고리의 다른 글

CodeEngn Basic 14  (0) 2017.10.11
CodeEngn Basic 13  (0) 2017.10.11
CodeEngn Basic 11  (0) 2017.10.08
CodeEngn Basic 10  (2) 2017.10.02
CodeEngn Basic 9  (0) 2017.09.26

#About


Author : abex


Korean :

OEP를 찾으시오. Ex) 00401000 / Stolenbyte를 찾으시오. Ex) FF35CA204000E84D000000

정답인증은 OEP + Stolenbyte

Ex ) 00401000FF35CA204000E84D000000


English :

Find the OEP, Ex) 00401000 / Find the Stolenbyte. Ex) FF35CA204000E84D000000

The solution should be in this format : OEP + Serial

Ex ) 00401000FF35CA204000E84D000000




#Contents


Basic 9번과 같은 문제이며, 패킹을 진행할 때 사용되는 StolenByte의 개념이해를 목적으로 한다




#Solutions


[그림 1] - 실행화면


11.exe를 실행하게 되면, keyfile을 체크하기 위한 OK버튼을 누르라고 한다


[그림 1-2] - 실행화면


확인버튼을 누르고 나면 파일을 찾지 못했다는 에러메시지를 확인할 수 있다


OEP를 찾으라는 문제에서 패킹이 되어 있음을 생각할 수 있고 PEiD를 통해 아래와 같이 UPX로 패킹되어 있음을 확인할 수 있다


[그림 2] - UPX 패킹


UPX의 특성상 디버거에 올렸을 때, 맨 아래의 코드에 OEP로 JMP 하는 구문을 통해 이동 후, 덤프를 통해 언패킹을 진행할 수 있지만,

편하게 아래와 같이 upx의 언패킹을 진행할 수 있는 프로그램을 통해 언패킹을 진행하였다


[그림 3] - UPX 언패킹


언패킹을 진행 후 올리디버거에 올리고 실행을 해주었더니 아래와 같은 메세지를 확인할 수 있다


[그림 4] - 깨진 메시지창


깨진 메시지창을 확인 후, 순간 StolenByte를 잊고 있었음을 깨달았고, [그림 4]에서 실행하기 전 화면인,

아래의 화면에서 MessageBoxA 함수 호출에 필요한 인자(StolenByte)가 부족함을 알 수 있었다


[그림 5] - 인자 부족


[그림 4]의 깨진 메시지창이 뜨기 전 상태로 돌아가 확인해 보았더니 12줄의 NOP 명령과, MessageBoxA에 필요한 인자가 부족함을 확인할 수 있었다


부족한 인자를 채워주기 위해 NOP 부분을 활용하기로 했고, 그 인자는 아래와 같이 

언패킹 진행 전 프로그램의 POPAD 명령이후 PUSH 되는 값에서 얻어 올 수 있었다


[그림 6] - Find StolenByte


위 그림에서 StolenByte로 추정되는 값을 확인할 수 있었고, 해당 OPCODE를 단축키 Ctrl+E를 통해

아래와 같이 넣어 주었더니 MessageBoxA 함수에 부족한 인자가 채워짐을 확인할 수 있다


[그림 7] - 인자 완성


부족한 인자를 완성 시키고 실행시켰더니 아래와 같이 정상적으로 실행됨을 확인할 수 있다


[그림 8]




※ OEP는 0040100C가 아니라, 추가해준 OPCODE의 시작점인 00401000임



'Wargame' 카테고리의 다른 글

CodeEngn Basic 13  (0) 2017.10.11
CodeEngn Basic 12  (0) 2017.10.08
CodeEngn Basic 10  (2) 2017.10.02
CodeEngn Basic 9  (0) 2017.09.26
CodeEngn Basic 8  (0) 2017.09.25

#About


Author : ArturDents


Korean :

OEP를 구한 후 "등록성공"으로 가는 분기점의 OPCODE를 구하시오. 정답인증은 OEP + OPCODE

EX) 00400000EB03


English :

After finding the OEP, find the OPCODE of the branch instruction going to the "goodboy routine"
The solution should be in this format : OEP + Serial

EX) 00400000EB03





#Contents


이전 문제에 나왔던 UPX와 다른 ASPACK의 이해와, Import Address Table의 이해를 목표로 한다




#Solution


[그림 1] - 실행화면


10.exe를 실행하면 위와 같은 UI를 볼 수 있으며 Name과 Serial란에 아무값도 입력이 되지 않음을 알 수 있다


[그림 2] - ASPack


OEP를 구하는 문제이기에 패킹이 되어 있을거라 예상, PEiD를 통해 ASPack로 패킹되어 있음을 알 수 있었다


앞서 나왔던 UPX며 해당 문제에서 나온 ASPack이며 패킹에 대해 더 해지는 언급으로

정확한 원리를 알아보기 위해 검색 결과 아래와 같은 원리가 적용됨을 알 수 있었다


PUSHAD 명령을 통한

스택에 레지스터값 적재

정상 코드

메모리에 복구 

POPAD 명령을 통한

레지스터값 복구 

OEP로 분기 

[표 1] - 레지스터를 이용한 패킹의 원리


이러한 점을 이용한 언패킹 방법으로는, PUSHAD 명령 이후 ESP 값을

접근하는 지점(POPAD 명령을 통한 접근)에 BP를 걸어두면 OEP를 분기하기 전으로 이동할 수 있다 

(출처 : stih.tistory.com/68)


[그림 3] - ESP 값 확인


F8(Step-Over)을 이용해 PUSHAD 명령 이후 ESP 값을 확인결과, 0018FF6C을 참조함을 알 수 있다

0018FF6C은 POPAD가 진행되기 전, 정상 코드를 메모리에 복구한 뒤, 레지스터 복구를 위해 현재 ESP가 가리키는

메모리 주소에 접근할 때 사용되며 한마디로 0018FF6C는 현재 ESP이다

 

[그림 4] - BreakPoint > 0018FF6C


따라서 [그림 4]와 같이 PUSHAD 이후 ESP가 가리키는 메모리 주소에 접근할 때 Break Point를 걸어두고 실행시키게 되면, 메모리 상에 복구를

마친 뒤 OEP로 분기전 상태가 되며 F9를 통해 프로그램을 실행하게 되면 아래와 같이 BreakPoint에서 멈추는 것을 확인할 수 있다


[그림 5]


BreakPoint가 걸린 부분을 살펴보면, JNZ 구문에 의해 분기가 일어나며 PUSH 명령을 통해 00445834(OEP)

주소를 스택에 저장한 이후 RETN 명령을 통해, 00445834로 점프하는 것을 알 수 있다


[그림 6] - OEP로 이동


OEP로 이동했더니 디버거가 OPCODE를 인식하지 못하는 것을 확인할 수 있어 아래와 같이 OllyDump를 통해 OEP 값을 수정해 주었다


[그림 7] - Modify OEP 


위와 같이 덤프 진행 후, 파일을 열었더니 아래와 같이 함수의 프롤로그를 의미하는 PUSH EBP 구문이 보이지 않아, 무언가 잘못됨을 알 수 있었다


[그림 8]


검색 결과, IAT(Import Address Table) 정보가 정확하게 복구 되지 않아 정상실행이 되지 않는다는 결과를 얻을 수 있었고,

IAT 복구를 위해 아래의 LordPE로 Rebuild를 진행해주었다


[그림 9] - Rebuild


[그림 9]와 같이 진행한 후 올리디버거로 열어주었더니 아래와 같이 프롤로그를 의미하는 PUSH EBP 구문을 확인할 수 있었다


[그림 10] - 프롤로그


올바르게 IAT 복구과정을 거쳤으니, 문제로 넘어가 "등록성공으로 가는 분기문의 OPCODE"를 찾는 것이 목표이다


등록성공이라는 문구는 이전 문제들과 같이 아스키 값으로 저장되어 있을 거라 생각 후

텍스트 값만 뽑아 내었더니 아래와 같이 확인할 수 있었다


[그림 11] - 아스키 값 확인


[그림 12] - 분기문의 OPCODE 확인


[그림 11]에서 아스키 값 Registered ... well done!이 위치하는 곳으로 갔더니 위과 같았고,

등록성공으로 가는 분기문의 OPCODE를 확인할 수 있었다



'Wargame' 카테고리의 다른 글

CodeEngn Basic 12  (0) 2017.10.08
CodeEngn Basic 11  (0) 2017.10.08
CodeEngn Basic 9  (0) 2017.09.26
CodeEngn Basic 8  (0) 2017.09.25
CodeEngn Basic 7  (0) 2017.09.24

+ Recent posts