1 Attachment(s)
[VB6] - Store data to EXE.
Hello everyone!
There are times when you want to save the data after completion of the program, but did not want to have external dependencies, registry entries, etc. However you can store the data in your EXE. Unfortunately, Windows doesn't allow to write into the running EXE (i don't consider NTFS streams), and any attempt of the writing will be rejected with the ERROR_ACCESS_DENIED error. Although if the process is complete it can be performed by another process. Here is the way I decided to choose.
Firstly, you'd run cmd.exe with the suspended state. Further you'd create code that will be injected to it and will change the resources of our EXE. Then you'd run this code. This code waits for termination of our process and then rewrites the needed data (you've passed them to there). Eventually it is terminated.
In order to simplify the code (it only needs single form) i decide to make it in assembler. It is simpler and requires less code (source is included). Because the code is published especially for the review and test, it doesn't perform any synchronizations.
Code:
' Store data to EXE
' © Krivous Anatolii Anatolevich (The trick), 2014
' Writing is performed only after process termination
Option Explicit
Private Type STARTUPINFO
cb As Long
lpReserved As Long
lpDesktop As Long
lpTitle As Long
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End Type
Private Type ThreadData
hParent As Long
lpFileName As Long
lpRsrcName As Long
lpData As Long
dwDataCount As Long
lpWFSO As Long
lpCH As Long
lpBUR As Long
lpUR As Long
lpEUR As Long
lpEP As Long
End Type
Private Declare Function CloseHandle Lib "kernel32" ( _
ByVal hObject As Long) As Long
Private Declare Function CreateProcess Lib "kernel32" _
Alias "CreateProcessW" ( _
ByVal lpApplicationName As Long, _
ByVal lpCommandLine As Long, _
lpProcessAttributes As Any, _
lpThreadAttributes As Any, _
ByVal bInheritHandles As Long, _
ByVal dwCreationFlags As Long, _
lpEnvironment As Any, _
ByVal lpCurrentDirectory As Long, _
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
Alias "GetModuleHandleA" ( _
ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" ( _
ByVal hModule As Long, _
ByVal lpProcName As String) As Long
Private Declare Function DuplicateHandle Lib "kernel32" ( _
ByVal hSourceProcessHandle As Long, _
ByVal hSourceHandle As Long, _
ByVal hTargetProcessHandle As Long, _
lpTargetHandle As Long, _
ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwOptions As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function VirtualAllocEx Lib "kernel32.dll" ( _
ByVal hProcess As Long, _
lpAddress As Any, _
ByVal dwSize As Long, _
ByVal flAllocationType As Long, _
ByVal flProtect As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" ( _
ByVal hProcess As Long, _
ByVal lpBaseAddress As Long, _
lpBuffer As Any, _
ByVal nSize As Long, _
lpNumberOfBytesWritten As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
src As Any, _
dst As Any) As Long
Private Declare Function VirtualFreeEx Lib "kernel32.dll" ( _
ByVal hProcess As Long, _
lpAddress As Any, _
ByVal dwSize As Long, _
ByVal dwFreeType As Long) As Long
Private Declare Function CreateRemoteThread Lib "kernel32" ( _
ByVal hProcess As Long, _
lpThreadAttributes As Any, _
ByVal dwStackSize As Long, _
ByVal lpStartAddress As Long, _
lpParameter As Any, _
ByVal dwCreationFlags As Long, _
lpThreadId As Long) As Long
Private Declare Function FindResource Lib "kernel32" _
Alias "FindResourceW" ( _
ByVal hInstance As Long, _
ByVal lpName As Long, _
ByVal lpType As Long) As Long
Private Declare Function LoadResource Lib "kernel32" ( _
ByVal hInstance As Long, _
ByVal hResInfo As Long) As Long
Private Declare Function LockResource Lib "kernel32" ( _
ByVal hResData As Long) As Long
Private Declare Function SizeofResource Lib "kernel32" ( _
ByVal hInstance As Long, _
ByVal hResInfo As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" ( _
Destination As Any, _
Source As Any, _
ByVal Length As Long)
Private Const STARTF_USESHOWWINDOW As Long = &H1
Private Const SW_HIDE As Long = 0
Private Const MEM_COMMIT As Long = &H1000&
Private Const MEM_RESERVE As Long = &H2000&
Private Const MEM_RELEASE As Long = &H8000&
Private Const PAGE_EXECUTE_READWRITE As Long = &H40&
Private Const INFINITE As Long = -1&
Private Const MAX_PATH As Long = 260
Private Const RT_RCDATA As Long = 10&
Private Const CREATE_SUSPENDED As Long = &H4
Private Const DUPLICATE_SAME_ACCESS As Long = &H2
Private Const ResName As String = "TRICKRESOURCE" & vbNullChar ' Only capital letters
' // Procedure load data from EXE
Private Sub LoadFromEXE()
Dim hRes As Long, hMem As Long, ptr As Long, l As Long, Msg As String
hRes = FindResource(0, StrPtr(ResName), RT_RCDATA)
If hRes Then
hMem = LoadResource(0, hRes)
If hMem Then
l = SizeofResource(0, hRes)
If l Then
ptr = LockResource(hMem)
GetMem4 ByVal ptr, l
Msg = Space(l \ 2)
CopyMemory ByVal StrPtr(Msg), ByVal ptr + 4, l
txtData.Text = Msg
End If
End If
End If
End Sub
' // Procedure store data to EXE
Private Sub StoreToExe()
Dim hLib As Long
Dim td As ThreadData, ts As Long, path As String, pi As PROCESS_INFORMATION, si As STARTUPINFO, hProc As Long, lpDat As Long, pt As Long
Dim Code() As Byte, Data() As Byte, ret As Long, thr As Long, otd As Long
' // Get the Kernel32 handle
hLib = GetModuleHandle("kernel32")
If hLib = 0 Then MsgBox "Error": Exit Sub
' // Get the functions addresses
td.lpWFSO = GetProcAddress(hLib, "WaitForSingleObject")
td.lpCH = GetProcAddress(hLib, "CloseHandle")
td.lpBUR = GetProcAddress(hLib, "BeginUpdateResourceW")
td.lpUR = GetProcAddress(hLib, "UpdateResourceW")
td.lpEUR = GetProcAddress(hLib, "EndUpdateResourceW")
td.lpEP = GetProcAddress(hLib, "ExitProcess")
path = App.path & "\" & App.EXEName & ".exe" & vbNullChar
' // Create the machine code
CreateCode Code
' // Calculate size of the needed memory
ts = LenB(path) + LenB(ResName) + (UBound(Code) + 1) + LenB(txtData.Text) + Len(td) + 4
si.cb = Len(si)
si.dwFlags = STARTF_USESHOWWINDOW
si.wShowWindow = SW_HIDE
' // Launch "victim" (CMD.EXE)
If CreateProcess(StrPtr(Environ("ComSpec")), 0, ByVal 0&, ByVal 0&, False, CREATE_SUSPENDED, ByVal 0, 0, si, pi) = 0 Then
MsgBox "error": Exit Sub
End If
' // Get handle of the our process for CMD process
hProc = GetCurrentProcess()
DuplicateHandle hProc, hProc, pi.hProcess, td.hParent, 0, False, DUPLICATE_SAME_ACCESS
td.dwDataCount = LenB(txtData.Text) + 4 ' Размер данных
' // Allocate memory in the CMD
lpDat = VirtualAllocEx(pi.hProcess, ByVal 0, ts, MEM_COMMIT Or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
If lpDat = 0 Then
MsgBox "Error": CloseHandle pi.hThread: CloseHandle pi.hProcess
VirtualFreeEx pi.hProcess, ByVal lpDat, 0, MEM_RELEASE
Exit Sub
End If
' // Ok, all is ready for the writing to cmd
' // Create buffer with data
ReDim Data(ts - 1)
' // Copy the file name of our process
CopyMemory Data(pt), ByVal StrPtr(path), LenB(path)
td.lpFileName = lpDat + pt: pt = pt + LenB(path)
' // Copy the name of the resource
CopyMemory Data(pt), ByVal StrPtr(ResName), LenB(ResName)
td.lpRsrcName = lpDat + pt: pt = pt + LenB(ResName)
' // Copy the data of the resource
GetMem4 LenB(txtData.Text), Data(pt) ' Размер
CopyMemory Data(pt + 4), ByVal StrPtr(txtData.Text), LenB(txtData.Text)
td.lpData = lpDat + pt: pt = pt + LenB(txtData.Text) + 4
' // Copy the structure to buffer
CopyMemory Data(pt), td, Len(td): otd = pt: pt = pt + Len(td)
' // Copy the code
CopyMemory Data(pt), Code(0), UBound(Code) + 1
' // Buffer is ready, inject it to cmd
If WriteProcessMemory(pi.hProcess, lpDat, Data(0), ts, ret) Then
If ret <> ts Then
MsgBox "Error": CloseHandle pi.hThread: CloseHandle pi.hProcess
VirtualFreeEx pi.hProcess, ByVal lpDat, 0, MEM_RELEASE
Exit Sub
End If
' // Launch the injected code
thr = CreateRemoteThread(pi.hProcess, ByVal 0, 0, lpDat + pt, ByVal lpDat + otd, 0, 0)
If thr = 0 Then
MsgBox "Error": CloseHandle pi.hThread: CloseHandle pi.hProcess
VirtualFreeEx pi.hProcess, ByVal lpDat, 0, MEM_RELEASE
Exit Sub
End If
End If
' // Close handles
CloseHandle thr
CloseHandle pi.hThread
CloseHandle pi.hProcess
End Sub
Private Sub CreateCode(Code() As Byte)
ReDim Code(63)
Code(0) = &H8B: Code(1) = &H74: Code(2) = &H24: Code(3) = &H4: Code(4) = &H31: Code(5) = &HDB: Code(6) = &H53: Code(7) = &H6A
Code(8) = &HFF: Code(9) = &HFF: Code(10) = &H36: Code(11) = &HFF: Code(12) = &H56: Code(13) = &H14: Code(14) = &HFF: Code(15) = &H36
Code(16) = &HFF: Code(17) = &H56: Code(18) = &H18: Code(19) = &H53: Code(20) = &HFF: Code(21) = &H76: Code(22) = &H4: Code(23) = &HFF
Code(24) = &H56: Code(25) = &H1C: Code(26) = &H89: Code(27) = &H4: Code(28) = &H24: Code(29) = &H85: Code(30) = &HC0: Code(31) = &H74
Code(32) = &H1B: Code(33) = &HFF: Code(34) = &H76: Code(35) = &H10: Code(36) = &HFF: Code(37) = &H76: Code(38) = &HC: Code(39) = &H53
Code(40) = &HFF: Code(41) = &H76: Code(42) = &H8: Code(43) = &H6A: Code(44) = &HA: Code(45) = &HFF: Code(46) = &H74: Code(47) = &H24
Code(48) = &H14: Code(49) = &HFF: Code(50) = &H56: Code(51) = &H20: Code(52) = &H53: Code(53) = &HFF: Code(54) = &H74: Code(55) = &H24
Code(56) = &H4: Code(57) = &HFF: Code(58) = &H56: Code(59) = &H24: Code(60) = &H53: Code(61) = &HFF: Code(62) = &H56: Code(63) = &H28
End Sub
Private Sub Form_Load()
LoadFromEXE
End Sub
Private Sub Form_Unload(Cancel As Integer)
StoreToExe
End Sub
'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ This procedure is running in other process \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
' Similar code in VB6
'Private Sub ThreadProc(dat As ThreadData)
' Dim hRes As Long
' ' Wait for the termination of the main process
' WaitForSingleObject dat.hParent, INFINITE
' ' Process has ended, close handle
' CloseHandle dat.hParent
' ' Get handle of the editing of the resource
' hRes = BeginUpdateResource(dat.lpFileName, False)
' If hRes Then
' ' Wirte the needed data to EXE
' UpdateResource hRes, RT_RCDATA, dat.lpRsrcName, 0, ByVal dat.lpData, dat.dwDataCount
' ' Ending of the updating
' EndUpdateResource hRes, False
' End if
' ' Done !!!
' ExitProcess 0
'End Sub
' Assembly code (NASM)
'[BITS 32]
'; ThreadProc
'mov esi,dword [esp+0x04]; ESI = &dat
'xor ebx,ebx ; Const 0&
'push ebx ; Dim hRes As Long
'push 0xFFFFFFFF ; INFINITE
'push dword [esi+0x00] ; dat.hParent
'call [esi+0x14] ; WaitForSingleObject dat.hParent, INFINITE
'push dword [esi+0x00] ; dat.hParent
'call [esi+0x18] ; CloseHandle dat.hParent
'push ebx ; False
'push dword [esi+0x04] ; dat.lpFileName
'call [esi+0x1c] ; BeginUpdateResource(dat.lpFileName, False)
'mov [esp],eax ; hRes = eax
'test eax,eax ; IF hRes=0
'je ExtProc ; GoTo ExtProc
'push dword [esi+0x10] ; dat.dwDataCount
'push dword [esi+0x0c] ; dat.lpData
'push ebx ; 0
'push dword [esi+0x08] ; dat.lpRsrcName
'push 0x0000000a ; RT_RCDATA
'push dword [esp+0x14] ; hRes
'call [esi+0x20] ; UpdateResource hRes, RT_RCDATA, dat.lpRsrcName, 0, ByVal dat.lpData, dat.dwDataCount
'push ebx ; False
'push dword [esp+0x04] ; hRes
'call [esi+0x24] ; EndUpdateResource hRes, False
'ExtProc:
'push ebx ; 0
'call [esi+0x28] ; ExitProcess 0
Re: [VB6] - Store data to EXE.
GOOD ider.thanks .may be you have many good Projects
Re: [VB6] - Store data to EXE.
I don't know how to read the *.res file or edit by vb code or vb6 addin, Can you help me?
1 Attachment(s)
Re: [VB6] - Store data to EXE.
xiaoyao, you can use VB 6 Resource Editor standard Add-in.
Attachment 174053
Re: [VB6] - Store data to EXE.
Quote:
Originally Posted by
The trick
where is the code sources about resource edit tool?
Re: [VB6] - Store data to EXE.
is this tested on all windows like as xp 32bit or win 7 64 bit or win 10?
i want use this code but how can protect that resource created itself or hide it inside exe,can i do that?or maybe another way to can save my data and edit data inside exe without need resource?
Re: [VB6] - Store data to EXE.
Hi The Trck
Very interesting.
A module or a class would be welcome
Re: [VB6] - Store data to EXE.
Quote:
Originally Posted by
Black_Storm
is this tested on all windows like as xp 32bit or win 7 64 bit or win 10?
i want use this code but how can protect that resource created itself or hide it inside exe,can i do that?or maybe another way to can save my data and edit data inside exe without need resource?
The protection isn't related to storing here. You can encrypt your data and store it to resource in the simpliest case.
Quote:
Hi The Trck
Very interesting.
A module or a class would be welcome
What do you mean?]
BTW this is other way to store the data to EXE tail. https://github.com/thetrik/CEmbeddedFiles
Re: [VB6] - Store data to EXE.
my means of protect is how protect this resource added in exe "RCDATA" part,i dont want somebody can see it in resource editors i want protect that "RCDATA" part or hide that "RCDATA" tab
.
https://www.vbforums.com/images/ieimages/2022/02/7.png
image link : https://postimg.cc/3WrYxDdg
because everybody easy can find it or replace it with another resource in res editors.
any way to can hide it ?
and i cant use any packer or etc to protect this exe file because after protect by other softwares it cant work for save data intself.
any way to can fix this problem?
i see that github too but i have 2 questsion about it
1- can i add or modify string data too because maybe i dont need add files jst i want add or edit string data?
for example i want jst save a counter data to can make my exe limited for 5 times jst with saved that counter variable itself.
2- how size support , can i add a 100 mb file inside it or more than 10 files with each 100 mb or longer? and how can play theme for example i want add 4 mp4 videos but i want play theme inside exe too.
Re: [VB6] - Store data to EXE.
Anyone can replace the data anywhere. Just encrypt it and make checking by a checksum. There is no difference if you place the data in resources or inside an executable.
Quote:
1- can i add or modify string data too because maybe i dont need add files jst i want add or edit string data?
for example i want jst save a counter data to can make my exe limited for 5 times jst with saved that counter variable itself.
There is no difference a file or a string.
Quote:
how size support , can i add a 100 mb file inside it or more than 10 files with each 100 mb or longer? and how can play theme for example i want add 4 mp4 videos but i want play theme inside exe too.
The size doesn't matter. If you plan to store big files inside an EXE it's better to use the second approach (append to tail) because no VM is used for this when the executable is loaded.
Re: [VB6] - Store data to EXE.
so its not safe for protect that rcdata and the only way for protect is checksum?!!! if yes which check sum vb project is better and worked on win xp till win 10?can send a best source code for check sum to can run in xp till win 10?
if i dont want use like as this thread and using resource but if i want save inside exe so CEmbeddedFiles class is better?!! i seen before but CEmbeddedFiles saved files in .text section? because i did not find resource part in final exe when i use CEmbeddedFiles project.
my english is weak but ur means of append to tail is same append to the file or appened to resource?
can i use jst CEmbeddedFiles for what i want is that support (append to tail)?
i ask this question in my other thread too how can save string and edit or delete it inside exe when i want use CEmbeddedFiles without need add files on disk
Re: [VB6] - Store data to EXE.
I think you can't use resources and EOF in the same exe. If you need to change some data in exe (like a counter or a small string) you just need to update it directly in the file (using a shellcode or an external executable). I think you can't write a shellcode so you can create a small executable which patches the main exe. Put it to main exe resources/section. Before finish your application extract this small executable to a file and run it with specified command line. This executable waits for the main executable has ended and patches the data.
Re: [VB6] - Store data to EXE.
Quote:
Originally Posted by
The trick
I think you can't use resources and EOF in the same exe. If you need to change some data in exe (like a counter or a small string) you just need to update it directly in the file (using a shellcode or an external executable). I think you can't write a shellcode so you can create a small executable which patches the main exe. Put it to main exe resources/section. Before finish your application extract this small executable to a file and run it with specified command line. This executable waits for the main executable has ended and patches the data.
i said this too here in linked thread so am i on correct way ?
Quote:
maybe need another modifer exe but created with vb and can access to resources in opened exe and edited and saved with replace to opened exe?
if yes any sample code to can modify another exe vb and access to resource part and edit it?!!
thread link : Re: any simple code for create ,add or edit or delete from resouce in runtime?
my new thread about all we talked till now :
add/delete/edit strings or files at runtime inside exe without res/section and show ?
Re: [VB6] - Store data to EXE.
Your program EOFData.exe It's buggy. Does not want to add a large CAB file of 100 MB.