/KernelMessAgeBox.c
uty@uaty
#include <ntddk.h>
#ifdef DBG
#define u_DbgPrint(_x_) /
DbgPrint _x_;
#else
#define u_DbgPrint(_x_)
#endif
//--------------------------------------------------------------------
typedef enum _KAPC_ENVIRONMENT{
OriginalApcEnvironment,
AttachedApcEnvironment,
CurrentApcEnvironment
}KAPC_ENVIRONMENT;
typedef struct _KAPC_STATE{
LIST_ENTRY ApcListHead[2];
PEPROCESS Process;
UCHAR KernelApcInProgress;
UCHAR KernelApcPending;
UCHAR UserApcPending;
}KAPC_STATE,*PKAPC_STATE;
typedef struct _messAgepArA{
PCHAR lpText;
PCHAR lpCAption;
ULONG ulType;
}MESSAGEPARA,*PMESSAGEPARA;
//--------------------------------------------------------------------
NTSTATUS
uSetTheApc(
ULONG process,
ULONG threAd,
ULONG MAppedAddress,
PKEVENT pEvent,
PMESSAGEPARA pPArA
);
VOID
WorkThreAd(
IN PVOID pContext
);
VOID
KernelApcCAllBAck(
PKAPC Apc,
PKNORMAL_ROUTINE *NormalRoutine,
PVOID *NormalContext,
PVOID *SystemArgument1,
PVOID *SystemArgument2
);
VOID
OnUnloAd(
IN PDRIVER_OBJECT DriverObject
);
BOOLEAN
find_threAd(
OUT ULONG *process,
OUT ULONG *threAd
);
UserMessAgeBox(
PCHAR MessAgeText,
PCHAR MessAgeCAption,
ULONG ulType
);
UserMessAgeBox_end(
VOID
);
BOOLEAN
CheckVersion(
VOID
);
/* Function prototypes for APCs */
VOID
KeInitializeApc(
PKAPC Apc,
PKTHREAD Thread,
CCHAR ApcStateIndex,
PKKERNEL_ROUTINE KernelRoutine,
PKRUNDOWN_ROUTINE RundownRoutine,
PKNORMAL_ROUTINE NormalRoutine,
KPROCESSOR_MODE ApcMode,
PVOID NormalContext
);
BOOLEAN
KeInsertQueueApc(
PKAPC Apc,
PVOID SystemArgument1,
PVOID SystemArgument2,
UCHAR unknown
);
/* Function prototypes for AttAch process */
NTKERNELAPI VOID
KeStackAttachProcess(
IN PEPROCESS Process,
OUT PKAPC_STATE ApcState
);
NTKERNELAPI VOID
KeUnstackDetachProcess(
IN PKAPC_STATE ApcState
);
//--------------------------------------------------------------------
ULONG THREADLISTHEAD_OFFSET;
ULONG THREADLISTENTRY_OFFSET;
ULONG IMAGEFILENAME_OFFSET;
ULONG ACTIVEPROCESSLINKS_OFFSET;
ULONG USERAPCPENDING_OFFSET;
ULONG TCB_TEB_OFFSET;
BOOLEAN
KMessAgeBox(
PCHAR lpText,
PCHAR lpCAption,
ULONG ulType
)
{
PMESSAGEPARA pPArA = NULL;
HANDLE hThreAd = NULL;
NTSTATUS dwStAtus;
if(strlen(lpText)+strlen(lpCAption) > 98){ //two bytes for '/0'
DbgPrint("Text And CAption is too long,At most 100 bytes/n");
return FALSE;
}
pPArA = ExAllocatePool(PagedPool,sizeof(MESSAGEPARA));
if(pPArA == NULL){
DbgPrint("ExAllocAtePool fAiled/n");
return FALSE;
}
pPArA->lpText = lpText;
pPArA->lpCAption = lpCAption;
pPArA->ulType = ulType;
if(FALSE == CheckVersion()){
DbgPrint("os version not supported/n");
return FALSE;
}
dwStAtus = PsCreateSystemThread(&hThreAd,
(ACCESS_MASK)0,
NULL,
(HANDLE)0,
NULL,
WorkThreAd,
pPArA
);
if (!NT_SUCCESS(dwStAtus)){
DbgPrint("error when creAte the threAd/n");
ExFreePool(pPArA);
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------
BOOLEAN
CheckVersion(
VOID
)
{
RTL_OSVERSIONINFOEXW osversion = {0};
osversion.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
RtlGetVersion((RTL_OSVERSIONINFOW*)&osversion);
u_DbgPrint(("dwMAjorVersion: %d/n",osversion.dwMajorVersion));
u_DbgPrint(("dwMinorVersion: %d/n",osversion.dwMinorVersion));
u_DbgPrint(("dwBuildNumber: %d/n",osversion.dwBuildNumber));
u_DbgPrint(("wServicePAckMAjor: %d/n",osversion.wServicePackMajor));
u_DbgPrint(("wServicePAckMinor: %d/n",osversion.wServicePackMinor));
if( (osversion.dwMajorVersion == 5)
&& (osversion.dwMinorVersion == 1)
&& (osversion.dwBuildNumber == 2600)
&& (osversion.wServicePackMajor == 1)
//&& (osversion.wServicePackMinor == 0)
)
{
THREADLISTHEAD_OFFSET = 0x190;
THREADLISTENTRY_OFFSET = 0x22c;//both ThreAdListEntry in ETHREAD KTHREAD works;
IMAGEFILENAME_OFFSET = 0x174;
ACTIVEPROCESSLINKS_OFFSET = 0x88;
USERAPCPENDING_OFFSET = 0x4A;
TCB_TEB_OFFSET = 0x20;
return TRUE;
}
return FALSE;
}
//PMDL pMdl = NULL;
VOID
WorkThreAd(
IN PVOID pContext
)
{
ULONG process,threAd;
PKEVENT pEvent = NULL;
PMDL pMdl = NULL;
PVOID MAppedAddress = NULL;
ULONG size;
KAPC_STATE ApcStAte;
PMESSAGEPARA pPArA = NULL;
pPArA = (PMESSAGEPARA)pContext;
if (!find_threAd(&process,&threAd)){
DbgPrint("cAnnot find the right threAd/n");
PsTerminateSystemThread(STATUS_SUCCESS);
}
pEvent = ExAllocatePool(NonPagedPool,sizeof(KEVENT));
if(!pEvent){
DbgPrint("ExAllocatePool(pEvent) fAiled/n");
PsTerminateSystemThread(STATUS_SUCCESS);
}
memcpy((UCHAR*)UserMessAgeBox_end,pPArA->lpText,strlen(pPArA->lpText));
memset((UCHAR*)((ULONG)UserMessAgeBox_end+strlen(pPArA->lpText)),0,1);
memcpy((UCHAR*)((ULONG)UserMessAgeBox_end+strlen(pPArA->lpText) + 1),pPArA->lpCAption,strlen(pPArA->lpCAption));
memset((UCHAR*)((ULONG)UserMessAgeBox_end+strlen(pPArA->lpText) + 1 + strlen(pPArA->lpCAption)),0,1);
size = (UCHAR*)UserMessAgeBox_end - (UCHAR*)UserMessAgeBox + 100;//最多100个字节的MessAge
u_DbgPrint(("size: %d/n",size));
pMdl = IoAllocateMdl(
UserMessAgeBox,
size,
FALSE,
FALSE,
NULL
);
if(!pMdl){
ExFreePool (pEvent);
DbgPrint("IoAllocateMdl fAiled/n");
PsTerminateSystemThread(STATUS_SUCCESS);
}
__try{
MmProbeAndLockPages(
pMdl,
KernelMode,
IoWriteAccess
);
}
__except(EXCEPTION_EXECUTE_HANDLER){
IoFreeMdl(pMdl);
ExFreePool(pEvent);
DbgPrint("MmProbeAndLockPAges fAiled/n");
PsTerminateSystemThread(STATUS_SUCCESS);
}
u_DbgPrint(("process 0x%x/n",process));
KeStackAttachProcess((PEPROCESS)process,&ApcStAte);
__try{
MAppedAddress = MmMapLockedPagesSpecifyCache(
pMdl,
UserMode,
MmCached,
NULL,
FALSE,
NormalPagePriority
);
}
__except(EXCEPTION_EXECUTE_HANDLER){
MmUnlockPages(pMdl);
IoFreeMdl(pMdl);
ExFreePool(pEvent);
DbgPrint("MmMApLockedPagesSpecifyCAche fAiled/n");
PsTerminateSystemThread(STATUS_SUCCESS);
}
u_DbgPrint(("MAppedAddress: 0x%x/n",MAppedAddress));
if (!MAppedAddress){
KeUnstackDetachProcess(&ApcStAte);
MmUnlockPages(pMdl);
IoFreeMdl(pMdl);
ExFreePool(pEvent);
DbgPrint("MmMApLockedPAgesSpecifyCAche fAiled/n");
PsTerminateSystemThread(STATUS_SUCCESS);
}
//reuse his pPArAm,freed in APC->KernelRoutine
(ULONG)pPArA->lpText = (ULONG)MAppedAddress + (ULONG)((UCHAR*)UserMessAgeBox_end - (UCHAR*)UserMessAgeBox);
(ULONG)pPArA->lpCAption = (ULONG)MAppedAddress + (ULONG)((UCHAR*)UserMessAgeBox_end - (UCHAR*)UserMessAgeBox) + strlen(pPArA->lpText) + 1 ;
KeUnstackDetachProcess(&ApcStAte);
KeInitializeEvent(pEvent,NotificationEvent,FALSE);
uSetTheApc(process,threAd,(ULONG)MAppedAddress,pEvent,pPArA);
KeWaitForSingleObject(
pEvent,
Executive,
KernelMode,
FALSE,
NULL
);
u_DbgPrint(("ok free pEvent pMdl now/n"));
ExFreePool(pEvent);
MmUnlockPages(pMdl);
IoFreeMdl(pMdl);
PsTerminateSystemThread(STATUS_SUCCESS);
DbgPrint("Never be here /n");
}
//--------------------------------------------------------------------
NTSTATUS
uSetTheApc(
ULONG process,
ULONG threAd,
ULONG MAppedAddress,
PKEVENT pEvent,
PMESSAGEPARA pPArA
)
{
NTSTATUS dwStAtus = STATUS_SUCCESS;
PKAPC pkApc;
BOOLEAN bBool;
*((unsigned char *)threAd + USERAPCPENDING_OFFSET)=1; //
//*((unsigned char *)threAd+0x164)=1; //both of them works :>
pkApc = ExAllocatePool(NonPagedPool,sizeof(KAPC));
if (pkApc == NULL){
DbgPrint("error:ExAllocAtePool/n");
return STATUS_INSUFFICIENT_RESOURCES;
}
u_DbgPrint(("MessAgeText: 0x%x/n",pPArA->lpText));
KeInitializeApc(
pkApc,
(PKTHREAD)threAd,
OriginalApcEnvironment,
(PKKERNEL_ROUTINE)KernelApcCAllBAck,
NULL,
(PKNORMAL_ROUTINE)MAppedAddress,//UserApcCAllBAck,
UserMode,
(PVOID)pPArA
);
bBool = KeInsertQueueApc(pkApc,pEvent,(PVOID)pPArA->ulType,0); //ticky
if(bBool == FALSE){
DbgPrint("error:KeInsertQueueApc/n");
}
return STATUS_SUCCESS;
}
//--------------------------------------------------------------------
VOID
KernelApcCAllBAck(
PKAPC Apc,
PKNORMAL_ROUTINE *NormAlRoutine,
IN OUT PVOID *NormAlContext,
IN OUT PVOID *SystemArgument1,
IN OUT PVOID *SystemArgument2
)
{
PKEVENT pEvent;
PMESSAGEPARA pPArA;
u_DbgPrint(("NormAlContext: 0x%x/n",(ULONG)*NormAlContext));
pEvent = (PKEVENT)*SystemArgument1;
KeSetEvent(pEvent,IO_NO_INCREMENT,FALSE);
pPArA = (PMESSAGEPARA)*NormAlContext;
*SystemArgument1 = (PVOID)pPArA->lpCAption;
*SystemArgument2 = (PVOID)pPArA->ulType;
*NormAlContext = (PVOID)pPArA->lpText;
u_DbgPrint(("SystemArgument1: 0x%x/n",(ULONG)*SystemArgument1));
u_DbgPrint(("SystemArgument2: 0x%x/n",(ULONG)*SystemArgument2));
ExFreePool(pPArA);///free the pool AllocAted in KernelMessAgeBox
u_DbgPrint(("Freeing APC Object/n"));
ExFreePool(Apc); // free the kernel memory
}
//--------------------------------------------------------------------
BOOLEAN
find_threAd(
OUT ULONG *process,
OUT ULONG *threAd
)
{
ULONG eproc;
ULONG begin_proc;
ULONG ethreAd;
ULONG begin_threAd;
PLIST_ENTRY plist_Active_procs;
PLIST_ENTRY plist_threAd;
/*
#define IS_SYSTEM_THREAD(thread) /
(((thread)->Tcb.Teb == NULL) || /
(IS_SYSTEM_ADDRESS((thread)->Tcb.Teb)))
*/
eproc = (ULONG)PsGetCurrentProcess();
begin_proc = eproc;
while(1){
u_DbgPrint(("%s/n",(CHAR*)(eproc + IMAGEFILENAME_OFFSET)));
if (0 == strcmp((CHAR*)(eproc + IMAGEFILENAME_OFFSET),"explorer.exe")){
break;
}
else{
plist_Active_procs = (LIST_ENTRY*)(eproc + ACTIVEPROCESSLINKS_OFFSET);
eproc = (ULONG) plist_Active_procs->Flink;
eproc = eproc - ACTIVEPROCESSLINKS_OFFSET;
if(eproc == begin_proc) return FALSE;
}
}
plist_threAd = (LIST_ENTRY*)(eproc + THREADLISTHEAD_OFFSET);
ethreAd = (ULONG)plist_threAd->Flink;
ethreAd = ethreAd - THREADLISTENTRY_OFFSET;
u_DbgPrint(("threAd: 0x%x/n",ethreAd));
begin_threAd = ethreAd;
while(1){
//if !IS_SYSTEM_THREAD(threAd)
u_DbgPrint(("(*(ULONG*)((ULONG)ethreAd+TCB_TEB_OFFSET): 0x%x/n",*(ULONG*)((CHAR*)ethreAd+TCB_TEB_OFFSET)));
if( (*(ULONG*)((ULONG)ethreAd+TCB_TEB_OFFSET) != 0) &&
(*(ULONG*)((ULONG)ethreAd+TCB_TEB_OFFSET) <= 0x80000000 )
){
break;
}
else{
plist_threAd = (LIST_ENTRY*)(ethreAd + THREADLISTENTRY_OFFSET);
ethreAd = (ULONG)plist_threAd->Flink;
ethreAd = ethreAd - THREADLISTENTRY_OFFSET;
u_DbgPrint(("ethreAd: 0x%x/n",ethreAd));
if(ethreAd == begin_threAd) return FALSE;
}
}
*process = eproc;
*threAd = ethreAd;
return TRUE;
}
//--------------------------------------------------------------------
__declspec(naked)
UserMessAgeBox(
PCHAR MessAgeText,
PCHAR MessAgeCAption,
ULONG ulType
)
{
__asm{
push ebp
mov ebp, esp
}
__asm{
pushad
sub esp, 20 //存放得到的函数地址
jmp end
start:
pop edx // 指令表起始地址存放在 esp -> edx
push ebp//u 保存 下面这段程序用到了ebp
// ===== 从 PEB 中取得KERNEL32.DLL的起始地址 =====
//
// 输入:
// edx => 指令表起始地址 (不需要)
//
// 输出:
// eax => kernel32.dll起始地址
// edx => 指令表起始地址
mov eax, fs:0x30 // PEB
mov eax, [eax + 0x0c] // PROCESS_MODULE_INFO
mov esi, [eax + 0x1c] // InInitOrder.flink
lodsd
mov eax, [eax+8]
// ========== 定位GetProcAddress的地址 ==========
//
// 输入:
// eax => kernel32.dll起始地址
// edx => 指令表起始地址
//
// 输出:
// ebx => kernel32.dll起始地址
// eax => GetProcAddress地址
// edx => 指令表起始地址
mov ebx, eax // 取kernel32.dll的起始地址
mov esi, dword ptr [ebx+0x3C] //u 在e_lfanew中得到pe heAder
mov esi, dword ptr [esi+ebx+0x78] //u export directory rvA
add esi, ebx
mov edi, dword ptr [esi+0x20] //u struct _IMAGE_EXPORT_DIRECTORY 中AddressOfNames; // RVA from base of image
add edi, ebx
mov ecx, dword ptr [esi+0x14] //u AddressOfFunctions; // RVA from base of image
xor ebp, ebp
push esi
search_GetProcAddress:
push edi
push ecx
mov edi,dword ptr [edi]
add edi,ebx // 把输出函数名表起始地址存人edi
mov esi,edx // 指令表起始地址存入esi
//mov ecx,0Eh // 函数getprocAddress长度为0Eh
push 0xE
pop ecx
repe cmps byte ptr [esi],byte ptr [edi]
je search_GetProcAddress_ok
pop ecx
pop edi
add edi,4 ///
inc ebp
loop search_GetProcAddress
search_GetProcAddress_ok:
pop ecx
pop edi
pop esi
mov ecx, ebp
mov eax, dword ptr [esi+24h] //u AddressOfNameOrdinals; // RVA from base of image
add eax, ebx
shl ecx, 1
add eax, ecx
xor ecx, ecx
mov cx, word ptr [eax]
mov eax, dword ptr [esi+1Ch] //AddressOfFunctions; // RVA from base of image
add eax, ebx
shl ecx, 2
add eax, ecx
mov eax, dword ptr [eax]
add eax, ebx
pop ebp//u 保存
//--------------------------------------------------------------------
// ============ 调用函数解决api地址 ============
//
// 输入:
// ebx =>kernel32.dll起始地址
// eax =>GetProcAddress地址
// edx =>指令表起始地址
//
// 输出:
// edi =>函数地址base addr
// esi =>指令表当前位置
// edx =>GetProcAddress 地址
mov edi,edx
mov esi,edi
add esi,0xE // 0xE 跳过1个字符串"GetProcAddress"
// ============ 解决kernel32.dll中的函数地址 ============
mov edx,eax // 把GetProcAddress 地址存放在edx
push 0x1 // 需要解决的函数地址的个数 硬编码可以节省两个字节
pop ecx
mov edi, esp / get some spAce to edi
call locator_api_addr
// -------------加载user32.dll------------------------
add esi, 0xd // 0xd即"user32"前面那个字符串的长度,硬编码可以节省两个字节
push edx // edx是GetProcAddress 地址
push esi // 字符"user32"地址
call dword ptr [edi-4] // LoadLibraryA/????
// ============ 解决user32中的函数地址 ============
pop edx
mov ebx, eax // 将user32起始地址存放在ebx
push 0x1 // 函数个数
pop ecx // 函数个数 <-这种方式省两个字节
call locator_api_addr
add esi, 0xB // MessAgeBoxA 的长度为0xB
//--------------------------------------------------------------------
//
push ulType
push MessAgeCAption
push MessAgeText;
push 0
call dword ptr [edi-4]
jmp end_func
//--------------------------------------------------------------------
// ============ 解决api地址的函数 ============
//
// 输入参数:
// ecx 函数个数
// edx GetProcAddress 地址
// ebx 输出函数的dll起始地址
// esi 函数名表起始地址
// edi 保存函数地址的起始地址
locator_api_addr:
locator_space:
xor eax, eax
lodsb
test eax, eax // 寻找函数名之间的空格x00
jne locator_space
push ecx
push edx
push esi // 函数名
push ebx // 输出函数的dll起始地址
call edx
pop edx
pop ecx
stos dword ptr [edi]
loop locator_space
xor eax, eax
ret
//--------------------------------------------------------------------
// ================== 结束调用 ====================
end:
call start
__emit 'G'
__emit 'e'
__emit 't'
__emit 'P'
__emit 'r'
__emit 'o'
__emit 'c'
__emit 'A'
__emit 'd'
__emit 'd'
__emit 'r'
__emit 'e'
__emit 's'
__emit 's'
__emit 0
__emit 'L'
__emit 'o'
__emit 'a'
__emit 'd'
__emit 'L'
__emit 'i'
__emit 'b'
__emit 'r'
__emit 'a'
__emit 'r'
__emit 'y'
__emit 'A'
__emit 0
__emit 'u'
__emit 's'
__emit 'e'
__emit 'r'
__emit '3'
__emit '2'
__emit 0
__emit 'M'
__emit 'e'
__emit 's'
__emit 's'
__emit 'a'
__emit 'g'
__emit 'e'
__emit 'B'
__emit 'o'
__emit 'x'
__emit 'A'
__emit 0
end_func:
add esp,20
popad
}
__asm{
mov esp,ebp
pop ebp
ret //don't forget this :>
}
}
//--------------------------------------------------------------------
__declspec(naked) UserMessAgeBox_end(VOID)
{
__asm{
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0
__emit 0 //100
}
}