-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupgrade.c
82 lines (62 loc) · 1.98 KB
/
upgrade.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
/* Copyright 2021. Martin Uecker
*
* gcc -Wall -O2 -z noexecstack upgrade.c
*
*
* */
#include <assert.h>
#include <stdio.h>
#if __GNUC__ >= 5
#define NESTED_CHAIN(p) \
({ \
struct { unsigned short mov1; unsigned int addr; unsigned short mov2; void* chain; unsigned int jmp; } \
__attribute__((packed))* __t = (void*)p; \
assert((0xbb41 == __t->mov1) && (0xba49 == __t->mov2) && (0x90e3ff49 == __t->jmp)); \
__t->chain; \
})
#define NESTED_ADDR(p) \
({ \
__auto_type __p = (p); \
struct { unsigned short mov1; unsigned int addr; unsigned short mov2; void* chain; unsigned int jmp; } \
__attribute__((packed))* __t = (void*)__p; \
assert((0xbb41 == __t->mov1) && (0xba49 == __t->mov2) && (0x90e3ff49 == __t->jmp)); \
(typeof(__p))(unsigned long)__t->addr; \
})
#else
#define NESTED_CHAIN(p) \
({ \
struct { unsigned short mov1; void* addr; unsigned short mov2; void* chain; unsigned int jmp; } \
__attribute__((packed))* __t = (void*)p; \
assert((0xbb49 == __t->mov1) && (0xba49 == __t->mov2) && (0x90e3ff49 == __t->jmp)); \
__t->chain; \
})
#define NESTED_ADDR(p) \
({ \
__auto_type __p = (p); \
struct { unsigned short mov1; void* addr; unsigned short mov2; void* chain; unsigned int jmp; } \
__attribute__((packed))* __t = (void*)__p; \
assert((0xbb49 == __t->mov1) && (0xba49 == __t->mov2) && (0x90e3ff49 == __t->jmp)); \
(typeof(__p))__t->addr; \
})
#endif
#ifndef __x86_64__
#error only supported on x86_64
#endif
#define NESTED_UPGRADE(self, ptr, args) \
if (self != ptr) return __builtin_call_with_static_chain(NESTED_ADDR((typeof(self)*)ptr) args, NESTED_CHAIN(ptr))
int bar(int (*p)(void* data, int x), void* data)
{
return p(data, 4);
}
int main()
{
int x = 3;
int r;
int foo(void* self, int y)
{
NESTED_UPGRADE(foo, self, (self, y));
return x + y;
}
r = bar(NESTED_ADDR(foo), foo);
printf("%d\n", r);
}