Sometimes you want to change a configuration, strings, integers or other static variable values dynamically and NOT in the building actual source process. For example:
You trying to write a client-server application and the server address can change anytime as the user needs. I know I know, we can store it in config.ini, databases (sqlite), Windows registry, etc.
But when you are writing a security tool (malware actually) you will try to touch the file-system as low as possible to avoid detection. Another example for those who don't make security tools (malwares):
You are selling an single application that you want to be portable and single file (just because you are cool) and you need to store data INSIDE your executable file, what would you do ?
Thus, I made a way for my self to store values inside my executable file and I will read them anytime I want and those values can actually change by a another application (ex. foo application builder).
I think I gave you the basic idea, lets get started how it works and how we can write it :)
Option 1:
We can use EOF (End of file) to store and read values from the arbitarry/unused bits at the end of our file. for example when you open a executable file in HxD (hex editor) at the last hex/bits of file you can see the following:
- Open file and reach the EOF
- Know the size of data you wrote
- Read from EOF by size of data
Option 2 (The nice one, Windows Only):
WRITE:
Here is the way you can write data to your String Table (I assume you know some WinAPI/C++ to modify this by your self):BOOL setResourceData(LPCTSTR szSSPath, LPCTSTR szSSName, int order)
{
HANDLE h = ::BeginUpdateResource(szSSPath, FALSE);
if (!h)
{
// BeginUpdateResource failed
return FALSE;
}
CString sNewString = szSSName;
int iCharCount = sNewString.GetLength() + 1;
LPWSTR pUnicodeString = new WCHAR[iCharCount];
if (!pUnicodeString)
{
// new failed
return FALSE;
}
DWORD dwUnicodeCharCount =
MultiByteToWideChar(CP_ACP, NULL, sNewString.GetBuffer(0),
-1, pUnicodeString, iCharCount);
HGLOBAL hGlob =
GlobalAlloc(GHND, (dwUnicodeCharCount + 4) * sizeof(WCHAR));
if (!hGlob)
{
// GlobalAlloc failed
delete pUnicodeString;
return FALSE;
}
LPWSTR pBufStart = (LPWSTR)GlobalLock(hGlob);
if (!pBufStart)
{
// GlobalLock failed
GlobalFree(hGlob);
delete pUnicodeString;
return FALSE;
}
LPWSTR pBuf = pBufStart;
pBuf++;
// offset to make it string ID=1. Increment by more
// to change to a different string ID
// next 2 bytes is string length
*(pBuf++) = (WCHAR)dwUnicodeCharCount - 1;
for (int i = 0; i<(int)dwUnicodeCharCount - 1; i++)
// remaining bytes are string in wide chars (2 bytes each)
*(pBuf++) = pUnicodeString[i];
delete pUnicodeString;
if (++dwUnicodeCharCount % 1)
// make sure we write an even number
dwUnicodeCharCount++;
BOOL bSuccess = TRUE;
if (!::UpdateResource(h, RT_STRING, MAKEINTRESOURCE(order),
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
pBufStart, dwUnicodeCharCount * sizeof(WCHAR)))
{
// UpdateResource failed
bSuccess = FALSE;
}
GlobalUnlock(hGlob);
GlobalFree(hGlob);
::EndUpdateResource(h, FALSE); // write changes
return bSuccess;
}
Parameters:
- szSSPath: The executable file path
- szSSName: The name of your variable to set
- order: The order number (put it randomly), this value is REQUIRE later to read values
READ
TCHAR Connection[160];
HINSTANCE hInstance = GetModuleHandle(NULL);
if (LoadStringA(hInstance, ORDER, Connection, sizeof(Connection) / sizeof(TCHAR)) == 0) {
}
return Connection;
}
This function simply does the reading process from executable it-self. where ORDER is the order number you set before.
That's it, feel free to ask.
-Good Luck ✌
nice and useful tricks.
ReplyDeletelike the theme and these beautiful images for your posts.
---
publish the link to your post in social networks (especially hackernews or reddit).
Yourwelcome!
DeleteI will do it, thanks :)