20190ctf ageis
Posted Y0n1an
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20190ctf ageis相关的知识,希望对你有一定的参考价值。
文章目录
Analysis
checksec
franex@franex-virtual-machine:~/桌面/babyaegis$ checksec aegis
[*] '/home/franex/\\xe6\\xa1\\x8c\\xe9\\x9d\\xa2/babyaegis/aegis'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
FORTIFY: Enabled
ASAN: Enabled
UBSAN: Enabled
七个保护…我在网上查了一下
ASAN
是指AddressSanitizer
,这是一款用于检测C/C++内存错误的工具。而UBSAN
是指UndefinedBehaviorSanitizer
, 这是一款用于检测未定义行为的检测器,比如使用没对齐的或者为空的指针什么的。
会检测以下的行为
检测以下行为
Use after free (dangling pointer dereference)
Heap buffer overflow
Stack buffer overflow
Global buffer overflow
Use after return
Use after scope
Initialization order bugs
Memory leaks
然后放到ida里面看一下
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
__int64 v3; // rdx
const char *v4; // rdi
int v5; // eax
__int64 v6; // rdx
if ( *(_BYTE *)(((unsigned __int64)&stdin >> 3) + 0x7FFF8000) )
_asan_report_load8(&stdin, argv, envp);
setvbuf(stdin, 0LL, 2, 0LL);
if ( *(_BYTE *)(((unsigned __int64)&stdout >> 3) + 0x7FFF8000) )
_asan_report_load8(&stdout, 0LL, v3);
setvbuf(stdout, 0LL, 2, 0LL);
v4 = dword_78;
alarm(0x78u);
banner();
while ( 1 )
while ( 1 )
v5 = menu();
if ( v5 != 1 )
break;
add_note(v4, 0LL, v6, 0LL);
switch ( v5 )
case 2:
show_note(v4, 0LL, v6, 0LL);
break;
case 3:
update_note(v4, 0LL, v6, 0LL);
break;
case 4:
delete_note(v4, 0LL, v6, 0LL);
break;
case 5:
puts("Bye!");
_asan_handle_no_return();
exit(0);
case 666:
secret(v4, 0LL, v6, 661LL);
break;
default:
v4 = "Error!";
puts("Error!");
break;
查看各个函数
ADD:
unsigned __int64 __fastcall add_note(__int64 a1, __int64 a2, __int64 a3, int a4, int a5, int a6)
unsigned __int64 v6; // rdi
int v7; // edx
int v8; // ecx
int v9; // er8
int v10; // er9
__int64 v11; // rsi
int v12; // edx
int v13; // ecx
int v14; // er8
int v15; // er9
__int64 ul; // rax
unsigned __int64 v17; // rdi
__int64 v18; // rax
__int64 v19; // rdx
unsigned __int64 v20; // rdi
unsigned __int64 v21; // rcx
__int64 v22; // rcx
unsigned __int64 v23; // rdi
__int64 *v24; // rax
unsigned __int64 v25; // rdx
unsigned __int64 v26; // rdi
unsigned __int64 v27; // rdi
__int64 v29; // [rsp+8h] [rbp-28h]
int until_nl_or_max; // [rsp+18h] [rbp-18h]
int v31; // [rsp+1Ch] [rbp-14h]
int v32; // [rsp+20h] [rbp-10h]
int i; // [rsp+24h] [rbp-Ch]
v32 = -1;
for ( i = 0; i < 10; ++i )
v6 = (unsigned __int64)¬es + 8 * i;
if ( *(_BYTE *)((v6 >> 3) + 0x7FFF8000) )
_asan_report_load8(v6, a2, a3);
if ( !*(_QWORD *)v6 )
v32 = i;
break;
if ( v32 == -1 )
error();
printf((unsigned int)"Size: ", a2, a3, a4, a5, a6);
v31 = read_int();
if ( v31 < 16 || v31 > 1024 )
error();
v29 = malloc((__asan *)v31);
if ( !v29 )
error();
printf((unsigned int)"Content: ", a2, v7, v8, v9, v10);
v11 = v31 - 8;
until_nl_or_max = read_until_nl_or_max(v29, v11);
printf((unsigned int)"ID: ", v11, v12, v13, v14, v15);
ul = read_ul();
v17 = until_nl_or_max + v29;
if ( *(_BYTE *)((v17 >> 3) + 0x7FFF8000) )
ul = _asan_report_store8(v17);
*(_QWORD *)v17 = ul;
v18 = malloc((__asan *)&word_10);
v20 = (unsigned __int64)¬es + 8 * v32;
if ( *(_BYTE *)((v20 >> 3) + 0x7FFF8000) )
v18 = _asan_report_store8(v20);
*(_QWORD *)v20 = v18;
v21 = (unsigned __int64)¬es + 8 * v32;
if ( *(_BYTE *)((v21 >> 3) + 0x7FFF8000) )
_asan_report_load8((char *)¬es + 8 * v32, v11, v19);
if ( !*(_QWORD *)v21 )
error();
v22 = v29;
v23 = (unsigned __int64)¬es + 8 * v32;
if ( *(_BYTE *)((v23 >> 3) + 0x7FFF8000) )
_asan_report_load8(v23, v11, v19);
v24 = *(__int64 **)v23;
v25 = *(_QWORD *)v23 >> 3;
if ( *(_BYTE *)(v25 + 0x7FFF8000) )
v24 = (__int64 *)_asan_report_store8((unsigned __int64)v24);
*v24 = v22;
v26 = (unsigned __int64)¬es + 8 * v32;
if ( *(_BYTE *)((v26 >> 3) + 0x7FFF8000) )
_asan_report_load8(v26, v11, v25);
v27 = *(_QWORD *)v26 + 8LL;
if ( *(_BYTE *)((v27 >> 3) + 0x7FFF8000) )
_asan_report_store8(v27);
*(_QWORD *)v27 = cfi_check;
puts("Add success!");
return __readfsqword(0x28u);
只能分配十个note,每个note在0x10到0x400之间
然后在分配的buf下面,有一个指针指向check函数
打印出来
unsigned __int64 __fastcall show_note(__int64 a1, int a2, int a3, int a4, int a5, int a6)
unsigned __int64 v6; // rdi
unsigned __int64 v7; // rdi
__int64 v8; // r14
__int64 v9; // rbx
int v10; // ecx
unsigned __int64 v11; // rbx
int v12; // er8
int v13; // er9
unsigned __int64 v15; // [rsp+8h] [rbp-28h]
int v16; // [rsp+10h] [rbp-20h]
printf((unsigned int)"Index: ", a2, a3, a4, a5, a6);
v16 = read_int();
if ( v16 < 0 || v16 >= 10 )
goto LABEL_6;
v6 = (unsigned __int64)¬es + 8 * v16;
if ( *(_BYTE *)((v6 >> 3) + 0x7FFF8000) )
_asan_report_load8(v6);
if ( !*(_QWORD *)v6 )
LABEL_6:
error();
v7 = (unsigned __int64)¬es + 8 * v16;
if ( *(_BYTE *)((v7 >> 3) + 0x7FFF8000) )
_asan_report_load8(v7);
v15 = *(_QWORD *)v7;
if ( *(_BYTE *)((*(_QWORD *)v7 >> 3) + 0x7FFF8000LL) )
_asan_report_load8(v15);
v8 = *(_QWORD *)v15;
if ( *(_BYTE *)((v15 >> 3) + 0x7FFF8000) )
_asan_report_load8(v15);
v9 = *(_QWORD *)v15;
if ( *(_BYTE *)((v15 >> 3) + 0x7FFF8000) )
_asan_report_load8(v15);
v11 = strlen(*(_QWORD *)v15) + v9 + 1;
if ( *(_BYTE *)((v11 >> 3) + 0x7FFF8000) )
_asan_report_load8(v11);
printf((unsigned int)"Content: %s\\nID: %lu\\n", v8, *(_QWORD *)v11, v10, v12, v13);
return __readfsqword(0x28u);
根据输入的id,打印note
unsigned __int64 __fastcall delete_note(__int64 a1, int a2, int a3, int a4, int a5, int a6)
unsigned __int64 v6; // rdi
unsigned __int64 v7; // rdi
unsigned __int64 v8; // rdi
unsigned __int64 v9; // rdi
int v11; // [rsp+14h] [rbp-Ch]
printf((unsigned int)"Index: ", a2, a3, a4, a5, a6);
v11 = read_int();
if ( v11 < 0 || v11 >= 10 )
goto LABEL_6;
v6 = (unsigned __int64)¬es + 8 * v11;
if ( *(_BYTE *)((v6 >> 3) + 0x7FFF8000) )
_asan_report_load8(v6);
if ( !*(_QWORD *)v6 )
LABEL_6:
error();
v7 = (unsigned __int64)¬es + 8 * v11;
if ( *(_BYTE *)((v7 >> 3) + 0x7FFF8000) )
_asan_report_load8(v7);
v8 = *(_QWORD *)v7;
if ( *(_BYTE *)((v8 >> 3) + 0x7FFF8000) )
_asan_report_load8(v8);
free(*(__sanitizer **)v8);
v9 = (unsigned __int64)¬es + 8 * v11;
if ( *(_BYTE *)((v9 >> 3) + 0x7FFF8000) )
_asan_report_load8(v9);
free(*(__sanitizer **)v9);
puts("Delete success!");
return __readfsqword(0x28u);
UAF,因为free没有置空,但是这里可以看到开启了asan,比较难以利用
看一下update_note
unsigned __int64 __fastcall update_note(__int64 a1, int a2, int a3, int a4, int a5, int a6)
int v6; // edx
int v7; // er8
int v8; // er9
unsigned __int64 v9; // rdi
unsigned __int64 v10; // rdi
__int64 v11; // rbx
unsigned __int64 v12; // rsi
int v13; // edx
int v14; // ecx
int v15; // er8
int v16; // er9
__int64 ul; // rax
unsigned __int64 v18; // rdi
__int64 (__fastcall **v19)(); // rdi
__int64 (__fastcall *v20)(); // rbx
unsigned __int64 v22; // [rsp+8h] [rbp-28h]
int until_nl_or_max; // [rsp+18h] [rbp-18h]
int v24; // [rsp+1Ch] [rbp-14h]
printf((unsigned int)"Index: ", a2, a3, a4, a5, a6);
v24 = read_int();
if ( v24 < 0 || v24 >= 10 )
goto LABEL_6;
v9 = (unsigned __int64)¬es + 8 * v24;
if ( *(_BYTE *)((v9 >> 3) + 0x7FFF8000) )
_asan_report_load8(v9);
if ( !*(_QWORD *)v9 )
LABEL_6:
error();
v10 = (unsigned __int64)¬es + 8 * v24;
if ( *(_BYTE *)((v10 >> 3) + 0x7FFF8000) )
_asan_report_load8(v10);
v22 = *(_QWORD *)v10;
printf((unsigned int)"New Content: ", a2, v6, *(_QWORD *)v10, v7, v8);
if ( *(_BYTE *)((v22 >> 3) + 0x7FFF8000) )
_asan_report_load8(v22)20190ctf ageis