您的位置:首页 > 其它

HCTF wzwzDingDing writeup

2014-11-21 11:55 447 查看
CTF以前也没怎么参加过,参加也是抱大腿,这次师弟拉着我玩HCTF,就分析了一下里面wzwzDingDing 这个题目。

这个题目是一个64位的驱动,在ida里分析了一下。

首先找到正常的驱动分发函数里,看看这个驱动都完成什么功能。下面是驱动分发函数中,比较iocontrol code的地方。



然后进入每个处理分支,观察一下都做了什么。发现每个分支都有一个特点,满足相应的条件判断,就会将全局变量dword_148E0某位置为F。

比如: 88102004这个分支,当从ring3输入字符串为"^lejAJ]O" "MNIII" 时,会分别置dword_148E0第六位 第五位为F,两次在ring3调用DeviceIoControlcode即可。

后面的分支每次按条件要求,依次在ring3调用DeviceIoControlcode, 让驱动走完每个iocontrol code的处理分支。

注意:8810200c的分支是判断ring3的映像文件名是否含有HCTF这几个字符。

流程还需要走一个其它分支,这里就选择了0x88102014,就是jmp loc12788,这个分支会给第一位置F

接着写个ring3的程序,跑一下看看什么情况

<span style="font-size:14px;">  HANDLE hDev = CreateFile("\\\\.\\Hctf",GENERIC_READ |GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING ,0, NULL);
DWORD code=0;
DWORD dwShellcodeSize=0x104;
char InBuf[] = "^lejAJ]O";
char mniii[]="MNIII";
char ret[]="\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3";
char OutBuf[0x100]={0};
DWORD dwRetBytes  = 0;
char OutBuf2[0x100]={0};

DeviceIoControl(hDev, 0x88102004,InBuf, 0x9, OutBuf, 0x100, &dwRetBytes, 0);
DeviceIoControl(hDev, 0x88102004,mniii, 0x6, OutBuf, 0x100, &dwRetBytes, 0);
DeviceIoControl(hDev, 0x88102008,ret, 16, OutBuf, 0x100, &dwRetBytes, 0);
DeviceIoControl(hDev, 0x8810200c,ret, 16, OutBuf, 0x100, &dwRetBytes, 0);
DeviceIoControl(hDev, 0x8810200c,ret, 16, OutBuf, 0x100, &dwRetBytes, 0);
DeviceIoControl(hDev, 0x88102014,ret, 16, OutBuf, 0x100, &dwRetBytes, 0);
DeviceIoControl(hDev, 0x88102010,ret, 16, OutBuf2, 0x100, &dwRetBytes, 0);

CloseHandle(hDev);</span>


发现驱动直接crash在下面这个call里,调用到栈上的一个地址



到这就太想吐槽了,crash在这后,发现里面有一部分代码,还有类似循环的代码,还以为要怎么补成一个计算flag的算法,尼玛最后知道就是补成栈平衡就行,真是没做过ctf啊,太天真了。。

这题还有一个一直疑惑的问题,就是补的字节怎么从用户态传到内核,驱动知识太匮乏了。。因为看到在调用[rsp+0xC8+P]之前,有一部分代码,是往shellcode的位置写9个字节。推想应该是从ring3传进来的,然后在驱动里补齐。如下图所示这段代码:



补什么就不写了,平衡堆栈就行了,flag就是补的字节,有点坑。

前面也看到了对mdl的操作,貌似也没有映射用户态的内存。也应该不是从ring3的输入缓冲传进来的。 谁知道怎么搞,求指导,纠结~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: