By passket | April 2, 2016
Codegate 2016 oldschool 롸업 음주ver
에…. passket 님이 술 한잔 하시고 빡치셔서(…) 써둔 writeup 입니다.
공개할까 말까 고민하다가 공개합니다. ㅇ<-<
음주 롸잇업으로 스알짝 말투가 격하십니다만,
그래도 0-day 드리니 양해해주세요 ;3
“The top-point pwnable was a simple format string vuln, in 2016…”
라고 ctftime에 누가 올려놨길래
손수 가르침을 좀 드림.
#include
#include
#include
int main( )
{
char buf[1024] = { 0, };
fgets( buf, 1024, stdin );
printf( buf );
return 0;
}
그렇다. 존나 단순한 format string bug 다.
그렇지만 문제는…
printf 로 fsb 가 일어나고 나서 함수가 끝난다는 거다.
fsb로 메모리는 보거나 고칠 수 있는데
어디를 고쳐야함 ?
을 물어보는 문제이다.
무려
attribute destrucctor를 만들어 보면
삼척동자도 여기(0x08049644)를 고쳐야 한다는 사실은 알 수 있다.
주니어에도 낼 문제여서 좀 봐줌
사실 비밀이 좀 있는데
08048000-08049000 r-xp 00000000 fc:00 125831508 /home/passket/pwn/chals/oldschool/test
08049000-0804a000 r–p 00000000 fc:00 125831508 /home/passket/pwn/chals/oldschool/test
0804a000-0804b000 rw-p 00001000 fc:00 125831508 /home/passket/pwn/chals/oldschool/test
f7e23000-f7e24000 rw-p 00000000 00:00 0
f7e24000-f7fc9000 r-xp 00000000 fc:00 60555283 /lib32/libc-2.19.so
f7fc9000-f7fcb000 r–p 001a5000 fc:00 60555283 /lib32/libc-2.19.so
f7fcb000-f7fcc000 rw-p 001a7000 fc:00 60555283 /lib32/libc-2.19.so
f7fcc000-f7fd0000 rw-p 00000000 00:00 0
f7fda000-f7fdb000 rw-p 00000000 00:00 0
f7fdb000-f7fdc000 r-xp 00000000 00:00 0 [vdso]
f7fdc000-f7ffc000 r-xp 00000000 fc:00 60555276 /lib32/ld-2.19.so
f7ffc000-f7ffd000 r–p 0001f000 fc:00 60555276 /lib32/ld-2.19.so
f7ffd000-f7ffe000 rw-p 00020000 fc:00 60555276 /lib32/ld-2.19.so
fffdd000-ffffe000 rw-p 00000000 00:00 0 [stack]
원래 정상적으로 컴파일하면
dtors 영역에
w 를 할 수 가 없다.
그래서 w 권한 줘서 문제내줌.
아 나란남자 멋진 실력에 친절함도 같이 있다니
유부남인게 존나 아까움
사실 w 권한 다시 빼서 본선에 문제 낼까 했음
근데 푼 팀중에 많은 팀들이 브포 해서 문제 푼 팀도 존나 많아서
중생들 구제하고자 좀 봐줌.
사실 이 문제를 2011년에 padocon CTF에 냈었음.
그러함. padocon CTF에 Karma와 goe flow 낸 사람이 나임. 한명 더 있음.
요걸로 현재 oldschool 바이너리는 풀수 있음.
릭만 추가하면 댐
그러나, w 권한이 추가되면서
현재 니들은 못품.
힌트를 좀 더 주고 공부할 거리를 좀 더 주자면
ida로 libc 좀 열어봤음
// local variable allocation has failed, the output may be wrong!
int __cdecl __noreturn _libc_start_main(int (__cdecl *main)(int, char **, char **), int argc, char **ubp_av, void (*init)(void), void (*fini)(void), void (*rtld_fini)(void), void *stack_end)
{
void (*v7)(void); // rbp@1
int v8; // edx@2
void *v9; // rdx@5
int v10; // ebx@5
int v11; // er14@9
int v12; // eax@13
__int64 v13; // rax@16
__int64 v14; // rax@16
volatile signed __int32 *v15; // rax@16
__int64 v16; // r13@18
unsigned int v17; // er12@18
__int64 v18; // rbp@18
void (__fastcall *v19)(signed __int64, _QWORD, void *, void (*)(void), void (*)(void)); // rax@19
char **v20; // [sp+8h] [bp-B0h]@1
int v21; // [sp+14h] [bp-A4h]@1
char v22; // [sp+20h] [bp-98h]@12
__int64 v23; // [sp+68h] [bp-50h]@13
__int64 v24; // [sp+70h] [bp-48h]@13
v7 = init;
v21 = argc;
v20 = ubp_av;
if ( &dl_starting_up )
v8 = dl_starting_up == 0;
else
v8 = 0;
dword_3C4080 = v8;
if ( rtld_fini )
{
(_QWORD *)&argc = 0LL;
_cxa_atexit(rtld_fini, 0LL, 0LL, init, fini);
}
v9 = &rtld_global_ro;
v10 = rtld_global_ro & 2;
if ( rtld_global_ro & 2 )
{
*(_QWORD *)&argc = *v20;
(((void (fastcall **)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD))&rtld_global_ro + 25))(
“\ninitialize program: %s\n\n”,
*v20,
&rtld_global_ro,
init,
fini
);
}
if ( v7 )
{
*(_QWORD *)&argc = v20;
((void (__fastcall *)(_QWORD, char **, char **, void (*)(void), void (*)(void)))v7)(
(unsigned int)v21,
v20,
environ,
init,
fini
);
}
v11 = *((_DWORD *)&rtld_global_ro + 72);
if ( v11 )
{
v16 = *((_QWORD *)&rtld_global_ro + 35);
v17 = 0;
v18 = rtld_global;
do
{
v19 = *(void (__fastcall **)(signed __int64, _QWORD, void *, void (*)(void), void (*)(void)))(v16 + 24);
if ( v19 )
v19(v18 + 16 * (v17 + 71LL), *(_QWORD *)&argc, v9, init, fini);
++v17;
v16 = *(_QWORD *)(v16 + 64);
}
while ( v11 != v17 );
}
if ( v10 )
{
*(_QWORD *)&argc = *v20;
(*((void (__fastcall **)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD))&rtld_global_ro + 25))(
“\ntransferring control: %s\n\n”,
*v20,
&rtld_global_ro,
init,
fini
);
}
if ( setjmp((struct __jmp_buf_tag *__attribute((org_typedef(jmp_buf))) )&v22) )
{
v13 = __ROR8(qword_3C9C50, 17);
((void (fastcall )(char *, _QWORD))(MK_FP(__FS, 48LL) ^ v13))(&v22, *(_QWORD *)&argc);
v14 = ROR8(qword_3C9C40, 17);
v15 = (volatile signed int32 )(MK_FP(__FS, 48LL) ^ v14);
_InterlockedDecrement(v15);
if ( v15 )
{
while ( 1 )
asm { syscall }
}
v12 = 0;
}
else
{
v23 = *MK_FP(__FS, 768LL);
v24 = *MK_FP(FS, 760LL);
*MK_FP(FS, 768LL) = &v22;
v12 = ((int (__fastcall *)(_QWORD, char **, char **))main)((unsigned int)v21, v20, environ);
}
exit(v12);
}
끝에 exit 보임 ?
이거 우리가 아는 그 exit 아님
void __fastcall __noreturn sub_39C40(int status, __int64 *a2, char a3)
{
char v3; // r12@1
__int64 *v4; // rbp@1
int v5; // ebx@1
__int64 v6; // r13@2
__int64 v7; // rax@3
__int64 *v8; // rcx@3
__int64 v9; // rdx@4
bool v10; // zf@8
void (**v11)(void); // rbp@10
__int64 v12; // rsi@13
__int64 v13; // rax@13
__int64 v14; // rdi@14
__int64 v15; // rax@14
__int64 v16; // rax@15
v3 = a3;
v4 = a2;
v5 = status;
_call_tls_dtors();
while ( 1 )
{
v6 = *v4;
if ( !*v4 )
{
LABEL_9:
if ( v3 )
{
v11 = (void ()(void))&off_3C0748;
if ( &off_3C0748 < &off_3C0750 )
{
do
{
(*v11)();
++v11;
}
while ( v11 < (void ()(void))&off_3C0750 );
}
}
exit(v5);
}
LABEL_3:
while ( 1 )
{
v7 = *(_QWORD *)(v6 + 8);
v8 = (int64 *)(v6 + 32LL * *(_QWORD *)(v6 + 8) – 16);
if ( !v7 )
break;
while ( 1 )
{
*(_QWORD *)(v6 + 8) = –v7;
v9 = *v8;
if ( *v8 == 3 )
break;
if ( v9 == 4 )
{
v14 = *(_QWORD *)(v6 + 32 * v7 + 32);
v15 = __ROR8(*(_QWORD *)(v6 + 32 * v7 + 24), 17);
((void (fastcall *)(__int64, _QWORD))(*MK_FP(__FS, 48LL) ^ v15))(v14, (unsigned int)v5);
goto LABEL_3;
}
if ( v9 == 2 )
{
v12 = *(_QWORD *)(v6 + 32 * v7 + 32);
v13 = ROR8(*(_QWORD *)(v6 + 32 * v7 + 24), 17);
((void (fastcall *)(_QWORD, __int64))(*MK_FP(__FS, 48LL) ^ v13))((unsigned int)v5, v12);
goto LABEL_3;
}
v8 -= 4;
if ( !v7 )
goto LABEL_8;
}
v16 = ROR8(*(_QWORD *)(v6 + 32 * v7 + 24), 17);
((void (*)(void))(*MK_FP(FS, 48LL) ^ v16))();
}
LABEL_8:
v10 = *(_QWORD *)v6 == 0LL;
*v4 = *(_QWORD *)v6;
if ( v10 )
goto LABEL_9;
free((void *)v6);
}
여기 보임 ? 여기에 무려 0-day가 3개는 됨.
다시 말하지만 opensource 프로그램 코드로 보는것과 ida로 보는것은
매우 다름. 직접 해봐야 암.
술도 먹었겠다. 기분도 나쁘겠다.
이정도 0-day는 심심하면 나오니
본선에서 보겠음
각오들 하시고 오는게 좋겠음.
나 라우터 만들었음.