Jump to content
View in the app

A better way to browse. Learn more.

Tuts 4 You

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

Custom Protector CrackMe

It is written in FASM, anti-debugging methods are used.
You need to get the keys that were used to encrypt the hash being checked
(Enter the necessary values in the input field to get "Success", and throw these values here)

File Information

Submitter Twaoperder

Submitted 08/21/2021

Category CrackMe

View File

Custom Protector CrackMe

Solved by dtor135

Go to solution
  • 9 months later...
  • Solution

Used tools: x64dbg, Triton

The anti-debugging and obfuscation is straightforward: consisting solely of int3s and junk code.

Below is the cleaned version of main, just about 30 lines of assembly. Main reads 8 inputs, stores them to their registers and executes the hash function.

dis.png.93bcece02aa3b6abb9582bff6d1086eb.png

The hash function itself is clean (no obfuscation or anti-debugging), and cannot be simplified further (according to Triton).

The tricky part is to find the 8 keys to generate the correct "hash".

I used Triton for that. For some reason, Triton ignores the restriction on x64's div instruction sizes, a real machine errors with a #DE when tying to divide a number too large.

I had to specify a additional code path constraint for RDX for that single instruction.

Then the result is correct and executes on a real machine.

keys.png.7ce39dc41db4c9407c21735d5d061c32.png

The solver using Triton:

#!/usr/bin/env python
## -*- coding: utf-8 -*-

import sys
from triton import *
from tabulate import tabulate

# int64 f(rax, r8, r9, r10, r11, r12, r13, r14)
CODE=b"\x4D\x31\xFF\x48\xC1\xC0\x08\x3C\x00\x75\x50\x49\x0F\xBA\xEF\x3C\x50\x4C\x89\xC0\x49\xF7\xE1\x49\x89\xC0\x58\x49\xF7\xD0\x4D\x01\xE8\x49\x81\xF0\x0F\x0F\x0F\x0F\x49\x81\xC0\x0F\x0F\x0F\x0F\x48\xC1\xE0\x04\x48\xC1\xC0\x10\x4C\x01\xC0\x4C\x31\xD8\x48\xC1\xE8\x02\x4C\x01\xF0\x48\xC1\xE8\x03\x48\xC1\xC8\x06\x4D\x01\xD8\x4C\x01\xC0\x4D\x8D\x7F\x01\x80\xFC\xAA\x76\xE9\x48\x0F\xBA\xE0\x3C\x73\x05\x48\x0F\xBA\xF0\x3C\x4D\x31\xC8\x49\xF7\xD0\x4D\x01\xE8\x49\x81\xF0\x0F\x0F\x0F\x0F\x49\xC1\xE0\x08\x49\x81\xC0\xEF\xEF\xEF\x0F\x48\xC1\xE8\x04\x48\xC1\xC0\x10\x4C\x01\xC0\x4C\x31\xD8\x49\xF7\xF4\x49\xC1\xC7\x20\x4C\x01\xD8\x48\xF7\xD0\x4C\x01\xC0\x48\xC1\xC0\x03\x4C\x31\xD0\x4D\x01\xF0\x4C\x01\xC0\x4D\x8D\x7F\x01\x80\xFC\x55\x76\xE4\x49\xC1\xCF\x20\x48\xBB\x06\x73\x32\x60\xF3\x49\xB3\xD1\x39\xD8\xC3"

def emulate(ctx, pc):
    while pc:
        opcode = ctx.getConcreteMemoryAreaValue(pc, 16)
        instruction = Instruction(pc, opcode)
        ctx.processing(instruction)

        if instruction.isSymbolized():
            print("\033[92m" + str(instruction) + "\033[0m")
        else:
            print(instruction)

        pc = ctx.getRegisterAst(ctx.registers.rip).evaluate()

        if pc == 0x1090: # constrain RDX to avoid #DE on a real machine (RDX:RAX too big)
            ctx.pushPathConstraint(ctx.getRegisterAst(ctx.registers.rdx) < 0x1000)
    return

def main():
    ctx = TritonContext(ARCH.X86_64)
    ast = ctx.getAstContext()

    # Triton Settings
    ctx.setMode(MODE.CONSTANT_FOLDING, True)
    ctx.setMode(MODE.ALIGNED_MEMORY, True)
    ctx.setMode(MODE.AST_OPTIMIZATIONS, True)
    ctx.setMode(MODE.CONCRETIZE_UNDEFINED_REGISTERS, True)
    ctx.setSolver(SOLVER.Z3)

    # declare inputs
    ctx.symbolizeRegister(ctx.registers.rax, "rax")
    ctx.symbolizeRegister(ctx.registers.r8, "r8")
    ctx.symbolizeRegister(ctx.registers.r9, "r9")
    ctx.symbolizeRegister(ctx.registers.r10, "r10")
    ctx.symbolizeRegister(ctx.registers.r11, "r11")
    ctx.symbolizeRegister(ctx.registers.r12, "r12")
    ctx.symbolizeRegister(ctx.registers.r13, "r13")
    ctx.symbolizeRegister(ctx.registers.r14, "r14")
    ctx.symbolizeRegister(ctx.registers.r15, "r15")

    print('Emulating...')
    ctx.setConcreteMemoryAreaValue(0x1000, CODE)
    emulate(ctx, 0x1000)

    eaxAST = ctx.getSymbolicRegister(ctx.registers.eax).getAst()
    #print("raxAST = ", ast.unroll(eaxAST))

    # hashes in eax (generated) and ebx (loaded) must be equal
    ctx.pushPathConstraint(ctx.getRegisterAst(ctx.registers.zf) == 1)

    print("solving...")
    model = ctx.getModel(ctx.getPathPredicate())

    print(tabulate(sorted(model.items())))
    print(tabulate(sorted({k: v.getValue() for k, v in model.items()}.items())))
    return 0

if __name__ == '__main__':
    sys.exit(main())

 

solver.py

Create an account or sign in to comment

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.