aboutsummaryrefslogtreecommitdiff
path: root/entry.c
blob: f5bdf3d081913a879313f969e0452a3197753d96 (plain)
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
 * clang -s -m32 -nostdlib -nodefaultlibs -fPIC -Wl,-shared entry.c -oentry
 */

__attribute__((naked)) void entry() {
    __asm__ volatile(
      ".intel_syntax noprefix\n"
      "push eax\n"
      "pushad\n"
      "pushfd\n"

      "sub esp, 0x5000\n"

      // get the pathname of the binary with readlink
      "mov eax, 85\n"
      // /proc/self/exe
      "push 0x6578\n"
      "push 0x652f666c\n"
      "push 0x65732f63\n"
      "push 0x6f72702f\n"
      // pathname of the symlink
      "mov ebx, esp\n"
      // buf
      "lea ecx, [esp + 0x4010]\n"
      // bufsiz
      "mov edx, 0xfff\n"
      "int 0x80\n"

      // cleanup arguments from stack
      "add esp, 0x10\n"

      "cmp eax, 0\n"
      "jle fail\n"

      // save the length of the pathname
      "mov edi, eax\n"

      // write newline at the end of the pathname
      "lea ecx, [esp + 0x4000 + eax]\n"
      "mov byte ptr [ecx], 0xa\n"

      // inc saved length, to also compare the newline
      "inc edi\n"

      // open /proc/self/maps to get the base address of the binary
      "mov eax, 5\n"
      "push 0x737061\n"
      "push 0x6d2f666c\n"
      "push 0x65732f63\n"
      "push 0x6f72702f\n"
      "mov ebx, esp\n"
      "xor ecx, ecx\n"
      "int 0x80\n"

      // cleanup arguments from stack
      "add esp, 0x10\n"

      "cmp eax, 0\n"
      "jl fail\n"

      // save the fd
      "mov esi, eax\n"

      // loop to get the program base
      // read from /proc/self/maps
      "read:"
      "mov eax, 3\n"
      "mov ebx, esi\n"
      "mov ecx, esp\n"
      "mov edx, 0x4000\n"
      "int 0x80\n"

      "cmp eax, 0\n"
      "jle close\n"

      // set maps iterator to 0
      "xor ecx, ecx\n"
      // set pathname iterator to 0
      "xor edx, edx\n"
      // ebp will be set to 0, if we got a match
      "mov ebp, 1\n"

      "find_pathname:\n"
      "cmp ecx, eax\n"
      "jge find_pathname_finished\n"

      // char from the maps buffer
      "movzx ebx, byte ptr [esp + ecx]\n"
      // compare with char in the pathname buffer
      // always inc maps iterator
      "inc ecx\n"
      "cmp byte ptr [esp + edx + 0x4000], bl\n"
      "jnz find_pathname_no_match\n"
      // inc pathname iterator
      "inc edx\n"
      // have we found the full pathname?
      "cmp edx, edi\n"
      "jnz find_pathname\n"
      // jepp
      "xor ebp, ebp\n"
      "jmp find_pathname_finished\n"

      "find_pathname_no_match:\n"
      // reset pathname iterator
      "xor edx, edx\n"
      "jmp find_pathname\n"

      "find_pathname_finished:\n"

      // did we have a match?
      "test ebp, ebp\n"
      "jnz read\n"
      // jepp
      // search the beginning of the maps line
      "find_beginning_of_line:"
      "xor ebx, ebx\n"
      "dec ecx\n"
      // is the maps iterator non null?
      "cmp ecx, 0\n"
      "setg bl\n"
      // is the char before the maps iterator not a '\n'
      "cmp byte ptr [esp + ecx - 1], 0xa\n"
      "setnz bh\n"
      "test bl, bh\n"
      "jnz find_beginning_of_line\n"

      // convert the 8 hex digits to 4 bytes => the base address
      "xor edx, edx\n"
      "mov ebp, ecx\n"
      "add ecx, 8\n"
      "convert_base:"
      "cmp ebp, ecx\n"
      "jge close\n"
      "rol edx, 4\n"

      // check if it's a number
      "xor ebx, ebx\n"
      "cmp byte ptr [esp + ecx + ebp], 0x30\n"
      "setge bl\n"
      "cmp byte ptr [esp + ecx + ebp], 0x39\n"
      "setle bh\n"
      "sub byte ptr [esp + ecx + ebp], 0x30\n"
      "xor dl, byte ptr [esp + ecx + ebp]\n"
      "inc ebp\n"
      "test bl, bh\n"
      "jnz convert_base\n"
      // wasn't a number, revert stuff
      "dec ebp\n"
      "xor dl, byte ptr [esp + ecx + ebp]\n"
      "add byte ptr [esp + ecx + ebp], 0x30\n"
      // check if it's a lowercase hex letter
      "xor ebx, ebx\n"
      "cmp byte ptr [esp + ecx + ebp], 0x61\n"
      "setge bl\n"
      "cmp byte ptr [esp + ecx + ebp], 0x7a\n"
      "setle bh\n"
      "sub byte ptr [esp + ecx + ebp], 0x57\n"
      "xor dl, byte ptr [esp + ecx + ebp]\n"
      "inc ebp\n"
      "test bl, bh\n"
      "jnz convert_base\n"
      // wasn't a lowercase hex letter, revert stuff
      "dec ebp\n"
      "xor dl, byte ptr [esp + ecx + ebp]\n"
      "add byte ptr [esp + ecx + ebp], 0x61\n"
      // check if it's an uppercase hex letter
      "xor ebx, ebx\n"
      "cmp byte ptr [esp + ecx + ebp], 0x41\n"
      "setge bl\n"
      "cmp byte ptr [esp + ecx + ebp], 0x5a\n"
      "setle bh\n"
      "sub byte ptr [esp + ecx + ebp], 0x37\n"
      "xor dl, byte ptr [esp + ecx + ebp]\n"
      "inc ebp\n"
      "test bl, bh\n"
      "jnz convert_base\n"
      // wasn't an uppercase hex letter, failed to convert
      "xor edx, edx\n"
      "jmp close\n"

      "jmp read\n"

      "close:\n"
      // close the fd
      "mov eax, 6\n"
      "mov ebx, esi\n"
      "int 0x80\n"

      // if the base hasn't been found quit
      "test edx, edx\n"
      "jz fail\n"

      // set the oep as return
      "add edx, 0x2050\n"
      "mov dword ptr [esp + 0x5024], edx\n"
      "sub edx, 0x50\n"

      "mov ebp, eax\n"
      "inc eax\n"
      "inc eax\n"

      "dec_outer_loop:\n"
      "mov esi, 0x466c7578\n"
      "xor ebx, ebx\n"
      "cmp eax, ebp\n"
      "jz dec_outer_loop_finished\n"

      "mov ecx, 0x400\n"

      "dec_inner_loop:\n"
      "xor dword ptr [edx], ebx\n"
      "xor dword ptr [edx], esi\n"
      "ror esi, 8\n"
      "mov ebx, dword ptr [edx]\n"
      "add edx, 4\n"
      "loop dec_inner_loop\n"

      "dec eax\n"
      "jmp dec_outer_loop\n"

      "dec_outer_loop_finished:\n"

      "add esp, 0x5000\n"
      "popfd\n"
      "popad\n"
      "ret\n"

      "fail:\n"
      // exit the program gracefully
      "mov eax, 1\n"
      "xor ebx, ebx\n"
      "int 0x80");
}