http://bbs.pediy.com/showthread.php?t=104069按这个来写的,
RtlCopyMemory(pBuffer,ShellCode,size);到这一句就蓝了,找不到原因。。
sp3测试,
FuncType KeSuspendThread = NULL;
FuncType KeResumeThread = NULL; 都直接赋值了,就地windbg改下把。。
#include "ntifs.h"
typedef struct _X86_KTRAP_FRAME {
ULONG DbgEbp;
ULONG DbgEip;
ULONG DbgArgMark;
ULONG DbgArgPointer;
ULONG TempSegCs;
ULONG TempEsp;
ULONG Dr0;
ULONG Dr1;
ULONG Dr2;
ULONG Dr3;
ULONG Dr6;
ULONG Dr7;
ULONG SegGs;
ULONG SegEs;
ULONG SegDs;
ULONG Edx;
ULONG Ecx;
ULONG Eax;
ULONG PreviousPreviousMode;
ULONG ExceptionList;
ULONG SegFs;
ULONG Edi;
ULONG Esi;
ULONG Ebx;
ULONG Ebp;
ULONG ErrCode;
ULONG Eip;
ULONG SegCs;
ULONG EFlags;
ULONG HardwareEsp;
ULONG HardwareSegSs;
ULONG V86Es;
ULONG V86Ds;
ULONG V86Fs;
ULONG V86Gs;
} X86_KTRAP_FRAME, *PX86_KTRAP_FRAME;
typedef struct _MODULE_ENTRY {
LIST_ENTRY le_mod;
ULONG unknown[4];
ULONG base;
ULONG driver_start;
ULONG unk1;
UNICODE_STRING driver_Path;
UNICODE_STRING driver_Name;
//.......
} MODULE_ENTRY, *PMODULE_ENTRY;
typedef ULONG (*FuncType)(PETHREAD Thread);
FuncType KeSuspendThread = NULL;
FuncType KeResumeThread = NULL;
_declspec (naked) void ShellCode()
{
_asm
{
push eax
push 0
push 0
push 0
push 0
mov eax,0x77D66534 // jmp ds:12345678H, 绝对地址跳转
call eax
pop eax
// jmp ds:12345678H, 绝对地址跳转
_emit 0xEA
_emit 0x78
_emit 0x56
_emit 0x34
_emit 0x12
_emit 0x1B
_emit 0x00
}
}
VOID InjectShellCode(PETHREAD pThread,PEPROCESS pProcess)
{
ULONG i;
PX86_KTRAP_FRAME pTrapFrame;
PCLIENT_ID pCid;
OBJECT_ATTRIBUTES oa;
HANDLE hProcess;
NTSTATUS ntStatus;
_asm int 3
KeSuspendThread(pThread);
pTrapFrame = *(PX86_KTRAP_FRAME*)((ULONG)pThread + 0x134);
for (i=(ULONG)ShellCode; i<=(ULONG)ShellCode+0x20; ++i) //先修改好shellcode,在把它复制到进程的用户空间
{
if ( MmIsAddressValid((PVOID)i)
&&
MmIsAddressValid((PVOID)(i+3)) )
{
if ( *(PULONG)i == 0x12345678)
{
*(PULONG)i = pTrapFrame->Eip;
break;
}
}
}
//分配空间,复制shellcode到指定进程的用户空间
InitializeObjectAttributes(&oa,0,0,0,0);
pCid = (CLIENT_ID *)((ULONG)pThread + 0x1ec);//不用加4,或者-> //ntdll!_CLIENT_ID
//+0x000 UniqueProcess : Ptr32 Void
//+0x004 UniqueThread : Ptr32 Void
ntStatus = ZwOpenProcess(&hProcess, //hProcess是返回的句柄
PROCESS_ALL_ACCESS,
&oa, //要么指定oa,要么指定pCid
pCid); //这里指定了pCid的地址,就是进程ID的地址
if (NT_SUCCESS(ntStatus))
{
PVOID pBuffer = NULL;
SIZE_T size = 0x20;
ntStatus = NtAllocateVirtualMemory(hProcess,//hProcess是ZwOpenProcess的返回值
&pBuffer,//返回分配的地址值的指针
0,
&size, //返回实际分配的大小
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (NT_SUCCESS(ntStatus))
{
KAPC_STATE kapc;
KeStackAttachProcess(pProcess,&kapc);
RtlCopyMemory(pBuffer,ShellCode,size);
KeUnstackDetachProcess(&kapc);
pTrapFrame->Eip = (ULONG)pBuffer;
//修改用户空间的EIP为分配的shellcode地址
}
ZwClose(hProcess);
}
KeResumeThread(pThread);
}
VOID Inject(char* strProc, int len) {
PEPROCESS pProcess;
PETHREAD pThread;
PLIST_ENTRY pListHead, pNextEntry;
PLIST_ENTRY pThListHead, pThNextEntry;
_asm int 3;
pProcess = PsGetCurrentProcess();
pListHead = (PLIST_ENTRY)((ULONG)pProcess + 0x88); //ActiveProcessLinks
pNextEntry = pListHead;
// 先找到要注入的进程,通过ZwQuerySystemInformation来查找更稳定一些
// 不过本人很讨厌那个繁琐的函数……
do {
pProcess = (PEPROCESS)((ULONG)pNextEntry - 0x88);
if ( !_strnicmp((char*)pProcess + 0x174, strProc, len) ) {
DbgPrint("find process\n");
pThListHead = (PLIST_ENTRY)((ULONG)pProcess + 0x190); // ThreadListHead, XP SP2
pThNextEntry = pThListHead->Flink;
while ( pThNextEntry != pThListHead) {
// 接着查找符合条件的线程
UCHAR SuspendCount;
ULONG CrossThreadFlags;
pThread = (PETHREAD)((ULONG)pThNextEntry - 0x22c); // ThreadListEntry, XP SP2
SuspendCount = *(PUCHAR)((ULONG)pThread + 0x1b9);
CrossThreadFlags = *(PULONG)((ULONG)pThread + 0x248);
if( !SuspendCount && !(CrossThreadFlags & 0x13) )
{ // 非Suspend,非退出态,非内核线程
DbgPrint("find thread\n");
// 注入找到的线程
InjectShellCode(pThread,pProcess);
break;
}
pThNextEntry = pThNextEntry->Flink;
}
break;
}
pNextEntry = pNextEntry->Flink;
} while(pNextEntry != pListHead);
}
VOID OnUnload(IN PDRIVER_OBJECT o){
DbgPrint("unload!\n");
return;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
char *strProc = "try.exe";
_asm int 3
DriverObject->DriverUnload = OnUnload;
KeSuspendThread = (FuncType)0x804fcbdc;
KeResumeThread = (FuncType)0x804fc806;
Inject(strProc,strlen(strProc));
return STATUS_SUCCESS;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!