直接插上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);

我们将断点先下在第一个断点处,名字输入sakura,信息填message,回车

你会在backtrace处发现两个栈帧,__libc_start_main栈帧和main栈帧

注意这个时候的栈信息,栈里面先把sakura对应的地址和格式化字符串分别入栈

通过step指令由main栈帧进入printf栈帧

此时的backtrace是

此时的栈是

其中栈中的第一行为返回地址,这是创建printf栈帧后才出现的,其余两个参数不变。
我们再输入frame f 1

使程序回到main栈帧,重复执行上述断点

你会发现,返回地址无了。
注意
gdb调试时,要分清哪些是地址,哪些是数据,其中字符串信息的传递是通过指向字符串的地址传递的。