吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 15761|回复: 32
收起左侧

[调试逆向] HDUSEC内核jpg分析

  [复制链接]
JoyChou 发表于 2014-3-30 18:06
本帖最后由 JoyChou 于 2014-3-30 20:36 编辑

0x1.去花
首先载入IDA,发现有比较多的花指令。那就先去除花指令吧。
此文件花指令格式大概为如下几种:

[Asm] 纯文本查看 复制代码
[/align][align=left]__asm
{  
        xor eax,eax    
        jz label1
        __emit e7h
        __emit e8h   // call
        __emit e9h   // jmp
             
label1:
}

[Asm] 纯文本查看 复制代码
__asm
{
        xor eax,eax
        jz label2
        /* junk code */
        __emit 74h // jz
labe2:
}


去除花指令可以用winhex搜索特征码来改成nop,当然直接用idc插件改更方便。简单写个idc脚本
[C++] 纯文本查看 复制代码
#include <idc.idc>
 
static main()
{
    auto i,j,from,size;
    from=0x11400; //起始地址
    size=0x1000;//扫描数据块大小
     
    for ( i=0; i < size;i++ )
    {
         
        //查找 E7 E8 E9 替换90
         
        if ((Byte(from) == 0xE7) &&
            (Byte(from+1) == 0xE8) &&
            (Byte(from+2) == 0xE9))
        {
            Message("test\n");
            for(j=0;j<3;j++)
            {
                PatchByte(from,0x90);
                from++;
            }
            continue;  //回到for
        }
         
        // 查找 33 c0 74 10 ?? ?? ?? ?? …… 后16个替换成90
        if (Byte(from) == 0x33 && Byte(from+1) == 0xC0 && Byte(from + 2) == 0x74 &&
            Byte(from + 3) == 0x10)
        {
            for (j = 0; j < 16; j++)
            {
                PatchByte(from+4, 0x90);
                from++;
            }
            continue;
        }
        from++;
         
    }
    Message("\n" + "OK\n");
     
 }


执行了idc脚本后,再用d和c再调整下代码(最好先设置下Number of opcode bytes 为8)。
此时修改的数据是保存在idb数据库文件里的,文件本身是没有被修改的,所以此时如果想用UDA的F5,那就必须还得用winhex等编辑器手动修改。

0x2. 分析代码
为了方便还是用F5吧,所以用winhex修改好。

可以看到,程序写了三个文件。并且在DPC例程里一直在写一个第一字节为0xAA,大小为0xAB的文件。
程序造成蓝屏的原因是因为在DPC例程里读写文件。因为DPC例程是运行在DISPATCH_LEVEL的IRQL级别,因此不能使用分页内存。读写文件必须是分页内存。

动态分析这个sys可以发现是DPC例程在调用11780call的时候,调用ZwCreateFile就蓝屏了。
动态分析的方法在xp上,可以在双击调试的环境下(xp), bp IopLoadDriver + 0x663,再载入驱动,此时断下,
call    dword ptr [edi+2Ch]  进入这个call就可以到DriverEntry。


0x3. 解题
当逆出&#8203;源码后,就很简单了。在没逆出之前呢?
写了其他两个文件都是骗人的,我们着重看11780这个call干的事,F5后,双击V2变量。
1.png


定义一个大小为0xA8的数组,再重新F5,就可以看到是数组的形式,此时自己用C写到另外一个文件保存下来即可(fread fwrite等)。

2.png


如果不能F5,就只能对着机器码了。目的就是获取下面红框里面的数据。
3.png


这里用python简单匹配下,再用winhex也可以得到上面的结果。
[Python] 纯文本查看 复制代码
# -*- coding:utf-8 -*-
 
import re
__author__ = 'JoyChou'
 
if __name__ == '__main__':
    fp = open('2.txt', 'r')
    content = fp.read()
    result = re.findall(r'\w{2}C6', content)  #findall以列表形式返回所有匹配结果
 
    bmp_fp = open('1.txt', 'wb')
    for i in result:  #i都是整数
 
        szStr = str(i)  #用str将整数转换为字符串
        print '0x%s' % szStr[0:2]
        bmp_fp.write(szStr[0:2])
 
    # 最后还要加上一个0x00  加上后为0xA8  以及要手动修改B1为C6
 
    bmp_fp.close()
    fp.close()



最后,可以发现,0xAA和0xA8就差两个'BM'字节,添加到头部,解base64即可。
得到图片
4.png


base64解密:hdu1s
这bmp图片大小就0xAA个字节,这是怎么做到的呢?唔

0x4. 代码
[C++] 纯文本查看 复制代码
#include "ntddk.h"
 
 
typedef unsigned long DWORD;
typedef unsigned short WORD;
 
KDPC dpc;
LARGE_INTEGER DueTime;
KTIMER Timer;
 
void DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
    KdPrint(("Leave JoyChou's Driver\n"));
}
 
VOID test1()
{
    UNICODE_STRING UnicodeString2={0};  // 三个结构都为0,如果不设置length,length将为0
    NTSTATUS nStatus;
    UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool,1024);
    UnicodeString2.MaximumLength = 1024;
 
    // 将200以16进制转换为字符串,最后为字符串 C8
    nStatus = RtlIntegerToUnicodeString(200,16,&UnicodeString2);
 
    if ( NT_SUCCESS(nStatus))
    {
        KdPrint(("Conver to string succussfully!\n"));
        KdPrint(("Result:%wZ\n",&UnicodeString2));
    }else
    {
        KdPrint(("Conver to string unsuccessfully!\n"));
    }
 
    //销毁UnicodeString2
    RtlFreeUnicodeString(&UnicodeString2);
}
 
int test2(int a1)
{
    int result;
    LARGE_INTEGER LocalTime;
    LARGE_INTEGER CurrentTime;
    TIME_FIELDS TimeFields;
 
    // 得到当前时间(是一个格林威治时间)
    KeQuerySystemTime(&CurrentTime);
 
    // 转换为当地时间
    ExSystemTimeToLocalTime(&CurrentTime, &LocalTime);
 
    // 转换为TIME_FIELDS 可读的时间(人类可以理解的时间)
    RtlTimeToTimeFields(&LocalTime, &TimeFields);
 
 
    *(ULONG *)a1 = 74017 * TimeFields.Minute + TimeFields.Second + 4625;
    *(ULONG *)a1 = 18 * TimeFields.Hour + 2340 * *(ULONG *)a1;
    result = a1;
    *(ULONG *)a1 >>= 1;
    return result;
}
 
 
int __cdecl sub_11780()
{
    ULONG Value; // [sp+0h] [bp-F4h]@1
    char v2[168]; // [sp+4h] [bp-F0h]@1
    NTSTATUS v3; // [sp+ACh] [bp-48h]@1
    UNICODE_STRING String; // [sp+B0h] [bp-44h]@1
    HANDLE Handle; // [sp+B8h] [bp-3Ch]@1
    struct _IO_STATUS_BLOCK IoStatusBlock; // [sp+BCh] [bp-38h]@1
    LARGE_INTEGER Interval; // [sp+C4h] [bp-30h]@1
    UNICODE_STRING Destination; // [sp+D0h] [bp-24h]@1
    OBJECT_ATTRIBUTES ObjectAttributes; // [sp+D8h] [bp-1Ch]@1
    void *Buffer; // [sp+F0h] [bp-4h]@1
 
    String.Length = 0;
    String.MaximumLength = 0;
 
    __asm
    {
        mov word ptr String.Buffer + 2, 0
    }
    //HIWORD(String.Buffer) = 0;
    v2[0] = -86;
    v2[1] = 0;
    v2[2] = 0;
    v2[3] = 0;
    v2[4] = 0;
    v2[5] = 0;
    v2[6] = 0;
    v2[7] = 0;
    v2[8] = 62;
    v2[9] = 0;
    v2[10] = 0;
    v2[11] = 0;
    v2[12] = 40;
    v2[13] = 0;
    v2[14] = 0;
    v2[15] = 0;
    v2[16] = 72;
    v2[17] = 0;
    v2[18] = 0;
    v2[19] = 0;
    v2[20] = 9;
    v2[21] = 0;
    v2[22] = 0;
    v2[23] = 0;
    v2[24] = 1;
    v2[25] = 0;
    v2[26] = 1;
    v2[27] = 0;
    v2[28] = 0;
    v2[29] = 0;
    v2[30] = 0;
    v2[31] = 0;
    v2[32] = 108;
    v2[33] = 0;
    v2[34] = 0;
    v2[35] = 0;
    v2[36] = 0;
    v2[37] = 0;
    v2[38] = 0;
    v2[39] = 0;
    v2[40] = 0;
    v2[41] = 0;
    v2[42] = 0;
    v2[43] = 0;
    v2[44] = 0;
    v2[45] = 0;
    v2[46] = 0;
    v2[47] = 0;
    v2[48] = 0;
    v2[49] = 0;
    v2[50] = 0;
    v2[51] = 0;
    v2[52] = 0;
    v2[53] = 0;
    v2[54] = 0;
    v2[55] = 0;
    v2[56] = -1;
    v2[57] = -1;
    v2[58] = -1;
    v2[59] = 0;
    v2[60] = 118;
    v2[61] = 121;
    v2[62] = -98;
    v2[63] = -3;
    v2[64] = -26;
    v2[65] = 55;
    v2[66] = 119;
    v2[67] = 49;
    v2[68] = -80;
    v2[69] = 0;
    v2[70] = 0;
    v2[71] = 0;
    v2[72] = 118;
    v2[73] = -7;
    v2[74] = -98;
    v2[75] = -3;
    v2[76] = -26;
    v2[77] = -73;
    v2[78] = 39;
    v2[79] = 53;
    v2[80] = -65;
    v2[81] = 0;
    v2[82] = 0;
    v2[83] = 0;
    v2[84] = -106;
    v2[85] = -7;
    v2[86] = -98;
    v2[87] = -3;
    v2[88] = -27;
    v2[89] = -73;
    v2[90] = -81;
    v2[91] = 45;
    v2[92] = -65;
    v2[93] = 0;
    v2[94] = 0;
    v2[95] = 0;
    v2[96] = -26;
    v2[97] = -63;
    v2[98] = -128;
    v2[99] = -3;
    v2[100] = -27;
    v2[101] = -73;
    v2[102] = -113;
    v2[103] = 45;
    v2[104] = -80;
    v2[105] = 0;
    v2[106] = 0;
    v2[107] = 0;
    v2[108] = 118;
    v2[109] = -1;
    v2[110] = -127;
    v2[111] = -3;
    v2[112] = -27;
    v2[113] = -105;
    v2[114] = -33;
    v2[115] = 44;
    v2[116] = -65;
    v2[117] = 0;
    v2[118] = 0;
    v2[119] = 0;
    v2[120] = 118;
    v2[121] = -1;
    v2[122] = -98;
    v2[123] = -3;
    v2[124] = -27;
    v2[125] = -41;
    v2[126] = -81;
    v2[127] = 46;
    v2[128] = -65;
    v2[129] = 0;
    v2[130] = 0;
    v2[131] = 0;
    v2[132] = -114;
    v2[133] = -5;
    v2[134] = -98;
    v2[135] = -3;
    v2[136] = -29;
    v2[137] = -41;
    v2[138] = 39;
    v2[139] = 30;
    v2[140] = -65;
    v2[141] = 0;
    v2[142] = 0;
    v2[143] = 0;
    v2[144] = -2;
    v2[145] = 123;
    v2[146] = -98;
    v2[147] = -31;
    v2[148] = -29;
    v2[149] = -41;
    v2[150] = 119;
    v2[151] = 30;
    v2[152] = -65;
    v2[153] = 0;
    v2[154] = 0;
    v2[155] = 0;
    v2[156] = -1;
    v2[157] = 115;
    v2[158] = -100;
    v2[159] = -3;
    v2[160] = -29;
    v2[161] = -58;
    v2[162] = 115;
    v2[163] = 30;
    v2[164] = 63;
    v2[165] = 0;
    v2[166] = 0;
    v2[167] = 0;
    Interval.LowPart = 0xFE363C80u;
    Interval.HighPart = 0xFFFFFFFFu;
    test2(&Value);
    // 申请分页内存
    String.Buffer = (PWSTR)ExAllocatePool(PagedPool, 0x100u);
    String.MaximumLength = 0x100u;
    Destination.Buffer = (PWSTR)ExAllocatePool(PagedPool, 0x200u);
    Destination.MaximumLength = 0x7FFFu;           // 原来是0x7FFF
    v3 = RtlIntegerToUnicodeString(Value, 0x10u, &String);
    RtlAppendUnicodeToString(&Destination, L"\\??\\C:\\windows\\system32\\");
    RtlAppendUnicodeStringToString(&Destination, &String);
    RtlAppendUnicodeToString(&Destination, L".dll");
    ObjectAttributes.Length = 24;
    ObjectAttributes.RootDirectory = 0;
    ObjectAttributes.Attributes = 64;
    ObjectAttributes.ObjectName = &Destination;
    ObjectAttributes.SecurityDescriptor = 0;
    ObjectAttributes.SecurityQualityOfService = 0;
    v3 = ZwCreateFile(&Handle, 0x40000000u, &ObjectAttributes, &IoStatusBlock, 0, 0x80u, 2u, 3u, 0x20u, 0, 0);
    Buffer = ExAllocatePool(PagedPool, 0xA8u);
    memcpy(Buffer, v2, 0xA8u);
    ZwWriteFile(Handle, 0, 0, 0, &IoStatusBlock, Buffer, 0xA8u, 0, 0);
    KeDelayExecutionThread(0, 0, &Interval);
    ZwClose(Handle);
    //ZwDeleteFile(&ObjectAttributes);
    RtlFreeUnicodeString(&String);
    return 0;
}
 
// DPC例程是运行在DISPATCH_LEVEL级别,因为不能使用分页内存。
// 读写文件就会造成蓝屏 ,读写文件必须是分页内存
 
BOOLEAN DeferredRoutine(
    IN PKDPC pDpc,
    IN PVOID  DeferredContext,
    IN PVOID  SystemArgument1,
    IN PVOID  SystemArgument2
    )
{
    sub_11780();
 
    return KeSetTimer(&Timer, DueTime, &dpc);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegisterPath)
{
     
    PKDEFERRED_ROUTINE DeferredRoutine;
 
    sub_11780();
    KeInitializeTimer(&Timer);
 
    KeInitializeDpc(&dpc, DeferredRoutine, 0);
 
    DueTime.LowPart = 0xFE363C80u;
    DueTime.HighPart = 0xFFFFFFFFu;
 
    // 这里只会调用一次DPC例程
    KeSetTimer(&Timer, DueTime, &dpc);
 
 
    pDriverObject->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}


附件: Driver.zip (5.35 KB, 下载次数: 19)





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

小小淘气 发表于 2014-3-30 18:50
内核分析是??

点评

驱动级的  发表于 2014-3-30 20:35
brack 发表于 2014-3-30 18:08
头像被屏蔽
892644330 发表于 2014-3-30 18:54
一看到这看不懂的标题我第一个就猜到是lz  没想到是真的!
 楼主| JoyChou 发表于 2014-3-30 20:30
892644330 发表于 2014-3-30 18:54
一看到这看不懂的标题我第一个就猜到是lz  没想到是真的!

囧。这是怎么猜到的。
 楼主| JoyChou 发表于 2014-3-30 20:31

膜拜brack师傅
小小淘气 发表于 2014-3-31 13:24
知道了,膜拜啊
h_one 发表于 2014-4-1 22:03
直接 .writemem c:\FileName.dump 地址 LA8     

点评

恩。这个也可以,写py就是为了练习下py。 啊哈哈  发表于 2014-4-1 22:12
fanyu 发表于 2014-4-1 22:17
学习学习。。。
L4Nce 发表于 2014-4-1 22:47
  膜拜jc老师看雪一血
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-22 00:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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