⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sectionadd.asm

📁 一个小巧的 PE 文件区段添加工具
💻 ASM
字号:
.486
.model flat,stdcall
option casemap:none

include \tasm\win32.inc
include \tasm\extrn.inc

sSEH STRUCT
	OrgEsp            DD 0
	OrgEbp            DD 0
	SaveEip           DD 0
sSEH ENDS

pesection struc		; my version of IMAGE_SECTION_HEADER - simplified (same result)
	name		db 8 dup (0)
	vsz		dd 0
	voff		dd 0
	sz		dd 0
	off		dd 0
	junk		db 12 dup (0)
	char		dd 0
pesection ends

.DATA
filter  	db 'PE-executables (*.exe)',0,'*.exe',0,0
buffer		db MAX dup (0)
about		db 'Please Pick the Target File',0
notpe		db "Chosen file is not a Win32 PE file.",13,10
		db "Please choose another file",0
sec_name	db ".freddyk",0
OpenStruct:	dd 76, 0
		dd 0
		dd offset filter, 0,0,0, offset buffer, MAX, 0,0,0, offset about
		dd OFN_FILEMUSTEXIST or OFN_HIDEREADONLY or OFN_EXPLORER
		dd 0, 0, 0, 0, 0
fhandle		dd 0
fsize		dd 0
buff		dd 0

pMem		dd 0		; global alloc mem for file

peHdr		dd 0		; PE hdr offset
sections	dd 0		; original
image_sz	dd 0		; original

.CONST
MIN_KERNEL_SEARCH_BASE	equ 070000000h
MAX_API_STRING_LENGTH	equ 150
LENGTH			equ (offset section_end - offset section)
MAX			equ 255
SECTION_VSZ		equ 1000h
SECTION_PADD		equ 1000h
CHAR			equ 0E0000020h

.CODE
main:
	call 	GetOpenFileNameA, offset OpenStruct
	.if eax==0
		jmp	main_exit
	.endif
        call 	CreateFileA, offset buffer, GENERIC_READ or GENERIC_WRITE,\
		0,0, OPEN_EXISTING, 0,0
	.if eax==INVALID_HANDLE_VALUE
		jmp	main_exit
	.endif
	mov	fhandle, eax
	call	GetFileSize, fhandle, 0
	mov	fsize, eax
  	add	eax, SECTION_VSZ + SECTION_PADD

	call	GlobalAlloc, GMEM_FIXED OR GMEM_ZEROINIT, eax
	mov	pMem, eax

	call	ReadFile, fhandle, pMem, fsize, offset buff, 0
	mov	esi, pMem				; esi now points to file
	.if word ptr [esi] != IMAGE_DOS_SIGNATURE
		jmp	not_pe
	.endif
	add	esi, 03ch
	mov	eax, dword ptr [esi]
	mov	peHdr, eax
	sub	eax, 03ch
	add	esi, eax				; now points to PE HDR
	.if dword ptr [esi] != IMAGE_NT_SIGNATURE
		jmp	not_pe
	.endif

; adjust old PE Header
	assume	esi:ptr IMAGE_NT_HEADERS
	mov	ax, [esi].FileHeader.NumberOfSections
	mov	sections, eax
	inc	[esi].FileHeader.NumberOfSections		; sections
	mov	eax, [esi].OptionalHeader.AddressOfEntryPoint	; OEP entry
	add	eax, [esi].OptionalHeader.ImageBase		; base
	mov	oep, eax					; .CODE VARIABLE - needs writable
	mov	eax, [esi].OptionalHeader.SizeOfImage
	mov	image_sz, eax
	add	[esi].OptionalHeader.SizeOfImage, SECTION_VSZ	; image size
	mov	[esi].OptionalHeader.AddressOfEntryPoint, eax	; NEW OEP = OLD EOF
	assume	esi:

	mov	esi, pMem
	add	esi, peHdr				; now points to PE HDR
	add	esi, 0f8h				; now 1st section offset				

	mov	eax, 28h				; each section size=28h bytes
	mov	ecx, sections
	imul	ecx
	add	esi, eax				; now points to NEW last section

; add our section in
	assume 	esi:ptr pesection
	mov	dword ptr [esi].name, " kf."		; name
	mov	eax, SECTION_VSZ
	mov	[esi].vsz, eax				; virtual size
	mov	eax, image_sz
	mov	[esi].voff, eax				; virtual offset
	mov	eax, LENGTH
	mov	[esi].sz, eax				; real size
	mov	eax, fsize
	mov	[esi].off, eax				; real offset
	mov	eax, CHAR
	mov	[esi].char, eax				; characteristics (writeable...)
	assume	esi:

	mov	edi, pMem
	add	edi, fsize				; edi now points to EOF
	lea	eax, section
	xchg	esi, eax				; esi->new section
	mov	ecx, LENGTH
	rep	movsb

	call	SetFilePointer, fhandle, 0,0, FILE_BEGIN
	mov	eax, fsize
	add	eax, LENGTH
	call 	WriteFile, [fhandle], pMem, eax, offset buff, 0
close_file:
	call	CloseHandle, fhandle
	call	GlobalFree, pMem

	mov	oep, 0					; CODE VARIABLE - needs writable
	jmp	section

main_exit:
	call	ExitProcess, 0
not_pe:
	call	MessageBoxA, 0, offset notpe, offset about, MB_OK+MB_ICONSTOP
	jmp	close_file

; . All code from here on IS the new section - variables are relative to
; where we are (ebp+whatever) NOT accessed normally
; . The code from here is predominantly YODA (with some tasm fixes and code moving)
; so look at his src for more info
section:
	ASSUME 	FS:NOTHING
	pushad
	call	delta
delta:
	pop	ebp
	sub	ebp, offset delta	; ebp now holds where we are (basically)

	call 	GetKernelBase, dword ptr [esp+20h]
	or   	EAX, EAX
	jz   	QUIT
	mov  	[ebp+dwKernelBase], EAX

; collect all API's addresses needed here	
	lea	eax, [ebp+OFFSET szLoadLibrary]
	CALL 	GetProcAddr, [ebp+dwKernelBase], eax
	OR   	EAX, EAX
	JZ   	QUIT
	MOV  	[ebp+_LoadLibrary], EAX
	
	lea 	eax, [ebp+OFFSET szGetProcAddress]
	CALL 	GetProcAddr, [ebp+dwKernelBase], eax
	OR   	EAX, EAX
	JZ   	QUIT
	MOV  	[ebp+_GetProcAddress], EAX
	
	lea 	eax, [ebp+OFFSET szExitProcess]
	CALL 	GetProcAddr, [ebp+dwKernelBase], eax
	OR   	EAX, EAX
	JZ   	QUIT
	MOV  	[ebp+_ExitProcess], EAX
	
	lea 	eax, [ebp+OFFSET szUser32]
	CALL 	[ebp+_LoadLibrary], eax
	OR   	EAX, EAX
	JZ   	QUIT
	MOV  	[ebp+dwUserBase], EAX
	
	lea	eax, [ebp+OFFSET szMessageBox]
	CALL 	GetProcAddr, [ebp+dwUserBase], eax
	OR   	EAX, EAX
	JZ   	QUIT
	MOV  	[ebp+_MessageBox], EAX

; here is the actual code that executes like a normal prog (in the section)	
	lea 	eax, [ebp+OFFSET szInfoCap]
	CALL 	[ebp+_MessageBox], 0, eax, eax, MB_ICONINFORMATION OR MB_SYSTEMMODAL
	
QUIT:
	mov	eax, [ebp+oep]
	.if eax != 0			; are we on host ?
		mov	[esp+1ch], eax
		popad			; yup - back to original OEP
		jmp	eax
	.endif
	popad
	call	ExitProcess, 0		; no - use REAL call as still in original prog

szLoadLibrary		db "LoadLibraryA",0
szGetProcAddress	db "GetProcAddress",0
szExitProcess		db "ExitProcess",0
szUser32		db "user32",0
szMessageBox		db "MessageBoxA",0
szInfoCap		db "- Hello! -",0

_LoadLibrary		dd 0
_GetProcAddress		dd 0
_ExitProcess		dd 0
_MessageBox		dd 0

SEH 			sSEH <0>
dwKernelBase		dd 0
dwUserBase		dd 0
oep			dd 4010cch		; HOSTS OEP

; returns NULL in the case of an error
GetKernelBase:
	mov	edi, [esp+4]

	lea 	eax, [ebp+OFFSET SehHandler]
	push	eax
	push 	dword ptr FS:[0]
	lea	eax, [ebp+offset SEH]
	assume	eax:ptr sSEH
	MOV  	[eax].OrgEsp, ESP
	MOV  	[eax].OrgEbp, EBP	
	lea	ebx, [ebp+OFFSET ExceptCont]
	MOV  	[eax].SaveEip, ebx
	MOV  	FS:[0], ESP
	assume	eax:
	
	; start the search
	AND  	EDI, 0FFFF0000h		; wipe the LOWORD !
	.WHILE TRUE
	   	.IF WORD PTR [EDI] == IMAGE_DOS_SIGNATURE
	      		MOV  ESI, EDI
	      		ADD  ESI, [ESI+03Ch]
	      		.IF  DWORD PTR [ESI] == IMAGE_NT_SIGNATURE
	         		.BREAK
	      		.ENDIF
	   	.ENDIF
           	ExceptCont:
	   	SUB  EDI, 010000h
	   	.IF EDI < MIN_KERNEL_SEARCH_BASE
	      		MOV  EDI, 0BFF70000h
	      		.BREAK
	   	.ENDIF
	.ENDW
	XCHG 	EAX, EDI	
	
	POP  	dword ptr FS:[0]
	ADD  	ESP, 4
	ret	4

; returns address or NULL in the case of an error
GetProcAddr:
	lea 	eax, [ebp+OFFSET SehHandler]
	push	eax
	push 	dword ptr FS:[0]
	lea	eax, [ebp+offset SEH]
	assume	eax:ptr sSEH
	MOV  	[eax].OrgEsp, ESP
	MOV  	[eax].OrgEbp, EBP	
	lea	ebx, [ebp+OFFSET ExceptCont]
	MOV  	[eax].SaveEip, ebx
	MOV  	FS:[0], ESP
	assume	eax:
	
	; check PE Signarue
	MOV  	ESI, [esp+0ch]
	CMP  	WORD PTR [ESI], IMAGE_DOS_SIGNATURE
	JNZ 	@@BadExit
	ADD  	ESI, [ESI+03Ch]
	CMP  	DWORD PTR [ESI], IMAGE_NT_SIGNATURE
	JNZ 	@@BadExit
	
	; get the string length of the target Api
	MOV  	EDI, [esp+10h]
	MOV  	ECX, MAX_API_STRING_LENGTH
	XOR  	AL, AL
	REPNZ  SCASB
	MOV  	ECX, EDI
	SUB  	ECX, [esp+10h]				; ECX -> Api string length
	
	; trace the export table
	MOV  	EDX, [ESI+078h]				; EDX -> Export table
	ADD  	EDX, [esp+0ch]
	ASSUME 	EDX:PTR IMAGE_EXPORT_DIRECTORY
	MOV  	EBX, [EDX].AddressOfNames		; EBX -> AddressOfNames array pointer
	ADD  	EBX, [esp+0ch]
	XOR  	EAX, EAX				; EAX AddressOfNames Index
	.REPEAT
	   	MOV  	EDI, [EBX]
	   	ADD  	EDI, [esp+0ch]			; imagebase
	   	MOV  	ESI, [esp+10h]			; szAPI
	   	PUSH 	ECX				; save the api string length
	   	REPZ CMPSB
	   	.IF ZERO?
	      		ADD  ESP, 4
	      		.BREAK
	   	.ENDIF
	   	POP  	ECX
	   	ADD  	EBX, 4
	   	INC  	EAX   
	.UNTIL EAX == [EDX].NumberOfNames
	
	; did we found sth ?
	.IF EAX == [EDX].NumberOfNames
	   	JMP @@BadExit
	.ENDIF
	
	; find the corresponding Ordinal
	MOV  	ESI, [EDX].AddressOfNameOrdinals
	ADD  	ESI, [esp+0ch]
	PUSH 	EDX				; save the export table pointer
	MOV  	EBX, 2
	XOR  	EDX, EDX
	MUL  	EBX
	POP  	EDX
	ADD  	EAX, ESI
	XOR  	ECX, ECX
	MOV  	WORD PTR CX, [EAX]		; ECX -> Api Ordinal
	
	MOV  	EDI, [EDX].AddressOfFunctions	; get the address of the api
	XOR  	EDX, EDX
	MOV  	EBX, 4
	MOV  	EAX, ECX
	MUL  	EBX
	ADD  	EAX, [esp+0ch]
	ADD  	EAX, EDI
	MOV  	EAX, [EAX]
	ADD  	EAX, [esp+0ch]			; dwDllBase
	JMP  	@@ExitProc
	
	ASSUME 	EDX:	
		
@@BadExit:
   	XOR  	EAX, EAX   
@@ExitProc:
	POP  	dword ptr FS:[0]		; shutdown SEH frame
	ADD  	ESP, 4
	ret	8

SehHandler PROC C pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORD
	MOV 	EAX, pContext
	ASSUME 	EAX:PTR CONTEXT
	PUSH 	SEH.SaveEip
	POP  	[EAX].regEip
	PUSH 	SEH.OrgEsp
	POP  	[EAX].regEsp
	PUSH 	SEH.OrgEbp
	POP  	[EAX].regEbp
	MOV  	EAX, ExceptionContinueExecution
	RET
SehHandler ENDP

section_end:
end main

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -