-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinjector.cpp
More file actions
158 lines (134 loc) · 3.99 KB
/
Copy pathinjector.cpp
File metadata and controls
158 lines (134 loc) · 3.99 KB
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
/*
Copyright (c) 2014 Daniel Rempel <danil.rempel@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/*
All information in README.
*/
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
/*
mapWritableMemory():
Method creates about 8192 + length bytes memory, changes access rights to +rwx on length of them.
Arguments:
length - count bytes to prepare
deleteptr - pointer to voidptr, receives address of the whole mapped memory area (not only executable area) or NULL on error
Return value:
address of the first of length bytes of executable memory or NULL on error
Mapped memory must be free()-d by hand, using deleteptr, not return value!
*/
void* mapWritableMemory(int length, void** deleteptr);
/*
generateCode():
calls mapWritableMemory, calls writeCode, prepares stack, executes the code
*/
void generateCode();
/*
writeCode():
writes two sequences of opcodes to given address:
popq %rax
call %rax
popq %rax
jmp %rax
the opcodes expect to receive address of functions and return point from stack
*/
void writeCode(void* mem);
/*
Method which is executed to show that the code works
*/
void beeper() {
printf("beep-beep\n");
}
/*
Opcodes which I used
58 popq %rax
FFD0 call %rax
58 popq %rax
FFE0 jmp %rax
*/
void writeCode(void* mem) {
char* data = (char*) mem;
data[0] = 0x58; // popq %rax
data[1] = 0xff; // call %rax
data[2] = 0xd0; //
data[3] = 0x58; // popq %rax
data[4] = 0xff; // jmp %rax
data[5] = 0xe0; //
}
void generateCode() {
void* deleteptr;
void* memptr = mapWritableMemory(1000, &deleteptr);
if(memptr == NULL) {
printf("generateCode(): mapWritableMemory() failed\n");
return;
}
writeCode(memptr);
// push return address to stack
// $ is mandatory, because otherwise I don't know what happens. Segfault happens
asm( "pushq $back\n" );
// push the address of demonstrational function
asm( "pushq %0\n"
:
:"r"(&beeper)
:
);
// jump to prepared code
asm( "jmp %0\n"
:
:"r"(memptr)
:
);
// return anchor
asm( "back: nop\n" );
// clean everything
free(deleteptr);
}
void* mapWritableMemory(int length, void** deleteptr) {
// firstly, allocate some memory
// we allocate 8192 bytes more
// Not sure if we need more than 4096, because my memory uses 4 kb pages
// but let's leave it like that
void* memptr = malloc(4096*2 + length);
if(memptr == NULL) {
printf("mapWritableMemory(): Got no mem!\n");
return NULL;
}
// We've got memory, lets give the caller ability to free() it afterwards
*deleteptr = memptr;
unsigned long shift = -1;
int result;
do {
++shift;
// maybe we may jump by 16 bytes, but we won't die if we'll do 4k iterations instead of 255
}
// try to set rights on memory until we receive positive result
while ( (result = mprotect ( (void*) ( memptr+shift ), length, PROT_READ|PROT_WRITE|PROT_EXEC ) ) == -1);
if(result == 0) {
// success
return (void*)(memptr+shift);
}
else {
// fail: don't forget to turn off the lights
free(memptr);
*deleteptr = 0;
return NULL;
}
}
int main() {
generateCode();
}