-->

[reversing.kr] PEPassword 풀이

먼저 복호화 루틴을 찾고, original 파일이 왜 주어졌는지 생각해보면 문제를 풀 수 있다. 그리고 ror rol이나 하위 레지스터 bh 등 사용때문에 인라인 어셈코드 작성이 필수이다. reversing.kr 중반쯤으로 넘어가면서 문제가 점점 어려워지고 있어서 한문제를 푸는데 시간이 오래걸리고 있는데 그만큼 도움이 많이 되는 것 같고 풀었을 때 뿌듯해서 좋다.

 

 

 

reversing.kr PEPassword 풀이

original.exe를 실행시켜보면 "~ Password is ????????????" 메시지 박스가 나오고 packed.exe를 실행시켜보면 Password Check로 입력값을 받고 있다. 원본파일이든 패킹된 파일이든 메모리에서의 실행코드는 같기 때문에 실행 결과?가 같아야되는데 다른것을 보니 같은 프로그램은 아닌 것 같고 일단 packed.exe를 중점적으로 보면서 두 파일이 어떻게 연결?되어 있는지를 봐야할 것 같다.

 

 

 

packed.exe의 패킹 정보를 알아보면 Unknown  패커로 패킹되어 있다.

 

 

 

라이브러리 로드하는 부분을 지나면 첫번째 루프문이 나오느넫 다이얼로그 박스 생성 후 첫번째 루프가 등장하는데 메시지가 올때까지 루프를 돌게된다.

 

 

 

어느곳에서 입력값을 받는지, 실행을 시킨 후 한바이트를 입력해보면 아래 부분에서 bp가 걸리게 되는데 (노가다로 분기 부분에 전부 bp를 걸어서 찾았다) SendMessage 함수 호출 후 입력한 한바이트가 [edi+402A40]에 저장된 것을 볼 수 있다. 그리고 바로 4091D8 함수를 호출한다.

 

 

 

4091D8에서는 xor, ror 연산을 수행하고 일정 조건을 통과하면 연산이 끝나게 된다. 

 

 

 

어쨌든 4091D8 함수 호출 결과 eax가 0xE98F842A인지 비교하고있고 같다면, EndDialog 함수 호출로 다이얼로그가 끝나게 된다. 일단 jne 부분을 je로 패치한 후 더 트레이싱해보았다.

 

 

 

트레이싱하다보니 jne일때는 볼 수 없었던 복호화 코드를 찾을 수 있었다. 위에 입력값 찾아내는 삽질을 안해서 다행이다. 일단 pushad, popad가 있었고 중간에 call로 4091DA를 2번 호출한다. 그리고 그밑에 루프문이 하나 있는데 이게 찐 복호화 코드일 확률이 높은 것이 edi 값이 401000 (원본코드의 EP)이고 여태까지는 연산 결과값을 코드나 데이터에 쓰는 부분은 없었는데 이번엔 xor 결과를 [edi] (코드영역)에 쓰기 때문이다. 

 

 

 

그럼 여기서 내가 줄 수 있는 부분?은 처음 [edi]와 xor을 수행하는 eax값인데 이 eax값을 어떻게 줘야 원본 코드로 복호화가 될지는 해당 문제 zip파일에 쓸데없이 original 파일이 있었다는 점을 생각하고 reversing.kr의 ransomware 문제를 풀었다면 알 수 있다. ransomware 문제를 풀때, 암호화된 코드가 원본 코드로 복호화되기 위한 값을 계산하기 위해 PE파일의 Dos Stub 값을 사용했었다. 이번 문제는 패킹된 코드도 있고 원본 코드도 있으니 eax값을 구할 수 있을 것이다.

 

즉, 정리하자면 아래와 같고 401000부터 복호화되기 때문에 아래 영역부터 바뀌게 된다.

 

- edi 값이 401000 : 원본코드의 EP이자 코드영역

- [edi]값에 직접적으로 연산 결과가 써지고 있음

- original 파일이 있기 때문에 원본 코드와 패킹된 코드 둘다 알 수 있음

- 입력을 줄 수 있는 값 -> eax

 

 

 

한가지 문제는 eax값이 고정이 아니고 ebx 값에 의해 바뀐다는 것이다 ^^:;;;;;;; 여기서 엄청 당황했지만 일단 첫번째에서 두번째 반복으로 넘어갈 때의 알맞는 ebx값을 구해보기로 했다. 첫번째 4바이트와 두번째 4바이트를 원본 코드로 바꿀 eax값 2개를 먼저 구해보면 아래와 같다.

 

 

 

그리고 첫번째 eax값에서 두번째 eax값이 되게 하는 ebx 값을 아래 연산 부분을 참조해서 계산해내는 코드를 짜야하는데, 일단 rol ror 계산은 파이썬으로는 힘들고 ebx 뿐 아니라 중간에 bh 값도 들어가기 때문에 연산부분은 어셈코드로 계산하는게 효율적이다.

 

0040921F | 3107            | xor dword ptr ds:[edi],eax           
00409221 | 8AC8            | mov cl,al                         
00409223 | 83C7 04         | add edi,4                             
00409226 | D3C3            | rol ebx,cl                            
00409228 | 33C3            | xor eax,ebx                         
0040922A | 8ACF            | mov cl,bh                           
0040922C | D3C8            | ror eax,cl                        
0040922E | 03D8            | add ebx,eax                      
00409230 | 4A              | dec edx        

 

 

사실 코드를 공개하면 거의 정답을 공개하는 것과 마찬가지여서 전체 코드 공개는 하지 않겠지만, 위 어셈블리어 중 eax와 ebx 관련된 코드를 그대로 옮겨서 __asm 안에 넣어주고 0x0부터 0xffffffff 까지 무한루프를 돌게하면서 두번째 eax값이 나오는 값을 구하면 된다. 

 

#include <stdio.h>

int main()
{
	int i = 0;
	int tmp = 0;
	for (i = 0; i <= 0xffffffff; i++)
	{
		__asm
		{
			mov eax, 0xb7aac296
			mov ebx, i // ebx: 0x0 ~ 0xffffffff
			
            // ...

 

 

참고로, 나는 코드를 돌렸더니 ebx가 2개가 나왔는데 첫번째는 제대로 복호화가 안됐고 두번째 ebx를 넣어주었더니 알맞게 복호화가 됐다.

 

 

 

아래는 정상적으로 복호화가 된 코드 모습이다.

 

 

 

패스워드는 메모리에서 확인해도 되지만 실행시켜서 확인할 수 있다.

 

 

'리버싱 > reversing.kr' 카테고리의 다른 글

[reversing.kr] HateIntel 풀이  (0) 2020.03.20
[reversing.kr] CSHOP 풀이  (0) 2020.03.19
[reversing.kr] AutoHotkey1 풀이  (2) 2020.03.17
[reversing.kr] WindowsKernel 풀이  (0) 2020.03.15
[reversing.kr] Easy ELF 풀이  (0) 2020.03.15

댓글

Designed by JB FACTORY