作者丨selph
appointment_book
程序信息
程序保护信息:
➜ HeroCTF checksec appointment_book
[*] '/home/selph/ctf/HeroCTF/appointment_book'
Arch: amd64-64-little
RELRO: No RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
这里其实已经给出提示了,没有Relocation Read-Only,没有PIE,说明可以去修改got表项,当时咋就没想到呢hhhh
程序运行信息:
***** Select an option *****
1) List appointments
2) Add an appointment
3) Exit
Your choice: 2
[+] Enter the index of this appointment (0-7): 0
[+] Enter a date and time (YYYY-MM-DD HH:MM:SS): 1111-11-11 22:22:22
[+] Converted to UNIX timestamp using local timezone: -27080300601
[+] Enter an associated message (place, people, notes...): YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
***** Select an option *****
1) List appointments
2) Add an appointment
3) Exit
Your choice: 1
[+] List of appointments:
- Appointment n°1:
- Date: 1111-11-11 22:22:22
- Message: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
- Appointment n°2:
[NO APPOINTMENT]
- Appointment n°3:
[NO APPOINTMENT]
- Appointment n°4:
[NO APPOINTMENT]
- Appointment n°5:
[NO APPOINTMENT]
- Appointment n°6:
[NO APPOINTMENT]
- Appointment n°7:
[NO APPOINTMENT]
- Appointment n°8:
[NO APPOINTMENT]
***** Select an option *****
1) List appointments
2) Add an appointment
3) Exit
逆向分析
主程序:就是提供个菜单项,主要功能在菜单函数内
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
char *v3; // rax
int v4; // [rsp+4h] [rbp-Ch]
time_t v5; // [rsp+8h] [rbp-8h]
memset(&appointments, 0, 0x80uLL);
puts("========== Welcome to your appointment book. ==========");
v5 = time(0LL);
v3 = timestamp_to_date(v5);
printf("\n[LOCAL TIME] %s\n", v3);
fflush(stdout);
while ( 1 )
{
v4 = menu();
if ( v4 == 3 )
{
puts("\n[+] Good bye!");
fflush(stdout);
exit(1);
}
if ( v4 > 3 )
{
LABEL_10:
puts("\n[-] Unknwon choice\n");
fflush(stdout);
}
else if ( v4 == 1 )
{
list_appointments();
}
else
{
if ( v4 != 2 )
goto LABEL_10;
create_appointment();
}
}
}
list_appointments函数:这里只是展示结构体保存的内容,没有什么特别的
int list_appointments()
{
int result; // eax
char *v1; // rax
int i; // [rsp+4h] [rbp-Ch]
const char **v3; // [rsp+8h] [rbp-8h]
puts("\n[+] List of appointments: ");
result = fflush(stdout);
for ( i = 0; i <= 7; ++i )
{
v3 = (const char **)((char *)&appointments + 16 * i);
printf("- Appointment n°%d:\n", (unsigned int)(i + 1));
if ( v3[1] )
{
v1 = timestamp_to_date((time_t)*v3);
printf("\t- Date: %s\n", v1);
printf("\t- Message: %s\n", v3[1]);
}
else
{
puts("\t[NO APPOINTMENT]");
}
result = fflush(stdout);
}
return result;
}
create_appointment():这里是向结构体里填充内容,但不存在堆栈相关漏洞
这里的结构体是在IDA里手动创建的,打开结构体窗口,然后右键创建即可
unsigned __int64 create_appointment()
{
__int64 v0; // rax
int i; // [rsp+Ch] [rbp-24h] BYREF
void *tmp_data; // [rsp+10h] [rbp-20h]
char *content; // [rsp+18h] [rbp-18h]
Appointment *v5; // [rsp+20h] [rbp-10h]
unsigned __int64 v6; // [rsp+28h] [rbp-8h]
v6 = __readfsqword(0x28u);
tmp_data = malloc(0x20uLL);
content = (char *)malloc(0x40uLL); // 可以申请一堆,导致内存泄露,但没啥用
memset(tmp_data, 0, 0x20uLL);
memset(content, 0, 0x40uLL);
do
{
printf("[+] Enter the index of this appointment (0-7): ");
fflush(stdout);
__isoc99_scanf("%d", &i);
getchar();
}
while ( i > 7 ); // 【关键点!!!!!】
v5 = &appointments[i];
printf("[+] Enter a date and time (YYYY-MM-DD HH:MM:SS): ");
fflush(stdout);
fgets((char *)tmp_data, 0x1E, stdin);
v0 = date_to_timestamp((__int64)tmp_data); // 接收到一个数字
v5->time