那些你不知道的Gdb调试

直接插上CGfsb伪代码

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int buf; // [esp+1Eh] [ebp-7Eh]
int v5; // [esp+22h] [ebp-7Ah]
__int16 v6; // [esp+26h] [ebp-76h]
char s; // [esp+28h] [ebp-74h]
unsigned int v8; // [esp+8Ch] [ebp-10h]

v8 = __readgsdword(0x14u);
setbuf(stdin, 0);
setbuf(stdout, 0);
setbuf(stderr, 0);
buf = 0;
v5 = 0;
v6 = 0;
memset(&s, 0, 0x64u);
puts("please tell me your name:");
read(0, &buf, 0xAu);
puts("leave your message please:");
fgets(&s, 100, stdin);
printf("hello %s", &buf);
puts("your message is:");
printf(&s);
if ( pwnme == 8 )
{
puts("you pwned me, here is your flag:\n");
system("cat flag");
}
else
{
puts("Thank you!");
}
return 0;
}

我要调试的是printf指令,这里有两个,我们先调试第一个 printf(“hello %s”, &buf);
1.png
我们将断点先下在第一个断点处,名字输入sakura,信息填message,回车
2.png
你会在backtrace处发现两个栈帧,__libc_start_main栈帧和main栈帧
3.png
注意这个时候的栈信息,栈里面先把sakura对应的地址和格式化字符串分别入栈
4.png
通过step指令由main栈帧进入printf栈帧
5.png
此时的backtrace是
6.png
此时的栈是
7.png
其中栈中的第一行为返回地址,这是创建printf栈帧后才出现的,其余两个参数不变。
我们再输入frame f 1
8.png
使程序回到main栈帧,重复执行上述断点
9.png
你会发现,返回地址无了。

注意

gdb调试时,要分清哪些是地址,哪些是数据,其中字符串信息的传递是通过指向字符串的地址传递的。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!