본문 바로가기

2. Reversing (리버싱)/1) Write UP

[2020.10.10]CodeEngn Challenges Basic RCE L09 ~ L12 라이트업

L09. StolenByte를 구하시오 Ex) 75156A0068352040

 

Upx로 패킹된 것을 확인한다.

 

언패킹을 해주었다.

 

언패킹 해주고 올리 디버거로 열었는데 MessageBox를 보면 출력할 값이 없는 것을 확인.

이 부분이 stolenbyte일 것이라고 추측. 

Stolen byte? 

패킹된 바이너리를 언패킹 할 때의 과정을 방해하기 위한 방법으로, 프로그램의 일부 바이트를 별도의 영역에서 실행되게 하여 OEP를 다른 위치로 가장하고 덤프를 쉽게 하지 못하도록 구현한 기법이다.

패커가 패킹을 진행할 때 원본 코드 중 일부를 다른 곳으로 이동 시킨 코드로써, 주로 엔트리 포인트 위의 몇 줄의 코드이다

 

★ 올바른 프로그램을 얻기 위해서는 패킹 과정에서 떼어진 StolenByte를 함께 복원해야 덤프가 성공적으로 이루어진다.

★ UPX패킹은 코드의 마지막에 있는 JMP명령어를 통해 원래 OEP로 이동합니다.

 

언패킹 전에 패킹된 파일을 살펴본 결과 OEP로 점프하는 부분에 break point를 걸고 실행한 결과 MessageBox 함수 호출에 필요한 인자들이 스택에 push되고 있는 것을 확인. 이 push 되는 인자들이 stolenbyte임을 확인.

 

패킹되면서 숨겨졌던 부분을 NOP코드에 stolenbyte의 op코드를  ctrl+E를 이용하여 넣어주었다. Stolen byte는 6A 00 68 00 20 40 00 68 12 20 40 00 이다.

 

OEP가 40100C가 아닌 401000인 것을 알 수 있다. 따라서 ollydump를 이용해 entrypoint 값을 100C에서 1000으로 바꿔서 덤프를 실행시켜 준다.

 

정상적으로 실행되는 것 확인.

 

L10. OEP를 구한 후 '등록성공'으로 가는 분기점의 OPCODE를 구하시오.

정답인증은 OEP + OPCODE

EX) 00400000EB03

 PEiD를 통해 10.exe를 실행시켜 ASPack으로 패킹 되어있음을 확인한다.

 10.exe 프로그램을 올리디버거로 실행하면 PUSHAD라는 문자열을 확인할 수 있다. PUSHAD 명령은 범용 레지스터에 저장된 값들을 스택에 저장하는 명령어입니다. 현재 레지스터 값을 스택에 저장하고 원본 코드로 복구한 다음, POPAD 명령을 이용해서 원래의 레지스터 값으로 되돌립니다. 

 [Ctrl]+[F]키를 통해 ‘retn 0c’를 검색하여 밑에 있는 두 줄에 브레이크 포인트를 걸고 실행한다.

 그렇게 하면 OEP 주소가 변경된다. OEP 주소는 445834이다. RETN을 통해 OEP 코드가 있는 곳으로 이동한다.

이동하면 새로운 코드들이 보인다.

 [Ctrl]+[A]키를 누르면 원래 코드가 나온다. 언패킹이 완료되었다.

 Search for > All referenced text strings를 클릭하여 코드에서 참조되는 문자열 목록을 확인한다. 등록 성공 문자열의 위치로 이동한다.

 등록 성공으로 가는 분기점 바로 위에 JNZ 명령을 발견했다. 해당 코드의 OPCODE는 75 55이다.

 그러므로 정답은 04458347555이다.

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

Upx로 패킹

언패킹

언패킹 해주고 올리 디버거로 열었는데 MessageBox를 보면 출력할 값이 없는 것을 확인.

이 부분이 stolenbyte일 것이라고 추측.

 

언패킹 전에 패킹된 파일을 살펴본 결과 OEP로 점프하는 부분에 break point를 걸고 실행한 결과 MessageBox 함수 호출에 필요한 인자들이 스택에 push되고 있는 것을 확인. 이 push 되는 인자들이 stolenbyte임을 확인

언패킹 진행 전 POPAD 명령 이후 PUSH 되는 값에서 ctrl+E를 이용해 OPCODE 확인.

OEP는 00401000이다.  Stolen byte는 6A 00 68 00 20 40 00 68 12 20 40 00

 



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

이때 성공메시지 대신 Key 값이 MessageBox에 출력 되도록 하려면 파일을 HexEdit로 오픈 한 다음 0x???? ~ 0x???? 영역에 Key 값을 overwrite 하면 된다.

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

Ex) 7777777????????

 

 12.exe를 PEiD를 통해 실행시켜 패킹 되어있지 않다는 것을 확인한다.

 실행화면을 보면 키 값을 입력해야 한다는 것을 알 수 있다.

 올리디버거에서 Search for > All referenced text strings를 클릭하여 코드에서 참조되는 문자열 목록을 확인한다. 성공 메시지가 있는 위치로 이동한다.

 성공 메시지 위쪽을 보면 EAX와 7A2896BF를 비교하는 CMP 명령이 있다. EAX에서 7A2896BF를 빼서 0이 나와 JNZ 명령에서 점프하지 않고 다음 명령을 실행한다. 만약 0이 되지 않으면 JNZ 명령은 401098로 점프할 것이다. 그렇다면 EAX의 값은 7A2896BF가 된다. 하지만 7A2896BF는 16진수이므로 10진수로 바꾸면 2049480383이 된다. 그리고 처음 실행화면의 입력값이 EAX 값일 것이라고 추측할 수 있다.

 입력 값이 EAX 값이라는 추측을 확실히 하기 위해 CMP 명령에서 브레이크 포인트를 걸고 프로그램을 실행시킨다.

EAX 값이 F가 되는 것을 보고 입력한 값이 EAX 값이라는 사실이 확실해졌다.

다시 10.exe를 실행시켜 키 값에 2049480383를 기입하여 성공 메시지를 출력한다.

문제 출제 의도는 성공 메시지 출력이 아니라 key 값을 출력하는 것이므로 HxD로 성공 문자열 부분을 수정한다. 그리고 값을 넣을 때 16진수 아스키 코드로 넣어야 한다.

 차례대로 값을 수정하고 남은 부분은 00으로 채운다.

 수정한 영역은 00000003B부터 0000000D45까지이다. 0x????~0x????라는 표현에 맞추면 0x0D3B~0x0D45이다. Key 값은 2049480383이므로 정답은 20494803830D3B0D45이다.