(Written by c0m0r1)
Simple android app reversing w/ native library. just reversing the logic and running solver code in arm64-v8a CPU android phone with a given native library can solve it.
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#define __USE_GNU
#include <signal.h>
#define MEATBOX_OFFSET 0xCC0
#define SOULBOX_OFFSET 0xD80
#define GODBOX_OFFSET 0xD20
#define RES_ARR_OFFSET 0x47E8
typedef char *((*t_meatbox)(char *));
typedef char *((*t_soulbox)(char *));
typedef char *((*t_godbox)(char *));
/* Global symbols */
#define DEF(n) t_##n n = NULL
DEF(meatbox);
DEF(soulbox);
DEF(godbox);
#undef DEF
void print_hex(char * ptr, unsigned len){
unsigned i;
for(i = 0; i < len; i ++){
if(!(i & 0xf)) printf("\n");
printf("%x ", ptr[i]);
}
}
void read_maps(){
char buf[0x1000];
int fd = open("/proc/self/maps", O_RDONLY);
read(fd, buf, 0x1000);
printf("%s", buf);
close(fd);
}
unsigned long long find_base(){
char buf[0x1000];
unsigned long long res = 0;
FILE * fp = fopen("/proc/self/maps", "r");
while(fgets(buf, 0x1000, fp) != NULL){
if (!!strstr(buf, "libnative-lib.so")){
*strchr(buf, '-') = '\0';
res = strtoll(buf, NULL, 16);
break;
}
}
fclose(fp);
return res;
}
static void *resolve(void *lib, const char *name) {
void *sym;
sym = dlsym(lib, name);
printf("[D] Symbol %s is at %p\n", name, sym);
return sym;
}
void handler(int sig, siginfo_t* siginfo, void* context)
{
ucontext_t * uc;
int i;
uc = (ucontext_t *) context;
printf("[-] signal %d\n", siginfo->si_signo);
printf("[-] signal from %lx in %lx\n", uc->uc_mcontext.fault_address, uc->uc_mcontext.pc);
for(i = 0; i < 31; i++){
printf("r%d : 0x%llx\n", i, uc->uc_mcontext.regs[i]);
}
//dump_hex(uc->uc_mcontext.sp, 0x20);
exit(1);
}
int main(int argc, char *argv[]){
struct sigaction act;
memset(&act, 0, sizeof(sigaction));
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &act, NULL) < 0) {
printf("[-] signal handler register failed...");
return 1;
}
char buf[3];
int i,j;
void *base = dlopen("./libnative-lib.so", RTLD_NOW);
char meat_table[0xff] = {0,};
char soul_table[0xff] = {0,};
char god_table[0xff] = {0,};
if(!base){
printf("[-] dlopen failed...");
printf("[-] error: %s\n", dlerror());
}
else{
//why the fuck dlopen return gibberish???
// fine i'll find it manually
base = (void *)find_base();
printf("[+] library base : %p\n", base);
}
//#define SYM(n) n = resolve(base, #n)
// SYM(meatbox);
// SYM(soulbox);
// SYM(godbox);
//#undef SYM
meatbox = (char *)base + MEATBOX_OFFSET;
soulbox = (char *)base + SOULBOX_OFFSET;
godbox = (char *)base + GODBOX_OFFSET;
int * enc_vals = (char *)base + RES_ARR_OFFSET;
read_maps();
printf("[+] meatbox at %p\n", meatbox);
printf("[+] soulbox at %p\n", soulbox);
printf("[+] godbox at %p\n", godbox);
printf("%p ", meatbox("1"));
//print_hex(meatbox("1"), 0x8);
for(i = 0; i < 0x100; i++){
buf[0] = i;
buf[1] = '\0';
meat_table[i] = *(char *)(*meatbox)(buf);
}
for(i = 0; i < 0x100; i++){
buf[0] = i;
buf[1] = '\0';
soul_table[i] = *(char *)(*soulbox)(buf);
}
for(i = 0; i < 0x100; i++){
buf[0] = i;
buf[1] = '\0';
god_table[i] = *(char *)(*godbox)(buf);
}
for(i = 0 ; i < 153 ; i += 3){
//printf("%x %x %x\n", enc_vals[i * 4], enc_vals[i * 4 + 1],enc_vals[i * 4 + 2]);
for(j = 0; j < 0x100; j++){
if (enc_vals[i] == meat_table[j] &&
enc_vals[i + 1] == soul_table[j] &&
enc_vals[i + 2] == god_table[j]){
printf("%c", j);
}
}
}
return 0;
}