[reversing.kr] Twist1

취미/WarGame 2015. 2. 27. 09:53 |

1차 시도 : 15/02/27



PEB에서 비롯되는 Ldr, Heap 안티 디버깅을 지나  OEP 도달. 


scanf 로 입력을 받고 난 뒤 ZwQueryInformationProcess API를 사용하는 안티 디버깅에 걸려서 실패 . 

오늘은 여기까지.



2차시도 : 15/02/28 


2차시도 4시간 30분만에 클리어. 


내용이 너무 방대해 자세한 내용은 나중에 쓸까 말까 고민중입니다. .


간략히 설명하자면


처음엔 1차시도에서 확인한 PEB 관련(Ldr, HeapFlag ) 안티디버깅이 3회 출몰합니다. 

그리고는 이제 Main만 분석하면 될것처럼 OEP가 등장하고 


scanf로 입력을 받다가 뜬금없이

ZwQueryInformationProcess native API로 2회 안티디버깅이 나옵니다. 


이제 정말 끝이겠지 하고 분석을 하던 도중 GetThreadContext로 디버그 레지스터에서 하드웨어 브레이크가 있는지 없는지 검사합니다.(분석하면서 하드웨어 브레이크를 사용할 일이 없었기에 무사히 넘어갔습니다.)


여기까지 지나면 드디어 내가 입력한 값들이 어떤 연산으로 분기되는지 나옵니다. 


그리고 대망의 비교루틴에서도 한 두번씩 페이크가 나옵니다 - -. 


1번째 문자에대한 페이크와 몇번째인지 기억은 안나는데 예, 예, 예 버튼 막 누르던 도중에 예 버튼자리에 아니오가 온 느낌이랄까요. 


그런느낌으로 엄한데로 점프 시켜버립니다 --. 


다행히 점프하기전의 스택으로 돌려놓고 origin 바꿔서 되돌아 오긴했습니다만.. 인내심을 시험받은 듯한 느낌이 드네요..


일단 여기까지


'취미 > WarGame' 카테고리의 다른 글

[reversing.kr] PEPassword  (0) 2015.03.06
[reversing.kr] Ransomware  (0) 2015.02.24
[reversing.kr] Direct3D FPS  (1) 2015.02.24
[reversing.kr] ImagePrc  (0) 2015.02.21
[reversing.kr] Position  (0) 2013.10.30
Posted by $Zero
:

파일 디스크립트 문제, UPX 실행 압축과 매우 긴 쓰레기 코드로 리버싱을 방해한다.


중요 부분만 빠르게 체크하자





먼저 쓰레기 코드를 건너 뛰기 위해 printf 함수에 BP를 걸어 실행한다.


그러면 위와같은 파일관련 함수 호출이 연이어 등장하는 루틴을 발견할 수 있다.


401000 CALL 명령은 리버싱을 방해하는 쓰레기 코드이니 무시하자


내가 입력한 문자열을 순서대로 한개씩 돌려가면서 복호화 키로 사용하고 있다.




그리고 마지막 즈음에 파일 전체에 XOR EDX,0FF 명령으로 다시 한번 복호화를 진행한다.


암호화 루틴은 매우 간단하다.  내가 입력한 문자열을 순서대로 하나씩 뽑아서 암호화 하고, 다시 0xFF로 전체 파일을 암호화 한것이다.


그럼, 전체 파일을 0xFF로 한번 복호화 하고


일반적인 PE 실행파일에서 공통적으로 등장하는 부분을 0~0xFF 모든 경우로 다시 복호화해서 비교해보면 되겠다.


나는 도스 스텁 코드로 나오는 is program cannot 을 대상으로 복호화를 진행했고 복호화 키값을 얻어낼 수 있었다.

(간단한 프로그램을 짜서 is program cannot 스텁 부분의 문자열을 무차별 복호화 한 값하고 비교해보면 간단히 나온다.)



복호화 키값으로 원본 파일을 복호화 해보면 키값을 출력하는 프로그램이 나온다. 



복호화에 사용된 소스 :

#include "stdafx.h"
#include <string.h>

char sig[100];
char cksig[100];

int _tmain(int argc, _TCHAR* argv[])
{
    char chk;
    FILE* file = fopen("file", "r+b");


    strcpy(cksig, "is program cannot");

    rewind(file);
    fseek(file,0x50,SEEK_SET);

    for(int j=0; j<100; j++){
        sig[j] = fgetc(file);
        sig[j] ^= 0xFF;
        for(int i=0; i<=0xFF; i++){
            chk = sig[j] ^ i;

            if(chk == cksig[j]){
                printf("%c", i);
                break;
            }
        }
    }


    fclose(file);


    return 0;
}






'취미 > WarGame' 카테고리의 다른 글

[reversing.kr] PEPassword  (0) 2015.03.06
[reversing.kr] Twist1  (0) 2015.02.27
[reversing.kr] Direct3D FPS  (1) 2015.02.24
[reversing.kr] ImagePrc  (0) 2015.02.21
[reversing.kr] Position  (0) 2013.10.30
Posted by $Zero
:


크기가 매우 작은 간단한 게임이다.


처음 실행 하자마자 메모리 영역을 보면 알수 없는 문자들이 있는데


몬스터를 잡다보면 이 곳이 복호화 되는 것을 확인할 수 있다.


몬스터 한마리당 한글자를 복호화 하지만 총 글자수가 50개인 반면 몬스터는 48마리 밖에 없다.


해서 패스워드 버퍼에 메모리 브레이크 포인트를 건 뒤 몬스터를 잡아보면, 특정 메모리 공간에 있는 값으로 복호화 하는 루틴을 찾을 수 있다.


다시 복호화 값으로 사용되는 값중 하나를 골라 하드웨어 브레이크를 건 뒤 프로그램을 재 실행 해보자.

초기화 과정에서 해당 브레이크 포인트에 걸리는 것을 볼 수 있다. 그게 바로 위 사진의 루틴이다.

0x210 바이트 간격으로 데이터를 저장하는데, 이 값들이 몬스터들마다 하나씩 가지고 있는 복호화 키다.

반복문을 분석하면

키값이 0x4 만큼 계속 증가한다는 것을 확인할 수 있으며 이 규칙으로 나머지 값도 알아낼 수 있다.



'취미 > WarGame' 카테고리의 다른 글

[reversing.kr] Twist1  (0) 2015.02.27
[reversing.kr] Ransomware  (0) 2015.02.24
[reversing.kr] ImagePrc  (0) 2015.02.21
[reversing.kr] Position  (0) 2013.10.30
[reversing.kr] replace  (0) 2013.10.25
Posted by $Zero
: