📄 sectionadd.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 + -