吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4938|回复: 2
收起左侧

[会员申请] 申请会员ID:C0ss4ck【申请通过】

[复制链接]
吾爱游客  发表于 2018-7-28 00:12

申请ID:C0ss4ck
个人邮箱:769233061@qq.com (刚才发了篇一摸一样的忘记给邮箱了【滑稽】)
原创技术文章:

Windows Kernel

一只CTF二进制弱鸡打PWN打累了回头刷了点逆向……这道题是reversing.kr上面的唯一一道和Windows内核相关的题目,挑出来讲一讲咯,顺便用作我的申请文章。

Analysis of WindowsKernel.exe

Winmain(0x00401000):
push        0                                        ;dwInitParam
push         offset DialogFunc        ;lpDialogFunc
push        0                                        ;hWndParent
push        65h                                        ;lpTemplateName
push        eax                                        ;hInstance
call        ds:DialogBoxParamW
DialogFunc(0x00401020):
BOOL __stdcall DialogFunc(HWND hWnd, UINT a2, WPARAM a3, LPARAM a4)
{
        if ( a2 == 272 )                                                        //Timer set
        {
                SetDlgItemTextW(hWnd, 1001, L"Wait.. ");
                SetTimer(hWnd, 0x464u, 0x3E8u, 0);
                return 1;
        }
        if ( a2 != 273 )
        {
                if ( a2 == 275 )                                                //Error ocurr
                {
                        KillTimer(hWnd, 0x464u);
                        HandleError(hWnd);
                        return 1;
                }
                return 0;
        }
        if ( (unsigned __int16)a3 == 2 )                        //Dialog end
        {
                SetDlgItemTextW(hWnd, 1001, L"Wait.. ");
                CloseProc();
                EndDialog(hWnd, 2);
                return 1;
        }
        if ( (unsigned __int16)a3 == 1002 )                        //Unknown
        {
                if ( a3 >> 16 == 1024 )
                {
                        Sleep(0x1F4u);
                        return 1;
                }
                return 1;
        }
        if ( (unsigned __int16)a3 != 1003 )
                return 0;
        check(hWnd);                                                                //Judge the input
        return 1;
}
check(0x00401110):
HWND __thiscall check(HWND hDlg)
{
        HWND v1; // edi
        HWND result; // eax
        HWND v3; // eax
        HWND v4; // eax
        HWND v5; // eax
        WCHAR String; // [esp+8h] [ebp-204h]

        v1 = hDlg;
        GetDlgItemTextW(hDlg, 1003, &String, 512);
        if ( lstrcmpW(&String, L"Enable") )
        {
                result = (HWND)lstrcmpW(&String, L"Check");
                if ( !result )
                {
                        if ( click(v1, 0x2000u) == 1 )
                                MessageBoxW(v1, L"Correct!", L"Reversing.Kr", 0x40u);
                        else
                                MessageBoxW(v1, L"Wrong", L"Reversing.Kr", 0x10u);
                        SetDlgItemTextW(v1, 1002, &word_4021F0);
                        v5 = GetDlgItem(v1, 1002);
                        EnableWindow(v5, 0);
                        result = (HWND)SetDlgItemTextW(v1, 1003, L"Enable");
                }
        }
        else if ( click(v1, 0x1000u) )
        {
                v3 = GetDlgItem(v1, 1002);
                EnableWindow(v3, 1);
                SetDlgItemTextW(v1, 1003, L"Check");
                SetDlgItemTextW(v1, 1002, &word_4021F0);
                v4 = GetDlgItem(v1, 1002);
                result = SetFocus(v4);
        }
        else
        {
                result = (HWND)MessageBoxW(v1, L"Device Error", L"Reversing.Kr", 0x10u);
        }
        return result;
}

两次click,arg1==0x1000是点击Enable,按钮变成Check;arg1==0x2000是点击Check,回显Correct或者Wrong。

后来翻了夜影老哥的WP,发现这个0x1000和0x2000是dwIoControlCode,即DeviceIoControl的arg1,而dwIoControlCode值就是Windows内核中宏定义CTL_CODE所定义的。

详情请看MSDN对CTL_CODE的解释

click(0x00401280):
int __usercall sub_401280@<eax>(HWND a1@<edi>, DWORD dwIoControlCode)
{
        HANDLE v2; // esi
        int result; // eax
        DWORD BytesReturned; // [esp+4h] [ebp-8h]
        int OutBuffer; // [esp+8h] [ebp-4h]

        v2 = CreateFileW(L"\\\\.\\RevKr", 0xC0000000, 0, 0, 3u, 0, 0);
        if ( v2 == (HANDLE) - 1 )
        {
                MessageBoxW(a1, L"[Error] CreateFile", L"Reversing.Kr", 0x10u);
                result = 0;
        }
        else if ( DeviceIoControl(v2, dwIoControlCode, 0, 0, &OutBuffer, 4u, &BytesReturned, 0) )
        {
                CloseHandle(v2);
                result = OutBuffer;
        }
        else
        {
                MessageBoxW(a1, L"[Error] DeviceIoControl", L"Reversing.Kr", 0x10u);
                result = 0;
        }
        return result;
}

click函数内很明显通过DeviceIoControl与键盘设备进行了交互(快看这里有dwIoControlCode),并调用了WinKer.sys中的函数

接下来分析WinKer.sys

Analysis of WinKer.sys

KeyBoardInput(0x00011266):

这里通过静态分析找到了接收键盘设备输入的函数

void __stdcall getInput(struct _KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
  char input; // al

  input = READ_PORT_UCHAR((PUCHAR)0x60);
  sub_111DC(input);
}

READ_PORT_UCHAR是Windows内核I/O中从指定的PORT读入一字节数据的函数,其参数(PUCHAR)PORT在此为0x60,而大多数PC键盘控制器在PORT0x60与0x64是可寻址的,故此处为从键盘控制器逐次读入1byte。

Judge(0x000111DC,0x00011156,0x000110D0):

这些理解起来都简单。
在第一个Judge中通过switch(judgenum)先检查前3个byte的值,再检查最后1byte值,若正确则judgenum=100,并进入下一个Judge;
在第二个Judge中先对第5到最后的byte进行异或0x12的处理,再通过switch(judgenum)检查第5到7个byte,最后检查第8个byte,若正确则judgenum=200,并进入下一个Judge;
第三个Judge也是类似,只不过又对最后四字节进行了异或5的处理。

Solve

解密脚本如下

s=[0xa5,0x92,0x95,0xb0,0xb2,0x85,0xa3,0x86,0xb4,0x8f,0x8f,0xb2]
for i in range(4):
        s[i+4]^=0x12
        s[i+8]^=0x12
        s[i+8]^=0x5
mid=''
for i in s:
        mid+=str(hex(i))[2:]
print mid

得到a59295b0a097b194a39898a5
对应ScanCode码表解码得keybdinthook

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2018-8-1 11:06
I D:C0ss4ck
邮箱:769233061@qq.com

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。

ps:登录后把文章整理一下发到脱壳破解CTF分类吧。
C0ss4ck 发表于 2018-8-2 23:58
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 12:40

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表