constWORLDant

ROOTME NO SOFTWARE BREAKPOINTS 본문

0x02 Reverse Engineer/0x03. Etc

ROOTME NO SOFTWARE BREAKPOINTS

data type ConS_tanT 2018.05.19 10:06

풀이

해당 바이너리는 sys_write와 sys_read로 이루어져있다.

sys_read에서 51바이트를 입력받을 수 있지만, 코드를 분석해보면 25바이트만+"\0"만 사용하면 된다.

sys_read에서 입력한 값은 flag로 사용된다. 

하지만, flag를 추출할 수 있는 루틴은 보이지 않는다. 


flag를 입력한 뒤에 나오는 루틴을 살펴보면 while(1)을 통해 이러한 행위를 한다.

 while ( 1 )

  {

    v3 = __ROR4__(v3, 1);                       // ror edx ,1

    if ( (_BYTE)v3 != (flag[v4 - 1] ^ key_data[v4 - 1]) )// [0~24]

      break;

    if ( !--v4 )                                // v4가 0이되면 sys_write 수행

    {

      v5 = sys_write(1, &unk_8049124, 0x26u);   // SUCCESS

      goto LABEL_6;

    }

  }


이 행위에서 핵심은 두가지 이다.

// ror edx ,1 때문에 edx가 무엇인지 leak해야하고,

 if ( (_BYTE)v3 != (flag[v4 - 1] ^ key_data[v4 - 1]) )// [0~24]

이 녀석 때문에 내가 입력한 값의 길이 [0~24] xor checksum에 사용되는 데이터 [0~24] 

하지만, 인덱스가 감소 연산자를 띠고 있기 때문에 24 -> 0 순서대로 감소해야 한다.


이렇게 했을 때 v3값이 최종적으로 0이 되면 성공 가즈아~~


코드

#include <stdio.h>  

typedef unsigned int uint;

typedef unsigned char uchar;

int get_checksum();


// global


uint key[] = {

0x1e,0xcd,0x2a,0xd5,0x34,0x87,0xfc,0x78,

0x64,0x35,0x9d,0xec,0xde,0x15,0xac,0x97,

0x99,0xaf,0x96,0xda,0x79,0x26,0x4f,0x32,

0xe0

};


uchar shellcode[] =

"\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\xa1\x91\x04"

"\x08\xba\x26\x00\x00\x00\xcd\x80\xb8\x03\x00\x00\x00\x31"

"\xdb\xb9\x88\x91\x04\x08\xba\x33\x00\x00\x00\xcd\x80\x31"

"\xc9\xb8\x80\x80\x04\x08\xbb\x23\x81\x04\x08\xe8\x5b\x00"

"\x00\x00\x89\xca\xb9\x19\x00\x00\x00\xb8\x55\x91\x04\x08"

"\xbb\x88\x91\x04\x08\xd1\xca\x8a\x44\x08\xff\x8a\x5c\x0b"

"\xff\x30\xd8\x30\xd0\x75\x1b\x49\x75\xe3\xb8\x04\x00\x00"

"\x00\xbb\x01\x00\x00\x00\xb9\x24\x91\x04\x08\xba\x26\x00"

"\x00\x00\xcd\x80\xeb\x16\xb8\x04\x00\x00\x00\xbb\x01\x00"

"\x00\x00\xb9\x4a\x91\x04\x08\xba\x0b\x00\x00\x00\xcd\x80"

"\xb8\x01\x00\x00\x00\x31\xdb\xcd\x80\x29\xc3\x31\xc9\x02"

"\x08\xc1\xc1\x03\x40\x4b\x75\xf7\xc3";


int main(int argc, char const *argv[]) {



size_t i;

uint checksum;

char tmp;

char flag[25];


checksum = get_checksum();


printf("Checksum: %x\n\n", checksum);


for (i = 0; i < 25; i++) {

checksum = (checksum >> 1) | (checksum << (32 - 1)); // ror by 1

tmp = checksum ^ key[24 - i]; // 키 값 추출 

flag[24 - i] = tmp;

}

printf("\n\nSerial: ");

for (i = 0; i < 25; i++) printf("%c", *(flag + i));

return 0;

}


int get_checksum()

{

__asm

{

mov ebx, 0xA3; key length

xor ecx, ecx; init

lea eax, [shellcode]; copy 

_loop:

add cl, [eax]; shellcode

rol ecx, 0x3; ; rotate left 3 times

inc eax

dec ebx

jnz _loop


mov eax, ecx; __cdecl 

}

}


'0x02 Reverse Engineer > 0x03. Etc' 카테고리의 다른 글

ROOTME Macho keygen or not  (0) 2018.05.19
ROOTME ARM  (0) 2018.05.19
ROOTME NO SOFTWARE BREAKPOINTS  (0) 2018.05.19
ROOTME PYC-BYTECODE  (0) 2018.05.19
ROOTME ELF PTRACE  (0) 2018.05.19
ROOTME FAKE INSTRUCTION  (0) 2018.05.19
0 Comments
댓글쓰기 폼