Vector35 / Vector35/binaryninja-api

Register stack lifting

Open
#2,639 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Component: Core Core: MLIL Effort: High Impact: Medium
Dominant language
C++
Stars
1.3k
Forks
298
Avg merge
5d 5h
Merged PRs (30d)
19

Description

Is your feature request related to a problem? Please describe.
There exist a number of LLIL operations for register stacks that are unimplemented in MLIL. Trying to lift any stack-based language by using register stacks will leave you in unimplemented city.

Describe the solution you'd like
MLIL lifting support for all the register stack operations. Notably, LLIL_REG_STACK_PUSH, LLIL_REG_STACK_POP, LLIL_REG_STACK_REL[_SSA] and LLIL_SET_REG_STACK_REL[_SSA]. Ideally, register stacks would be lifted using the same dataflow code as the stack pointer, which could be generalized as a register stack if you're feeling brave.

Describe alternatives you've considered
There are a few other methods I've tried to simulate register stack lifting, each with their own limitations:

"""
Reg stacks via push/pop on sp (no separation for multiple stacks)
"""
def reg_stack_push(size, reg_stack, value, flags=0):
    return il.push(size, value)

def reg_stack_pop(size, reg_stack, flags=0):
    return il.pop(size)

def reg_stack_top_relative(size, reg_stack, offset):
    return il.load(size, il.add(size, il.reg(size, 'sp'), offset))
"""
Reg stacks via registers to global pointers (no dataflow)
"""
temps = []
def reg_stack_push(size, reg_stack, value, flags=0):
    il.append(il.set_reg(size, reg_stack, il.add(size, il.reg(size, reg_stack), il.const(size, size))))
    return il.store(size, il.reg(size, reg_stack), value)

def reg_stack_pop(size, reg_stack, flags=0):
    temps.append(len(temps) | (addr & 0xFFF))
    il.append(il.set_reg(size, LLIL_TEMP(temps[-1]), il.reg(size, reg_stack)))
    il.append(il.set_reg(size, reg_stack, il.sub(size, il.reg(size, reg_stack), il.const(size, size))))
    return il.reg(size, LLIL_TEMP(temps[-1]))

def reg_stack_top_relative(size, reg_stack, offset):
    temps.append(len(temps) | (addr & 0xFFF))
    il.append(il.set_reg(size, LLIL_TEMP(temps[-1]), il.load(size, il.add(size, il.reg(size, reg_stack), offset))))
    return il.reg(size, LLIL_TEMP(temps[-1]))
"""
Reg stacks via cursed (cursed)
"""
temps = []
if addr == il.source_function.start:
    il.append(il.set_reg(4, 'regstack', il.sub(4, il.reg(4, 'sp'), il.const(4, 0x1000))))
    il.append(il.set_reg(4, 'sp', il.sub(4, il.reg(4, 'sp'), il.const(4, 0x4000))))

def reg_stack_push(size: int, reg_stack: str, value: LowLevelILExpr, flags=0):
    il.append(il.set_reg(size, reg_stack, il.sub(size, il.reg(size, reg_stack), il.const(size, size))))
    il.append(il.store(size, il.reg(size, reg_stack), value))
    return il.nop()

def reg_stack_pop(size: int, reg_stack: str, flags=0):
    temps.append(len(temps) | (addr & 0xFFF))
    il.append(il.set_reg(size, LLIL_TEMP(temps[-1]), il.load(size, il.reg(size, reg_stack))))
    il.append(il.set_reg(size, reg_stack, il.add(size, il.reg(size, reg_stack), il.const(size, size))))
    return il.reg(size, LLIL_TEMP(temps[-1]))

def reg_stack_top_relative(size: int, reg_stack: str, offset: LowLevelILExpr):
    temps.append(len(temps) | (addr & 0xFFF))
    il.append(il.set_reg(size, LLIL_TEMP(temps[-1]), il.load(size, il.add(size, il.reg(size, reg_stack), offset))))
    return il.reg(size, LLIL_TEMP(temps[-1]))

def set_reg_stack_top_relative(size: int, reg_stack: str, offset: LowLevelILExpr, value: LowLevelILExpr):
    il.append(il.store(size, il.add(size, il.reg(size, reg_stack), offset), value))
    return il.nop()

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the MLIL lifting implementation for LLIL_REG_STACK_PUSH, LLIL_REG_STACK_POP, LLIL_REG_STACK_REL[_SSA], and LLIL_SET_REG_STACK_REL[_SSA]. Compare it with the existing stack-pointer dataflow handling and the Python workarounds in the issue. Done means all listed register-stack operations lift into MLIL without ending in unimplemented.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
compilers, reverse-engineering
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.