My C++ program calls LoadLibraryEx() to load a third party DLL. The result is a null handle - it fails to load. A call to GetLastError() returns zero afterwards which isn't of much use but at least it's not a missing DLL file.
The code goes something like this:
HINSTANCE instance = ::LoadLibraryExW(
path, 0, LOAD_WITH_ALTERED_SEARCH_PATH );
if (instance == 0)
{
DWORD lastError = GetLastError();
LOG( "Failed to load, error code is " +
LastErrorAsString( lastError ));
return E_FAIL;
}
I cannot access that machine - I can only deploy code there and observe logs uploaded into network storage.
How would I programmatically find why the DLL fails to load?
Probably your dll can be found but it has a dependency on a dll that cannot found on the remote machine.
If you cannot use Dependency Walker then you can try to use techniques as described in articles such as this:
How to determine a windows executables DLL dependencies programatically?
Okay, so I checked better - and indeed there was another WinAPI call which caused "last error" to be overwritten after LoadLibraryEx(). It was hidden deep inside several layers of C++ helper objects so I didn't notice it earlier. So it was a bug in the caller code and the real "last error" was non-zero.
It looks like the problem is likely to be third-party software that has installed a hook or other anti-virus measure, the hook might be buggy and not setting the correct last error code.
As a troubleshooting measure, you should try LdrLoadDll instead of LoadLibraryEx.
Note that this is an undocumented internal function, so you might prefer not to use it in production code, but it would be a useful troubleshooting step as it should produce a more useful error code.
Related
I have a DLL, which is commercial software, so therefore I cannot show the code here...
I get the error "6002" -floating point support not loaded, but only on some applications.
This dll is hooked to several applications, without problems.
I tried everything that I found on Google, like reinstalling VC++, clean PC, registry, everything.
So my conclusion is that either there is another dll compiled in another version of Visual Studio (2010) and it`s somehow conflicting with my dll ?!
Or, I have some memory leak, which I cannot find.
I use the following functions in my DLL which (I think) is the issue:
sscanf(); // DISABLED IT FOR TEST, BUT STILL GET ERROR
fprintf_s();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DisableThreadLibraryCalls(hModule);
DetourRestoreAfterWith();
_beginthreadex();
strtoul();
Example function I use for logging:
void ##SOFTWARE-CLASS##::write_log(char *text)
{
FILE *write_log;
char dateStr [9];
char timeStr [9];
_strdate( dateStr);
_strtime( timeStr );
write_log = fopen("##SOFTWARE-FILE##","a+");
fprintf_s(write_log,"[%s %s] %s \n", dateStr, timeStr, text);
fclose(write_log);
}
Nothing else is used that may cause floating errors...
The dll is hooked properly, I have no warnings, and no errors.
I must mention, that I have created an empty DLL, with a MessageBox, at the first run, I was getting the same error, but after switching to /fp:strict, the error disappeared. So I did the same thing to my project, but the error is still there. I even recoded the whole project, just to see if it fixes the problem, but no.
Please give me advice on how can I solve this problem, as this is the third day that I am testing...
From MSDN : R6002 the document says that a program will only load floating point support if needed. What this means, is that the detoured code is being injected into binaries which did not initialize the floating point subsystem. The solution would be to relink your commercial product without requiring the floating point code, or to relink with an alternative floating point library.
You could try and detect the missing initialization and perform it yourself, but that would have a larger impact on the injected system, and possibly create instabilities.
Use a debugger with the failing executable, and you should be able to get a call stack which identifies where the failure occurs.
I need to decompile a windows program which the source code was lost for a long time.
I am using boomerang in Windows 7 for this. However, it looks broken, gives this message and quits:
Could not open dynamic loader library Win32BinaryFile.dll (error #998)
Googling about it gives no useful results. Looking in the boomerang source code, it is apparently coming from this:
00137 hModule = LoadLibraryA(libName.c_str());
00138 if(hModule == NULL) {
00139 int err = GetLastError();
00140 fprintf( stderr, "Could not open dynamic loader library %s (error #%d)\n", libName.c_str(), err);
00141 fclose(f);
00142 return NULL;
00143 }
I.e. LoadLibraryA is failing with the status 998.
What could I do to fix that?
Edit, four hours later:
The program that I want to decompile is a work that me and a friend implemented in 2005. The source just gone in the mean time without we seeing that. Now, in 2013, when we searched it, nothing was found. In retrospect, it was probably lost in 2008 or in 2010, two occasions where my computer hardware crashed and I needed to get a new computer (and lost a lot of data with that). We had several backups scattered in several places, but after an exhaustive search, I found nothing.
I know that since boomerang is open source, I could just get its source code and hack it around. However, that sort of task is not what I originally intended to do, since the focus is just to decompile my program and I guess that I am missing something simple, since it can't load the DLL while it is clearly there.
I don't need the exact code back, just a sketch of what were the exact details of the algorithm that were implemented. Having that, I can rewrite the rest again.
Im starting a protector/packer/binder like project.
the goal is when you have a full app directory with
/images/
/music/
base *.ini files
dlls
exes
you just use packer.exe on it and all these files are packed, encrypted, and stored in the resulting exe.
the resulting exe then creates a transparent virtual filesystem that falls back to the "real" one if a file is not found.
i allready can handle (not very accurately) loading dlls from memory, etc but i have a problem with the hmm hooks..
for now, as a ProofOfConcept im attaching a debbuger (written in c++) to a target.exe
it looks somewhat like
======= Started [target.exe] =======
> Placing breakpoint on EP : 0x401130
Process started
Loaded module : [target.exe]
Loaded module : [ntdll.dll]
Loaded module : [kernel32.dll]
[...]
Break point at [0x401130]
> Restored EP byte.
Loaded module : [bass.dll]
Break point at [0x760fcc4e]
Found set bp : kernel32!CreateFileW
[!] CreateFileW Callback Function :
FileName : C:\Users\user\Desktop\cppve\loader\bin\Debug\target.exe
Access : 0x80000000
Return Addr: 0x741b91e6
> Re-setting bp at [0x760fcc4e]
Break point at [0x760fcc4e]
Found set bp : kernel32!CreateFileW
[!] CreateFileW Callback Function :
FileName : .\beyond_v.mod
Access : 0x80000000
Return Addr: 0x760fcfa0
i am handling breakpoints in the debugger for things like CreateFileW ReadFile etc
im having problems in supplying the target with useable data.
should i create a fake handle and then catch it and process it ? or are there too many things that can go very wrong with that approach ?
here is a sample callback function for CreateFileW
void callback_createfilew(CONTEXT* ct){
//stub
cout<<"[!] CreateFileW Callback Function :"<<endl;
void* returnaddr=MemReadDwordPtr(hProcess,(void*)ct->Esp);
string fn=MemReadCString(hProcess,MemReadDwordPtr(hProcess,(void*)ct->Esp+4),true);
void* access=MemReadDwordPtr(hProcess,(void*)ct->Esp+8);
void* sharemode=MemReadDwordPtr(hProcess,(void*)ct->Esp+12);
void* dwCreationDisposition=MemReadDwordPtr(hProcess,(void*)ct->Esp+20);
void* dwFlagsAndAttributes=MemReadDwordPtr(hProcess,(void*)ct->Esp+24);
cout<<" FileName : "<<fn<<endl;
cout<<" Access : "<<(void*)access<<endl;
cout<<" Return Addr: "<<(void*)returnaddr<<endl;
if(fn.compare(".\\beyond_v.mod")==0){
// this is wrong, we need to call it from the target process...
HANDLE ret=CreateFileA(".\\_beyond_v.mod",(DWORD)access,(DWORD)sharemode,NULL,(DWORD)dwCreationDisposition,(DWORD)dwFlagsAndAttributes,NULL);
ct->Esp+=0x20;
ct->Eax=(DWORD)ret;
ct->Eip=(DWORD)returnaddr;
}
should i make a codecave in the process and push shellcodes [ Edit: sorry, i use many of these words to describe different things but i think you will catch what i ment :) ] there to execute my faking code ?
or maybe inject a dll that will handle int3s and pass control to it via exception handlers set up by the loader ? however that can proove to be tricky... that dll would have to be in the virtual filesystem ! so i would have to hand-load it before any other initialisation takes place.
i would like, in the final version, to completly drop the debugger. it will only cause problems and seriously comprimise the protector part of the project.
If you want your "packer" to operate transparently on precompiled binaries and want everything to be inside the resultant single binary, the packer needs to add the hooking code to the binary, perhaps making it execute as the very first thing and only then pass control to the original entry point of the binary. This isn't very trivial, although is certainly doable.
But you have another problem here. This hooking code will contain the decryption code and probably the key as well and this all thing is breakable by a good programmer with a debugger and some other tools.
As for fake handles, I'd see if it's possible to open a file multiple times and get different handles. If it is, just open any existing file for reading in a shared mode, remember the handle and use it for an in-memory file. Need another handle? Open the file again to get one. That will guarantee no collision with other real handles.
I'm trying to get symbols from addresses I got from my stack, but SymFromAddr keeps failing with system error 126 (The specified module could not be found.)
I'm initializing the symboling thing with
SymInitialize(m_processHandle, NULL, TRUE);
(the last parameter == true ==> It loads the PDB automatically)
and I use SymFromAddr like this:
SYMBOL_INFO_PACKAGE sym = { sizeof(sym) };
sym.si.MaxNameLen = MAX_SYM_NAME;
DWORD64 displacement = 0;
bool ok = SymFromAddr(m_processHandle, address, &displacement, &sym.si);
The code is in C++ on windows.
and the PDB FILE IS IN THE DIRECTORY OF THE EXE!
What am I doing wrong?
thanks :)
SymFromAddr is a little bit capricious.
If any LoadLibrary occur between SymInitialize and SymFromAddr it may not work. If SymFromAddr you can perfom a SymInitialize again (hint: you can cache address to avoid a lot of SymInitialize which is a huge CPU consummer)
64 bits implementation of SymFromAddr (ie. SymFromAddr64) works better
If code is not optimized it'll work better
VC9 generated pdb works better than older version.
You can find some idea in the following code
http://code.google.com/p/nprof/source/browse/0.11/Hook/StackWalker.cpp?r=281
Decimal: 143196173
Hex: 0x889000D
Results from a call to IAudioSessionControl2->GetProcessId().
GetLastError = 126*
Message = "The specified module could not be found"
I'm not really sure how to interpret this error. Additionally, I can't find a description of the HRESULT anywhere. The documented return codes are S_OK, E_POINTER, AUDCLNT_E_NO_SINGLE_PROCESS, and AUDCLNT_E_DEVICE_INVALIDATED.
Anyone know what this code indicates?
*This is an error marshalled across a managed/unmanaged boundary, obtained by Marshal.GetLastError with a Win32Exception providing the message. It could be bogus, but its what I've got. The HRESULT is pulled out of the unmanaged code directly.
Further investigation, FAILED() doesn't seem to think this is an error. However, the out parameter is cleared (set to 0) which doesn't really make sense. Also, GetErrorInfo returns S_FALSE; so there isn't any additional debug info to go on.
This is AUDCLNT_S_NO_CURRENT_PROCESS - I realized that it somehow missed the Windows 7 SDK headers too late.
The SDK documentation is going to be updated to reflect this.
The result means that the session is a cross process session. The process ID returned is the process ID for the first process which created the session, but if you get this result, you really can't depend on the process ID since the process ID isn't unique.
COM methods can set IErrorInfo on failure. Try to retrieve it - it can contain additional information. In unmanaged code you use GetErrorInfo() for that.