wargames的leviathan 是以通关游戏的方式来练习程序分析。 文章记录在通关过程中新学习和关注的知识盲点。
LV00 默认用户名leviathan0
,密码leviathan0
ssh leviathan0@leviathan.labs.overthewire.org -p 2223
进入.backup
目录,cat
bookmarks.html
,用grep按leviathan关键字。可找到password
LV01 ssh leviathan2@leviathan.labs.overthewire.org -p 2223
echo bUVoNVBObDEwZQo= | base64 -d
目录下有一个check
文件, 使ltrace
命令简单看下check
的调用过程。:ltrace ./check
看调用情况,可知密码为”sex”。 再运行原程序,输入 “sex”之后,就进行入shell,而且是 leviathan2(uid=12003)的shell 能过cat /etc/leviathan_pass/leviathan2
获取到leviathan1的密码
1 2 3 4 5 6 7 8 9 10 11 __libc_start_main (0 x80491e6, 1 , 0 xffffd604, 0 <unfinished ...>printf ("password: " ) = 10 getchar (0 xf7fbe4a0, 0 xf7fd6f80, 0 x786573, 0 x646f67password: 123123 ) = 49 getchar (0 xf7fbe4a0, 0 xf7fd6f31, 0 x786573, 0 x646f67) = 50 getchar (0 xf7fbe4a0, 0 xf7fd3231, 0 x786573, 0 x646f67) = 51 strcmp ("123" , "sex" ) = -1 puts ("Wrong password, Good Bye ..." Wrong password, Good Bye ... ) = 29 +++ exited (status 0 ) +++
1 2 3 4 geteuid () = 12001 geteuid () = 12001 setreuid (12001 , 12001 ) = 0 system ("/bin/sh" )
LV02 ssh leviathan2@leviathan.labs.overthewire.org -p 2223
echo bUVoNVBObDEwZQo= | base64 -d
进入目录后,发再可执行文件printfile有gsu的权限设置。
-r-sr-x--- 1 leviathan3 leviathan2 15056 Sep 1 06:30 printfile
文件用法
1 2 *** File Printer *** Usage: ./printfile filename
用ida反编译,逻辑如下: 输入,然后检查文件权限(access),再格式化出一个包含输入的命令,系统调用输出。
这里用到了特殊的文件名称及软连接绕过。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 int __cdecl main (int argc, const char **argv, const char **envp) { int result; __uid_t v4; __uid_t v5; const char **argv_input; char s[512 ]; unsigned int v8; int *v9; v9 = &argc; argv_input = argv; v8 = __readgsdword(0x14 u); if ( argc > 1 ) { if ( access(argv[1 ], 4 ) ) { puts ("You cant have that file..." ); result = 1 ; } else { snprintf (s, 0x1FF u, "/bin/cat %s" , argv_input[1 ]); v4 = geteuid(); v5 = geteuid(); setreuid(v5, v4); system(s); result = 0 ; } } else { puts ("*** File Printer ***" ); printf ("Usage: %s filename\n" , *argv_input); result = -1 ; } return result; }
解决方法:
1 2 3 4 5 6 mkdir /tmp/ YT9dtMOUMO cd /tmp/ YT9dtMOUMO touch a\ b ln -s /etc/ leviathan_pass/leviathan3 / tmp/YT9dtMOUMO/ a ~/printfile "/ tmp/YT9dtMOUMO/ a b"
LV03 ssh leviathan3@leviathan.labs.overthewire.org -p 2223
echo UTBHOGo0c2Frbgo= | base64 -d
发现level3文件
ide后反编后,发现密码snlprintf
,可以进行leviathan4
的shell。 然后cat /etc/leviathan_pass/leviathan4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 int __cdecl main (int argc, const char **argv, const char **envp) { strcpy (v6, "...s3cr3t" ); strcpy (s1, "h0no33" ); strcpy (s2, "kakaka" ); strcpy (&v6[10 ], "*32.2*[x]" ); strcmp (s1, s2); printf ("Enter the password> " ); do_stuff(); return 0 ; } __int64 do_stuff () { __uid_t v0; __uid_t v1; __int64 result; char s2[267 ]; unsigned int v4; v4 = __readgsdword(0x14 u); strcpy (s2, "snlprintf\n" ); fgets(&s2[11 ], 256 , stdin ); if ( !strcmp (&s2[11 ], s2) ) { puts ("[You've got shell]!" ); v0 = geteuid(); v1 = geteuid(); setreuid(v1, v0); system("/bin/sh" ); } else { puts ("bzzzzzzzzap. WRONG" ); } LODWORD(result) = 0 ; HIDWORD(result) = v4 - __readgsdword(0x14 u); return result; }
LV04 ssh leviathan4@leviathan.labs.overthewire.org -p 2223
echo QWd2cm9wSTRPQQo= | base64 -d
发现文件
1 2 3 4 5 leviathan4@gibson:~/.trash$ ls -al total 24 dr-xr-x--- 2 root leviathan4 4096 Sep 1 06:30 . drwxr-xr-x 3 root root 4096 Sep 1 06:30 .. -r-sr-x--- 1 leviathan5 leviathan4 14924 Sep 1 06:30 bin
反编译后的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int __cdecl main (int argc, const char **argv, const char **envp) { char byte_var; size_t i; int j; FILE *stream; stream = fopen("/etc/leviathan_pass/leviathan5" , "r" ); if ( !stream ) return -1 ; fgets(buf, 256 , stream); for ( i = 0 ; strlen (buf) > i; ++i ) { byte_var = *(_BYTE *)(i + 0x804C060 ); for ( j = 0 ; j <= 7 ; ++j ) { if ( byte_var >= 0 ) putchar ('0' ); else putchar ('1' ); byte_var *= 2 ; } putchar (' ' ); } putchar ('\n' ); return 0 ; }
其中buf是全局变量,在bbs段上,代码中常量的0x804C060
就是buf的地址。
1 .bss:0804 C060 buf db 100 h dup (?)
代码简单分析,就是读出密码,写入buf中,然后每次取一个字节。 判断最高位的符号,输出0或者1,再乘以2(目地是溢出后,判断下一位(bit)是0还是1。
所以找一个在线把binary转ascii的地https://www.rapidtables.com/convert/number/binary-to-ascii.html
LV05 ssh leviathan5@leviathan.labs.overthewire.org -p 2223
echo RUtLbFRGMVhxcwo= | base64 -d
直接上ltrace,逻辑是读/tmp/file.log
,那上一个软链接到密码上。
1 2 3 4 5 6 7 leviathan5@gibson:~$ ltrace ./leviathan5 __libc_start_main(0x8049206, 1, 0xffffd5f4, 0 <unfinished ...> fopen("/tmp/file.log", "r") = 0 puts("Cannot find /tmp/file.log"Cannot find /tmp/file.log ) = 26 exit(-1 <no return ...> +++ exited (status 255) +++
1 2 ln -s /etc/ leviathan_pass/leviathan6 / tmp/file .log ./leviathan5
LV06 ssh leviathan6@leviathan.labs.overthewire.org -p 2223
echo WVo1NVhQVmsybAo= | base64 -d
反编译leviathan6
文件,密码7123,然后进入shellcat /etc/leviathan_pass/leviathan7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int __cdecl main (int argc, const char **argv, const char **envp) { __uid_t v3; __uid_t v4; if ( argc != 2 ) { printf ("usage: %s <4 digit code>\n" , *argv); exit (-1 ); } if ( atoi(argv[1 ]) == 7123 ) { v3 = geteuid(); v4 = geteuid(); setreuid(v4, v3); system("/bin/sh" ); } else { puts ("Wrong" ); } return 0 ; }
这题可能出题人想让大家用爆破的方式
1 2 3 4 5 #!/bin/bash for a in {0000..9999}do ~/leviathan6 $a done
LV07 ssh leviathan7@leviathan.labs.overthewire.org -p 2223
echo OEdwWjVmOEh6ZQo= | base64 -d
这是最后一关
1 2 3 leviathan7@gibson:~$ cat CONGRATULATIONS Well Done, you seem to have used a *nix system before , now try something more serious. (Please don't post writeups, solutions or spoilers about the games on the web. Thank you!)
这里让大家不要上传writepus上blog上。 但其实很多人并没有遵守这个(包括我)
总结 这里用了ltrace
可以大概猜出逻辑。 也可用gdb
,也可用ida
等
这里的可执行程序都是用ACL;Setuid、Setgid、Stick bit特殊权限
来构成关卡的。
这里用文件名的特殊符号及软链接是个巧妙的方法。
其它wp https://jhalon.github.io/over-the-wire-leviathan/ https://juejin.cn/post/6844903572044251150