func_call() method to automatically generate ROP chains that invoke functions with proper calling conventions, argument setup, and optional return handling.
Basic Function Calls: func_call()
The func_call() method handles all the complexity of setting up function arguments according to the target architecture’s calling convention.
Method Signature
address: Function address (integer) or name (string)args: List or tuple of arguments to pass to the functionpreserve_regs: Set of registers that should not be modifiedneeds_return: Whether execution should continue after the function (default:True)
RopChain that calls the function with the specified arguments
Basic Examples
1
Call a function by name
2
Call a function by address
3
Call without returning
Angrop automatically detects the calling convention based on the architecture and platform. On x86_64 Linux, arguments go in
rdi, rsi, rdx, rcx, r8, r9, then stack. On x86, arguments go on the stack.Real-World Example: File Operations
From angrop’s Python API documentation:Calling Convention Details
x86_64 (System V AMD64 ABI)
Arguments are passed in registers:rdi- First argumentrsi- Second argumentrdx- Third argumentrcx- Fourth argumentr8- Fifth argumentr9- Sixth argument- Stack - Additional arguments
rax.
x86 (32-bit cdecl)
All arguments passed on the stack in reverse order:eax.
ARM
Arguments inr0, r1, r2, r3, then stack:
Preserving Registers Across Calls
Usepreserve_regs to maintain register values across function calls:
Real-World Example: Kernel Function Calls
From angrop’s kernel test suite (solve.py:38-44):
- Calling functions that return values (in
rax) - Moving return values to argument registers
- Preserving multiple registers across calls
- Building complex multi-stage exploits
When calling functions that return values, the result is typically in
rax (x64) or eax (x86). Use move_regs() to move return values to other registers before the next call.Using Function Return Values
Calling Functions from PLT/GOT
Angrop automatically resolves function names from the PLT (Procedure Linkage Table):How PLT/GOT Resolution Works
From the source code (func_caller.py:48-72), angrop:
- Checks if the name exists in PLT
- Looks for the symbol in the binary
- Finds function pointers in GOT if available
- Searches for pointers to the function in readable segments
Handling Stack Arguments
For functions with more than 6 arguments on x86_64 (or any arguments on x86):- Sets up register arguments
- Pushes stack arguments
- Aligns the stack properly
- Handles cleanup if
needs_return=True
Advanced: Direct Register Control
From angrop’s Python API documentation (pythonapi.md:101-111), you can use registers directly as arguments:
preserve_regs={'rdi'}, angrop skips setting rdi and uses whatever value is already there (e.g., from a previous function’s return value).
Calling Functions Without Returning
When you don’t need to return from a function, setneeds_return=False:
Setting
needs_return=False generates shorter chains because angrop doesn’t need to set up stack frames for returning to the ROP chain. Use this for the last function call in your exploit.Common Function Call Patterns
Pattern 1: Open-Read-Write
Pattern 2: Allocate-Write-Execute
Pattern 3: Chain Library Calls
Troubleshooting
”Symbol does not exist” Error
”Fail to invoke function” Error
This occurs when angrop can’t find suitable gadgets:Return Value Not Preserved
If you need to use a function’s return value:Best Practices
- Use function names when possible instead of hardcoded addresses
- Set
needs_return=Falsefor the final call to reduce chain size - Preserve return values by moving them before subsequent operations
- Use
preserve_regswhen you need to maintain state across calls - Test incrementally - build and test each function call before chaining
- Check calling conventions for your target architecture
Performance Tips
- Function calls without returns are faster to generate
- Preserving many registers increases constraint complexity
- Using stack arguments adds overhead
- PLT/GOT calls may be more efficient than direct addresses
Next Steps
- Syscalls - Make system calls instead of library calls
- Register Operations - Manually set up arguments
- Memory Operations - Prepare data for function calls