Skip to content

Commit 5aefffc

Browse files
[函数调用]
1 parent 52092df commit 5aefffc

File tree

6 files changed

+305
-4
lines changed

6 files changed

+305
-4
lines changed

example_code/function/test.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#include <stdio.h>
2+
#include <string.h>
3+
#include <signal.h>
4+
#include <dlfcn.h>
5+
#include <errno.h>
6+
#include <stdint.h>
7+
#include <sys/mman.h>
8+
#include <unistd.h>
9+
10+
int MyFunction(int x, int y);
11+
int MyFunctionNew(int x, int y);
12+
13+
char new_func[] =
14+
{
15+
0x55,
16+
0x48, 0x89, 0xe5,
17+
0x89, 0x7d, 0xec,
18+
0x89, 0x75, 0xe8,
19+
20+
0xc7, 0x45, 0xfc, 0x0a, 0x00, 0x00, 0x00,
21+
22+
0xc7, 0x45, 0xf8, 0x01, 0x00, 0x00, 0x00,
23+
24+
0x8b, 0x45, 0xfc,
25+
0x5d,
26+
0xc3
27+
};
28+
29+
void sig_user1_handler(int sig, siginfo_t *si, void *data)
30+
{
31+
int pagesize = sysconf(_SC_PAGE_SIZE);
32+
if (pagesize < 0) {
33+
pagesize = 4096;
34+
}
35+
36+
int len = sizeof(new_func);
37+
38+
uintptr_t addr = (((uintptr_t)MyFunction) / pagesize) * pagesize;
39+
fprintf(stderr, "%s: iminus: %p, aligned: 0x%lx, sz %d\n", __func__, MyFunction, addr, len);
40+
if (mprotect((void*)addr, (uintptr_t)MyFunction - addr + len, PROT_WRITE|PROT_READ|PROT_EXEC) < 0) {
41+
fprintf(stderr, "%s\n", strerror(errno));
42+
}
43+
44+
memcpy((void*)MyFunction, (void*)new_func, len);
45+
46+
if (mprotect((void*)addr, (uintptr_t)MyFunction - addr + len, PROT_READ|PROT_EXEC) < 0) {
47+
fprintf(stderr, "%s\n", strerror(errno));
48+
}
49+
}
50+
51+
int MyFunction(int x, int y)
52+
{
53+
int a, b;
54+
a = 10;
55+
b = 1;
56+
57+
int val = a * x + b * y;
58+
return val;
59+
}
60+
61+
int MyFunctionNew(int x, int y)
62+
{
63+
int a = 10;
64+
return a;
65+
}
66+
67+
int main()
68+
{
69+
struct sigaction newact, oldact;
70+
sigemptyset(&newact.sa_mask);
71+
newact.sa_sigaction = sig_user1_handler;
72+
sigaction(SIGUSR1, &newact, &oldact);
73+
74+
void * ptr = &MyFunction;
75+
printf("addr %p , sizeof %d\n", ptr, sizeof(new_func));
76+
77+
int a = 10;
78+
int b = 10;
79+
80+
while (1)
81+
{
82+
int val = MyFunction(a, b);
83+
printf("val : %d \n", val);
84+
sleep(3);
85+
}
86+
return 0;
87+
}

example_code/function/test_asm.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <unistd.h>
4+
5+
void function()
6+
{
7+
while(1)
8+
{
9+
printf("hello,function!\n");
10+
sleep(1);
11+
}
12+
}
13+
14+
void test()
15+
{
16+
int val = 10;
17+
printf("val %d\n", val);
18+
19+
// set val = 11
20+
asm("movl $0xb, -0x4(%rbp)");
21+
printf("val %d\n", val);
22+
23+
long addr = function;
24+
asm("movl $0x401156, 0x18(%rbp)");
25+
}
26+
27+
int main()
28+
{
29+
printf("addr %p \n", &function);
30+
test();
31+
printf("hello,world!\n");
32+
return 0;
33+
}
34+
35+
// https://blog.csdn.net/yiftss/article/details/89474622

example_code/function/test_jmp.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <setjmp.h>
4+
5+
jmp_buf env;
6+
7+
int my_func(int a, int b)
8+
{
9+
if (b == 0) {
10+
printf("do not allow division by 0\n");
11+
longjmp(env, 1);
12+
}
13+
return a / b;
14+
}
15+
16+
int main(int argc, char const *argv[])
17+
{
18+
int res = setjmp(env);
19+
if (res == 0) {
20+
printf("return from setjmp\n");
21+
my_func(10, 0);
22+
} else {
23+
printf("return from longjmp: %d\n", res);
24+
}
25+
return 0;
26+
}

note/函数调用过程.md

Lines changed: 157 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,175 @@
2525

2626
* c调用汇编的代码
2727

28-
todo
28+
在c语言中,使用asm可以调用汇编:
29+
```
30+
void function();
31+
32+
void test()
33+
{
34+
int val = 10;
35+
printf("val %d\n", val);
36+
37+
// set val = 11
38+
asm("movl $0xb, -0x4(%rbp)");
39+
printf("val %d\n", val);
40+
41+
long addr = function;
42+
asm("movl $0x401156, 0x18(%rbp)");
43+
}
44+
```
45+
46+
完成代码:
47+
48+
[example_code](../example_code/function/test_asm.c)
2949
3050
## 函数栈切换
3151
3252
搞明白函数的调用过程,可以进一步去思考如何去进行函数切换。
3353
3454
1. 思路1:堆栈溢出攻击
3555
36-
覆盖返回地址,实现函数跳转
56+
覆盖返回地址,实现函数跳转。
57+
```
58+
#include <stdio.h>
59+
#include <stdlib.h>
60+
#include <unistd.h>
61+
#include <unistd.h>
62+
63+
void fun()
64+
{
65+
while(1)
66+
{
67+
printf("Hello, I'm fun!\n");
68+
sleep(1);
69+
}
70+
}
71+
72+
int foo2()
73+
{
74+
long a[5] = { 0 };
75+
76+
// 溢出攻击
77+
a[9] = fun; // 覆盖返回地址 // 为什么是a[9] 尝试不同的移动偏移去覆盖rbp的上一条地址 (不同的机器可能不太一样)
78+
}
79+
80+
int main()
81+
{
82+
printf("main \n");
83+
foo2();
84+
return 0;
85+
}
86+
```
87+
3788
3889
2. 思路2:覆盖函数的地址的汇编代码,实现函数跳转
3990
91+
```
92+
void fun()
93+
{
94+
while(1)
95+
{
96+
printf("Hello, I'm fun!\n");
97+
sleep(1);
98+
}
99+
}
100+
101+
int foo()
102+
{
103+
int a[5] = { 0 };
104+
105+
// 溢出攻击
106+
asm("mov $0x401136,%eax"); // 0x401136 是fun的入口地址
107+
asm("mov %rax,0x18(%rbp)");
108+
}
109+
```
110+
111+
fun的地址可以通过查看汇编代码找到:
112+
![](../pic/函数调用3.png)
113+
114+
执行结果:
115+
![](../pic/函数调用4.png)
116+
40117
3. 思路3:覆盖函数的地址首部,插入跳转到其他函数的汇编代码,实现函数跳转
41118
119+
如果想要从函数a调到函数b,可以把函数b的栈copy覆盖过去。
120+
121+
```
122+
// 希望跳转到的函数
123+
(gdb) disas/rs MyFunctionNew
124+
Dump of assembler code for function MyFunctionNew:
125+
0x0000000000401334 <+0>: 55 push %rbp
126+
0x0000000000401335 <+1>: 48 89 e5 mov %rsp,%rbp
127+
0x0000000000401338 <+4>: 89 7d ec mov %edi,-0x14(%rbp)
128+
0x000000000040133b <+7>: 89 75 e8 mov %esi,-0x18(%rbp)
129+
0x000000000040133e <+10>: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
130+
0x0000000000401345 <+17>: 8b 45 fc mov -0x4(%rbp),%eax
131+
0x0000000000401348 <+20>: 5d pop %rbp
132+
0x0000000000401349 <+21>: c3 retq
133+
End of assembler dump.
134+
```
135+
136+
137+
```
138+
// 希望跳转到的函数的对应的汇编代码
139+
char new_func[] =
140+
{
141+
0x55,
142+
0x48, 0x89, 0xe5,
143+
0x89, 0x7d, 0xec,
144+
0x89, 0x75, 0xe8,
145+
146+
0xc7, 0x45, 0xfc, 0x0a, 0x00, 0x00, 0x00,
147+
148+
0xc7, 0x45, 0xf8, 0x01, 0x00, 0x00, 0x00,
149+
150+
0x8b, 0x45, 0xfc,
151+
0x5d,
152+
0xc3
153+
};
154+
```
155+
156+
```
157+
// 用新的代码去覆盖旧的函数的代码
158+
int len = sizeof(new_func);
159+
memcpy((void*)MyFunction, (void*)new_func, len);
160+
```
161+
162+
完成代码:
163+
164+
[example_code](../example_code/function/test.c)
165+
42166
4. set/jump的方案
43167
168+
```
169+
jmp_buf env;
170+
171+
int my_func(int a, int b)
172+
{
173+
if (b == 0) {
174+
printf("do not allow division by 0\n");
175+
longjmp(env, 1);
176+
}
177+
return a / b;
178+
}
179+
180+
int main(int argc, char const *argv[])
181+
{
182+
int res = setjmp(env);
183+
if (res == 0) {
184+
printf("return from setjmp\n");
185+
my_func(10, 0);
186+
} else {
187+
printf("return from longjmp: %d\n", res);
188+
}
189+
return 0;
190+
}
191+
```
192+
193+
完成代码:
194+
195+
[example_code](../example_code/function/test_jmp.c)
196+
44197
## 协程的基本原理
45198
46199
核心 :
@@ -54,7 +207,7 @@ libco 上下文切换的思路
54207
55208
2. libco hook 系统函数的思路
56209
57-
3.
58210
59211
## 热更新的基本原理
60-
todo
212+
213+
todo

pic/函数调用3.png

85.1 KB
Loading

pic/函数调用4.png

44.6 KB
Loading

0 commit comments

Comments
 (0)