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

addresssainter的原理

然后放到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)&notes + 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)&notes + 8 * v32;
  if ( *(_BYTE *)((v20 >> 3) + 0x7FFF8000) )
    v18 = _asan_report_store8(v20);
  *(_QWORD *)v20 = v18;
  v21 = (unsigned __int64)&notes + 8 * v32;
  if ( *(_BYTE *)((v21 >> 3) + 0x7FFF8000) )
    _asan_report_load8((char *)&notes + 8 * v32, v11, v19);
  if ( !*(_QWORD *)v21 )
    error();
  v22 = v29;
  v23 = (unsigned __int64)&notes + 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)&notes + 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)&notes + 8 * v16;
  if ( *(_BYTE *)((v6 >> 3) + 0x7FFF8000) )
    _asan_report_load8(v6);
  if ( !*(_QWORD *)v6 )
LABEL_6:
    error();
  v7 = (unsigned __int64)&notes + 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)&notes + 8 * v11;
  if ( *(_BYTE *)((v6 >> 3) + 0x7FFF8000) )
    _asan_report_load8(v6);
  if ( !*(_QWORD *)v6 )
LABEL_6:
    error();
  v7 = (unsigned __int64)&notes + 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)&notes + 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)&notes + 8 * v24;
  if ( *(_BYTE *)((v9 >> 3) + 0x7FFF8000) )
    _asan_report_load8(v9);
  if ( !*(_QWORD *)v9 )
LABEL_6:
    error();
  v10 = (unsigned __int64)&notes + 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

ctf基本的文件上传与绕过学习

Real World CTF一日游

CTF

在数据框中移动列

ctf之隐写工具篇