好友
阅读权限30
听众
最后登录1970-1-1
|
本帖最后由 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. 解题
当逆出​源码后,就很简单了。在没逆出之前呢?
写了其他两个文件都是骗人的,我们着重看11780这个call干的事,F5后,双击V2变量。
定义一个大小为0xA8的数组,再重新F5,就可以看到是数组的形式,此时自己用C写到另外一个文件保存下来即可(fread fwrite等)。
如果不能F5,就只能对着机器码了。目的就是获取下面红框里面的数据。
这里用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即可。
得到图片
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)
|
|