I'm working with Visual Studio 2012 & 2017 with C++ 11 and Pelles C 9.0 with C++ 11...
When I build a empty program and DLL but they contain lots of unused imports in pe file!
VC++ has 26 imports of KERNEL32 and Pelles has 70 imports of KERNEL32
My project is totally empty!
I need to remove them from linker and compiled file.
I have an DLL is compiled with Pelles C and it only has 4 import that it really use :
KERNEL32.dll
VirtualProtect ord:0 rva2iat: 000012A0
GetModuleHandleA ord:0 rva2iat: 000012A8
Sleep ord:0 rva2iat: 000012B0
CreateThread ord:0 rva2iat: 000012B8
I want to do the same , I don't need any of those 70 imports and functions , How Can I do it ?
Thanks to TimoVJL | Here's the solution :
#include <windows.h>
#ifdef _WIN64
#pragma comment(linker, "/ENTRY:DllMainCRTStartup")
#else
#pragma comment(linker, "/ENTRY:_DllMainCRTStartup#12")
#endif
BOOL WINAPI DllMainCRTStartup(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH) g_hmod = hDLL;
return TRUE;
}
Related
I was using this source code for learning purpose https://github.com/W1lliam1337/digital-sdk. It was working since last week but then I changed some Visual Studio settings and copy&pasted source to other folder and today it started not working anymore.There it generates some dll files on debug/release folder when I compile project.I was only injecting cheat dll to make it work and it was working but now its not working if I only inject cheat dll and then as you can see I tried to inject all of them together after I click inject button 3 times Its worked. Can someone help me with that ? Other projects works well. What did I change and its caused this ? I really have no idea I don't have knowledge on Visual Studio settings too.Please someone help me
Edit : I tried other injectors too still not working Its more like I messed up with project/Visual Studio settings
VIDEO
https://streamable.com/rvn7bg
Here is how my DllMain and Thread looks like.
DWORD WINAPI HackThread(HMODULE hModule)
{
AllocConsole();
FILE* f;
freopen_s(&f, "CONOUT$", "w", stdout);
//My Stuff bla bla..
while (!GetAsyncKeyState(VK_END) & 1)
{
Sleep(20);
}
if (f) fclose(f);
FreeConsole();
FreeLibraryAndExitThread(hModule, 0);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hmodule,
DWORD reason_for_call,
LPVOID reserved
) {
if ( reason_for_call != DLL_PROCESS_ATTACH )
return FALSE;
/* #xref: https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-disablethreadlibrarycalls */
DisableThreadLibraryCalls( hmodule );
std::thread( instance ).detach( );
return TRUE;
}
I have a most peculiar bug... I'm hooking HeapAlloc to log all calls and get the name the DLLs calling the API. The code works on Windows 7, but doesn't work on Windows 10. I use miniHook for hooking. Everything compiled with Visual Studio 2019, v142.
// BasicTest.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <windows.h>
#include <iostream>
#include <intrin.h>
#include <psapi.h>
#include "minihook.h"
#pragma intrinsic(_ReturnAddress)
#pragma comment(lib, "libMinHook.x64.lib") //v142
LPVOID(WINAPI* OldHeapAlloc)(HANDLE, DWORD, SIZE_T);
template <typename T>
inline MH_STATUS MH_CreateHookApiEx(
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, T** ppOriginal)
{
return MH_CreateHookApi(
pszModule, pszProcName, pDetour, reinterpret_cast<LPVOID*>(ppOriginal));
}
BOOL intercept = FALSE;
int iMbox = 0;
int iTotal = 0;
LPVOID HookedHeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes) {
iTotal++;
LPVOID ptr = OldHeapAlloc(hHeap, dwFlags, dwBytes);
if (intercept) {
return ptr;
}
intercept = TRUE;
iMbox++;
HMODULE hModule;
char lpBaseName[32];
if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)_ReturnAddress(), &hModule) != 0) {
if (GetModuleBaseNameA(GetCurrentProcess(), hModule, lpBaseName, sizeof(lpBaseName)) != 0) {
printf("Reserved %d at %08x from %s\n", dwBytes, ptr, lpBaseName);
}
}
intercept = FALSE;
return ptr;
}
int main()
{
if (MH_Initialize() != MH_OK)
{
return 1;
}
if (MH_CreateHookApiEx(
L"ntdll.dll", "RtlAllocateHeap", &HookedHeapAlloc, &OldHeapAlloc) != MH_OK)
{
return 1;
}
if (MH_EnableHook(MH_ALL_HOOKS) != MH_OK)
{
return 1;
}
MessageBoxA(NULL, "This is a test", "Test", MB_OK);
MH_DisableHook(MH_ALL_HOOKS);
printf("RtlAllocateHeap calls for MessageBoxA = %d\n", iMbox);
printf("RtlAllocateHeap total calls = %d\n", iTotal);
return 0;
}
intercept is to prevent recurrence inside HookedHeapAlloc. Because GetModule* like functions call HeapAlloc. It is important to note that the code works if you call HeapAlloc yourself, even with recurrence (HeapAlloc -> HeapAlloc -> HeapAlloc). You can call HeapAlloc 5000 times, and put a depth of 5 recursion inside HookedHeapAlloc (intercept prevents any crash).
But when using MessageBoxA, the program hangs on Windows 10 (tested in 20H2 and 21H1).
The output on Windows 7 is something like that
[.......]
Reserved 24 at 004528f0 from KERNELBASE.dll
Reserved 40 at 0046afb0 from KERNELBASE.dll
Reserved 520 at 02aae4f0 from uxtheme.dll
Reserved 512 at 0046dd90 from IMM32.DLL
Reserved 48 at 00468960 from ntdll.dll
Reserved 48 at 004689a0 from ntdll.dll
Reserved 512 at 004612a0 from USER32.dll
Reserved 48 at 004689e0 from ntdll.dll
Reserved 48 at 00468a20 from ntdll.dll
Reserved 48 at 00468a60 from ntdll.dll
RtlAllocateHeap calls for MessageBoxA = 828
RtlAllocateHeap total calls = 1657
On Windows 10, the program hangs after a couple of outputs. When inside a debugger, it hangs at ZwWaitForAlertByThreadId.
Thanks for the help :)
So, answering my own question. I found the issue.
GetModuleHandleExA increments the module's reference count. Turns out, if you increment the reference count too much, there is a deadlock. I have no idea why... Adding the flag GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT fixes the issue.
I have created this dll in Go with an exported function which works fine while I'm calling it with rundll32 or from a c++ executable with the loadlbraryA. But I get an error when calling from c++ dll which I tried to read GetLastError() And it says cannot find the module you are calling. I tried every possible way to give the full path to loadlibraryA but the same error happens and the handle to Go DLL is null every time. Also, I examined the Go DLL, and the Test function is exported properly.
In short, It works in calling Test():
From rundll32
From c++ main() and loadlibrary
And doesn't work in Test():
From c++ DllMain() and loadlibrary
From c++ DllMain() and loadlibrary directly called from kernel32.dll
From c++ DllMain() and a ThreadFunction created in DllMain()
Folder structure
ProjectFolder
-- main.go
-- dllmain.h
-- dllmain.go
Build with
go build -buildmode=c-shared -o my-go-library.dll main.go
Call example dll
rundll32 my-go-library.dll Test
Working source
main.go:
package main
import "C"
import (
"syscall"
"time"
"unsafe"
)
//export Test
func Test() {
MessageBoxPlain("TestMsgbox","Test")
main()
}
//export OnProcessAttach
func OnProcessAttach() {
MessageBoxPlain("OnAttachMsgbox","OnAttach")
Test()
}
// MessageBox of Win32 API.
func MessageBox(hwnd uintptr, caption, title string, flags uint) int {
ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call(
uintptr(hwnd),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(title))),
uintptr(flags))
return int(ret)
}
// MessageBoxPlain of Win32 API.
func MessageBoxPlain(title, caption string) int {
const (
NULL = 0
MB_OK = 0
)
return MessageBox(NULL, caption, title, MB_OK)
}
func main() {}
dllmain.h:
#include <windows.h>
void OnProcessAttach(HINSTANCE, DWORD, LPVOID);
typedef struct {
HINSTANCE hinstDLL; // handle to DLL module
DWORD fdwReason; // reason for calling function // reserved
LPVOID lpReserved; // reserved
} MyThreadParams;
DWORD WINAPI MyThreadFunction(LPVOID lpParam) {
MyThreadParams params = *((MyThreadParams*)lpParam);
OnProcessAttach(params.hinstDLL, params.fdwReason, params.lpReserved);
free(lpParam);
return 0;
}
BOOL WINAPI DllMain(
HINSTANCE _hinstDLL, // handle to DLL module
DWORD _fdwReason, // reason for calling function
LPVOID _lpReserved) // reserved
{
switch (_fdwReason) {
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
{
MyThreadParams* lpThrdParam = (MyThreadParams*)malloc(sizeof(MyThreadParams));
lpThrdParam->hinstDLL = _hinstDLL;
lpThrdParam->fdwReason = _fdwReason;
lpThrdParam->lpReserved = _lpReserved;
HANDLE hThread = CreateThread(NULL, 0, MyThreadFunction, lpThrdParam, 0, NULL);
// CreateThread() because otherwise DllMain() is highly likely to deadlock.
}
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
}
return TRUE; // Successful.
}
dllmain.go:
package main
//#include "dllmain.h"
import "C"
C++ DLL
Now the c++ dll source which calls Test from my-go-library.dll:
#include "pch.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winternl.h>
#include <malloc.h>
#include <intrin.h>
#include <Windows.h>
#include <winternl.h>
#include <malloc.h>
#include <ostream>
#include <iostream>
#include <string>
using namespace std;
typedef int(__stdcall* TestFromGo)();
void Error()
{
wchar_t err[256];
memset(err, 0, 256);
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err, 255, NULL);
int msgboxID = MessageBoxW(NULL,err,(LPCWSTR)L"Error",MB_OK);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
MessageBoxA(0, "The C++ DLL", "title", 0);
HINSTANCE hGetProcIDDLL = LoadLibraryA("C:\\User\\.....path to go dll.....\\my-go-library.dll");
if (!hGetProcIDDLL) {
Error();
MessageBoxA(0, "could not load the dynamic library", "Test", 0);
}
TestFromGo TestFunction = (TestFromGo)GetProcAddress(hGetProcIDDLL, "Test");
if (!TestFunction) {
MessageBoxA(0, "could not locate the function", "Test", 0);
}
TestFromGo();
}
extern "C" __declspec(dllexport) void jojo()
{
DllMain(0, 1, 0);
}
Calling the c++ dll
Now this one supposed to call jojo then DllMain then calling my-go-library.dll and Test
rundll32 theCiplasplas.dll jojo
I can't help with Golang. But there are problems in your DllMain. There are only a limited set of API functions allowed in DllMain.
The Dynamic-Link Library Best Practices explicitly states that you should not create a thread in DllMain:
You should never perform the following tasks from within DllMain:
Call CreateThread. Creating a thread can work if you do not synchronize with other threads, but it is risky.
Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash
So it might work when you use rundll32, it might not work if you load your DLL in another way.
Edit : Added excerpt about LoadLibrary
I created a simple DLL that open cmd.exe.
I did it with these options:
In the default dlllmain.cpp I added a code that creates a new cmd.exe:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <Windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
BOOL h = CreateProcessW(L"C:\\Windows\\System32\\cmd.exe", L"", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
These three lines below the DLL_PROCESS_ATTACH worked for me when I tested it with a console application.
I am expecting that every process that will load this DLL will open cmd.exe.
I tried to load the DLL with PowerShell:
Add-Type -TypeDefinition #"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public static class Kernel32
{
[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
public static extern IntPtr LoadLibrary(
[MarshalAs(UnmanagedType.LPStr)]string lpFileName);
}
"#
$LibHandle = [Kernel32]::LoadLibrary("C:\tmp\myDll.dll")
But nothing happens, the value of the $LibHandle was 0.
What I am doing wrong ?
I found what was the problem.
My system is 64 bit and the file was compiled in 32 bit.
I needed to specify in Visual Studio that I am compiling it in x64 bit.
I didn't check it in the beginning because I thought that when I am compiling it on "Any CPU" mode, it compile the file in 64 bit automatically as the OS architecture.
Now it works fine.
I am attempting to use the WinAPI function GUIDFromString() but it requires some finagling to include it in my project.
According to the msdn documentation:
This function is not declared in a header or exported by name from a
.dll file. It must be loaded from Shell32.dll as ordinal 703 for
GUIDFromStringA and ordinal 704 for GUIDFromStringW.
It can also be accessed from Shlwapi.dll as ordinal 269 for
GUIDFromStringA and ordinal 270 for GUIDFromStringW.
I have never loaded a DLL before so I am not sure what I should do and I am unsure if loading the DLL is enough, do I also have to include an 'ordinal' with the number 703? Would anyone be able to provide any advice on what I need to do to use this function and even an example?
My attempt below does not work(I am using VC++ 2010 Express):
#pragma comment(lib, "shell32.lib") // if I am including the dll do I need to include the lib aswell?
// I've heard that the dll location differs across versions of windows
// Does anyone know of a Cross-Windows-Version way to include Shell32.dll no matter where it is? Maybe use a keyword like "%SYSTEM%/Shell32.dll"
HINSTANCE shell32DLL = LoadLibary("C:/System/Shell32.dll");
// Now do I include 'Ordinal 703' as described in msdn? And how do I do that?
If you read the documentation for GUIDFromString(), it says:
GUIDFromString is available through Windows XP with Service Pack 2 (SP2) or Windows Vista. It might be altered or unavailable in subsequent versions. Applications should use CLSIDFromString or IIDFromString in place of this function.
CLSIDFromString() and IIDFromString() are both exported by name from Ole32.dll, so you can use them like you would any other DLL function.
With that said, if you still want to use GUIDFromString() then use LoadLibrary() to load shell32.dll and then use GetProcAddress() to access the function. MSDN documentation demonstrates how to do that. To load a function by ordinal, you can use the MAKEINTRESOURCE() macro when calling GetProcAddress().
So, for example:
// MAKEINTRESOURCE() returns an LPTSTR, but GetProcAddress()
// expects LPSTR even in UNICODE, so using MAKEINTRESOURCEA()...
#ifdef UNICODE
#define MAKEINTRESOURCEA_T(a, u) MAKEINTRESOURCEA(u)
#else
#define MAKEINTRESOURCEA_T(a, u) MAKEINTRESOURCEA(a)
#endif
BOOL myGUIDFromString(LPCTSTR psz, LPGUID pguid)
{
BOOL bRet = FALSE;
typedef BOOL (WINAPI *LPFN_GUIDFromString)(LPCTSTR, LPGUID);
LPFN_GUIDFromString pGUIDFromString = NULL;
HINSTANCE hInst = LoadLibrary(TEXT("shell32.dll"));
if (hInst)
{
pGUIDFromString = (LPFN_GUIDFromString) GetProcAddress(hInst, MAKEINTRESOURCEA_T(703, 704));
if (pGUIDFromString)
bRet = pGUIDFromString(psz, pguid);
FreeLibrary(hInst);
}
if (!pGUIDFromString)
{
hInst = LoadLibrary(TEXT("Shlwapi.dll"));
if (hInst)
{
pGUIDFromString = (LPFN_GUIDFromString) GetProcAddress(hInst, MAKEINTRESOURCEA_T(269, 270));
if (pGUIDFromString)
bRet = pGUIDFromString(psz, pguid);
FreeLibrary(hInst);
}
}
return bRet;
}
Save the following lines as SHLWAPIX.DEF:
LIBRARY SHLWAPI
VERSION 6.0
EXPORTS
GUIDFromStringA #269
GUIDFromStringW #270
Save the following lines as SHLWAPIX.C:
// https://msdn.microsoft.com/en-us/library/bb776431.aspx
__declspec(dllexport)
int __stdcall GUIDFromStringA(void *_1, void *_2)
{ return 0; }
__declspec(dllexport)
int __stdcall GUIDFromStringW(void *_1, void *_2)
{ return 0; }
Run
CL.EXE /LD /Zl SHLWAPIX.C /link /DEF:SHLWAPIX.DEF /NOENTRY
to create the import library SHLWAPIX.LIB, then delete SHLWAPIX.OBJ, SHLWAPIX.EXP and SHLWAPIX.DLL
Save the following lines as SHLWAPIX.H:
#pragma once
#pragma comment(linker, "/DEFAULTLIB:SHLWAPIX.LIB")
__declspec(dllimport)
BOOL WINAPI GUIDFromStringA(LPCSTR psz, LPGUID pguid);
__declspec(dllimport)
BOOL WINAPI GUIDFromStringW(LPCWSTR psz, LPGUID pguid);
Finally save the following lines as SHLWAPIX.C:
#pragma comment(lib, "SHLWAPIX.LIB")
#pragma comment(lib, "USER32.LIB")
#pragma comment(linker, "/ENTRY:wWinMainCRTStartup")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS,5.0")
#pragma comment(linker, "/VERSION:1.0")
#define STRICT
#define UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "shlwapix.h"
VOID wWinMainCRTStartup()
{
GUID guid = {0};
WCHAR szBuffer[1025] = L"";
if (GUIDFromStringA("{00112233-4455-6677-8899-AABBCCDDEEFF}", &guid))
if (wsprintf(szBuffer, L"GUID = {%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",`
guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]) > 0)
MessageBox((HWND) NULL, szBuffer, L"GUIDFromStringA()", MB_OK);
if (GUIDFromStringW(L"{FFEEDDCC-BBAA-9988-7766-554433221100}", &guid))
if (wsprintf(szBuffer, L"GUID = {%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]) > 0)
MessageBox((HWND) NULL, szBuffer, L"GUIDFromStringW()", MB_OK);
}
Finally run CL.EXE /GS- SHLWAPIX.C to create SHLWAPIX.EXE, then run the latter.
This gives your an error "syntax error '('":
typedef BOOL WINAPI (*LPFN_GUIDFromString)(LPCTSTR, LPGUID);
The proper version is:
typedef BOOL (WINAPI *LPFN_GUIDFromString)(LPCTSTR, LPGUID);