[REVERSE-ENGEERING] Краш

_chapman_

Новичок
Автор темы
4
0
Всех приветствую.
На днях пришла идея пореверсить один известный CRMP-мобайл проект, чем я собственно и занялся.
Но, какую бы я функцию не пробовал хукать, итог один - краш. Сидеть рандомно искать ошибку я не хотел, поэтому написал простенький краш хандлер:
C++:
void crash_handler(int signum, siginfo_t *info, void* contextPtr) {
    ucontext* context = (ucontext_t*)contextPtr;
    if (info->si_signo == SIGSEGV) {
        uintptr_t pc, lr;
        #if defined(__arm__)
            pc = context->uc_mcontext.arm_pc;
            lr = context->uc_mcontext.arm_lr;
        #endif
        __android_log_print(ANDROID_LOG_ERROR, "CrashHandler", "Segmentation fault at address 0x%x, return address: 0x%x", pc, lr);
        exit(EXIT_FAILURE);
    }
}

__attribute__((constructor))
void lib_main() {
    struct sigaction act;
    act.sa_sigaction = crash_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO;
    sigaction(SIGSEGV, &act, 0);
}

Однако, к большому сожалению, код не завелся, хотя на предыдущих приложениях, что я реверсил, все было четко.
Тогда в голову пришла идея - что, если хандлер резервируется процессом игры и из-за этого мой хандлер не получает информации?
Чтобы проверить догадку, понадобилось секунд 10, и вот оно:
C++:
unsigned int __fastcall INT123_catchsignal(int a1, int a2)
{
  int v3; // r1
  unsigned int result; // r0
  unsigned int v5; // [sp+4h] [bp-2Ch] BYREF
  int v6; // [sp+14h] [bp-1Ch] BYREF
  _DWORD v7[3]; // [sp+18h] [bp-18h] BYREF

  v6 = a2;
  sigemptyset((sigset_t *)v7);
  v7[1] = 0;
  v3 = sigaction(a1, (const struct sigaction *)&v6, (struct sigaction *)&v5);
  result = v5;
  if ( v3 == -0x1 )
    return -0x1;
  return result;
}

Тогда я подумал, что если при старте попробовать загрузить туда свою структуру? В принципе, может сработать, так что почему бы и нет?

C++:
void install_crash_handler();
void SetupHooks() {
    do {
        sleep(1);
    } while (!findLibrary(targetLibName));
    LOG(ANDROID_LOG_INFO, format_char("Target lib address is 0x%X", findLibrary(targetLibName)).get());
    install_crash_handler();
}

void install_crash_handler() {
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = crash_handler;

    int result = ((int(*)(int code, int func))getAbsoluteAddress(targetLibName, 0x391604))(14, (int)&sa);
    __android_log_print(ANDROID_LOG_INFO, "CrashHandler", "Install crash handler func returned %d.", result);
}

Однако, чуда не произошло, на этот раз я получил краш при попытке вызова функции INT123_catchsignal.
Подскажите, пожалуйста, в чем моя ошибка?
 
Решение
thumb - 16-и битный набор инструкций, может выполняться на некоторых процессорах arm
arm - 32-ух битный набор инструкций, предоставляет полный набор возможностей ARM. Однако, я не совсем понимаю, чем оно мне поможет. Не просвятишь?)

Дополнение:
Решил поэксперементировать и хукнуть функцию INT123_catchsignal.
C++:
int handler(int signal, int *structure) {
    __android_log_print(ANDROID_LOG_INFO, "[SIGNAL]", "Installing handler....");
    // return o_handler(signal, structure);
    sigemptyset(0);
    __android_log_print(ANDROID_LOG_INFO, "[SIGNAL]", "Calling sigaction....");
    int v3 = sigaction(signal, (const struct sigaction *)&structure, 0);
    int result = 0;
    if(v3 == -0x1)
        return -0x1;
    return result...

mhertz

Известный
125
174
Всех приветствую.
На днях пришла идея пореверсить один известный CRMP-мобайл проект, чем я собственно и занялся.
Но, какую бы я функцию не пробовал хукать, итог один - краш. Сидеть рандомно искать ошибку я не хотел, поэтому написал простенький краш хандлер:
C++:
void crash_handler(int signum, siginfo_t *info, void* contextPtr) {
    ucontext* context = (ucontext_t*)contextPtr;
    if (info->si_signo == SIGSEGV) {
        uintptr_t pc, lr;
        #if defined(__arm__)
            pc = context->uc_mcontext.arm_pc;
            lr = context->uc_mcontext.arm_lr;
        #endif
        __android_log_print(ANDROID_LOG_ERROR, "CrashHandler", "Segmentation fault at address 0x%x, return address: 0x%x", pc, lr);
        exit(EXIT_FAILURE);
    }
}

__attribute__((constructor))
void lib_main() {
    struct sigaction act;
    act.sa_sigaction = crash_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO;
    sigaction(SIGSEGV, &act, 0);
}

Однако, к большому сожалению, код не завелся, хотя на предыдущих приложениях, что я реверсил, все было четко.
Тогда в голову пришла идея - что, если хандлер резервируется процессом игры и из-за этого мой хандлер не получает информации?
Чтобы проверить догадку, понадобилось секунд 10, и вот оно:
C++:
unsigned int __fastcall INT123_catchsignal(int a1, int a2)
{
  int v3; // r1
  unsigned int result; // r0
  unsigned int v5; // [sp+4h] [bp-2Ch] BYREF
  int v6; // [sp+14h] [bp-1Ch] BYREF
  _DWORD v7[3]; // [sp+18h] [bp-18h] BYREF

  v6 = a2;
  sigemptyset((sigset_t *)v7);
  v7[1] = 0;
  v3 = sigaction(a1, (const struct sigaction *)&v6, (struct sigaction *)&v5);
  result = v5;
  if ( v3 == -0x1 )
    return -0x1;
  return result;
}

Тогда я подумал, что если при старте попробовать загрузить туда свою структуру? В принципе, может сработать, так что почему бы и нет?

C++:
void install_crash_handler();
void SetupHooks() {
    do {
        sleep(1);
    } while (!findLibrary(targetLibName));
    LOG(ANDROID_LOG_INFO, format_char("Target lib address is 0x%X", findLibrary(targetLibName)).get());
    install_crash_handler();
}

void install_crash_handler() {
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = crash_handler;

    int result = ((int(*)(int code, int func))getAbsoluteAddress(targetLibName, 0x391604))(14, (int)&sa);
    __android_log_print(ANDROID_LOG_INFO, "CrashHandler", "Install crash handler func returned %d.", result);
}

Однако, чуда не произошло, на этот раз я получил краш при попытке вызова функции INT123_catchsignal.
Подскажите, пожалуйста, в чем моя ошибка?
для начала узнай о разнице между thumb и arm (из-за чего тут скорее всего и происходит краш), а потом и пиши свои шедеврочиты
 
  • Нравится
Реакции: legendabrn

_chapman_

Новичок
Автор темы
4
0
для начала узнай о разнице между thumb и arm (из-за чего тут скорее всего и происходит краш), а потом и пиши свои шедеврочиты
thumb - 16-и битный набор инструкций, может выполняться на некоторых процессорах arm
arm - 32-ух битный набор инструкций, предоставляет полный набор возможностей ARM. Однако, я не совсем понимаю, чем оно мне поможет. Не просвятишь?)

Дополнение:
Решил поэксперементировать и хукнуть функцию INT123_catchsignal.
C++:
int handler(int signal, int *structure) {
    __android_log_print(ANDROID_LOG_INFO, "[SIGNAL]", "Installing handler....");
    // return o_handler(signal, structure);
    sigemptyset(0);
    __android_log_print(ANDROID_LOG_INFO, "[SIGNAL]", "Calling sigaction....");
    int v3 = sigaction(signal, (const struct sigaction *)&structure, 0);
    int result = 0;
    if(v3 == -0x1)
        return -0x1;
    return result;
}
Результат меня удивил: все заработало. Просвятите, пожалуйста, почему) По сути, код в хуке и изначальный код идентичны, но первый работает, а второй - нет. А еще, краш хандлер так и не заработал :( может, есть альтернативные варианты по его установке?
 
Последнее редактирование:

mhertz

Известный
125
174
thumb - 16-и битный набор инструкций, может выполняться на некоторых процессорах arm
arm - 32-ух битный набор инструкций, предоставляет полный набор возможностей ARM. Однако, я не совсем понимаю, чем оно мне поможет. Не просвятишь?)

Дополнение:
Решил поэксперементировать и хукнуть функцию INT123_catchsignal.
C++:
int handler(int signal, int *structure) {
    __android_log_print(ANDROID_LOG_INFO, "[SIGNAL]", "Installing handler....");
    // return o_handler(signal, structure);
    sigemptyset(0);
    __android_log_print(ANDROID_LOG_INFO, "[SIGNAL]", "Calling sigaction....");
    int v3 = sigaction(signal, (const struct sigaction *)&structure, 0);
    int result = 0;
    if(v3 == -0x1)
        return -0x1;
    return result;
}
Результат меня удивил: все заработало. Просвятите, пожалуйста, почему) По сути, код в хуке и изначальный код идентичны, но первый работает, а второй - нет. А еще, краш хандлер так и не заработал :( может, есть альтернативные варианты по его установке?
все проблемы у тебя из-за того, что ты вызываешь функции в режиме arm (что видно по тому, что твои адреса чётные), их нужно вызывать в режиме thumb, если он используется ( т.е. делать их нечётными добавлением единицы (+ 1), или ты думал, зачем все самп клиенты это делают?) )

а на счёт твоего крашхандлера - он обрабатывает только SIGSEGV, хотя в данном случае скорее всего будет SIGILL (т.е. недействительня инструкция), и поэтому ты ничего не видишь

ну и ещё можешь не скрывать, что это блек кака, это и так очевидно
 
  • Нравится
Реакции: _chapman_

_chapman_

Новичок
Автор темы
4
0
все проблемы у тебя из-за того, что ты вызываешь функции в режиме arm (что видно по тому, что твои адреса чётные), их нужно вызывать в режиме thumb, если он используется ( т.е. делать их нечётными добавлением единицы (+ 1), или ты думал, зачем все самп клиенты это делают?) )

а на счёт твоего крашхандлера - он обрабатывает только SIGSEGV, хотя в данном случае скорее всего будет SIGILL (т.е. недействительня инструкция), и поэтому ты ничего не видишь

ну и ещё можешь не скрывать, что это блек кака, это и так очевидно
спасибо большое за информацию =)
а на счет "не скрывать" - я не скрываю) просто не видел смысла упоминать
можешь, пожалуйста, сказать, как определить, как определить, где thumb, а где - нет? ну, или литературу на эту тему скинуть, было бы интересно почитать
 

mhertz

Известный
125
174
спасибо большое за информацию =)
а на счет "не скрывать" - я не скрываю) просто не видел смысла упоминать
можешь, пожалуйста, сказать, как определить, как определить, где thumb, а где - нет? ну, или литературу на эту тему скинуть, было бы интересно почитать
в иде сразу видно по инструкциям - все 4-х байтные - arm, есть двухбайтные - тамб
 
  • Нравится
Реакции: _chapman_