I have a Win32 C++ application and I need to modify the command line arguments in the application. Specifically, I want to edit the command line arguments in such a way that GetCommandLineW() returns my new arguments.
Believe it or not, this works (since we have a non-const pointer to the character array):
LPTSTR args = GetCommandLineW();
LPTSTR new_args = L"foo --bar=baz";
wmemcpy(args, new_args, lstrlenW(new_args));
// ...
LPTSTR args2 = GetGommentLineW(); // <- equals "foo --bar=baz"
But I don't know how long much memory Windows allocates for the LPTSTR provided by GetCommandLineW().
Is there another way to do this? Or does anyone know if there is a predictable amount of memory allocated for the command line arguments?
GetCommandLineW() does not allocate any memory. It simply returns a pointer to a buffer that is allocated by the OS in the process's PEB structure when the process is created. That buffer exists for the lifetime of the process.
The cleanest and safest way to modify what that function returns is to modify the function. Install a detour so that any calls to the function from inside your process are re-routed to a function that you provide.
Use the following code to inspect on PEB structure, where the CommandLine (unicode) string lies.
On my machine, under both x86 and x64 CommandLine is right after ImagePathName, so I think there won't be more space for the former one either. Writing a longer string to that buffer does might cause an overflow.
#include <winnt.h>
#include <winternl.h>
int main()
{
// Thread Environment Block (TEB)
#if defined(_M_X64) // x64
PTEB tebPtr = (PTEB)__readgsqword((DWORD) & (*(NT_TIB*)NULL).Self);
#else // x86
PTEB tebPtr = (PTEB)__readfsdword((DWORD) & (*(NT_TIB*)NULL).Self);
#endif
// Process Environment Block (PEB)
PPEB pebPtr = tebPtr->ProcessEnvironmentBlock;
PRTL_USER_PROCESS_PARAMETERS ppPtr = pebPtr->ProcessParameters;
printf("ImagePathName:\tlen=%d maxlen=%d ptr=%p\n", ppPtr->ImagePathName.Length, ppPtr->ImagePathName.MaximumLength, ppPtr->ImagePathName.Buffer);
printf("CommandLine:\tlen=%d maxlen=%d ptr=%p\n", ppPtr->CommandLine.Length, ppPtr->CommandLine.MaximumLength, ppPtr->CommandLine.Buffer);
printf("GetCommandLineA:\tptr=%p\n", GetCommandLineA());
printf("GetCommandLineW:\tptr=%p\n", GetCommandLineW());
printf("Addr Delta between CommandLine and ImagePathName: %d\n", (char*)ppPtr->CommandLine.Buffer - (char*)ppPtr->ImagePathName.Buffer);
}
Related
I have written a hooking dll using the mhook library. In a spezial case the NtOpenFile() fails when a std::wstring is defined as stack var. Defining it on the heap the code is working.
The code is working without problems except when a certain win32 application (lets call it nuisance.exe) tries to open an existing testfile (like c:\temp\anyfile.log) the access fails. Mostly STATUS_INVALID_ACL (0xC0000077) is returned then.
I have reduced my code line by line and finally found that the error happens when in a called function a std::wstring is defined (this example below). The error happens every time an on different OS's
NTSTATUS NtOpenFileApiHook::NtOpenFileHook(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG ShareAccess,
ULONG OpenOptions
)
{
NTSTATUS Status = STATUS_SUCCESS;
// using this function the call will fail
AfterThis_NtOpenFile_WillFail();
// using this function INSTEAD the call will work
AfterThis_NtOpenFile_WillWork();
// calling the real NtOpenFile using a pointer
// nothing was changed hier, the original parameters are passed
Status = RealNtOpenFile(FileHandle, ...);
return Status;
}
int AfterThis_NtOpenFile_WillFail()
{
std::wstring String = L"";
return 0;
}
int AfterThis_NtOpenFile_WillWork()
{
std::wstring * pString = new std::wstring();
pString->assign(L"");
delete pString;
return 0;
}
I have fixed it this way for this call. But I'm afraid that other functions in other circumstainces could fail so I'm looking for the reason and (probably) for a solution.
Nuisance.exe is a C# application with default stacksize callling a win32 dll about which I know nothing.
If Nuisance.exe was a C++ application, I would imagine that it calls NtOpenFile in a way similar to this, allocating one of pointer parameters on overwritten stack:
POBJECT_ATTRIBUTES MakeObjectAttributes()
{
POBJECT_ATTRIBUTES oa = {...};
return &oa; // Pointer to stack variable - UB
}
...
NtOpenFile(..., MakeObjectAttributes(), ...)
STATUS_INVALID_ACL (0xC0000077) error might suggest that SecurityDescriptor within OBJECT_ATTRIBUTES is allocated this way.
Then it matters how much stack is used by AfterThis_NtOpenFile_WillFail, and it is more than AfterThis_NtOpenFile_WillWork, since std::wstring would be larger than just a couple of pointers due to small string optimization.
If the call chain is always the same, the corruption may be deterministic.
I don't know if code equivalent of returning address of temporary is possible in C#. But the DLL may be in C/C++ or similar language that allows dandling pointers.
To prove/disprove the role of stack, try to allocate other data on stack that has std::wstring size. More precise proof could be checking passed pointer to see if they point to stack area that is about to be overwritten.
I'm writing C++ dll on Visual studio 2013. My dll should read parameters from ini file. So, I've created a function for this purpose (ReadConnectionSettings()). My static variable serverIP gets value properly during the function working, however once the function complete running the variable (serverIP) loses its value. What seems to be the problem?
static LPTSTR serverIP = _TEXT("");
void ReadConnectionSettings()
{
TCHAR url[256];
GetPrivateProfileString(_T("Connection"), _T("Url"), _T(""), url, 256, NameOfIniFile);
serverIP = url;
}
You are pointing the pointer serverIP at stack memory url.
This goes out of scope when the function exits, so your pointer is left pointing to junk.
What you could do is make serverIP a buffer instead, and copy the URL into it. Then it would persist.
That is:
static TCHAR serverIP[256] = _TEXT("");
Then:
_tcsnccpy(serverIP, url, 255);
Or as #DavidOtano suggested, you could keep your existing serverIP pointer, and use:
serverIP = _tcsdup(url);
But if you do this, you're dynamically allocating memory, so will need to remember to call:
free(serverIP);
when you no longer need it, to avoid a memory leak.
You're setting the static pointer variable to point at a local variable that does not exist anymore after the function has returned.
A good way to return a string from a function in a Windows program, is to return a std::wstring.
Try that.
Regarding LPTSTR and _TEXT, you only need this if you intend to support MFC in DLLs in Windows 9x. Is that the case? If not, just ditch that Microsoft silliness.
The code fixed according to above advice (off the cuff, untouched by compiler's hands):
auto connection_settings()
-> std::wstring
{
std::wstring url( 256, L'#' );
auto const n = GetPrivateProfileString( L"Connection", L"Url", L"", &url[0], url.size(), NameOfIniFile );
url.resize( n );
return url;
}
One nice property of this code is that it no longer modifies a global variable.
I have a code in C++ that calls functions from external library. The function I called is CreateProcess like below.
CreateProcess(NULL,pProcessName,NULL,NULL,false,CREATE_SUSPENDED,
NULL,NULL,&suStartUpInformation,&piProcessInformation)
Now when I compile the code and dissemble it, the assembly shows the plain text as CreateProcess(args1, args2, ...). Is there any way to obfuscate or encrypt the function call to API so that if someone dissembles it then he won't ever know which functions are called.
Thanks!
Any function that is imported by name will always have the name embedded into the binary (in the import descriptor thunk to be exact), the detailed parameter info is gotten from the pdbs as Steve mentioned (however analysing debuggers like ollydbg can deduce args, due to the symbol name being available). The only ways to avoid this is to either encrypt to IAT (using 3rd party packers/virtualizers/binary protection systems etc, like enigma) or use a custom version of GetModuleHandle (basically just a PEB spelunking tool) and GetProcAddress (a PE spelunking tool this time), then by storing all the api calls you need as runtime encrypted strings, you can then call whatever you need without plain text giving you away (securerom does this, though it uses GetProcAddress directly, along with some binary obfuscation).
Update:
for compile-time 'obfuscated' strings, you can use something like this (really simple, but it should be portable, if you use C++0x, this is a lot easier):
#define c(x) char((x) - 1) //really simple, complexity is up to the coder
#define un(x) char((x) + 1)
typedef int (WINAPI* MSGBOX)(HWND, LPCSTR, LPCSTR, UINT);
const int ORD_MASK = 0x10101010;
const char szMessageBoxA[] = {c('M'),c('e'),c('s'),c('s'),c('a'),c('g'),c('e'),c('B'),c('o'),c('x'),c('A')};
FARPROC GetProcAddressEncrypted(HMODULE hModule, const char* szName, BOOL bOrd = FALSE)
{
if(bOrd)
return GetProcAddress(hModule,reinterpret_cast<const char*>(reinterpret_cast<int>(szName) ^ ORD_MASK)); //this requires that ordinals be stored as ordinal ^ ORD_MASK
char szFunc[128] = {'\0'};
for(int i = 0; *szName; i++)
szFunc[i] = uc(*szName++);
return GetProcAddress(hModule,szName);
}
MSGBOX pfMsgBox = static_cast<MSGBOX>(GetProcAddressEncrypted(GetHandleEncrypted(szUser32),szMessageBox));
Optionally you may want to use MSVC's EncodePointer to hide the values in the global function pointers (just remember to use DecodePointer when you call them).
note: code is untested, as its just off the top of my head
You might use dynamic linking. In Windows, use LoadLibrary, LoadLibraryEx, GetProcAddress. Now in you code, include some form in obfuscated form of name instead of the real lib/symbol names and unofuscate it at runtime.
You might want to use dynamic dispatch (function pointers) so that the function called cannot be deduced easily from the code.
You might delegate the work of calling this function to another thread (using some IPC mechanism).
But it's quite useless, using a debugger it will very simple to find that this function has been called. And it will be very simple to detect that a process has been created.
Ok! here is the solution. Lets say I want to call "MessageBoxA" from "user32.dll".
So here is how I will do it using LoadLibraryA & GetProcAddress .
//Ok here you can see.
//I am passing DLL name(user32.dll) and DLL function(MessageBoxA) as String
//So I can also perform Encrypt & Decrypt operation on Strings and obfuscate it.
//Like i can encrypt the string "user32.dll" and at runtime decrypt it and pass it as
//an argument to "LoadLibraryA" and same for the Function name "MessageBoxA".
//The code is compiled in DevC++ 4.9.9.2.
#include <windows.h>
#include <iostream>
using namespace std;
void HelloWorld()
{
char* szMessage = "Hello World!";
char* szCaption = "Hello!";
HMODULE hModule = LoadLibraryA( "user32.dll" );
FARPROC fFuncProc = GetProcAddress( hModule, "MessageBoxA" );
( ( int ( WINAPI *)( HWND, LPCSTR, LPCSTR, UINT ) ) fFuncProc )( 0, szMessage, szCaption, 0 );
}
int main()
{
HelloWorld();
}
I have a win32 c++ application & I getting all the environment variables & storing them in a map.
When I call the Win32 function FreeEnvironmentStrings() in my application I get a weird Windows Breakpoint in MSVC++. First I dont know what this means & why its occuring?
How can I fix my problem & what is going wrong?
This the function that I call in my main function & the one that causes the breakpoint:
std::map <tstring, tstring> GetEnvironmentVariablesEx()
{
// Post: Get all windows environment variables & store in a
// map(key=env.. variable name, value=env variable value)
std::map <tstring, tstring> envVariables;
TCHAR* environVar = GetEnvironmentStrings();
TCHAR* pos = _tcschr( environVar, _T('\0') );
// Skip over the "=::=::\0" of the environVar string
if ( pos != NULL ) { environVar = ++pos; pos = _tcschr( environVar, _T('\0') ); }
else return envVariables;
// I removed the following code because its long & distracting: the error still occurs without the code
// Code: ...use cstring functions to extract environ variables & values & store in map
FreeEnvironmentStrings( environVar ); // Breakpoint triggered here: "Windows has triggered a breakpoint in the application. This may be due to a corruption of the heap, which indicates a bug in myApp.exe or any of the DLLs it has loaded."
return envVariables;
}
You're changing what environVar points to, so you're not handing the FreeEnvironmentString function a valid environment string pointer.
Save the original environVar somewhere before modifying it and use that in the Free call.
TCHAR* tobefreeed = GetEnvironmentStrings();
TCHAR* environVar = tobefreeed;
...
FreeEnvironmentStrings( tobefreeed );
After you skip reserved characters environVar no longer points at data area allocated by GetEnvironmentStrings. This causes FreeEnvironmentStrings to fail.
Preserve original pointer intact (modify a copy if you need) and you'll solve the problem.
I found many ways, but they are too easy, they always get a return-value from the dll file.
dll file: a file with the sufix ".dll"
It's just like any other WINAPI
// assuming you are using windows
LPCTSTR lpszXml = _T("<xml> </xml>");
TCHAR szResult[1000] = _T("");
HMODULE hModule = LoadLibrary(_T("mylibrary.dll"));
int (*DoWorkFunc)(LPCTSTR lpszXmlData, LPTSTR lpszResult, int cchMaxSize);
*(FARPROC*)&DoWorkFunc = GetProcAddress(hModule, _T("DoWork"));
int nLength = DoWorkFunc(lpszXml, szResult, 1000);
_tprintf(_T("input [%s] output [%s] length of the result [%d]\n")
, lpszXml, szResult, nLength);
FreeLibrary(hModule);
// warning: no error handling is performed
Edit:
Since I speak multiple-languages, I can roughly guess what the OP asked. It is probably along this line:
I found many ways [in the internet] to load a DLL file and call a function inside it. But those that I found involve simple functions like int add(int a, int b). They only get a return value from the function. What I want to do is to pass a big chunk of data and get another big chunk of data from the function. How can I pass a big chunk of data and get a big chunk of data as the return value?