一、目标程序分析
main()函数分析
要进行劫持的目标程序如下
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>
void start() {
printf("IOLI Crackme Level 0x00\n");
printf("Password:");
char buf[64];
memset(buf, 0, sizeof(buf));
read(0, buf, 256);
if (!strcmp(buf, "250382"))
printf("Password OK :)\n");
else
printf("Invalid Password!\n");
}
int main(int argc, char *argv[]) {
setreuid(geteuid(), geteuid());
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF,0);
start();
return 0;
}
主程序这里三段代码的功能都是进行简单的安全防护
setreuid(geteuid(), geteuid());
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF,0);
我们可以找到geteuid()与setreuid()函数的相关解释,简单来说,euid(有效用户)是创建程序的用户id,uid(真实用户)是运行程序过程中的用户id,一般情况下来说两者是相等的,但由于程序运行过程中某些操作可能需要更高的特权级来进行,于是这时的uid就会临时变为更高权限的用户id,比如root
所以这里的setreuid()将程序执行中的uid也设置为euid,为了避免特权级被非法的提升
getuid() : 函数返回一个调用程序的真实用户ID。表明当前运行位置程序的执行者。
geteuid(): 函数返回返回一个有效用户的ID。(EUID)是你最初执行程序时所用的ID,该ID
是程序的所有者。
setreuid(uid_t ruid, uid_t euid)用来将参数ruid 设为目前进程的真实用户识别码, 将参数euid 设置为目前进程的有效用户识别码. 如果参数ruid 或euid 值为-1, 则对应的识别码不会改变。
setvbuf()函数的定义如下
int setvbuf(
FILE *stream,
char *buffer,
int mode,
size_t size
);
是对stream流的缓冲区进行设置,在这里我们只需要关心其中的mode参数的含义,可以看到程序中使用的_IONBF是将缓冲区设置为无,这样的目的是可以部分防止缓冲区溢出漏洞
模式 | 描述 |
---|---|
_IOFBF | 全缓冲:对于输出,数据在缓冲填满时被一次性写入。对于输入,缓冲会在请求输入且缓冲为空时被填充。 |
_IOLBF | 行缓冲 |