binary analysis in linux box without symbol

2009. 6. 15. 16:31

제목이 너무 거창한 감이..

시작은 symbol table 이 제거된 바이너리 분석을 어떻게 해야 될까 였다. codegate 2009 1번 문제,
io.smashthestack.org 의 2번 문제가 이런 형태였다. 할줄 아는건 gdb 뿐인데 볼게 없으니 T_T.

여기저기 자료를 디벼보다 혹시나 하는 마음에
http://www.wowhacker.org Q/A 게시판에 여쭈어봤더니 strace 로 접근한다는 답변을 얻었다.

system call tracer의 종류와 내용에 대한 링크  http://kldp.org/node/900

ltrace를 사용한 역분석 (from OLSP)  http://linux-virus.springnote.com/pages/2737040

리눅스 디버깅에 관련된 링크. http://www.ibm.com/developerworks/kr/library/l-debug/index.html

예선에서 9등을 한 베트남 친구들이 쓴 보고서를 참조해서 binary 1번을 생성했다.

http://vnsecurity.net/Members/lamer/archive/2009/03/11/codegate2009/


int main(int argc, char **argv)
{
int len;
void *retaddr;
len = 0;
if (!argv[1])
{
puts("argv[1] is null");
exit(1);
}
if ( len > 23 )
exit(1);
len = strlen(argv[1]);
memfrob(argv[1], len);
retaddr = (char *)&retaddr + 11; // return address;
         원래는 0x0C --> 10진수 11로 수정 (ubuntu 8.10)
printf("argv[1] = %s \n size = %d\n", argv[1], len);
*(int *)retaddr = argv[1];
}


gcc로 컴파일 하고 strip -s 옵션으로 심볼테이블을 모두 삭제하고 strace로 살펴보았다.

adcob@badcob-desktop:~/work$ strace ./beistcon1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa

execve("./beistcon1", ["./beistcon1", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...], [/* 36 vars */]) = 0
brk(0)                                  = 0x9a8c000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb8008000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=50837, ...}) = 0
mmap2(NULL, 50837, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7ffb000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/cmov/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\340g\1"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1425800, ...}) = 0
mmap2(NULL, 1431152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7e9d000
mmap2(0xb7ff5000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x158) = 0xb7ff5000
mmap2(0xb7ff8000, 9840, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7ff8000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e9c000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7e9c6b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb7ff5000, 8192, PROT_READ)   = 0
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xb8025000, 4096, PROT_READ)   = 0
munmap(0xb7ffb000, 50837)               = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb8007000
write(1, "argv[1] = kkkkkkkkkkkkkkkkkkkkkk"..., 52argv[1] = kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
) = 52
write(1, " size = 41\n", 11 size = 41
)            = 11

--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Process 14067 detached

이것만 봐서는 memfrob 를 쓴다는 것을 확인할 수가 없다. ltrace로도 돌려보았다.
 
badcob@badcob-desktop:~/work$ ltrace ./beistcon1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa

__libc_start_main(0x8048494, 2, 0xbfc22a04, 0x8048570, 0x8048560 <unfinished ...>
strlen("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...)                                  = 37
memfrob(0xbfc2373d, 37, 0xbfc22958, 0xbfc22980, 0xb7ef3ff4)                    = 0xbfc2373d
printf("argv[1] = %s\n size = %d\n", "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"..., 37argv[1] = kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
 size = 37
) = 59
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++


아하. 요렇게 보니 조금 감이 온다. 하지만 100% 분석은 어렵다 .저기서 발생하는 세그먼테이션 폴트가 리턴어드레스를 덮어 씌워서 발생하는 것이라는 것을 알수 있는 방법은 경험에 의한 직감 뿐이 없는것일까. (지금이라면 나도 리턴어드레스 일지도 모른다고 예상을 할것 같다..)

실로 불충분한 글이다.. 어디다 물어볼 곳도 없고 답답함..

별거 없었다. 걍 scp든 ftp든 파일 가져와서 IDA 로 돌리면 디스어셈블된다.. IDA 가 진리다...ㅅㅂ 단 심볼이 없으므로 함수 이름 등의 정보는 확인할 수 없다.

static + runtime 조합으로 윈도우에서 분석하는것처럼
IDA 로 디스어셈블해서 펼쳐놓고 EDB로 하나하나 확인하면 비슷하게 할수 있을듯.  으라챠!

PS. http://simples.kr/bbs/board.php?bo_table=13_1&wr_id=21&page=2 에 정적 링크된 Stripped ELF 바이너리 상에서의 함수 탐지 기법 이라는 글을 발견. 2nd CodeEngn에서 태인규님(blog.hackken.org)이 발표하신 자료로
Grayresolve라는 IDA plugin을 이용해서 함수 이름을 탐지하는 방법에 대해서 나와있다.

grayresolve down http://www.codeengn.com/2008/Archive/grayResolve.plw







'OS > Linux' 카테고리의 다른 글

redhat 9.0 networking problem in vmware  (0) 2010.06.20
about Signal  (0) 2009.12.09
Advanced Programming in the Unix Environment  (0) 2009.12.02
APUE 7장 연습문제  (0) 2009.11.27
codegate 2009. hamburger  (0) 2009.08.14
linux socket source  (0) 2009.08.05

badcob OS/Linux