IDA로 열어본다.

...
 GetWindowTextA(::hWnd, &String, 128);
    SetWindowTextA(hWnd, &String);
    v16 = 5;
    do
    {
      String -= v16;
      String ^= 3u;
      --v16;
    }
    while ( v16 );
    v17 = 4;
    do
    {
      v23 -= v17;
      v23 ^= 4u;
      --v17;
    }
    while ( v17 );
    v18 = 3;
    do
    {
      v24 -= v18;
      v24 ^= 5u;
      --v18;
    }
    while ( v18 );
    v19 = 2;
    do
    {
      v25 -= v19;
      v25 ^= 6u;
      --v19;
    }
    while ( v19 );
    v20 = strcmp(&String, "C;@R");
    if ( v20 )
      v20 = -(v20 < 0) | 1;
    if ( v20 )
    {
      MessageBoxA(hWnd, ";;", "ohtahacker", 0);
      exit(0);
    }
    MessageBoxA(hWnd, "congratulation", "ohtahacker", 0);
...


어디선가 받은 문자를, 이상한 조작을 한 후, C;@R과 비교한다.


그러면, C;@R에 역조작을 해서 원래 문자를 알아낸다.


>>> chr((((((((((ord('C')^3)+1)^3)+2)^3)+3)^3)+4)^3)+5)

'S'

>>> chr((((((((ord(';')^4)+1)^4)+2)^4)+3)^4)+4)

'E'

>>> chr((((((ord('@')^5)+1)^5)+2)^5)+3)
'C'
>>> chr((((ord('R')^6)+1)^6)+2)
'U'

정답은 SECU


posted by tunz

peid를 통해서, 혹은 그냥 프로그램을 바로 켜봐도 느낌상 C# 파일이라는것을 확인할수 있다.


그러므로, net reflector를 이용해서 디컴파일했다.


코드를 쭉 살펴보다보면, 우리에게 보여주는 중요한 string은 암호화 되어있고


xor과 AES encrypt로 되어있다는것을 알수있다.


blocksize가 0x100이므로, Rijndael 방식중에서도 256비트라는것을 알수있고,


key값은 9e2ea73295c7201c5ccd044477228527 이다.

iv값도 key값과 같은 값을 사용한다.


그리고 중요한점은, utf-8방식으로 해야한다는것이다.


그래서 온라인상에 있는 rijndael decrypt 페이지에서는 안되더라..


그래서 처음엔 python으로 진행하다가 나중에 php를 이용해서 디코딩했다..


[python] 먼저 xor 디코딩


c = [ 0x3f, 30, 0x39, 0x2f, 20, 0x4e, 50, 0x36, 0x33, 5, 0x25, 0x29, 0x52, 40, 0x45, 30, 0x2a, 0x38, 0x24, 0x49, 60, 0x44, 0x4f, 0x56, 0x18, 0x49, 0x4c, 0x13, 9, 0x1b, 0x2a, 4, 0x52, 0x2a, 0x1c, 0x56, 0x4f, 11, 0x11, 0x3f, 0x17, 14, 0x30, 0x40 ]


af = ""
i=0
while i< len(c):
        af += chr(c[i] ^ 0x25 ^ 0x58)
        i = i+1

print af


[php] aes decrypt


class Foo {
        protected $mcrypt_cipher = MCRYPT_RIJNDAEL_256;
        protected $mcrypt_mode = MCRYPT_MODE_CBC;

        public function decrypt($key, $iv, $encrypted)
        {
                $iv_utf = mb_convert_encoding($iv, 'UTF-8');
                return mcrypt_decrypt($this->mcrypt_cipher, $key, base64_decode($encrypted), $this->mcrypt_mode, $iv_utf);
        }
}



$encrypted = "BcDRi3OKNxXT/U8cWEY4A92+e41ntfWy/Wa+2vlBjsM=";
$key = "9e2ea73295c7201c5ccd044477228527";
$iv = "9e2ea73295c7201c5ccd044477228527";

$foo = new Foo;
echo $foo->decrypt($key, $iv, $encrypted);


posted by tunz
문제파일:

저한테는 Binary 100 치고는 어려웠던 문제였습니다.


우선 PEID로 살펴보았습니다.

 



UPX로 패킹이 되어있네요.


IDA를 사용하기위해 우선 upx308w를 이용하여 언패킹을 하였습니다.




언패킹을 한후, 파일이름을 unpacked.exe로 바꾸고 작업하였습니다.



그냥 실행하면, "Ups, some calls are wrong or missing" 이라는 말만 하고는 끝납니다..




올리디버거로 그 부분을 찾아가보면,


[403790] 에 있는 값이 0이기때문에 아까와같은 메세지가 떴습니다.


억지로 flag를 보여주는곳으로 점프를 시켜봤자, "HoppaKey"가 뜰 뿐입니다.


하지만, 문제에서 답은 MD5로 주어진다고 했으므로, 이 "HoppaKey"는 답이 아닙니다.


그렇다면, [403790]의 값을 0이 아닌값으로 바꿔줘야 한다는것인데............


올리디버거만으로 풀어보려고 했으나, 너무 보기가 힘들어서, hex-ray의 도움을 구해보았습니다.




main의 수도코드를 살펴보니, 이렇습니다.


printf 윗부분을 저는 정확히는 이해를 못하겠지만, 함수포인터를 넘기고 있는것 같네요.


어찌됬든, 쓰이지않는 함수 5개가 있습니다. 주어졌으니 써야겠죠?


이제야, 아까 some calls are wrong or missing의 뜻이 이해가 되었습니다.


말 그대로 function call이 missing이 되었다는 거군요..


이제 그럼 function call을 집어넣어주면 되는데, 어떤 순서대로 집어넣을지가 또 문제입니다.


각각의 함수들의 수도코드를 살펴보겠습니다.








401400은 귀찮아서...... 생략하겠습니다.


각 함수들은 argument를 하나씩 받고 있고, 그 argument의 값을 조작하고 있습니다.


그러면 추측할수 있는것은, argument로 Key를 넘기고, 그 Key가 이 함수들을 거쳐가면서 점점 MD5의 형태를 갖춰갈 것으로 예상할 수 있습니다.


각각의 함수들을 분석해보겠습니다.


401000 :

- Key의 9~16번째에 있는 글자들을 조작합니다.


401060 :

- Key의 1~32번째에 있는 글자들을 조작합니다.


4011C0 :

- Key의 17~32번째에 있는 글자들을 조작합니다.

- Key가 16글자 이상이어야 작동합니다.

- 403790에 401400의 함수포인터를 넣습니다. (중요)


401370 :

- 뒤에서 8글자를 조작합니다.


여기서 4011C0의 함수를 보시면, 403790에 함수포인터를 집어넣습니다.

아까, JE의 조건이 403790이 비어있는가? 였는데,

이 과정이 실행된다면, 점프를 안할것입니다. 그러므로, 4011C0은 무조건 실행되어야하는 함수입니다.


근데 문제는 4011C0이 실행되기위해서는 Key가 16글자 이상이어야합니다. 하지만 처음 Key의 글자는 8글자입니다.

그렇다면, 다른 함수를 이용해서 Key를 16글자 이상으로 만들어야합니다.

그럴수있는 함수는 401000이 있습니다.


그러므로, 현재까지 알수있는 함수의 순서는

401000

4011C0

입니다.


그리고 401060은 알고리즘을 살펴보셔도 되고, 직접 실행하셔도 되는데, 해보시면

글자가 없을경우 '1'로 변환이 됩니다. 즉, HoppaKey를 예시로 변환해보면, ????????111111111111111111111111

이런식으로 변환이 되어버립니다.

즉, 변환전에 글자가 이미 32글자여야 할것 같다는 추측을 할수있으므로,


현재까지 알수있는 함수의 순서는

401000

4011C0

401060

입니다.


그리고 마지막으로 문제되는것은 401370인데, 이 함수는 어딜 들어가도 상관없는것처럼 보입니다.

이미 함수 3개의 순서를 알아냈으므로, 어디다 넣든 경우의수는 4밖에 안되므로, 그냥 브루트포스를 하기로 해봤습니다.


이제 올리디버거를 이용해, 점프를 하기전에 함수콜을 해보겠습니다.

자리가 부족한것같아서, 함수포인터를 넘기는 부분은 지워버리고 작업했습니다.



그리고 실행하면..




이와 같이 나오고, 이것이 답입니다.

posted by tunz