--- lang: ja-jp breaks: true --- logger === ## 問題概要 ### ジャンル exploit (Linuxカテゴリな気がする) ### 点数 300 points ### 問題文 logger Host : logger.pwn.seccon.jp Port : 6565 logger (SHA1 : fee7140cb33d79c0406de49f7f8985fd459468ea) libc-2.19.so (SHA1 : 8674307c6c294e2f710def8c57925a50e60ee69e) ### フラグ ??? ### 挑戦者 tkmru K_atc ## 解法 ## 議論 可能性: * ディレクトリトラバース脆弱性によるflagファイル読み取り * ログファイルにshellcode * fopenの引数書き換えてflag読ませる ### 表層調査 ``` $ checksec.sh --file ./logger RELRO STACK CANARY NX PIE RPATH RUNPATH FILE Partial RELRO Canary found NX disabled Not an ELF file No RPATH No RUNPATH ./logger $ ./logger Welcome to logging service. Log file will be removed every 5 minites. 1. Login 2. exit 1 Name :1234 Password:1234 1. Read log 2. Append log 3. Display info 4. exit 1 qqqqq 1. Read log 2. Append log 3. Display info 4. exit 3 =====Info===== Your Name: 1234Your Password: 1234filename: ed2b1f468c5f915f3f1cf75d7068baaeP2`============== 1. Read log 2. Append log 3. Display info 4. exit ``` * __NX disabled__ ファイル読み取り処理があるのでどうにかflag読ませるとか? free()してないのでheap exploitingではない気がする。 ファイル名の後ろにゴミが付いているのが気になる えーそんな問題ある? ``` =====Info===== Your Name: nameYour Password: passfilename: efc2792ddf38f661f9d3965005555f3d\x10 #\x0c\x89\x7f============== ``` なんかのアドレスがリークしてる([rsp+0x100+X]) 0x401234 call j_fopenの引数書き換えたい。 0x401037 call j_fopenの引数は直前のf_openの間にcalc_filenameがあるからきびしい気がする stack_chk_fail()はcalc_filename()の中でしか読まれない。 0x40116d call j___isoc99_scanfで書き換えたい。 scanf('%ld', buf)なのでだめだった。 自由に書き込めるのLog size(max 128byte):のとこくらいかな??? * 負数指定可能 ### main() ```clike function main { rax = *__TMC_END__; setvbuf(rax, 0x0, 0x2, 0x0); rax = *stdout@@GLIBC_2.2.5; setvbuf(rax, 0x0, 0x2, 0x0); puts("Welcome to logging service."); puts("Log file will be removed every 5 minites."); puts("1. Login\n2. exit"); __isoc99_scanf("%ld", var_1A0); getchar(); if (var_1A0 == 0x1) goto loc_400f78; loc_400f6e: // avoid rax = exit(0x0); return rax; loc_400f78: // BOF不可 printf("%s", "Name :"); __isoc99_scanf("%63s", var_90); printf("%s", "Password:"); __isoc99_scanf("%63s", var_50); rax = calc_filename(var_90, var_50, var_100); strcat('/tmp/log', rax); if (check_dir() != 0x0) goto loc_401023; loc_40100f: // avoid puts("/tmp/logger directory not exists"); rax = exit(0x1); return rax; loc_401023: *fp = fopen('/tmp/log', "a+"); if (*fp != 0x0) goto loc_40105e; loc_40104a: puts("open error."); rax = exit(0x1); return rax; loc_40105e: stat('/tmp/log', var_190); var_E0 = malloc(sign_extend_32(var_160)); goto loc_40108f; loc_40108f: do { puts("1. Read log\n2. Append log\n3. Display info\n4. exit"); __isoc99_scanf("%ld", var_1A0); getchar(); if (var_1A0 != 0x1) { break; } var_1A8 = 0x0; do { var_1A4 = fgetc(*fp); if (var_1A4 == 0xffffffff) { break; } *(int8_t *)(var_E0 + sign_extend_32(var_1A8)) = var_1A4; var_1A8 = var_1A8 + 0x1; } while (true); write(0x1, var_E0, var_160); } while (true); if (var_1A0 != 0x2) goto loc_40127d; loc_401145: printf("%s", "Log size(max 128byte):"); __isoc99_scanf("%ld", var_1A0); getchar(); if (var_1A0 <= 0x80) goto loc_40119a; loc_401186: puts("Size error."); rax = exit(0x1); return rax; loc_40119a: var_198 = malloc(var_1A0); rax = read(0x0, var_198, var_1A0); fwrite(var_198, sign_extend_64(rax), 0x1, *fp); rax = *fp; fclose(rax); stat('/tmp/log', var_190); // closeしてからreopenしていない? *fp = fopen('/tmp/log', "a+"); if (*fp != 0x0) goto loc_401260; loc_40124c: puts("open error."); rax = exit(0x1); return rax; loc_401260: var_E0 = malloc(sign_extend_32(var_160)); goto loc_40108f; loc_40127d: if (var_1A0 != 0x3) goto loc_4012e8; loc_40128a: puts("=====Info====="); printf("Your Name: %s", var_90); printf("Your Password: %s", var_50); printf("filename: %s", var_100); puts("=============="); goto loc_40108f; loc_4012e8: rax = *fp; fclose(rax); puts("Thank you for your logging :)"); rax = exit(0x0); return rax; } ```