向doskey大牛学习!偶还是菜鸟只好找个驱动软西柿子来捏!
正好前几天中了一堆病毒马马.删除了N个EXE.最后发现驻留了一个SYS.拿了一个最弱的捏!其实直到我把源代码逆出来了为直.因为我这里暂时搞不到完整的Window _KPROCESS结构体.很有有关它的偏移地址给大家就解释不了了,也就是它的主要功能不知道了.以后在说吧!我是菜鸟!!!当一次学习逆向的过程!
大牛别踩!!!
IRP_MJ_CREATE和IRP_MJ_CLOSE,DriverUnload例程很简单可以看下面逆出的C代码。
关键IRP_MJ_DEVICE_CONTROL例程有点复杂和用户层通信.如下:
.text:000103DB ; int __stdcall sub_103DB(PDRIVER_OBJECT DeviceObject,PIRP Irp)
.text:000103DB sub_103DB proc near ; DATA XREF: start+5Eo
.text:000103DB
.text:000103DB Information = dword ptr -8
.text:000103DB ntStatus = dword ptr -4
.text:000103DB DeviceObject = dword ptr 8
.text:000103DB Irp = dword ptr 0Ch
.text:000103DB
.text:000103DB push ebp
.text:000103DC mov ebp, esp
.text:000103DE add esp, 0FFFFFFF8h
.text:000103E1 push esi
.text:000103E2 push edi
.text:000103E3 push ebx
.text:000103E4 mov [ebp+Information], 0
.text:000103EB mov [ebp+ntStatus], 0C0000001h
.text:000103F2 mov esi, [ebp+Irp]
.text:000103F5 mov eax, esi
.text:000103F7 mov eax, [eax+60h] ; IrpStack
.text:000103FA mov edi, eax
.text:000103FC mov eax, [edi+0Ch]
.text:000103FF push edi ; IrpStack
.text:00010400 cmp eax, 22E000h
.text:00010405 jnz loc_104C3
.text:00010405
.text:0001040B mov ecx, 34h
.text:00010410 cmp [edi+4], ecx
.text:00010413 jb loc_104B7
.text:00010413
.text:00010419 mov edi, [esi+0Ch] ; Irp->AssociatedIrp.SystemBuffer
.text:0001041C push edi ; VirtualAddress
.text:0001041D call MmIsAddressValid
.text:0001041D
.text:00010422 test al, al
.text:00010424 jz loc_10547
.text:00010424
.text:0001042A mov esi, [edi]
.text:0001042C movzx eax, byte ptr [edi+4]
.text:00010430 movzx edx, byte ptr [edi+5]
.text:00010434 mov VarA, eax
.text:00010439 mov VarB, edx
.text:0001043F push esi ; VirtualAddress__PUnKownData
.text:00010440 call MmIsAddressValid ; XXXXXXXXXXXXXXXXX
.text:00010440
.text:00010445 test al, al
.text:00010447 jz loc_10547
.text:00010447
.text:0001044D mov ecx, 34h
.text:00010452 push esi ; PUnKownData
.text:00010453 push edi ; inBuf
.text:00010454 rep movsb
.text:00010456 pop edi ; inBuf
.text:00010457 pop esi ; PUnKownData
.text:00010458 mov esi, [edi+24h]
.text:0001045B cmp esi, 0FFFFFFFFh
.text:0001045E jz short loc_104A1
.text:0001045E
.text:00010460 mov ebx, [edi+8]
.text:00010463 mov ebx, [ebx]
.text:00010465 mov ecx, UnKnowVariable_1
.text:0001046B mov ebx, [ecx+ebx]
.text:0001046E push ebx ; VirtualAddress
.text:0001046F call MmIsAddressValid
.text:0001046F
.text:00010474 or al, al
.text:00010476 jnz short loc_1047F
.text:00010476
.text:00010478 mov esi, 0FFFFFFFFh
.text:0001047D jmp short loc_104A1
.text:0001047D
.text:0001047F ; ---------------------------------------------------------------------------
.text:0001047F
.text:0001047F loc_1047F: ; CODE XREF: sub_103DB+9Bj
.text:0001047F mov eax, VarA
.text:00010484 mov ebx, [eax+ebx]
.text:00010487 push ebx ; VirtualAddress
.text:00010488 call MmIsAddressValid
.text:00010488
.text:0001048D or al, al
.text:0001048F jnz short loc_10498
.text:0001048F
.text:00010491 mov esi, 0FFFFFFFFh
.text:00010496 jmp short loc_104A1
.text:00010496
.text:00010498 ; ---------------------------------------------------------------------------
.text:00010498
.text:00010498 loc_10498: ; CODE XREF: sub_103DB+B4j
.text:00010498 add ebx, VarB
.text:0001049E mov esi, [ebx+esi*4]
.text:0001049E
.text:000104A1
.text:000104A1 loc_104A1: ; CODE XREF: sub_103DB+83j
.text:000104A1 ; sub_103DB+A2j
.text:000104A1 ; sub_103DB+BBj
.text:000104A1 mov [edi+30h], esi
.text:000104A4 mov [ebp+Information], 34h
.text:000104AB mov [ebp+ntStatus], 0
.text:000104B2 jmp loc_10547
.text:000104B2
.text:000104B7 ; ---------------------------------------------------------------------------
.text:000104B7
.text:000104B7 loc_104B7: ; CODE XREF: sub_103DB+38j
.text:000104B7 mov [ebp+ntStatus], 0C0000023h ; STATUS_BUFFER_TOO_SMALL
.text:000104BE jmp loc_10547
.text:000104BE
.text:000104C3 ; ---------------------------------------------------------------------------
.text:000104C3
.text:000104C3 loc_104C3: ; CODE XREF: sub_103DB+2Aj
.text:000104C3 cmp eax, 22E004h
.text:000104C8 jnz short loc_10547
.text:000104C8
.text:000104CA cmp dword ptr [edi+4], 18h
.text:000104CE jb short loc_10540
.text:000104CE
.text:000104D0 mov edi, [esi+0Ch]
.text:000104D3 push edi ; VirtualAddress
.text:000104D4 call MmIsAddressValid
.text:000104D4
.text:000104D9 test al, al
.text:000104DB jz short loc_10547
.text:000104DB
.text:000104DD mov esi, [edi]
.text:000104DF push esi ; VirtualAddress
.text:000104E0 call MmIsAddressValid
.text:000104E0
.text:000104E5 test al, al
.text:000104E7 jz short loc_10547
.text:000104E7
.text:000104E9 mov esi, [esi]
.text:000104EB push esi ; VirtualAddress
.text:000104EC call MmIsAddressValid
.text:000104EC
.text:000104F1 test al, al
.text:000104F3 jz short loc_10547
.text:000104F3
.text:000104F5 push esi
.text:000104F6 call IoThreadToProcess
.text:000104F6
.text:000104FB mov ebx, eax
.text:000104FD push ebx ; VirtualAddress
.text:000104FE call MmIsAddressValid
.text:000104FE
.text:00010503 test al, al
.text:00010505 jz short loc_10547 ; xxxxxxxxxxxxx
.text:00010505
.text:00010507 mov ecx, UnKnowVariable_2
.text:0001050D push dword ptr [ecx+esi]
.text:00010510 pop dword ptr [edi]
.text:00010512 mov ecx, UnKnowVariable_3
.text:00010518 push dword ptr [ecx+esi]
.text:0001051B pop dword ptr [edi+4]
.text:0001051E mov ecx, 10h
.text:00010523 mov esi, UnKnowVariable_4
.text:00010529 add esi, ebx
.text:0001052B add edi, 8
.text:0001052E rep movsb
.text:00010530 mov [ebp+Information], 18h
.text:00010537 mov [ebp+ntStatus], 0
.text:0001053E jmp short loc_10547
.text:0001053E
.text:00010540 ; ---------------------------------------------------------------------------
.text:00010540
.text:00010540 loc_10540: ; CODE XREF: sub_103DB+F3j
.text:00010540 mov [ebp+ntStatus], 0C0000023h
.text:00010540
.text:00010547
.text:00010547 loc_10547: ; CODE XREF: sub_103DB+49j
.text:00010547 ; sub_103DB+6Cj
.text:00010547 ; sub_103DB+D7j
.text:00010547 ; sub_103DB+E3j
.text:00010547 ; sub_103DB+EDj
.text:00010547 ; sub_103DB+100j ...
.text:00010547 pop edi ; IrpStack
.text:00010548 mov esi, [ebp+Irp]
.text:0001054B push [ebp+ntStatus]
.text:0001054E pop dword ptr [esi+18h]
.text:00010551 push [ebp+Information]
.text:00010554 pop dword ptr [esi+1Ch]
.text:00010557 push 0
.text:00010559 push [ebp+Irp]
.text:0001055C call IoCompleteRequest
.text:0001055C
.text:00010561 mov eax, [ebp+ntStatus]
.text:00010564 pop ebx
.text:00010565 pop edi
.text:00010566 pop esi
.text:00010567 leave
.text:00010568 retn 8
.text:00010568
.text:00010568 sub_103DB endp
.text:00010568
下面给出所有逆向出来的C源代码:里边用的数据类型很生硬,PVOID指针多处用到我都是根据寄存器和内存的长度才转化成特定的类型的.
#include <ntddk.h>
#include <ntdef.h>
#define dHook_CtlCode_A 0x22E000
#define dHook_CtlCode_B 0x22E004
VOID dHookUnloadDriver(
IN PDRIVER_OBJECT DriverObject);
NTSTATUS dHookCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS dHookDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSYSAPI PEPROCESS NTAPI
IoThreadToProcess(
IN PETHREAD Thread
);
UNICODE_STRING DeviceNameString;
UNICODE_STRING LinkDeviceNameString;
ULONG UnKnowVariable[4];
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
ULONG MajorVersion;
ULONG MinorVersion;
PDEVICE_OBJECT deviceObject = NULL;
NTSTATUS ntStatus=STATUS_DEVICE_CONFIGURATION_ERROR;
RtlInitUnicodeString( &DeviceNameString, L"\\Device\\devEnumHook2" );
RtlInitUnicodeString( &LinkDeviceNameString,L"\\DosDevices\\slEnumHook2");
ntStatus = IoCreateDevice(
DriverObject,
0,
&DeviceNameString,
FILE_DEVICE_DISK_FILE_SYSTEM,//8790H
FILE_DEVICE_SECURE_OPEN,
FALSE,
& deviceObject );
if (!NT_SUCCESS( ntStatus ))
{
return ntStatus;;
}
ntStatus = IoCreateSymbolicLink(
(PUNICODE_STRING) &LinkDeviceNameString,
(PUNICODE_STRING) &DeviceNameString
);
if (!NT_SUCCESS(ntStatus))
{
IoDeleteDevice(deviceObject);
return ntStatus;;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = dHookCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = dHookCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = dHookDeviceControl;
DriverObject->DriverUnload=dHookUnloadDriver;
PsGetVersion(&MajorVersion,&MinorVersion,NULL,NULL);
ntStatus=STATUS_SUCCESS;
if(MajorVersion!=5)
{
ntStatus=STATUS_DEVICE_CONFIGURATION_ERROR;
return ntStatus;
}
if(MinorVersion==0)
{
UnKnowVariable[0]=0x22C;//这些常量在dHook_CtlCode_B过程中调用修改Window进程结构_KPROCESS体用的.
UnKnowVariable[1]=0x124;//具体我这里也没有各个window 的内核_KPROCESS结构体详细文挡.
UnKnowVariable[2]=0x1E0;
UnKnowVariable[3]=0x1E4;
UnKnowVariable[4]=0x1FC;
}
else if(MinorVersion==1)
{
UnKnowVariable[0]=0x220;
UnKnowVariable[1]=0x130;
UnKnowVariable[2]=0x1EC;
UnKnowVariable[3]=0x1F0;
UnKnowVariable[4]=0x174;
}
else if(MinorVersion==2)
{
UnKnowVariable[0]=0x228;
UnKnowVariable[1]=0x14C;
UnKnowVariable[2]=0x1F4;
UnKnowVariable[3]=0x1F8;
UnKnowVariable[4]=0x154;
}
return ntStatus; ;
}
VOID dHookUnloadDriver(
IN PDRIVER_OBJECT DriverObject)
{
IoDeleteSymbolicLink(&LinkDeviceNameString);
IoDeleteDevice( DriverObject->DeviceObject );
}
NTSTATUS dHookCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
NTSTATUS dHookDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PVOID PUnKownData,PUnKownData_A,PUnKownData_B;
ULONG outBufLength,inBufLength;
PIO_STACK_LOCATION IrpStack;
char VarA,VarB, VarC;
PEPROCESS peProcess;
PVOID inBuf, PInfoProcess_A,PInfoProcess_B;
int counter=0 ;
ULONG UEnd;
NTSTATUS ntStatus= STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
inBuf = Irp->AssociatedIrp.SystemBuffer;
IrpStack = IoGetCurrentIrpStackLocation( Irp );
outBufLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;//[ebp+60H+4]
switch(IrpStack->Parameters.DeviceIoControl.IoControlCode )
{
case dHook_CtlCode_A:
if(outBufLength<0x34)
{
ntStatus= STATUS_BUFFER_TOO_SMALL;
break;
}
if(!MmIsAddressValid(inBuf))
{
break;
}
PUnKownData=(PVOID)((PLONG)inBuf)[0];//I/0包中前四个字节数据类型是另一个缓冲区的(指针)虚拟地址,因为下边用传数据用. PUnKownData
VarA=(char)((PCHAR)inBuf)[4];//取出I/0包第5个字节
VarB=(char)((PCHAR)inBuf)[5];//取出I/0包第6个字节
if(!MmIsAddressValid(PUnKownData))
{
break;
}
for(counter=0;counter<=34;counter++)
{
VarC=*(((PCHAR)PUnKownData)+counter); //PUnKownData做源缓冲区地址,inBuf做目源缓冲区地址
VarC=(char)((PCHAR)inBuf)[counter];//counter=34传34个字节
}
UEnd=(ULONG)((PLONG)inBuf)[24];//传输完毕,inBuf有了新的内容.要检测是否为0XFFFFFFF;
if(UEnd==-1)//用-1做end标志.
{
(ULONG)((PULONG)inBuf)[30]=-1;//把设置-1标志做结束
Irp->IoStatus.Information=0x34;//记录I/0包传的字节数量
ntStatus=STATUS_SUCCESS;//设置成功
break;
}
PUnKownData_A=(PVOID)((PULONG)inBuf)[8]; //inBuf[8]里又是一个指针的指针:PUnKownData_A
PUnKownData_B=(PVOID)((PULONG)*(PULONG)((*(PULONG)PUnKownData_A)+UnKnowVariable[1]));//取出一个指针给PUnKownData_B
if(!MmIsAddressValid(PUnKownData_A))
{
(ULONG)((PULONG)inBuf)[30]=-1;
break;
}
PUnKownData_B=(PULONG)*((PULONG)PUnKownData_B+(ULONG)VarA); //设置缓冲区的偏移地址加VarA
if(!MmIsAddressValid(PUnKownData_B))
{
(ULONG)((PULONG)inBuf)[30]=-1;
break;
}
PUnKownData_B=(PULONG)*((PULONG)PUnKownData_B+(ULONG)VarB); //缓冲区的偏移地址加VarB
(ULONG)((PULONG)inBuf)[30]=(ULONG)*((PULONG)PUnKownData_B+(ULONG)(UEnd*0x04));
break;
case dHook_CtlCode_B:
if(outBufLength< 0x18)
{
ntStatus= STATUS_BUFFER_TOO_SMALL;
break;
}
if(!MmIsAddressValid(inBuf))
{
break;
}
PUnKownData=(PVOID)*((PLONG)inBuf);
if(!MmIsAddressValid(PUnKownData))
{
break;
}
PUnKownData_A=(PVOID)*(PULONG)PUnKownData;
peProcess=IoThreadToProcess((PETHREAD)PUnKownData_A);//获取进程上下文
if(!MmIsAddressValid(peProcess))
{
break;
}
PInfoProcess_A=(PULONG)peProcess+UnKnowVariable[2];//修改进程
*(PULONG)inBuf=(ULONG)*(PULONG)PInfoProcess_A;
PInfoProcess_B=(PULONG)peProcess+UnKnowVariable[3];//修改进程
((PULONG)inBuf)[1]=(ULONG)*(PULONG)PInfoProcess_B;
PInfoProcess_A=(PULONG)peProcess+UnKnowVariable[4];//修改进程
PInfoProcess_B=(PULONG)inBuf+2;
for(counter=0;counter<=0x10;counter++)
{
VarC=*((PCHAR)PInfoProcess_A+counter);
*((PCHAR)PInfoProcess_A+counter)=VarC;
}
break;
}
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return ntStatus;
}
=============================================
用户把一个函数或变量的虚拟地址或指针写入I/0缓冲区.然后驱动读出里边数据,通信的数据类型可能有常量,变量,或指针.函数指针等.
方便期间各个举了个例子,用C写点.可以放在VC.60中编译通过.
[注意下面的例子仅仅是针对我上边那个IRP_MJ_DEVICE_CONTRL例程中一些各个类型访问用的]
char Data[256];
int a;
PVOID PUnKnowData;
PVOID PAdd;//定义函数指针
ULONG A=1;//偏移地址A
PUnKnowData=Data;
((PCHAR)PUnKnowData)[2]='1';//写个某个类型的常量
char c= ((PCHAR)PUnKnowData)[2];//读
((PLONG)PUnKnowData)[4]=(ULONG)&a; //写入某个变量地址
a=((PLONG)PUnKnowData)[4];//读
((PULONG)PUnKnowData)[4]=(ULONG)add;//写入某个函数地址
PAdd=(PVOID)((PULONG)PUnKnowData)[4];//读
(ULONG)(*(PULONG)PUnKnowData)=(ULONG)add;//指针方式写
PAdd=(PULONG)((ULONG)(*(PULONG)PUnKnowData));//读
(ULONG)(*((PULONG)PUnKnowData+A))=(ULONG)add; //用户把一个函数或变量的虚拟地址或指针写入I/0缓冲区任意++或--的偏移地址A中
PAdd=(PULONG)(*((PULONG)PUnKnowData+A)); //这里是驱动的读出是个反向操作.
=============================================
源代码在附件中.多谢指正Bug!
特此声明:感谢六楼的throb同学指点如下:
mov ecx, UniqueProcess ; 1E0h
push dword ptr [ecx+esi] ; esi = PETHREAD ; dt _ETHREAD -b;
; ethread + 1e0h = UniqueProcess
pop dword ptr [edi]; 从AssociatedIrp.Systembuffer返回UniqueProcess
mov ecx, UniqueThread ; 1E4h
push dword ptr [ecx+esi] ; ethread +1e4h =UniqueThread
pop dword ptr [edi+4] ; ThreadListEntry->Flink ?
mov ecx, 10h
mov esi, NameOffSet
add esi, ebx ; esi = Get ImageName
add edi, 8
rep movsb
mov dword ptr [ebp-8], 18h ; szInformation ,这个地方我的代码用 Undefine 弄坏了
mov dword ptr [ebp-4], 0 ; NtStatus
jmp short RetIoctlControl
那个地方不是dt _KPROCESS -b 吧,
用到的几个变量的结构:
dt _EPROCESS -b
dt _ETHREAD -b
_KPROCESS的结构可以用
dt _KPROCESS -b得到
---------------------------------------------@
我是阿赖耶识....