Vector35 / Vector35/binaryninja-api
Register stack lifting
Nobody has claimed this yet.
- 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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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