Code archives/Miscellaneous/Metamorphic Code Example

This code has been declared by its author to be Public Domain code.

Download source code

Metamorphic Code Example by deus_deux2013
It is often useful or even necessary to create a program that modifies itself during runtime. Sometimes, this can entail evading a disassembler's presence in your code, or, on the very worse extreme, avoiding anti-virus detection algorithms. (Which is why this code is for educational purposes only!!) Anyways, this code is heavily documented (as best as I could explain it) and should provide a wholesome introduction to metamorphic coding and maybe even a little machine code.

NOTE: This example is intended for x86 machine code processing since blitz compiles to x86 architecture.
Graphics 1200,1080,0,2															;LET'S HAVE A NICE, BIG WINDOW FOR PLEEEENNNNTTTYYY OF OUTPUT, SHALL WE?

Global Kernel32PeekPokeBank=CreateBank(4) 										;BANK FOR MEMORY ACCESS (LONG NAME TO AVOID NAMING CONFLICTS...)

Global output% = 0																;USED TO SHOW HOW FUNCTIONS ARE BEING CALLED FROM THE C CODE, NOT BB
Global f																		;NEED THIS TO CALL BB FUNCTIONS FROM C (SYMBOLWRAP VARIABLE)
Local prog$,b,randFunc,randFuncPtr												;SOME LOCALS THAT WE WILL USE SHORTLY/LATER ON RESPECTIVELY
Local s = TCC_New()																;LETS SET UP A TCC BUILD ENVIRONMENT!
prog=prog+"int fptest ( int(*f)(int val) ) { return f(1); } "					;THE ACTUAL BB CALLING FUNCTION FROM C
prog=prog+"int fptest_w ( void * f ) { f = *((int*)(f)); return fptest(f); }"	;THIS IS JUST A WRAPPER TO GET THE ARGUMENT OUT OF THE PASSED BANK
TCC_SetOutputType(s, 0)															;OUTPUT THE C CODE TO MEMORY (COMPILING IN MEMORY)
TCC_CompileString(s, prog)														;COMPILE IT ALL!
TCC_Relocate(s)																	;CALL THIS TO LOAD THE MACHINE CODE INTO EXECUTABLE MEMORY!
f=TCC_GetSymbolWrap(s, "fptest_w")												;GET THE WRAPPER FUNCTION

startPointer = FunctionPointer()												;HERE WE ESTABLISH A STARTING POINT FOR OUR PROGRAM THROUGH THIS POINTER
Goto startskip
dummyFunction(0)
.startskip
Print "StartPointer : "+startPointer											;LET'S SEE WHAT WE ARE BEGINNING WITH...

Type memType																	;CLASS FOR HOLDING FUNCTIONS FROM MEMORY AND THEIR SIZES
	Field ptr%
	Field hexPtr$, hexPtr_1$, hexPtr_2$, hexPtr_3$, hexPtr_4$
	Field hexPtr_Rev%, hexPtr_Rev_1%, hexPtr_Rev_2%, hexPtr_Rev_3%, hexPtr_Rev_4%
	Field size%
	Field mem
End Type
Dim mem.memType(10)																;WE HAVE 9 DEMO FUNCTIONS IN TOTAL SO LETS ALLOCATE 10 CLASSES TO BE SAFE

For i=0 To 10																	;LOOP 'EM THROUGH!
	mem(i) = New memType														;CREATE THE CLASS IN MEMORY
	Select i																	;'i' DICTATES WHICH FUNCTION WE ARE GETTING THE POINTER OF
		Case 0:																	;HERE AND HEREAFTER, WE GET THE POINTER OF THE FUNCTION WE SKIP.
			mem(i)\ptr= FunctionPointer()
			Goto skip
			test0(0)
		Case 1:
			mem(i)\ptr = FunctionPointer()
			Goto skip
			test1(0)
		Case 2:
			mem(i)\ptr = FunctionPointer()
			Goto skip
			test2(0)
		Case 3:
			mem(i)\ptr = FunctionPointer()
			Goto skip
			test3(0)
		Case 4:
			mem(i)\ptr = FunctionPointer()
			Goto skip
			test4(0)
		Case 5:
			mem(i)\ptr = FunctionPointer()
			Goto skip
			test5(0)
		Case 6:
			mem(i)\ptr = FunctionPointer()
			Goto skip
			test6(0)
		Case 7:
			mem(i)\ptr = FunctionPointer()
			Goto skip
			test7(0)
		Case 8:
			mem(i)\ptr = FunctionPointer()
			Goto skip
			test8(0)
		Case 9:
			mem(i)\ptr = FunctionPointer()
			Goto skip
			test9(0)
		Case 10:																;THIS IS USED TO DETERMINE THE SIZE OF THE LAST FUNCTION ('test9')
			endPointer = FunctionPointer()
			Goto skip
			dummyFunction2(0)
	End Select
	.skip																		;WE END UP HERE AFTER EACH SKIP FROM ABOVE
	If i>0 And i<=9 Then														;IF WE AREN'T AT THE (FINAL FUNCTION)+1, [10], THEN...
		mem(i-1)\size = mem(i)\ptr - mem(i-1)\ptr								;THE SIZE OF A FUNCTION IN MEMORY IS DICTATED BY THE POINTER
																				;	LOCATED DIRECTLY AFTER IT MINUS THE POINTER TO THE FUNCTION
		mem(i-1)\mem = CreateBank(mem(i-1)\size)								;CREATE A BANK LARGE ENOUGH TO HOLD THE FUNCTION
		RtlMoveMemory2%(mem(i-1)\mem,mem(i-1)\ptr,mem(i-1)\size)				;COPY THE FUNCTION FROM MEMORY INTO THE BANK (IRONY HERE! :P)
		
		fp = WriteFile((i-1)+".txt")											;FOR DEBUGGING PURPOSES, LET'S OUPUT THE RAW MACHINE CODE OF THE
		For j=0 To mem(i-1)\size												;	FUNCTION INTO A TEXT FILE CORRESPONDING TO THE FUNCTION'S NUMBER
			WriteLine fp,Right$(Hex$(PeekB(mem(i-1)\ptr+j)),2)					;	THIS WILL HELP US SEE HOW THE MACHINE CODE BEHAVES IF WE PLUG
		Next																	;	IT INTO A DISSASSEMBLER (HTTP://ONLINEDISASSEMBLER.COM/ODAWEB/RUN_HEX)
		CloseFile fp															;	FOR EXAMPLE..
		
		Print "["+(i-1)+"] Function Size: "+mem(i-1)\size						;LETS PRINT WHAT THE FUNCTION SIZE IS AS WELL (ALSO DEBUGGING PURPOSES)
	Else If i=10 Then															;IF WE ARE ON THE (AMOUNT_OF_FUNCTIONS+1) THEN WE NEED TO USE 'endPointer'
																				;TO DETERMINE THE SIZE OF THE LAST FUNCTION ('test9')
		mem(i-1)\size  = endPointer - mem(i-1)\ptr								;ITS SIZE IS DETERMINED THE SAME WAY.. (FUNCTION_PTR_PROCEDING - FUNCTION_PTR)
		mem(i-1)\mem = CreateBank(mem(i-1)\size)								;CREATE A BANK LIKE WE DID FOR ALL THE OTHER FUNCTIONS...
		RtlMoveMemory2%(mem(i-1)\mem,mem(i-1)\ptr,mem(i-1)\size)				;STORE THE FUNCTION INTO THE BANK (STILL IRONIC!)
		
		fp = WriteFile((i-1)+".txt")											;DEBUGGING LIKE ABOVE...
		For j=0 To mem(i-1)\size
			WriteLine fp,Right$(Hex$(PeekB(mem(i-1)\ptr+j)),2)
		Next
		CloseFile fp
		
		Print "["+(i-1)+"] Function Size: "+mem(i-1)\size						;YOU GET THE DRIFT....
	End If
	Print "["+(i)+"] " + mem(i)\ptr												;WE ALSO PRINT THE FUNCTION'S POINTER FOR DEBUGGING PURPOSES
Next

Print ""
Print "================================="
Print ""

For i=0 To mem(9)\size-1								; LOOP THROUGH THE WHOLE OF THE FUNCTION'S ASM (MACHINE) CODE IN MEMORY.
	bt = PeekByte(mem(9)\mem,i)							; GET THE FUNCTION'S RAW ASM CODE...
	If bt = $e8 Then 									; $E8 = ASM FOR CALL
		times=times+1									; KEEP TRACK OF HOW MANY TIMES A CALL TO ANOTHER FUNCTION IS MADE.
		If times = 2 Then 								; PATCH THE SECOND CALL ($E8 x2)
			Print "FOUND AT "+(mem(9)\ptr)+" + "+i		; DEBUGGING PURPOSES
			n = (startPointer - (mem(9)\ptr + i)) + 5 	; ([WHERE WE WANT TO GO] - [WHERE THE ADDRESS IS NOW]) + [5 BYTES AFTERWARDS TO RETURN TO]
			PokeB(mem(9)\ptr+i+0,Int($E8)) 				; CALL (NOT REALLY NECESSARY TO RE-WRITE, BUT OH WELL! :P)
			PokeI(mem(9)\ptr+i+1,n) 					; POKE THE OFFSET TO CALL TO...
		End If
		;Print Hex$(PeekByte(mem(9)\mem,i+4)) + " " + Hex$(PeekByte(mem(9)\mem,i+3)) + " " + Hex$(PeekByte(mem(9)\mem,i+2)) + " " + Hex$((PeekByte(mem(9)\mem,i+1)-i-5))
	Else If bt = $c2 Then
		Exit
	End If
Next
Print "Found "+times+" CALLS..."

fp = WriteFile("9-PATCHED.txt")
For i=0 To mem(9)\size
	WriteLine fp,Right$(Hex$(PeekB(mem(9)\ptr+i)),2)
Next
CloseFile fp


;==========================================================================================================================
;==========================================================================================================================
; EXAMPLE OF CALLING A RANDOM FUNCTION (MAKES THINGS HARD FOR A DISSASEMBLER TO FOLLOW. PROGRAM CALLS CHANGE EVERY RUNTIME.
;==========================================================================================================================
;==========================================================================================================================
b=CreateBank(4)
SeedRnd MilliSecs()
randFunc = Rand(0,9)
randFuncPtr = mem(randFunc)\ptr
PokeInt b,0,randFuncPtr

Print "Function to Call        : "+randFunc
Print "Random Function Pointer : "+randFuncPtr
Print "Output% (before)        : "+output%
Print "Calling Faunction       : "+TCC_CallCFunc(f,b)  ;call the C function which in turn calls the passed function pointer... (round-about way of doing things...)
Print "Output% (after)         : "+output%
FreeBank b

Print ""
Print "================================="
Print ""
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================

;**************************************************************************************************************************

;==========================================================================================================================
;==========================================================================================================================
; EXAMPLE OF CALLING A FUNCTION THAT HAS ITS INTERNAL MEMORY (MACHINE CODE) CHANGED/PATCHED TO REDIRECT TO ANOTHER
;    ONE OF OUR FUNCTIONS. THIS IS A BAREBONES OR **VERY** BASIC EXAMPLE OF METAMORPHIC CODE.
;==========================================================================================================================
;==========================================================================================================================
output%=0
b=CreateBank(4)	
PokeInt b,0,mem(9)\ptr
Print "Function to Call        : mem(9)!"
Print "Random Function Pointer : "+mem(9)\ptr
Print "Output% (before)        : "+output%
Print "Calling Faunction       : "+TCC_CallCFunc(f,b)
Print "Output% (after)         : "+output%
FreeBank b

Print ""
Print "================================="
Print ""
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================

;**************************************************************************************************************************

;==========================================================================================================================
;==========================================================================================================================
; EXAMPLE OF MOVING FUNCTIONS AROUND IN MEMORY (PRESUMED SAME ALLOCATED SIZE FOR BOTH FUNCTIONS...) 
;
; DISSASSEMBLERS WILL NOT BE ABLE TO TELL WHAT FUNCTION IS ACTUALLY BEING CALLED IN THIS CASE EVEN IF THEY KNOW THE
;    DIFFERENT FUNCTION ADDRESSES... NOTE: THE FUNCTION'S ACTUAL CODE REMAINS UNCHANGED THOUGH SO DISAS'S MIGHT SEE IT'S 
;	 THE SAME CODE, JUST MOVED FROM ONE PLACE TO ANOTHER...
;
; FIRST, WE CALL THE UNTAMPERED FUNCTION AT STARTPOINTER. SECOND, WE CALL STARTPOINTER AFTER IT HAS BEEN FILLED WITH
;	 A DIFFERENT FUNCTION'S CODE (MACHINE CODE, THAT IS!) WHICH IN TURN EXECUTES THE NEW FUNCTION INSTEAD OF THAT WHICH
;	 WE HAD FIRST CALLED.
;
; @@@@@@@@@@@@
; @@@ NOTE @@@ -> THIS EXAMPLE FAILS WHEN EXTRA LINES OF CODE ARE ADDED INTO THIS PROGRAM'S SOURCE AND THEN COMPILED!!
; @@@@@@@@@@@@    SINCE THIS IS JUST A BASIC EXAMPLE, I WILL NOT GO INTO DEPTH ANY FURTHER.
;==========================================================================================================================
;==========================================================================================================================
output%=0
b=CreateBank(4)	
PokeInt b,0,startPointer
Print "Function to Call        : startPointer!"
Print "Function Pointer        : "+startPointer
Print "Output% (before)        : "+output%
Print "Calling Faunction       : "+TCC_CallCFunc(f,b) 	
Print "Output% (after)         : "+output%
FreeBank b

Print ""
Print "================================="
Print ""


Print (mem(0)\ptr-startPointer) + " VS " + mem(6)\size					;DEBUGGING PURPOSES! :)

If mem(6)\size <= (mem(0)\ptr-startPointer) Then						;LET'S GET STARTED. MAKE SURE THAT THE FUNCTION WE WANT TO MOVE WILL FIT INTO THE
																		;	SPACE AT STARTPOINTER
	oldProtection% = 0													;WE WILL NEED THIS LATER...
	Api_VirtualProtect(startPointer, mem(6)\size, 64, oldProtection)	;WE HAVE TO TELL THE KERNEL THAT WE WANT ACCESS TO THE MEMORY AT STARTPOINTER
	
	bnk = CreateBank(mem(6)\size)										;CREATE A BANK TO HOLD THE FUNCTION WE WANT TO MOVE TO STARTPOINTER
	RtlMoveMemory2%(bnk,mem(6)\ptr,mem(6)\size)							;MOVE THE FUNCTION AT THE GIVEN POINTER INTO THE NEWLY CREATED FUNCTION BANK
	
	For i=0 To BankSize(bnk)-1											;UNFORTUNATELY, WE HAVE TO PATCH EVERY 'CALL' COMMAND TO CORRECT THE OFFSETS IN
																		;	THE MACHINE CODE. (CALL'S REFER TO AN OFFSET FROM THE CURRENT MEMORY POSITION
																		;	TO THE FUNCTION THAT WE WANT TO GO TO)
		If PeekByte(bnk,i) = Int($E8) Then								;IF WE COME ACROSS A 'CALL' COMMAND IN THE MACHINE CODE...
			dp = PeekInt(bnk,i+1)										;GET IT'S ORIGINAL OFFSET (UNTAMPERED)
			;Print "OLD: "+dp
			n  = (dp - (startPointer - mem(6)\ptr))						;SET A NEW OFFSET RELATIVE TO THE NEW POSITION IN MEMORY (STARTPOINTER)
			;Print "NEW: "+n
			PokeInt(bnk,i+1,n)											;CORRECT THE OFFSET IN THE BANK THAT WILL BE UPDATED INTO STARTPOINTER.
		Else If PeekByte(bnk,i) = Int($C2) Then							;IF WE ENCOUNTER A 'RET' COMMAND...
			Exit														;EXIT MOTHA****AH!!!! :P
		End If															;YOU KNOW WHAT THIS DOES....
	Next																;THIS TOO, KEEP READING...
	
	Api_RtlMoveToMemory(startPointer,bnk,BankSize(bnk))					;MOVE THE PATCHED FUNCTION FROM THE BANK INTO THE GIVEN FUNCTION POINTER'S POSITION
	FreeBank bnk														;FREE THE BANK USED TO HOLD THE FUNCTION THAT WE PATCHED. WE WON'T NEED IT ANYMORE
	
	For i=(mem(6)\size+1) To (mem(0)\ptr-startPointer) 					;FOR THE REST OF THE BYTES LEFT OVER (SINCE WE HAVE EXTRA SPACE, POSSIBLY)
		PokeB(startPointer+i,$00)										;FILL IT ALL WITH $00'S (0'S) WHICH MEAN ABSOLUTELY NOTHING IN MACHINE CODE :)
	Next																;INCREMENTAL...
	
	Api_VirtualProtect(startPointer, mem(6)\size, oldprotection, 0)		;RESTORE THE READ/WRITE/EXECUTE PERMISSIONS ON THE MEMORY AT STARTPOINTER
End If																	;NOW WE'RE DONE. GRAB A COLD ONE, YOU DESERVE IT! :)

output%=0
b=CreateBank(4)	
PokeInt b,0,startPointer
Print "Function to Call        : startPointer (FILLED WITH ANOTHER FUNCTION)!"
Print "Function Pointer        : "+startPointer
Print "Output% (before)        : "+output%
Print "Calling Faunction       : "+TCC_CallCFunc(f,b) 							;call the C function which in turn calls the passed function pointer... (round-about way of doing things...)
Print "Output% (after)         : "+output%
FreeBank b
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================

;**************************************************************************************************************************

;==========================================================================================================================
;==========================================================================================================================
; THE REST OF THIS PROGRAM IS PRETTY SELF-EXPLANATORY... (DELETE TCC PROGRAM FROM MEMORY, PRINT A WAIT MESSAGE THEN
; 	WAIT FOR A KEY TO BE PRESSED FOR PROGRAM TERMINATION THEREAFTER.
;==========================================================================================================================
;==========================================================================================================================
TCC_Delete s	;Free the C code

Print ""
Print "================================="
Print "WAITKEY()"
WaitKey()
End
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================

;**************************************************************************************************************************

;==========================================================================================================================
;==========================================================================================================================
; THE FOLLLOWING FUNCTIONS ARE USED FOR THE EXAMPLES ABOVE. DO NOT MODIFY THEM UNLESS YOU REALLY HAVE A GRASP ON HOW THE
; ABOVE ROUTINES AND EXAMPLES WORK. MODIFICATION WITHOUT THIS KNOWLEDGE WILL LEAD TO MANY SLEEPLESS NIGHTS WITH COUNTLESS
; 'MEMORY ACCESS VIOLATION'S OR 'ILLEGAL INSTRUCTION'S OR, MY PERSONAL FAVORITE, 'UNKNOWN RUNTIME ERROR'S! SO PLEASE, JUST
; DO YOUR RESEARCH! :)
;==========================================================================================================================
;==========================================================================================================================
Function dummyFunction(argv%)
	VWait Rand(0,100)
	VWait Rand(0,100)
	VWait Rand(0,100)
	VWait Rand(0,100)
	Color 255,255,0
	Print "HELO! THIS IS SOME FILLER CODE"
	Delay 100
	Color 0,255,0
	Color 255,255,255
End Function

Function test0(argv%)		;Test function: returns a value and has a side-effect
	output% = argv%
	Color 255,0,0
	Print "FUNCTION0               : "+argv%
	;Print "FUNCTION                : "+PeekInt%(argv%,0)
	;b=CreateBank(4)
	;PokeInt b,0,PeekInt%(argv%,0)
	;TCC_CallCFunc(f,b) 
	;FreeBank b
	Color 255,255,255
End Function

Function test1(argv%)
	Local s = 1241512515
	Color 255,0,0
	Print "FUNCTION1               : "+argv%
	Print "FUNCTION1               : "+s
	Color 255,255,255
End Function

Function test2(argv%)
	Color 255,0,0
	Print "FUNCTION2               : "+argv%
	Print "FUNCTION2               : "+argv%
	Print "FUNCTION2               : "+argv%
	Color 255,255,255
End Function

Function test3(argv%)
	Color 255,0,0
	Print "FUNCTION3               : "+argv%
	Color 0,0,255
	Rect 0,0,100,200,1
	Color 255,255,255
End Function

Function test4(argv%)
	Color 255,0,0
	Print "FUNCTION4               : "+argv%
	Print "FUNCTION4               : "+CurrentDir$()
	Color 255,255,255
End Function

Function test5(argv%)
	Color 255,0,0
	Print "FUNCTION5               : "+argv%
	Print "FUNCTION5               : "+CurrentDate$()
	Color 255,255,255
End Function

Function test6(argv%)
	Color 255,0,0
	Print "FUNCTION6               : "+argv%
	Print "FUNCTION6               : "+CurrentTime$()
	Color 255,255,255
End Function

Function test7(argv%)
	Color 255,0,0
	Print "FUNCTION7               : "+argv%
	Print "FUNCTION7               : "+MilliSecs()
	Color 255,255,255
End Function

Function test8(argv%)
	Color 255,0,0
	Print "FUNCTION8               : "+argv%
	Print "FUNCTION8               : HABEUS CORPUS!"
	Color 255,255,255
End Function

Function test9(argv%)
	test1(0)
	;test5(125) ; PATCHED WITH test(1) EARLIER IN THE PROGRAM THROUGH ASM MODDING!
	Print "HELP!" ; ANY FUNCTION WITH A SINGLE PARAMETER CAN BE PATCHED HERE
	;Color 255,0,0
	;Print "FUNCTION9               : "+argv%
	;Color 0,255,0
	;Print "FUNCTION9               : TWO CAN TANGO!"
	;Color 255,255,255
End Function

Function allFunctions() ;This function is used to get the function pointers for all our functions from memory in the ASM code...
	test0(0)
	test1(0)
	test2(0)
	test3(0)
	test4(0)
	test5(0)
	test6(0)
	test7(0)
	test8(0)
	test9(0)
End Function

Function dummyFunction2(argv%)
	Delay Rand(0,200)
End Function
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================

;**************************************************************************************************************************

;==========================================================================================================================
;==========================================================================================================================
; THE FOLLOWING FUNCTION WAS TO BE USED TO GRAB ALL THE CALLS OUT OF A FUNCTION'S MACHINE CODE IN MEMORY AND REPORT THEM
; BACK TO THE MAIN PROGRAM. WOULD HAVE BEEN NEAT TO MAKE A FULL DISASSEMBLER THIS WAY... (FUTURE PROJECT ANYONE? :P)
;==========================================================================================================================
;==========================================================================================================================
Function getFunctionPointers(stPointer = 0)
	fp=WriteFile("AllFunctions.txt")
	Local i = 0, bt = 0, minus = -5
	If stPointer=0 Then Return
	While bt <> Int($C2) ;$C2 = RET
		bt = PeekB(stPointer+i)
		WriteLine fp,Right$(Hex$(bt),2)
		If bt = Int($E8) Then ;$E8 = CALL
			;WriteLine fp, "($E8) CALL TO : "+Right$(Hex$(PeekB(stPointer+i+4)),2) + " " + Right$(Hex$(PeekB(stPointer+i+3)),2) + " " + Right$(Hex$(PeekB(stPointer+i+2)),2) + " " + Right$(Hex$((PeekB(stPointer+i+1)+i+5)),2)
			;Print "IS       : "+Right$(Hex$(PeekB(stPointer+i+1)),2) + " " + Right$(Hex$(PeekB(stPointer+i+2)),2) + " " + Right$(Hex$(PeekB(stPointer+i+3)),2) + " " + Right$(Hex$(PeekB(stPointer+i+4)),2)
			;Print "SHOULD BE: "+Hex$(PeekB(stPointer+i+4)) + " " + Hex$(PeekB(stPointer+i+3)) + " " + Hex$(PeekB(stPointer+i+2)) + " " + Hex$(PeekB(stPointer+i+1))
			Print "CALL TO : "+Right$(Hex$(PeekB(stPointer+i+4)),2) + " " + Right$(Hex$(PeekB(stPointer+i+3)),2) + " " + Right$(Hex$(PeekB(stPointer+i+2)),2) + " " + Right$(Hex$((PeekB(stPointer+i+1)+i+5)),2)
			If (cnt <= 10 And cnt>1) Then
				mem(cnt-1)\hexPtr$ = Right$(Hex$(PeekB(stPointer+i+4)),2) + Right$(Hex$(PeekB(stPointer+i+3)),2) + Right$(Hex$(PeekB(stPointer+i+2)),2) + Right$(Hex$((PeekB(stPointer+i+1)+i+5)),2)
				mem(cnt-1)\hexPtr_1$ = Right$(Hex$(PeekB(stPointer+i+4)),2)
				mem(cnt-1)\hexPtr_2$ = Right$(Hex$(PeekB(stPointer+i+3)),2)
				mem(cnt-1)\hexPtr_3$ = Right$(Hex$(PeekB(stPointer+i+2)),2)
				mem(cnt-1)\hexPtr_4$ = Right$(Hex$((PeekB(stPointer+i+1)+i+5)),2)
				
				add% = stPointer + PeekI(stPointer+i+1) - i - 5
				mem(cnt-1)\hexPtr_Rev% = add% ;Right$(Hex$((PeekB(stPointer+i+1)+i+5)),2) + Right$(Hex$(PeekB(stPointer+i+2)),2) + Right$(Hex$(PeekB(stPointer+i+3)),2) + Right$(Hex$(PeekB(stPointer+i+4)),2)
				mem(cnt-1)\hexPtr_Rev_1% = PeekB(stPointer+i+1)+i;-5
				mem(cnt-1)\hexPtr_Rev_2% = PeekB(stPointer+i+2)
				mem(cnt-1)\hexPtr_Rev_3% = PeekB(stPointer+i+3)
				mem(cnt-1)\hexPtr_Rev_4% = PeekB(stPointer+i+4)
			End If
			cnt=cnt+1
		End If
		i=i+1
	Wend
	Print cnt+" CALL's FOUND!!"
	CloseFile fp
	Return
End Function
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================

;**************************************************************************************************************************

;==========================================================================================================================
;==========================================================================================================================
; THE FOLLOWING ARE BORROWED FUNCTIONS FROM THE BLITZBASIC ARCHIVES. THESE ARE NOT MY CREATION; YOU (AND I) SHOULD PAY
; A HUGE THANKS TO THOSE AT THE BLITZBASIC ARCHIVES FOR COMING UP WITH THIS CODE. THANK YOU :)
;==========================================================================================================================
;==========================================================================================================================
Function SaveBank(bank,file$ = "Bank.txt")
	fp = WriteFile(file$)
	WriteBytes(bank,fp,0,BankSize(bank))
	CloseFile fp
End Function

Function PeekB(address) ;PeekByte
	Api_RtlMoveToBank(Kernel32PeekPokeBank,address,1)
	Return PeekByte(Kernel32PeekPokeBank,0)
End Function

Function PeekS(address) ;PeekShort
	Api_RtlMoveToBank(Kernel32PeekPokeBank,address,2)
	Return PeekShort(Kernel32PeekPokeBank,0)
End Function

Function PeekI(address) ;PeekInteger
	Api_RtlMoveToBank(Kernel32PeekPokeBank,address,4)
	Return PeekInt(Kernel32PeekPokeBank,0)
End Function

Function PeekF#(address) ;PeekFloat
	Api_RtlMoveToBank(Kernel32PeekPokeBank,address,4)
	Return PeekFloat(Kernel32PeekPokeBank,0)
End Function

Function PokeB(address,value) ;PokeByte
	PokeByte Kernel32PeekPokeBank,0,value
	Api_RtlMoveToMemory(address,Kernel32PeekPokeBank,1)
End Function

Function PokeS(address,value) ;PokeShort
	PokeShort Kernel32PeekPokeBank,0,value
	Api_RtlMoveToMemory(address,Kernel32PeekPokeBank,2)
End Function

Function PokeI(address,value) ;PokeInteger
	PokeInt Kernel32PeekPokeBank,0,value
	Api_RtlMoveToMemory(address,Kernel32PeekPokeBank,4)
End Function

Function PokeF(address,value#) ;PokeFloat
	PokeFloat Kernel32PeekPokeBank,0,value#
	Api_RtlMoveToMemory(address,Kernel32PeekPokeBank,4)
End Function
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================
;==========================================================================================================================

;**************************************************************************************************************************
;END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*END*EN

Comments

deus_deux2013
Another note, you will need various kernel32 decl's that may be misnamed in the example above AND the TCC library/decls for blitz which can be found in the forum/archives . Here are the decls I used for the above code (all of these are not necessarily used...) :

.lib "Kernel32.dll"

Api_VirtualProtect(lpAddress%,flAllocationType%,flProtect%,flNewProect%) : "VirtualProtect"

;Win32 Decls, Memory Management Functions
RtlMoveMemory2%(Destination*,Source,Length) : "RtlMoveMemory"
Api_RtlMoveToBank(Destination*,Source,Length):"RtlMoveMemory"
Api_RtlMoveToMemory(Destination,Source*,Length):"RtlMoveMemory"
Api_RtlFillMemory(Destination,Length,Fill):"RtlFillMemory"
Api_RtlFillMemory_To(Destination*,Length,Fill):"RtlFillMemory"
Api_RtlFillMemory_From(Destination,Length,Fill*):"RtlFillMemory"
Api_RtlFillMemory_Ex(Destination*,Length,Fill*):"RtlFillMemory"
Api_RtlFillMemory_ExInt(Destination%,Length,Fill%):"RtlFillMemory"

;PeekPoke Module Decls
PeekB%(address)
PeekS%(address)
PeekI%(address)
PeekF#(address)
PokeB(address,value)
PokeS(address,value)
PokeI(address,value)
PokeF(address,value#)

RtlMoveMemory_To%(Destination%,Source*,Length%) : "RtlMoveMemory"
RtlMoveMemory_From%(Destination*,Source%,Length%) : "RtlMoveMemory"
RtlMoveMemory_Ex%(Destination%,Source%,Length%) : "RtlMoveMemory"
RtlMoveMemory(Destination*,Source*,Length%) : "RtlMoveMemory"





.lib "tcc.dll"

TCC_CallCFunc%(fPtr%, bData*) : "CallCFunc@8"
TCC_AddFile%(state%, filename$) : "tcc_add_file@8"
TCC_AddIncludePath%(state%, pathname$) : "tcc_add_include_path@8"
TCC_AddLibrary%(state%, libname$) : "tcc_add_library@8"
TCC_AddLibraryPath%(state%, pathname$) : "tcc_add_library_path@8"
TCC_AddSymbol%(state%, name$, value%) : "tcc_add_symbol@12"
TCC_AddSysIncludePath%(state%, pathname$) : "tcc_add_sysinclude_path@8"
TCC_CompileString%(state%, buffer$) : "tcc_compile_string@8"
TCC_DefineSymbol(state%, symbol$, value$) : "tcc_define_symbol@12"
TCC_Delete(state%) : "tcc_delete@4"
TCC_GetSymbolWrap%(state%, name$) : "tcc_get_symbol_wrap@8"
TCC_New%() : "tcc_new@0"
TCC_OutputFiles%(state%, filename) : "tcc_output_file@8"
TCC_Relocate%(state%) : "tcc_relocate@4"
TCC_Run%(state%, argc, argv*) : "tcc_run@12"
TCC_RunWrap%(state%, argc, argv*) : "tcc_run_wrap@12"
TCC_SetOutputType%(state%, outtype%) : "tcc_set_output_type@8"
TCC_UndefineSymbol(state%, symbol$) : "tcc_undefine_symbol@8"


MCP2013
Wow that's a very clever bit of code. Thanks for posting.


Code Archives Forum