| 
		
	
	
	
		
	Posts: 28Threads: 2
 Joined: 27.01.2025
 
	
		
		
		27.01.2025, 09:18 PM 
(This post was last modified: 27.01.2025, 09:57 PM by Pierre Bellisle.)
		
	 
		Calling opcode string discussion was started at https://forum.powerbasic.com/forum/user-...discussion 
It is an answer To Anne on how to get and embed a function in a string and call it via "call dword" 
This one show particularly how to find the end of the function code by inserting data near the end.
 Code: 'follow up of https://forum.powerbasic.com/forum/user-to-user-discussions/programming/838669-calling-opcode-string-discussion
 #compile exe '#Win 10.04 (D:\Dev\Pow\Bas\Jose Roca\Forum\Jose\Windows API Headers\3.1.07\uz)#
 #dim all
 '#register none
 '%Unicode = 1
 #include "Win32Api.inc"
 
 #RESOURCE MANIFEST, 1, "XPTheme.xml"
 
 global hDlg as dword
 
 $AppName  = "call dword"
 %Static01 = 101
 %Button01 = 201
 
 declare function myfunction(byval var1 as long ,byval var2 as long) as long 'for call dword to use
 '_____________________________________________________________________________
 
 function HexView$(sString as string) as string 'HexString
 local  pByte   as byte pointer
 local  sBuffer as string
 local  sChar16 as string
 local  Looper  as long
 
 pByte = strptr(sString)
 do
 if (Looper and 15) = 00 then                 'Like MOD 16
 sBuffer = sBuffer & hex$(Looper, 4) & ": " 'Line number:
 elseif (Looper and 07) = 00 then             'Like MOD 8
 sBuffer = sBuffer & "- "                   'Middle dash
 end if
 
 if Looper < len(sString) then                'Add data
 sBuffer = sBuffer & hex$(@pByte[Looper], 2) & $spc
 else
 #if %def(%pb_win32) 'A to F have bigger width
 sBuffer = sBuffer & "     "                'Windows: No more data, fill with five spaces
 #else 'Use STDOUT in console
 sBuffer = sBuffer & "   "                  'Console: No more data, fill with three spaces
 #endif
 end if
 
 if (Looper and 15) = 15 then                 'End of 16 bytes line
 sChar16 = mid$(sString, Looper -14, 16) 'Next line replace non visible characters with dot
 replace any chr$(0,1,7,9,10,13,27 to 31,127,129,140,141,143,144,152,157) with "..................." in sChar16
 sBuffer = sBuffer & "; " & sChar16 & $crlf 'Add ascii string and CRLF
 if Looper >= len(sString) - 1 then exit do 'Job done
 end if
 
 incr Looper
 
 loop
 function = "Binary data lenght is" & str$(len(sString)) & " bytes." & $crlf & sBuffer
 
 end function
 '____________________________________________________________________________
 
 function Add2Numbers(byval var1 as long ,byval var2 as long) as long
 
 function = var1 + var2
 'function = var2
 
 exit function
 !DB &h12, &h34, &h56, &h78, &h9A, &hBC, &hDE, &hF0
 
 end function
 '_____________________________________________________________________________
 
 callback function DlgProc
 local sAsm        as string
 local sTerminator as string
 local pcode       as dword
 local pString     as dword
 local RetVal      as long
 local byteVal     as byte
 
 select case cbmsg
 
 case %wm_command
 select case cbctl
 
 case %Button01
 if cbctlmsg = %bn_clicked or cbctlmsg = 1 then
 'call original function
 sTerminator = chr$(&h12, &h34, &h56, &h78, &h9A, &hBC, &hDE, &hF0)
 pcode       = codeptr(Add2Numbers)
 RetVal      = 0
 call dword pcode using myfunction(2, 2) to RetVal
 MessageBox(hDlg, "CALL DWORD pcode result =" & str$(RetVal), $AppName, 266240)
 '-----------------------------------------------------------------------------
 'call a copy of original function using myfunction()
 sAsm = ""
 do
 sAsm &= peek$(pcode, 1) 'build sAsm byte by byte to be sure to not access out of bound memory
 incr pcode
 if instr(sAsm, sTerminator) then
 sAsm &= peek$(pcode, 16) 'get the end of function
 exit do
 end if
 loop
 RetVal = 0
 pString = strptr(sAsm)
 call dword pString using myfunction(2, 3) to RetVal
 MessageBox(hDlg, "CALL DWORD pString result =" & str$(RetVal), $AppName, 266240)
 '-------------------------------------------------------------------------------------------------
 'call a copy of original function without using myfunction()
 pString = strptr(sAsm)
 ! push 4
 ! push 2
 call dword pString 'Or you may use !call pcode
 ! mov RetVal, eax
 MessageBox(hDlg, "CALL DWORD ASM result =" & str$(RetVal), $AppName, 266240)
 '-------------------------------------------------------------------------------------------------
 'show the copy and original function code side to side
 MessageBox(hDlg, "pcode:" & $crlf & HexView$(peek$(codeptr(Add2Numbers), len(sAsm))) & $crlf & $crlf & $crlf & _
 "pString:" & $crlf & HexView$(peek$(codeptr(Add2Numbers), len(sAsm))), $AppName, 266240)
 end if
 
 end select
 
 end select
 
 end function
 '_____________________________________________________________________________
 
 function pbmain()
 
 dialog font "Segoe UI", 9
 dialog new %hwnd_desktop, $AppName, , , 150, 50, _
 %ws_caption or %ws_minimizebox or %ws_maximizebox or %ws_sizebox or %ws_sysmenu, %ws_ex_left to hDlg
 
 control add label, hDlg, %Static01, "codeptr() and strptr() test", 5, 10, 140, 11, %ss_center
 
 control add button, hDlg, %Button01, "test codeptr() and strptr()", 15, 25, 120, 15
 
 dialog show modal hDlg call DlgProc
 
 end function
 '_____________________________________________________________________________
 '
 
	
	
	
		
	Posts: 23Threads: 5
 Joined: 18.05.2024
 
	
		
		
		29.01.2025, 06:17 PM 
(This post was last modified: 29.01.2025, 06:52 PM by Anne Wilson.)
		
	 
		Thanks so much Pierre 
I have created the following program "Obfuscator Maker.bas" to create 
hex strings out of the Opcode string pointers to 3 functions, namely 
Multiplication , Matrix Multiply and Addition.  
These 3 functions hex strings are to be written out to 3 text files.  
The hex strings can be subsequently used for deployment into another 
 new program without the need to declare these functions in this  
new program.
 
Two of these functions work --> Multiplication of 2 numbers and Addition 
of 3 numbers.   Unfortunately the MatrixMultiply function fail  and it GPF ?
 
Not sure why  the MatrixMultiply function fail but it works well directly  without  
using the CALL DWORD opcode string
 Code: ' Obfuscator Maker.bas
 ' Inspired by Pierre
 ' https://forum.powerbasic.com/forum/user-to-user-discussions/programming/838669-calling-opcode-string-discussion?p=838671#post838671
 ' http://pump.richheimer.de/showthread.php?tid=21&pid=78#pid78
 
 ' This program makes obfuscator hex strings of a given function
 ' and save this string into a txt file, which can then be deployed
 ' to other programs
 ' It is used to test out functions before deployment
 
 
 #COMPILE EXE
 #DIM ALL
 
 #INCLUDE "Win32Api.inc"
 
 
 GLOBAL hDlg AS DWORD
 
 ' pointers params for the Multiplication function
 GLOBAL pStringMult , pcodeMult  AS DWORD
 GLOBAL sAsmMult      AS STRING
 
 
 ' pointers params for the Matrix Multiply function
 GLOBAL pStringMat , pcodeMat  AS DWORD
 GLOBAL sAsmMat      AS STRING
 
 ' pointers params for the Addition function
 GLOBAL pStringAdd , pcodeAdd  AS DWORD
 GLOBAL sAsmAdd      AS STRING
 
 
 
 $AppName    = " Obfuscator Maker "
 %Lab01      = 101
 %ButtonMult = 201
 %ButtonMat  = 202
 %ButtonAdd  = 203
 
 
 
 'for call dword usage -- for Masquerading  the real functions
 ' for the multiplication function
 DECLARE FUNCTION MasqueradeMt(BYVAL var1 AS LONG ,BYVAL var2 AS LONG) AS LONG
 ' Function declaration string
 $DecFnStr1 = "DECLARE FUNCTION MasqueradeMt(BYVAL var1 AS LONG ,BYVAL var2 AS LONG) AS LONG"
 
 
 DECLARE FUNCTION MasqueradeM(  ) AS STRING
 $DecFnStr2 = "DECLARE FUNCTION MasqueradeM(  ) AS STRING "
 
 
 
 ' for the Add function
 DECLARE FUNCTION MasqueradeA(BYVAL var1 AS LONG , _
 BYVAL var2 AS LONG, BYVAL var3 AS LONG) AS LONG
 ' Function declaration string
 $DecFnStr3 = "DECLARE FUNCTION MasqueradeA(BYVAL var1 AS LONG ," + _
 " BYVAL var2 AS LONG, BYVAL var3 AS LONG) AS LONG"
 
 
 
 
 
 ' place your function here ********************
 
 
 '===================================
 ' a simple multiplication function
 FUNCTION Mult2Numbers(BYVAL var1 AS LONG , BYVAL var2 AS LONG) AS LONG
 
 
 FUNCTION = var1 * var2
 EXIT FUNCTION
 ' End of function marker to indicate the final end of function
 ' http://pump.richheimer.de/showthread.php?tid=21&pid=78#pid78
 !DB &h12, &h34, &h56, &h78, &h9A, &hBC, &hDE, &hF0
 
 END FUNCTION
 
 
 
 '===================================
 ' a simple addition function
 FUNCTION Add3Numbers(BYVAL var1 AS LONG , BYVAL var2 AS LONG ,_
 BYVAL var3 AS LONG) AS LONG
 
 
 FUNCTION = var1 + var2 + var3
 EXIT FUNCTION
 ' End of function marker to indicate the final end of function
 ' http://pump.richheimer.de/showthread.php?tid=21&pid=78#pid78
 !DB &h12, &h34, &h56, &h78, &h9A, &hBC, &hDE, &hF0
 
 END FUNCTION
 
 
 
 '=====================================
 ' a complex function
 FUNCTION MatrixMultiply(  ) AS STRING
 ' see the answers in
 ' https://www.mathsisfun.com/algebra/matrix-multiplying.html
 '
 LOCAL i, j, k AS LONG
 LOCAL sum AS LONG
 
 '  Note that do NOT use global as cannot pass **************
 '  global arguments into a CALL DWORD function
 ' for the Matrix Multiply function
 LOCAL   MResult() AS LONG
 LOCAL   MatA()    AS LONG
 LOCAL   MatB()    AS LONG
 ' setup the matrices -- one time only
 REDIM  MatA(5)       ' 2x3 matrix
 REDIM  MatB(5)       ' 3x2 matrix
 REDIM  MResult(4)    ' 2x2 matrix
 '    Assignments of values as in
 '    https://www.mathsisfun.com/algebra/matrix-multiplying.html
 ARRAY ASSIGN MatA() = 1,2,3,4,5,6
 ARRAY ASSIGN MatB() = 7,8,9,10,11,12
 
 
 FOR i = 0 TO 1
 FOR j = 0 TO 1
 sum = 0
 FOR k = 0 TO 2
 sum = sum + MatA(i * 3 + k) * MatB(k * 2 + j)
 NEXT k
 MResult(i * 2 + j) = sum
 NEXT j
 NEXT i
 
 '? " sum " + str$(sum)
 
 ' the result string
 LOCAL ResStr AS STRING
 LOCAL ResVal AS LONG
 ResStr = ""
 FOR i = 0 TO 1
 FOR j = 0 TO 1
 ResVal =  MResult(i * 2 + j)
 ResStr += " " + STR$(ResVal)
 NEXT j
 NEXT i
 
 
 FUNCTION = ResStr
 ' End of function marker to indicate the final end of function
 !DB &h12, &h34, &h56, &h78, &h9A, &hBC, &hDE, &hF0
 END FUNCTION
 
 
 
 
 
 
 '==================================
 '  Setup functions' parameters
 SUB SetupFunParams
 
 '  Get ready with these function params
 
 ' for the Mult2Numbers function
 pcodeMult = CODEPTR(Mult2Numbers)
 '   Obtain the pointer to the ASM string for the
 '   Mult2Numbers function
 Obtain_PtrStringGen( pcodeMult , pStringMult , sAsmMult , 1 )
 
 
 
 ' for the Matrix Multiply function  -->  Fail ***************************
 pcodeMat = CODEPTR(MatrixMultiply)
 '   Obtain the pointer to the ASM string for the
 '   Matrix Multiply function
 Obtain_PtrStringGen( pcodeMat , pStringMat , sAsmMat , 2 )
 
 
 
 ' for the Addition function
 pcodeAdd = CODEPTR(Add3Numbers)
 '   Obtain the pointer to the ASM string for the
 '   Addition function
 Obtain_PtrStringGen( pcodeAdd , pStringAdd , sAsmAdd , 3 )
 
 END SUB
 
 
 
 
 '============================
 FUNCTION PBMAIN()
 #REGISTER NONE
 
 ' Setup functions' parameters
 SetupFunParams
 
 DIALOG FONT "Segoe UI", 9
 DIALOG NEW %HWND_DESKTOP, $AppName, , , 200, 140, _
 %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_SIZEBOX _
 OR %WS_SYSMENU, %WS_EX_LEFT TO hDlg
 
 CONTROL ADD LABEL, hDlg, %Lab01 , "Obfuscate using String Pointers to functions",_
 15, 10, 190, 11
 
 CONTROL ADD BUTTON, hDlg, %ButtonMult ,  "Mult function strptr()",_
 55, 35, 90, 15
 
 CONTROL ADD BUTTON, hDlg, %ButtonMat, "Matix multiply function strptr()",_
 55, 65, 120, 15
 
 CONTROL ADD BUTTON, hDlg, %ButtonAdd ,  "Add function strptr()",_
 55, 95, 90, 15
 
 
 
 DIALOG SHOW MODAL hDlg CALL DlgProc
 
 END FUNCTION
 
 
 
 
 
 
 '====================================
 CALLBACK FUNCTION DlgProc
 
 
 LOCAL RetVal  AS LONG
 
 
 LOCAL dispst AS STRING
 
 SELECT CASE CB.MSG
 
 CASE %WM_INITDIALOG
 
 
 CASE %WM_COMMAND
 SELECT CASE CB.CTL
 
 CASE %ButtonMult
 ' compute -- You need to TEST the function out
 ' so that it is accurate before deployment
 IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
 RetVal = 0
 ' using string pointer to point to the Mult2Numbers function
 CALL DWORD pStringMult USING  MasqueradeMt(519, 23) TO RetVal
 MessageBox(hDlg, "CALL DWORD pStringMult result of 519 and 23 =" & _
 STR$(RetVal), "String Pointer to Mult function", 266240)
 END IF
 
 
 
 CASE %ButtonMat
 ' compute the
 IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
 dispst = ""
 ' using string pointer to point to the MatrixMultiply function --> Fail ***************
 CALL DWORD pStringMat USING  MasqueradeM() TO dispst
 
 ' Call the real function as a test the function first
 ' to ensure correct computation  --> this works
 ' dispst = MatrixMultiply()
 
 MessageBox(hDlg, "CALL DWORD pStringMat  with matrix result :   " + $CRLF+  dispst , _
 "String Pointer to Matrix Multiply function ", 266240)
 END IF
 
 
 
 CASE %ButtonAdd
 ' compute -- You need to TEST the function out
 ' so that it is accurate before deployment
 IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
 RetVal = 0
 ' using string pointer to point to the Add3Numbers function
 CALL DWORD pStringAdd USING  MasqueradeA(19,325, 93) TO RetVal
 MessageBox(hDlg, "CALL DWORD pStringAdd result of 19 , 325 and 93 =" & _
 STR$(RetVal), "String Pointer to Add function", 266240)
 END IF
 
 
 
 END SELECT
 
 END SELECT
 
 END FUNCTION
 
 
 
 
 
 
 
 '=========================
 '  Obtain the pointer to the ASM string
 '  for General usage.
 '  and creates the text file for the wsAsm string
 '  gpar = indicator for a specific function
 SUB Obtain_PtrStringGen( BYVAL gpcode AS DWORD, _
 BYREF WpString AS DWORD ,BYREF wsAsm  AS STRING , gpar AS LONG )
 LOCAL byteVal AS BYTE
 
 LOCAL sTerminator AS STRING
 sTerminator = CHR$(&h12, &h34, &h56, &h78, &h9A, &hBC, &hDE, &hF0  )
 
 
 ' clear off any prev values
 WpString = 0
 wsAsm    = ""
 
 
 ' Assemble WsAsm byte by byte
 ' and looking for the end of function marker
 DO
 WsAsm &= PEEK$(gpcode, 1)
 INCR gpcode
 IF INSTR(WsAsm, sTerminator) THEN
 'found the end of function marker
 WsAsm &= PEEK$(gpcode, 16)
 EXIT DO
 END IF
 LOOP
 
 
 
 ' Gets the pointer to the wanted function's ASM string
 WpString = STRPTR(WsAsm)
 
 ' Convert to hex as it is printable
 LOCAL HxStrAsm , OrigAsm AS STRING
 HxStrAsm = HexDump(WsAsm)
 SLEEP 10
 OrigAsm  = DeHex(HxStrAsm)
 SLEEP 10
 
 LOCAL filNamAsm , DecFn AS STRING
 filNamAsm = "Output WsAsm " + STR$(gpar) +  ".txt"
 
 ' gets the correct declaration function name
 ' according to gpar
 SELECT CASE gpar
 CASE  1
 DecFn = $DecFnStr1
 CASE  2
 DecFn = $DecFnStr2
 CASE  3
 DecFn = $DecFnStr3
 END SELECT
 
 ' clear off old file
 KILL  filNamAsm
 '  prints out the WsAsm string to a text file
 LOCAL bf AS LONG
 bf = FREEFILE
 OPEN filNamAsm FOR OUTPUT AS #bf
 PRINT #bf, WsAsm
 PRINT #bf,
 PRINT #bf,
 PRINT #bf,HxStrAsm
 PRINT #bf,
 PRINT #bf,
 PRINT #bf, OrigAsm
 PRINT #bf,
 PRINT #bf,
 PRINT #bf, "Masquerade Function declaration string"
 PRINT #bf, DecFn
 
 CLOSE #bf
 
 END SUB
 
 
 
 
 
 
 
 
 '======================================
 '  Provide a string of Hex characters
 '  for a given string sgBuf
 FUNCTION HexDump(sgBuf AS STRING) AS STRING
 LOCAL sbh AS ISTRINGBUILDERA
 sbh = CLASS "STRINGBUILDERA"
 LOCAL ihd AS LONG
 FOR ihd = 1 TO LEN(sgBuf)
 sbh.add  HEX$(ASC(MID$(sgBuf,ihd,1)),2)
 NEXT
 FUNCTION = sbh.string
 END FUNCTION
 
 
 
 '===================================================
 FUNCTION DeHex(Inpt AS STRING) AS STRING
 LOCAL i AS INTEGER
 LOCAL Xdh AS STRING
 
 FOR i = 1 TO LEN(Inpt) STEP 2
 Xdh = Xdh & CHR$(VAL("&H" & MID$(Inpt, i, 2)))
 NEXT i
 DeHex = Xdh
 END FUNCTION
 
Pierre 
What's the purpose of this line of code 
 Code: !DB &h12, &h34, &h56, &h78, &h9A, &hBC, &hDE, &hF0
 Is it a marker of some sort to mark the end of a function ?   
 how does it work ?  does it do some action ?
	 
	
	
	
		
	Posts: 28Threads: 2
 Joined: 27.01.2025
 
	
	
		>Is it a marker of some sort to mark the end of a function ?  
 Exactly,  sTerminator is the equivalent string that will be search for in the Button01 section.
 
	
	
	
		
	Posts: 28Threads: 2
 Joined: 27.01.2025
 
	
	
		Anne, I've made some quick test.Seems the problem is with a function that internally manipulate dynamic string.
 More study to do
 
	
	
	
		
	Posts: 23Threads: 5
 Joined: 18.05.2024
 
	
		
		
		02.02.2025, 10:17 PM 
(This post was last modified: 02.02.2025, 10:22 PM by Anne Wilson.)
		
	 
		Thank You Pierre 
I think I found the issue in regards to this Calling Dword using Opcodes :
 
This method cannot be used  when the target function has the following
 
   1.  Calling an external PB statement such as STR$()  , ARRAY ASSIGN ,   and even  to the power  statement 
        such as  Ab ^ 2    
        You need to make it as  Ab * Ab 
   2.  No string manipulation  ,   array function or statements 
   3.  Calling external API functions  such as GetModuleHandle()   ,  IsFile()  etc 
   Otherwise it will result in GPF
 
 Therefore, calling Opcode string method should be limited  to simple  additions, multiplications 
  and divisions of variables.  For  power ,  use  Ab * Ab * Ab   instead of  Ab^3  
  Surprisingly ,  we can still use SELECT CASE .... END SELECT  statements 
 
 As for the example of Obfuscator Maker.bas  it is finally listed as,  noting that 
 I have commented out the CALL DWORD statements  which fail 
 Code: ' Obfuscator Maker.bas
 ' Inspired by Pierre
 ' https://forum.powerbasic.com/forum/user-to-user-discussions/programming/838669-calling-opcode-string-discussion?p=838671#post838671
 ' http://pump.richheimer.de/showthread.php?tid=21&pid=78#pid78
 
 ' This program makes obfuscator hex strings of a given function
 ' and save this string into a txt file, which can then be deployed
 ' to other programs
 ' It is used to test out functions before deployment
 
 
 #COMPILE EXE
 #DIM ALL
 
 #INCLUDE "Win32Api.inc"
 
 
 GLOBAL hDlg AS DWORD
 
 ' pointers params for the Multiplication function
 GLOBAL pStringMult , pcodeMult  AS DWORD
 GLOBAL sAsmMult      AS STRING
 
 
 ' pointers params for the Matrix Multiply function
 GLOBAL pStringMat , pcodeMat  AS DWORD
 GLOBAL sAsmMat      AS STRING
 
 ' pointers params for the Addition function
 GLOBAL pStringAdd , pcodeAdd  AS DWORD
 GLOBAL sAsmAdd      AS STRING
 
 
 ' pointers params for the Compute Area and Volume function
 GLOBAL pStringCAV , pcodeCAV  AS DWORD
 GLOBAL sAsmCAV      AS STRING
 
 ' pointers params for the Check SandBoxie function
 GLOBAL pStringCSB , pcodeCSB  AS DWORD
 GLOBAL sAsmCSB      AS STRING
 
 
 $AppName    = " Obfuscator Maker "
 %Lab01      = 101
 %ButtonMult = 201
 %ButtonMat  = 202
 %ButtonAdd  = 203
 %ButtonCAV  = 204
 %ButtonCSB  = 205
 
 ' End of function marker to indicate the final end of function
 MACRO FN_END  = ! DB &HEB, &H08, &H56, &H4D, &H45, &H4E, &H44, &H31, &H00, &H00
 
 
 'for call dword usage -- for Masquerading  the real functions
 ' for the multiplication function
 DECLARE FUNCTION MasqueradeMt(BYVAL var1 AS LONG ,BYVAL var2 AS LONG) AS LONG
 ' Function declaration string
 $DecFnStr1 = "DECLARE FUNCTION MasqueradeMt(BYVAL var1 AS LONG ,BYVAL var2 AS LONG) AS LONG"
 
 
 
 'for the Matrix multiplication function
 DECLARE FUNCTION MasqueradeMatM(BYREF R1 AS LONG ,BYREF R2 AS LONG ,_
 BYREF  R3 AS LONG , BYREF R4 AS LONG  ) AS LONG
 ' Function declaration string
 $DecFnStr2 = "DECLARE FUNCTION MasqueradeMatM( BYREF R1 AS LONG ,BYREF R2 AS LONG , " + _
 " BYREF  R3 AS LONG , BYREF R4 AS LONG  ) AS LONG "
 
 
 
 ' for the Add function
 DECLARE FUNCTION MasqueradeA(BYVAL var1 AS LONG , _
 BYVAL var2 AS LONG, BYVAL var3 AS LONG) AS LONG
 ' Function declaration string
 $DecFnStr3 = "DECLARE FUNCTION MasqueradeA(BYVAL var1 AS LONG , " + _
 " BYVAL var2 AS LONG, BYVAL var3 AS LONG) AS LONG"
 
 
 
 ' for the compute Area and Volume function
 DECLARE FUNCTION Masq_AV(BYVAL v1 AS DOUBLE , BYVAL v2 AS DOUBLE , _
 BYVAL V3 AS LONG ) AS DOUBLE
 $DecFnStr4 = "DECLARE FUNCTION Masq_AV(BYVAL V1 AS DOUBLE , BYVAL V2 AS DOUBLE ," + _
 " BYVAL V3 AS LONG  ) AS DOUBLE"
 
 
 ' for the Check SandBoxie function
 DECLARE FUNCTION MasqueradeCSB() AS LONG
 ' Function declaration string
 $DecFnStr5 = "DECLARE FUNCTION MasqueradeCSB() AS LONG
 
 
 
 
 
 
 
 ' place your functions here ********************
 
 
 '===================================
 ' a simple multiplication function
 FUNCTION Mult2Numbers(BYVAL var1 AS LONG , BYVAL var2 AS LONG) AS LONG
 
 
 FUNCTION = var1 * var2
 EXIT FUNCTION
 ' End of function marker to indicate the final end of function
 FN_END
 
 END FUNCTION
 
 
 
 
 
 '===================================
 ' Compute Area and Volume function
 ' make sure that the input values are DOUBLE
 ' as its results are DOUBLE
 ' No need interpretation by PB -- No external function must be used
 ' Ensure that the computation is straight forward without
 ' interpretation using external function
 FUNCTION Compute_AreaVol(BYVAL V1 AS DOUBLE , BYVAL V2 AS DOUBLE , _
 BYVAL V3 AS LONG   ) AS DOUBLE
 
 LOCAL Mav AS DOUBLE
 Mav = 0
 
 SELECT CASE V3
 CASE 1
 '  Area of a rectangle
 Mav = V1 * V2
 
 CASE 2
 ' Area of a circle with v1 = radius
 ' note that we cannot have V1 ^ 2
 ' no external function for it to evaluate
 Mav = 3.1416 * V1 * V1
 
 CASE 3
 ' Circumference of circle with v1 = radius
 Mav = 2* 3.1416 * V1
 
 CASE 4
 '  Volume of a cone, v1 = radius, v2 = height
 Mav = 3.1416 * V1 * v1 * (v2 /3)
 
 END SELECT
 
 FUNCTION = Mav
 EXIT FUNCTION
 ' End of function marker to indicate the final end of function
 FN_END
 
 END FUNCTION
 
 
 
 
 
 
 '===================================
 ' a simple addition function
 FUNCTION Add3Numbers(BYVAL var1 AS LONG , BYVAL var2 AS LONG ,_
 BYVAL var3 AS LONG) AS LONG
 
 
 FUNCTION = var1 + var2 + var3
 EXIT FUNCTION
 ' End of function marker to indicate the final end of function
 FN_END
 
 END FUNCTION
 
 
 
 
 
 '===================================
 ' Check SandBoxie function
 FUNCTION IsSandboxie() AS LONG
 LOCAL hModule AS DWORD
 LOCAL SBChk AS LONG
 SBChk = 0
 ' check for module  SbieDll.dll
 hModule = GetModuleHandle("SbieDll.dll")
 IF hModule <> 0 THEN
 SBChk = 1
 END IF
 FUNCTION = SBChk
 EXIT FUNCTION
 ' End of function marker to indicate the final end of function
 FN_END
 
 END FUNCTION
 
 
 
 
 
 '=====================================
 ' a complex function
 FUNCTION MatrixMultiply( BYREF R1 AS LONG ,BYREF R2 AS LONG , _
 BYREF R3 AS LONG , BYREF R4 AS LONG  ) AS LONG
 ' see the answers in
 ' https://www.mathsisfun.com/algebra/matrix-multiplying.html
 '
 LOCAL i, j, k AS LONG
 LOCAL sum AS LONG
 
 '  Note that do NOT use global as cannot pass **************
 '  global arguments into a CALL DWORD function
 ' for the Matrix Multiply function
 '  LOCAL   MResult() AS LONG
 '  LOCAL   MatA()    AS LONG
 '  LOCAL   MatB()    AS LONG
 ' setup the matrices -- one time only
 '   REDIM  MatA(0 to 5)       ' 2x3 matrix
 '  REDIM  MatB(0 to 5)       ' 3x2 matrix
 '  REDIM  MResult(0 to 3)    ' 2x2 matrix
 
 
 DIM  MatA(0 TO 5)    AS LOCAL LONG     ' 2x3 matrix
 DIM  MatB(0 TO 5)    AS LOCAL LONG     ' 3x2 matrix
 DIM  MResult(0 TO 3) AS LOCAL LONG    ' 2x2 matrix
 
 
 '    Assignments of values as in
 '    https://www.mathsisfun.com/algebra/matrix-multiplying.html
 '   ARRAY ASSIGN MatA() = 1,2,3,4,5,6
 '   ARRAY ASSIGN MatB() = 7,8,9,10,11,12
 '   No longer use external PB function for array assignment
 '   assigns the array directly
 MatA(0) = 1
 MatA(1) = 2
 MatA(2) = 3
 MatA(3) = 4
 MatA(4) = 5
 MatA(5) = 6
 
 MatB(0) = 7
 MatB(1) = 8
 MatB(2) = 9
 MatB(3) = 10
 MatB(4) = 11
 MatB(5) = 12
 
 LOCAL ak , bk , asq , bsq , msq , ck AS LONG
 
 FOR i = 0 TO 1
 FOR j = 0 TO 1
 sum = 0
 FOR k = 0 TO 2
 asq = i * 3 + k
 bsq = k * 2 + j
 ak  = MatA(asq)
 bk  = MatB(bsq)
 ck  = ak*bk
 sum = sum + ck
 NEXT k
 msq = i * 2 + j
 MResult(msq) = sum
 NEXT j
 NEXT i
 
 
 '   Do not use external PB function like STR$()
 '   so we return with arguments values for the MResult() array
 '   There are 4 elements of MResult() and they are
 R1 =  MResult(0)
 R2 =  MResult(1)
 R3 =  MResult(2)
 R4 =  MResult(3)
 
 
 EXIT FUNCTION
 FN_END
 
 END FUNCTION
 
 
 
 
 
 
 '==================================
 '  Setup functions' parameters into Opcode strings
 SUB SetupFunParams
 
 '  Get ready with these function params
 
 ' for the Mult2Numbers function
 pcodeMult = CODEPTR(Mult2Numbers)
 '   Obtain the pointer to the ASM string for the
 '   Mult2Numbers function
 Obtain_PtrStringGen( pcodeMult , pStringMult , sAsmMult , 1 )
 
 
 
 ' for the Matrix Multiply function
 pcodeMat = CODEPTR(MatrixMultiply)
 '   Obtain the pointer to the ASM string for the
 '   Matrix Multiply function
 Obtain_PtrStringGen( pcodeMat , pStringMat , sAsmMat , 2 )
 
 
 
 ' for the Addition function
 pcodeAdd = CODEPTR(Add3Numbers)
 '   Obtain the pointer to the ASM string for the
 '   Addition function
 Obtain_PtrStringGen( pcodeAdd , pStringAdd , sAsmAdd , 3 )
 
 
 
 ' for the Compute Area and Volume function
 pcodeCAV = CODEPTR(Compute_AreaVol)
 '   Obtain the pointer to the ASM string for the
 '   Compute Area and Volume function
 Obtain_PtrStringGen( pcodeCAV , pStringCAV , sAsmCAV , 4 )
 
 
 
 ' for the Check SandBoxie function
 pcodeCSB = CODEPTR(IsSandboxie)
 '   Obtain the pointer to the ASM string for the
 '   IsSandboxie function
 Obtain_PtrStringGen( pcodeCSB , pStringCSB , sAsmCSB , 5 )
 
 END SUB
 
 
 
 
 '============================
 FUNCTION PBMAIN()
 #REGISTER NONE
 
 ' Setup functions' parameters
 SetupFunParams
 
 DIALOG FONT "Segoe UI", 9
 DIALOG NEW %HWND_DESKTOP, $AppName, , , 250, 220, _
 %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_SIZEBOX _
 OR %WS_SYSMENU, %WS_EX_LEFT TO hDlg
 
 CONTROL ADD LABEL, hDlg, %Lab01 , "Obfuscate using String Pointers to functions",_
 15, 10, 190, 11
 
 CONTROL ADD BUTTON, hDlg, %ButtonMult ,  "Mult function strptr()",_
 55, 35, 90, 15
 
 CONTROL ADD BUTTON, hDlg, %ButtonMat, "Matix multiply function strptr()",_
 55, 65, 120, 15
 
 CONTROL ADD BUTTON, hDlg, %ButtonAdd ,  "Add function strptr()",_
 55, 95, 90, 15
 
 CONTROL ADD BUTTON, hDlg, %ButtonCAV ,  "Comp Area Vol function strptr()",_
 55, 125, 100, 15
 
 CONTROL ADD BUTTON, hDlg, %ButtonCSB ,  "Check SandBoxie function strptr()",_
 55, 155, 110, 15
 
 
 DIALOG SHOW MODAL hDlg CALL DlgProc
 
 END FUNCTION
 
 
 
 
 
 
 '====================================
 CALLBACK FUNCTION DlgProc
 
 
 LOCAL RetVal  AS LONG
 
 
 LOCAL dispst AS STRING
 
 SELECT CASE CB.MSG
 
 CASE %WM_INITDIALOG
 
 
 
 CASE %WM_COMMAND
 SELECT CASE CB.CTL
 
 CASE %ButtonMult
 ' compute -- You need to TEST the function out
 ' so that it is accurate before deployment
 ' Simple Multiplication of 2 numbers
 IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
 RetVal = 0
 ' using string pointer to point to the Mult2Numbers function
 CALL DWORD pStringMult USING  MasqueradeMt(519, 23) TO RetVal
 MessageBox(hDlg, "CALL DWORD pStringMult result of 519 and 23 =" & _
 STR$(RetVal), "String Pointer to Mult function", 266240)
 END IF
 
 
 
 CASE %ButtonMat
 '  the MatrixMultiply function
 IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
 RetVal = 0
 
 LOCAL R1 , R2 , R3 , R4 AS LONG
 R1 = 0
 R2 = 0
 R3 = 0
 R4 = 0
 ' using string pointer to point to the MatrixMultiply function
 ' this fail ***************
 '  CALL DWORD pStringMat USING  MasqueradeMatM(R1 , R2 , R3 , R4) TO  RetVal
 
 ' this works
 MatrixMultiply(R1 , R2 , R3 , R4)
 
 '  Concatenate the result string -- do not place  external
 '  function STR$() inside the  obfuscated MatrixMultiply function
 dispst = ""
 dispst = STR$(R1) + "   " +  STR$(R2) + "   " + STR$(R3) + "   " + STR$(R4)
 
 MessageBox(hDlg, "CALL DWORD pStringMat  with matrix result :   " + $CRLF+  dispst , _
 "String Pointer to Matrix Multiply function ", 266240)
 '  https://www.mathsisfun.com/algebra/matrix-multiplying.html
 ' answers are 58 , 64 , 139 , 154
 END IF
 
 
 
 
 
 CASE %ButtonAdd
 ' compute -- You need to TEST the function out
 ' so that it is accurate before deployment
 ' Simple Addition of 3 numbers
 IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
 RetVal = 0
 ' using string pointer to point to the Add3Numbers function
 CALL DWORD pStringAdd USING  MasqueradeA(19,325, 93) TO RetVal
 MessageBox(hDlg, "CALL DWORD pStringAdd result of 19 , 325 and 93 =" & _
 STR$(RetVal), "String Pointer to Add function", 266240)
 END IF
 
 
 
 
 
 
 CASE %ButtonCAV
 ' compute -- You need to TEST the function out
 ' so that it is accurate before deployment
 ' compute Area and Volume function
 IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
 LOCAL RetValPar AS DOUBLE
 RetValPar = 0
 
 ' using string pointer to point to the compute Area and Volume function
 
 ' this case works   answer = 133316.933
 CALL DWORD pStringCAV USING  Masq_AV(206 , 0 , 2  ) TO RetValPar
 MessageBox(hDlg, "CALL DWORD pStringCAV,   Circle Area with radius 206  =" & _
 STR$(RetValPar), "String Pointer to compute Area and Volume function", 266240)
 
 ' this case works   answer =2414
 CALL DWORD pStringCAV USING  Masq_AV(34 , 71 , 1  ) TO RetValPar
 MessageBox(hDlg, "CALL DWORD pStringCAV,   Rectangle Area with sides lengths of 34 and 71  =" & _
 STR$(RetValPar), "String Pointer to compute Area and Volume function", 266240)
 
 ' this case works   answer =  1297.339156
 CALL DWORD pStringCAV USING  Masq_AV(206 , 0 , 3  ) TO RetValPar
 MessageBox(hDlg, "CALL DWORD pStringCAV,   Circle circumference with radius 206  =" & _
 STR$(RetValPar), "String Pointer to compute Area and Volume function", 266240)
 
 ' this case works   answer =  502655.9827
 CALL DWORD pStringCAV USING  Masq_AV(100 , 48 , 4  ) TO RetValPar
 MessageBox(hDlg, "CALL DWORD pStringCAV,   Cone volume with radius 100 and height of 48  =" & _
 STR$(RetValPar), "String Pointer to compute Area and Volume function", 266240)
 
 END IF
 
 
 
 
 
 CASE %ButtonCSB
 ' checks for SandBoxie
 IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
 RetVal = 0
 LOCAL Sbpresent AS STRING
 
 
 ' this fail ***************
 '  using string pointer to point to the Check Sandboxie function
 '  CALL DWORD pStringCSB USING  MasqueradeCSB() TO RetVal
 
 ' this works
 RetVal =  IsSandboxie()
 
 IF RetVal = 0 THEN
 Sbpresent = "SandBoxie NOT present"
 ELSE
 Sbpresent = "SandBoxie is present"
 END IF
 MessageBox(hDlg, "CALL DWORD pStringCSB result = " & _
 Sbpresent , "String Pointer to Check SandBoxie function", 266240)
 END IF
 
 
 
 END SELECT
 
 END SELECT
 
 END FUNCTION
 
 
 
 
 
 
 
 '=========================
 '  Obtain the pointer to the ASM string
 '  for General usage.
 '  and creates the text file for the wsAsm string
 '  gpar = indicator for a specific function
 SUB Obtain_PtrStringGen( BYVAL gpcode AS DWORD, _
 BYREF WpString AS DWORD ,BYREF wsAsm  AS STRING , gpar AS LONG )
 LOCAL byteVal AS BYTE
 
 '   LOCAL sTerminator AS STRING
 '  sTerminator = CHR$(&h12, &h34, &h56, &h78, &h9A, &hBC, &hDE, &hF0  )
 
 LOCAL sTerm AS STRING
 sTerm = CHR$( &HEB, &H08, &H56, &H4D, &H45, &H4E, &H44, &H31, &H00, &H00 )
 
 ' clear off any prev values
 WpString = 0
 wsAsm    = ""
 
 
 ' Assemble WsAsm byte by byte
 ' and looking for the end of function marker
 DO
 WsAsm &= PEEK$(gpcode, 1)
 INCR gpcode
 IF INSTR(WsAsm, sTerm )    THEN
 'found the end of function marker
 WsAsm &= PEEK$(gpcode, 16)
 EXIT DO
 END IF
 LOOP
 
 
 
 ' Gets the pointer to the wanted function's ASM string
 WpString = STRPTR(WsAsm)
 
 ' Convert to hex as it is printable
 LOCAL HxStrAsm , OrigAsm AS STRING
 HxStrAsm = HexDump(WsAsm)
 SLEEP 10
 OrigAsm  = DeHex(HxStrAsm)
 SLEEP 10
 
 LOCAL filNamAsm , DecFn AS STRING
 filNamAsm = "Output WsAsm " + STR$(gpar) +  ".txt"
 
 ' gets the correct declaration function name
 ' according to gpar
 SELECT CASE gpar
 CASE  1
 DecFn = $DecFnStr1
 CASE  2
 DecFn = $DecFnStr2
 CASE  3
 DecFn = $DecFnStr3
 CASE  4
 DecFn = $DecFnStr4
 CASE  5
 DecFn = $DecFnStr5
 END SELECT
 
 ' clear off old file
 KILL  filNamAsm
 '  prints out the WsAsm string to a text file
 LOCAL bf AS LONG
 bf = FREEFILE
 OPEN filNamAsm FOR OUTPUT AS #bf
 PRINT #bf, WsAsm
 PRINT #bf,
 PRINT #bf,
 PRINT #bf,HxStrAsm
 PRINT #bf,
 PRINT #bf,
 PRINT #bf, OrigAsm
 PRINT #bf,
 PRINT #bf,
 PRINT #bf, "Masquerade Function declaration string"
 PRINT #bf, DecFn
 
 CLOSE #bf
 
 END SUB
 
 
 
 
 
 
 
 
 '======================================
 '  Provide a string of Hex characters
 '  for a given string sgBuf
 FUNCTION HexDump(sgBuf AS STRING) AS STRING
 LOCAL sbh AS ISTRINGBUILDERA
 sbh = CLASS "STRINGBUILDERA"
 LOCAL ihd AS LONG
 FOR ihd = 1 TO LEN(sgBuf)
 sbh.add  HEX$(ASC(MID$(sgBuf,ihd,1)),2)
 NEXT
 FUNCTION = sbh.string
 END FUNCTION
 
 
 
 '===================================================
 FUNCTION DeHex(Inpt AS STRING) AS STRING
 LOCAL i AS INTEGER
 LOCAL Xdh AS STRING
 
 FOR i = 1 TO LEN(Inpt) STEP 2
 Xdh = Xdh & CHR$(VAL("&H" & MID$(Inpt, i, 2)))
 NEXT i
 DeHex = Xdh
 END FUNCTION
  Note that I have also use the MACRO to denote the end of function marker 
 
  MACRO FN_END  = ! DB &HEB, &H08, &H56, &H4D, &H45, &H4E, &H44, &H31, &H00, &H00
	 
	
	
	
		
	Posts: 77Threads: 5
 Joined: 27.05.2024
 
	
		
		
		03.02.2025, 02:13 AM 
(This post was last modified: 03.02.2025, 02:32 AM by Dale Yarker.)
		
	 
		" This method cannot be used when the target function has the following"
 I don't see any ! PUSH register operands in your code (nor &h50 in the strings), so of course some things will fail.
 
 I mentioned this before in PB Forum when it became clear you going to do it in any case.
 
 from pb Help:
 
 "There are special conditions with register preservation that apply when writing mixed assembler and BASIC code. PowerBASIC is a highly optimized compiler and among its optimizations are reductions in the stack overhead between BASIC code statements. Therefore, compiled PowerBASIC code is designed to expect that the EBX, ESI, and EDI registers will remain unchanged between lines of BASIC code.
 
 This means that if your assembler algorithm uses any of the EBX, ESI, or EDI registers, you must preserve their original state from the last line of BASIC code that precedes the Inline Assembler code. This is, you must PUSH them before your ASM code, and POP them again right before the BASIC code commences." (bold added)
 
 Memory addresses for jumps are also wrong because you're lifting code compiled with labels and putting it somewhere else where the relative address is different.
 
 Have a nice day
 
	
	
	
		
	Posts: 19Threads: 0
 Joined: 09.06.2024
 
	
	
		To push all the registers, except for the stack pointer itself esp, add these bytes to the start of your string:
 in hexadecimal:
 9c 50 51 52 53 55 56 57
 
 Then add this to the end of your string to pop them all back again
 
 5f 5e 5d 5b 5a 59 58 9d
 
 This should be safe for all integer arithmetic, and possibly floats. You might be able to do Windows API calls as well.
 
https://github.com/Charles-Pegge/OxygenBasichttps://forum.it-berater.org/index.php
 
	
	
	
		
	Posts: 23Threads: 5
 Joined: 18.05.2024
 
	
	
		Thanks Dale and Charles
 The push  9c 50 51 52 53 55 56 57   and pop 5f 5e 5d 5b 5a 59 58 9d  did not work
 
 These have no bearing in opcode
 
 I found that Calling opcode method cannot pass arguments in DOUBLE and we cannot use
 functions like INT()  and integer division operator  \
 So the best solution should be limited to simple addition , multiplication of LONG
 variables.   NO external PB functions nor WinAPI functions.
 
 di9c 50 51 52 53 55 56 57
 
	
	
	
		
	Posts: 19Threads: 0
 Joined: 09.06.2024
 
	
	
		You could make your own functions using Inline Assembly code, which you can design to run from any location, wherever you place the extracted binary string 
The simplest function you can call is ret  (which happens to be &hc3 )    
Would you be interested in pursuing this strategy?
	
https://github.com/Charles-Pegge/OxygenBasichttps://forum.it-berater.org/index.php
 
	
	
	
		
	Posts: 23Threads: 5
 Joined: 18.05.2024
 
	
	
		Thanks Charles for your offer. 
However the main objective of this program "Obfuscator maker.bas" is to
obfuscate  a given function's  Opcode string into a hex form as shown below
 Code: 558BEC535657683F13000083EC70688712200031F656565656568B450C034508034510898568FFFFFFE90A000000EB084678744DF0DE00008B8568FFFFFF8D65F45F5E5B5DC20C0000000000
 and then to use this hex string in another program .   It would make life very difficult for hackers.  
Even if they decompile the program, they have limited means to find out what this function 
is all about.  
 
Whereas if we were to use ASM, hackers can easily decompile it , view it and able to manipulate  
the codes directly in a linear fashion.
 
To add another layer of complexity we can also encrypt this hex string so that hackers will find 
it next to impossible to determine its contents.  
 
We can also split this single hex string into several  string components, encrypt these several strings.  
And at the time when we needed to run the function,  we decrypt these several string components,  
then concatenate  them into the final Opcode string. 
Finally execute CALL DWORD this final opcode string  to get the obfuscated function running.
	 |