2018. 5. 19. 10:06ㆍ0x02 Reverse Engineer/0x03. Etc
풀이
해당 바이너리는 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 PYC-BYTECODE (0) | 2018.05.19 |
ROOTME ELF PTRACE (0) | 2018.05.19 |
ROOTME FAKE INSTRUCTION (0) | 2018.05.19 |