取target与62进行16进制异或 for ( n17_2 0; n17_2 ! 17; n17_2 ) s1_[n17_2] input_buffer[n17_2] ^ 0x62; if ( !memcmp(s1_, TARGET, 0x11u) )取target与62进行16进制异或11 06 12 01 19 10 07 12 15 0C 12 15 0C 1F sdpc{repwnpwn}学几个函数proc_create(xor_check, 438, 0, xor_proc_fops);它做了以下几件事proc_create()这是一个内核函数别人已经写好的工具函数作用是在 /proc 目录下创建一个文件。/proc 是什么Linux 系统里有一个特殊的目录叫 /proc它里面的文件不是存在硬盘上的而是内核虚拟出来的。你读/写这些文件实际上是在和内核里的代码交互。比如你 cat /proc/cpuinfo 就能看到 CPU 信息。参数1 xor_check文件的名字。所以这个文件就叫 /proc/xor_check参数2 438这个数字是权限用8进制看就是 0666。6 表示 读写三个数字分别对应 文件主人/同组人/其他人 都能读写。这里所有人都可以读写这个文件。参数3 0父目录设为空意味着放在 /proc 根目录下参数4 xor_proc_fops最关键的一个参数。xor_proc_fops 是一个函数表fops file operations这张表里记录了当有人读这个文件时调用哪个函数、当有人写这个文件时调用哪个函数。 表示取这个表的地址告诉内核这张表在哪。在这个表里写操作指向的就是下面的 xor_proc_write 函数。_check_object_size(input_buffer, n17, 0);_check_object_size()又一个内核安全检查函数检查 input_buffer存用户数据的缓冲区有没有至少 n17 字节那么大防止越界访问参数3 的 0 表示这是一个读操作检查if ( copy_from_user(input_buffer, a2, n17) )return -14;copy_from_user()把数据从用户空间复制到内核空间为什么需要这步系统里有两块地盘用户空间普通程序待的地方和内核空间内核代码待的地方。程序不能直接访问内核的地盘需要通过 copy_from_user 这个海关来传输数据。参数1 input_buffer数据要存到内核的哪个位置参数2 a2从用户空间的哪个地址取数据参数3 n17复制多少个字节debugmeida打开int __fastcall main(int argc, const char **argv, const char **envp) { char Str[8]; // [rsp20h] [rbp-30h] BYREF __int64 v5; // [rsp28h] [rbp-28h] __int64 v6; // [rsp30h] [rbp-20h] __int64 v7; // [rsp38h] [rbp-18h] char v8; // [rsp40h] [rbp-10h] _main(); *(_QWORD *)Str 0; v5 0; v6 0; v7 0; v8 0; puts(Please input the flag: ); scanf(%32s, Str); if ( strlen(Str) 32 ) { decode_flag(flag); if ( !memcmp(Str, flag, 0x20u) ) puts(Right! ); else puts(Wrong! ); } else { puts(Length wrong! ); } return 0; }在比较处下断点然后debug输入任意32个字符回车lea rcx, flag ; rcx flag (flag 缓冲区的地址) call decode_flag ; 调用 RC4 解密函数把加密数据解密到 flag 缓冲区 ; 执行完这行后flag 地址处就是明文 flag 了 lea rax, [rbpStr] ; rax 用户输入的字符串地址 mov r8d, 20h ; r8 32 (第三个参数比较长度 32 字节) lea rdx, flag ; rdx flag 地址 (第二个参数解密后的 flag) mov rcx, rax ; rcx 用户输入地址 (第一个参数) call memcmp ; 调用 memcmp(用户输入, 解密后flag, 32)SDPCSEC{debug_to_do_1s_e53y}ezida直接打开然后ctrlF就能搜到依旧学习代码Stream __iob_func();__iob_func()获取标准输入/输出/错误流的信息。返回一个结构体数组其中包含 stdin键盘输入、stdout屏幕输出等。Stream 指向 stdin。fgets(Buffer, 100, Stream);fgets file get string从文件读取一行文字。第一个参数 Buffer → 把读到的内容存入 Buffer 数组。第二个参数 100 → 最多读 99 个字符留一个给字符串结尾标记 \0。第三个参数 Stream → 从键盘stdin读。效果你输入一行字按回车这行字被存进 Buffer。去掉换行符Buffer[strcspn(Buffer, \n)] 0;strcspn(Buffer, \n) string complement span找到 Buffer 里第一个 \n换行符的位置。因为你按了回车fgets 会把换行符也保留在 Buffer 末尾。例如你输入 abc\n这个函数返回 3\n 在第 3 个位置从 0 开始数。Buffer[位置] 0把那个位置的换行符替换成 0也就是字符串结束符 \0相当于剪掉换行符。检查长度if ( strlen(Buffer) correct_len )strlen(Buffer) string length数一下 Buffer 里有多少个字符遇到 \0 停止。correct_len一个事先定义好的全局变量值是 0x1f 31。if (...)如果括号里的条件成立就执行它下面的代码块否则跳到 else。这句话在说如果你输入的密码长度不等于 31就去报错。