# Decompile main() to readable C
import angr
proj = angr.Project("fauxware")
cfg = proj.analyses.CFGFast(normalize=True)// open-source binary analysis
Demystify binaries.
angr is a powerful Python platform for analyzing binaries, combining decompilation, symbolic execution, and more into one scriptable toolkit.
- BSD
- licensed
- 8+
- guest architectures
- 1
- pip install away
int main(unsigned int a0, unsigned long long a1)
{
unsigned long long v0; // [bp-0x48]
unsigned int v1; // [bp-0x3c]
char v2; // [bp-0x2c], Other Possible Types: unsigned int
char v3; // [bp-0x28]
char v4; // [bp-0x20]
char v5; // [bp-0x18]
char v6; // [bp-0x10]
v1 = a0;
v0 = a1;
v6 = 0;
v4 = 0;
puts("Username: ");
read(0, &v5, 8);
read(0, &v2, 1);
puts("Password: ");
read(0, &v3, 8);
read(0, &v2, 1);
v2 = authenticate(&v5, &v3, &v3);
if (!v2)
rejected(); /* do not return */
return accepted();
}
extern char *sneaky;
unsigned int authenticate(char *a0, char *a1)
{
unsigned int v5; // edx
char v0[8]; // [bp-0x18]
char v1; // [bp-0x10]
unsigned int v2; // [bp-0xc]
v1 = 0;
if (strcmp(a1, sneaky))
{
v2 = open(a0, 0, v5);
read(v2, v0, 8);
return (!strcmp(a1, v0) ? 1 : 0);
}
return 1;
}
void rejected(void)
{
printf("Go away!");
exit(1); /* do not return */
}
void accepted(void)
{
puts("Welcome to the admin console, trusted user!");
return;
}main: 40071d 55 push rbp 40071e 48 89 e5 mov rbp, rsp 400721 48 83 ec 40 sub rsp, 0x40 400725 89 7d cc mov dword ptr [rbp-0x34], edi 400728 48 89 75 c0 mov qword ptr [rbp-0x40], rsi 40072c c6 45 f8 00 mov byte ptr [rbp-0x8], 0x0 400730 c6 45 e8 00 mov byte ptr [rbp-0x18], 0x0 400734 bf 15 09 40 00 mov edi, 0x400915 400739 e8 d2 fd ff ff call puts 40073e 48 8d 45 f0 lea rax, [rbp-0x10] 400742 ba 08 00 00 00 mov edx, 0x8 400747 48 89 c6 mov rsi, rax 40074a bf 00 00 00 00 mov edi, 0x0 40074f e8 dc fd ff ff call read 400754 48 8d 45 dc lea rax, [rbp-0x24] 400758 ba 01 00 00 00 mov edx, 0x1 40075d 48 89 c6 mov rsi, rax 400760 bf 00 00 00 00 mov edi, 0x0 400765 e8 c6 fd ff ff call read 40076a bf 20 09 40 00 mov edi, 0x400920 40076f e8 9c fd ff ff call puts 400774 48 8d 45 e0 lea rax, [rbp-0x20] 400778 ba 08 00 00 00 mov edx, 0x8 40077d 48 89 c6 mov rsi, rax 400780 bf 00 00 00 00 mov edi, 0x0 400785 e8 a6 fd ff ff call read 40078a 48 8d 45 dc lea rax, [rbp-0x24] 40078e ba 01 00 00 00 mov edx, 0x1 400793 48 89 c6 mov rsi, rax 400796 bf 00 00 00 00 mov edi, 0x0 40079b e8 90 fd ff ff call read 4007a0 48 8d 55 e0 lea rdx, [rbp-0x20] 4007a4 48 8d 45 f0 lea rax, [rbp-0x10] 4007a8 48 89 d6 mov rsi, rdx 4007ab 48 89 c7 mov rdi, rax 4007ae e8 b1 fe ff ff call authenticate 4007b3 89 45 dc mov dword ptr [rbp-0x24], eax 4007b6 8b 45 dc mov eax, dword ptr [rbp-0x24] 4007b9 85 c0 test eax, eax ╭──╴4007bb 74 0c je 0x4007c9 │ │ 4007bd b8 00 00 00 00 mov eax, 0x0 │ 4007c2 e8 26 ff ff ff call accepted │ │ ╭╴4007c7 eb 0a jmp 0x4007d3 │ │ ╰▸│ 4007c9 b8 00 00 00 00 mov eax, 0x0 │ 4007ce e8 2a ff ff ff call rejected │ ╰▸4007d3 c9 leave 4007d4 c3 ret authenticate: 400664 55 push rbp 400665 48 89 e5 mov rbp, rsp 400668 48 83 ec 20 sub rsp, 0x20 40066c 48 89 7d e8 mov qword ptr [rbp-0x18], rdi 400670 48 89 75 e0 mov qword ptr [rbp-0x20], rsi 400674 c6 45 f8 00 mov byte ptr [rbp-0x8], 0x0 400678 48 8b 15 c9 09 mov rdx, qword ptr [sneaky] 20 00 40067f 48 8b 45 e0 mov rax, qword ptr [rbp-0x20] 400683 48 89 d6 mov rsi, rdx 400686 48 89 c7 mov rdi, rax 400689 e8 c2 fe ff ff call strcmp 40068e 85 c0 test eax, eax ╭╴400690 75 07 jne 0x400699 │ │ 400692 b8 01 00 00 00 mov eax, 0x1 ╭──╴│ 400697 eb 52 jmp 0x4006eb │ │ │ ╰▸400699 48 8b 45 e8 mov rax, qword ptr [rbp-0x18] │ 40069d be 00 00 00 00 mov esi, 0x0 │ 4006a2 48 89 c7 mov rdi, rax │ 4006a5 b8 00 00 00 00 mov eax, 0x0 │ 4006aa e8 b1 fe ff ff call open │ │ 4006af 89 45 fc mov dword ptr [rbp-0x4], eax │ 4006b2 48 8d 4d f0 lea rcx, [rbp-0x10] │ 4006b6 8b 45 fc mov eax, dword ptr [rbp-0x4] │ 4006b9 ba 08 00 00 00 mov edx, 0x8 │ 4006be 48 89 ce mov rsi, rcx │ 4006c1 89 c7 mov edi, eax │ 4006c3 e8 68 fe ff ff call read │ │ 4006c8 48 8d 55 f0 lea rdx, [rbp-0x10] │ 4006cc 48 8b 45 e0 mov rax, qword ptr [rbp-0x20] │ 4006d0 48 89 d6 mov rsi, rdx │ 4006d3 48 89 c7 mov rdi, rax │ 4006d6 e8 75 fe ff ff call strcmp │ │ 4006db 85 c0 test eax, eax │ ╭──╴4006dd 75 07 jne 0x4006e6 │ │ │ │ 4006df b8 01 00 00 00 mov eax, 0x1 │ │ ╭╴4006e4 eb 05 jmp 0x4006eb │ │ │ │ ╰▸│ 4006e6 b8 00 00 00 00 mov eax, 0x0 │ │ ╰──▸╰▸4006eb c9 leave 4006ec c3 ret rejected: 4006fd 55 push rbp 4006fe 48 89 e5 mov rbp, rsp 400701 b8 0c 09 40 00 mov eax, 0x40090c 400706 48 89 c7 mov rdi, rax 400709 b8 00 00 00 00 mov eax, 0x0 40070e e8 0d fe ff ff call printf 400713 bf 01 00 00 00 mov edi, 0x1 400718 e8 53 fe ff ff call exit accepted: 4006ed 55 push rbp 4006ee 48 89 e5 mov rbp, rsp 4006f1 bf e0 08 40 00 mov edi, 0x4008e0 4006f6 e8 15 fe ff ff call puts 4006fb 5d pop rbp 4006fc c3 ret
# Find the input that gets accepted
import angr
proj = angr.Project("fauxware")
simgr = proj.factory.simgr()
accepted = proj.loader.find_symbol("accepted").rebased_addr
simgr.explore(find=accepted)
print(simgr.found[0].posix.dumps(0))b'\x00\x00\x00\x00\x00\x00\x00\x00\x00SOSNEAKY\x00'
func main.main() {
v0 := 0
v1 := 0
v2 := 0
v3 := 0
v4 := 0
v10 := "Username: \nPassword: \nbad addressfile existsbroken pipebad messageassistQueuenetpollInitreflectOffsglobalAllocmSpanManualstart traceclobberfreegccheckmarkscheddetailunspecified"
syscall.RawSyscall(1, 1, "Username: \n", 11)
v9 := &v0
syscall.RawSyscall(0, 0, &v0, 8)
v8 := &v4
syscall.RawSyscall(0, 0, &v4, 1)
v7 := "Password: \nbad addressfile existsbroken pipebad messageassistQueuenetpollInitreflectOffsglobalAllocmSpanManualstart traceclobberfreegccheckmarkscheddetailunspecified"
syscall.RawSyscall(1, 1, "Password: \n", 11)
v6 := &v2
syscall.RawSyscall(0, 0, &v2, 8)
v5 := &v4
syscall.RawSyscall(0, 0, &v4, 1)
ok, v13 := main.authenticate(&v0, 9, 9, &v2, 8, 9)
if !ok {
main.rejected()
return
}
main.accepted()
return
}
func main.authenticate(a0 int, a1 int, a2 uint64, a3 unsafe.Pointer, a4 int, a5 uint64) (bool, uintptr) {
var v6 uint8 // al
var v7 int // rbx
if string{ptr: a3, len: a4} == "SOSNEAKY" {
return 1, a1
}
v0 := 0
v2 := a0
r1, r2, err := syscall.RawSyscall(2, a0, 0, 0)
v1 := &v0
r12, r22, err2 := syscall.RawSyscall(0, r1, &v0, 8)
if a4 != 8 {
v6 = 0
v7 = r22
} else {
v6 = runtime.memequal(a3, &v0, 8)
}
return v6, v7
}main.main: ╭──────▸47c780 49 3b 66 10 cmp rsp, qword ptr [r14+0x10] │ ╭────╴47c784 0f 86 08 01 00 jbe 0x47c892 │ │ 00 │ │ │ │ 47c78a 55 push rbp │ │ 47c78b 48 89 e5 mov rbp, rsp │ │ 47c78e 48 83 ec 78 sub rsp, 0x78 │ │ 47c792 48 c7 44 24 35 mov qword ptr [rsp+0x35], 0x0 │ │ 00 00 00 00 │ │ 47c79b c6 44 24 3d 00 mov byte ptr [rsp+0x3d], 0x0 │ │ 47c7a0 48 c7 44 24 3e mov qword ptr [rsp+0x3e], 0x0 │ │ 00 00 00 00 │ │ 47c7a9 c6 44 24 46 00 mov byte ptr [rsp+0x46], 0x0 │ │ 47c7ae c6 44 24 47 00 mov byte ptr [rsp+0x47], 0x0 │ │ 47c7b3 90 nop │ │ 47c7b4 48 8d 0d 71 78 lea rcx, [0x49402c] │ │ 01 00 │ │ 47c7bb 48 89 4c 24 70 mov qword ptr [rsp+0x70], rcx │ │ 47c7c0 b8 01 00 00 00 mov eax, 0x1 │ │ 47c7c5 48 89 c3 mov rbx, rax │ │ 47c7c8 bf 0b 00 00 00 mov edi, 0xb │ │ 47c7cd e8 4e fb ff ff call syscall.RawSyscall │ │ │ │ 47c7d2 90 nop │ │ 47c7d3 48 8d 4c 24 35 lea rcx, [rsp+0x35] │ │ 47c7d8 48 89 4c 24 68 mov qword ptr [rsp+0x68], rcx │ │ 47c7dd 31 c0 xor eax, eax │ │ 47c7df 48 89 c3 mov rbx, rax │ │ 47c7e2 bf 08 00 00 00 mov edi, 0x8 │ │ 47c7e7 e8 34 fb ff ff call syscall.RawSyscall │ │ │ │ 47c7ec 90 nop │ │ 47c7ed 48 8d 4c 24 47 lea rcx, [rsp+0x47] │ │ 47c7f2 48 89 4c 24 60 mov qword ptr [rsp+0x60], rcx │ │ 47c7f7 31 c0 xor eax, eax │ │ 47c7f9 48 89 c3 mov rbx, rax │ │ 47c7fc bf 01 00 00 00 mov edi, 0x1 │ │ 47c801 e8 1a fb ff ff call syscall.RawSyscall │ │ │ │ 47c806 90 nop │ │ 47c807 48 8d 0d 29 78 lea rcx, [0x494037] │ │ 01 00 │ │ 47c80e 48 89 4c 24 58 mov qword ptr [rsp+0x58], rcx │ │ 47c813 b8 01 00 00 00 mov eax, 0x1 │ │ 47c818 48 89 c3 mov rbx, rax │ │ 47c81b bf 0b 00 00 00 mov edi, 0xb │ │ 47c820 e8 fb fa ff ff call syscall.RawSyscall │ │ │ │ 47c825 90 nop │ │ 47c826 48 8d 4c 24 3e lea rcx, [rsp+0x3e] │ │ 47c82b 48 89 4c 24 50 mov qword ptr [rsp+0x50], rcx │ │ 47c830 31 c0 xor eax, eax │ │ 47c832 48 89 c3 mov rbx, rax │ │ 47c835 bf 08 00 00 00 mov edi, 0x8 │ │ 47c83a e8 e1 fa ff ff call syscall.RawSyscall │ │ │ │ 47c83f 90 nop │ │ 47c840 48 8d 4c 24 47 lea rcx, [rsp+0x47] │ │ 47c845 48 89 4c 24 48 mov qword ptr [rsp+0x48], rcx │ │ 47c84a 31 c0 xor eax, eax │ │ 47c84c 48 89 c3 mov rbx, rax │ │ 47c84f bf 01 00 00 00 mov edi, 0x1 │ │ 47c854 e8 c7 fa ff ff call syscall.RawSyscall │ │ │ │ 47c859 48 8d 44 24 35 lea rax, [rsp+0x35] │ │ 47c85e bb 09 00 00 00 mov ebx, 0x9 │ │ 47c863 48 89 d9 mov rcx, rbx │ │ 47c866 48 8d 7c 24 3e lea rdi, [rsp+0x3e] │ │ 47c86b be 08 00 00 00 mov esi, 0x8 │ │ 47c870 49 89 c8 mov r8, rcx │ │ 47c873 e8 48 fd ff ff call main.authenticate │ │ │ │ 47c878 84 c0 test al, al │ │ ╭──╴47c87a 74 0b je 0x47c887 │ │ │ │ │ │ 47c87c 0f 1f 40 00 nop dword ptr [rax] │ │ │ 47c880 e8 5b fe ff ff call main.accepted │ │ │ │ │ │ ╭╴47c885 eb 05 jmp 0x47c88c │ │ │ │ │ │ ╰▸│ 47c887 e8 94 fe ff ff call main.rejected │ │ │ │ │ ╰▸47c88c 48 83 c4 78 add rsp, 0x78 │ │ 47c890 5d pop rbp │ │ 47c891 c3 ret │ │ │ ╰────▸47c892 e8 29 9e ff ff call runtime.morestack_noctxt.abi0 │ ╰──────╴47c897 e9 e4 fe ff ff jmp main.main main.authenticate: ╭────────▸47c5c0 49 3b 66 10 cmp rsp, qword ptr [r14+0x10] │ ╭──────╴47c5c4 0f 86 b0 00 00 jbe 0x47c67a │ │ 00 │ │ │ │ 47c5ca 55 push rbp │ │ 47c5cb 48 89 e5 mov rbp, rsp │ │ 47c5ce 48 83 ec 38 sub rsp, 0x38 │ │ 47c5d2 48 89 44 24 48 mov qword ptr [rsp+0x48], rax │ │ 47c5d7 48 89 7c 24 60 mov qword ptr [rsp+0x60], rdi │ │ 47c5dc 0f 1f 40 00 nop dword ptr [rax] │ │ 47c5e0 48 83 fe 08 cmp rsi, 0x8 │ │ ╭──╴47c5e4 75 1b jne 0x47c601 │ │ │ │ │ │ 47c5e6 48 ba 53 4f 53 movabs rdx, 0x594b41454e534f53 │ │ │ 4e 45 41 4b 59 │ │ │ 47c5f0 48 39 17 cmp qword ptr [rdi], rdx │ │ │ ╭╴47c5f3 75 0c jne 0x47c601 │ │ │ │ │ │ │ │ 47c5f5 b8 01 00 00 00 mov eax, 0x1 │ │ │ │ 47c5fa 48 83 c4 38 add rsp, 0x38 │ │ │ │ 47c5fe 5d pop rbp │ │ │ │ 47c5ff 90 nop │ │ │ │ 47c600 c3 ret │ │ │ │ │ │ ╰▸╰▸47c601 48 c7 44 24 20 mov qword ptr [rsp+0x20], 0x0 │ │ 00 00 00 00 │ │ 47c60a 90 nop │ │ 47c60b 48 85 db test rbx, rbx │ │ ╭────╴47c60e 76 64 jbe 0x47c674 │ │ │ │ │ │ 47c610 48 89 74 24 68 mov qword ptr [rsp+0x68], rsi │ │ │ 47c615 48 89 7c 24 60 mov qword ptr [rsp+0x60], rdi │ │ │ 47c61a 48 89 44 24 30 mov qword ptr [rsp+0x30], rax │ │ │ 47c61f 48 89 c3 mov rbx, rax │ │ │ 47c622 31 c9 xor ecx, ecx │ │ │ 47c624 48 89 cf mov rdi, rcx │ │ │ 47c627 b8 02 00 00 00 mov eax, 0x2 │ │ │ 47c62c e8 ef fc ff ff call syscall.RawSyscall │ │ │ │ │ │ 47c631 90 nop │ │ │ 47c632 48 8d 4c 24 20 lea rcx, [rsp+0x20] │ │ │ 47c637 48 89 4c 24 28 mov qword ptr [rsp+0x28], rcx │ │ │ 47c63c 48 89 c3 mov rbx, rax │ │ │ 47c63f bf 08 00 00 00 mov edi, 0x8 │ │ │ 47c644 31 c0 xor eax, eax │ │ │ 47c646 e8 d5 fc ff ff call syscall.RawSyscall │ │ │ │ │ │ 47c64b 48 8b 54 24 68 mov rdx, qword ptr [rsp+0x68] │ │ │ 47c650 48 83 fa 08 cmp rdx, 0x8 │ │ │ ╭╴47c654 74 04 je 0x47c65a │ │ │ │ │ │ │ │ 47c656 31 c0 xor eax, eax │ │ │ ╭╴│ 47c658 eb 14 jmp 0x47c66e │ │ │ │ │ │ │ │ │ ╰▸47c65a 48 8b 44 24 60 mov rax, qword ptr [rsp+0x60] │ │ │ │ 47c65f 48 8d 5c 24 20 lea rbx, [rsp+0x20] │ │ │ │ 47c664 b9 08 00 00 00 mov ecx, 0x8 │ │ │ │ 47c669 e8 12 69 f8 ff call runtime.memequal │ │ │ │ │ │ │ ╰──▸47c66e 48 83 c4 38 add rsp, 0x38 │ │ │ 47c672 5d pop rbp │ │ │ 47c673 c3 ret │ │ │ │ │ ╰────▸47c674 e8 27 bd ff ff call runtime.panicBounds │ │ │ ╰──────▸47c67a 48 89 44 24 08 mov qword ptr [rsp+0x8], rax │ 47c67f 48 89 5c 24 10 mov qword ptr [rsp+0x10], rbx │ 47c684 48 89 4c 24 18 mov qword ptr [rsp+0x18], rcx │ 47c689 48 89 7c 24 20 mov qword ptr [rsp+0x20], rdi │ 47c68e 48 89 74 24 28 mov qword ptr [rsp+0x28], rsi │ 47c693 4c 89 44 24 30 mov qword ptr [rsp+0x30], r8 │ 47c698 e8 23 a0 ff ff call runtime.morestack_noctxt.abi0 │ │ 47c69d 48 8b 44 24 08 mov rax, qword ptr [rsp+0x8] │ 47c6a2 48 8b 5c 24 10 mov rbx, qword ptr [rsp+0x10] │ 47c6a7 48 8b 4c 24 18 mov rcx, qword ptr [rsp+0x18] │ 47c6ac 48 8b 7c 24 20 mov rdi, qword ptr [rsp+0x20] │ 47c6b1 48 8b 74 24 28 mov rsi, qword ptr [rsp+0x28] │ 47c6b6 4c 8b 44 24 30 mov r8, qword ptr [rsp+0x30] │ 47c6bb 0f 1f 44 00 00 nop dword ptr [rax+rax] ╰────────╴47c6c0 e9 fb fe ff ff jmp main.authenticate
# Find the input that gets accepted
import angr
proj = angr.Project("fauxware")
main = proj.loader.find_symbol("main.main").rebased_addr
accepted = proj.loader.find_symbol("main.accepted").rebased_addr
morestack = proj.loader.find_symbol("runtime.morestack_noctxt.abi0").rebased_addr
# skip the Go runtime's bootstrap: start right at main.main
state = proj.factory.blank_state(addr=main)
simgr = proj.factory.simgr(state)
simgr.explore(find=accepted, avoid=morestack)
print(simgr.found[0].posix.dumps(0))b'\x00\x00\x00\x00\x00\x00\x00\x00\x00SOSNEAKY\x00'
fn fauxware::main() -> int {
let v0: std::io::stdio::Stdin; // [bp-0x60]
let v1: u8; // [bp-0x51]
let v2: u8; // [bp-0x49]
let v3: u8; // [bp-0x41]
let v4: u64; // [bp-0x38]
let v5: u64; // [bp-0x28]
let v6: u64; // [bp-0x18]
let v7: u64; // [bp-0x8]
let v10: struct16; // rax:rdx
let v11: core::result::Result<usize, std::io::error::Error>; // rax:rdx
let v12: core::result::Result<usize, std::io::error::Error>; // rax:rdx
let v13: core::result::Result<usize, std::io::error::Error>; // rax:rdx
let v14: core::result::Result<usize, std::io::error::Error>; // rax:rdx
let v15: struct16; // rax:rdx
v0 = std::io::stdio::stdin();
memset(&v1, 0, 8);
memset(&v2, 0, 8);
v3 = 0;
v10 = <core::fmt::Arguments>::from_str("Username: \n");
std::io::stdio::_print(v10 as u64);
v13 = <std::io::stdio::Stdin as std::io::Read>::read(&v0, &v1, 8);
v4 = *((&v13 as &char + 8) as &i64);
core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>>(&v13 as i64);
v14 = <std::io::stdio::Stdin as std::io::Read>::read(&v0, &v3, 1);
v5 = *((&v14 as &char + 8) as &i64);
core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>>(&v14 as i64);
v15 = <core::fmt::Arguments>::from_str("Password: \n");
std::io::stdio::_print(v15 as u64);
v12 = <std::io::stdio::Stdin as std::io::Read>::read(&v0, &v2, 8);
v6 = *((&v12 as &char + 8) as &i64);
core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>>(&v12 as i64);
v11 = <std::io::stdio::Stdin as std::io::Read>::read(&v0, &v3, 1);
v7 = *((&v11 as &char + 8) as &i64);
core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>>(&v11 as i64);
if fauxware::authenticate(&v1, &v2) as char {
return fauxware::accepted();
}
fauxware::rejected(); /* do not return */
}
fn fauxware::authenticate() -> u0 {
let v0: u8; // [bp-0x51]
let v1: u8; // [bp-0x50]
let v2: u8; // [bp-0x48]
let v3: Result<struct4, struct8>; // [bp-0x30]
let v4: struct4; // [bp-0x2c]
let v5: struct4; // [bp-0x1c]
let v6: struct16; // [bp-0x18]
let v7: &st_40a840_0; // [bp-0x8]
let v9: u64; // rdi
let v11: u64; // rdx
let v12: struct16; // rax:rdx
if <&[u8; 8] as core::cmp::PartialEq>::eq(&rsi, "") as char {
return;
}
memset(&v1, 0, 8);
<alloc::string::String>::from_utf8_lossy(&v2, v9, 8);
v12 = <str>::trim_end_matches::<char>(&v2, 0, 0);
v3 = <std::fs::File>::open::<&str>(v12 as u64, (v12 >> 64) as u64);
if let Ok(v5) = v3 {
v6 = struct16 {
field_0: <std::sys::fs::unix::File>::read(&v5, &v1, 8) as u64
field_8: v11
};
core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>>(&v6);
core::ptr::drop_glue::<std::fs::File>(&v5);
}
if let Err(_) = v3 {
core::ptr::drop_glue::<core::result::Result<std::fs::File, core::io::error::Error>>(&v3);
}
v7 = &v1;
v0 = <&[u8; 8] as core::cmp::PartialEq>::eq(&rsi, &v7) & 1;
core::ptr::drop_glue::<alloc::borrow::Cow<str>>(&v2);
return;
}_RNvCsfJzwR3Dz023_8fauxware4main: 40a950 48 83 ec 68 sub rsp, 0x68 40a954 ff 15 36 96 05 call qword ptr [0x463f90] 00 40a95a 48 89 44 24 08 mov qword ptr [rsp+0x8], rax 40a95f 48 8d 7c 24 17 lea rdi, [rsp+0x17] 40a964 31 f6 xor esi, esi 40a966 ba 08 00 00 00 mov edx, 0x8 40a96b e8 e0 b6 ff ff call memset 40a970 48 8d 7c 24 1f lea rdi, [rsp+0x1f] 40a975 31 f6 xor esi, esi 40a977 ba 08 00 00 00 mov edx, 0x8 40a97c e8 cf b6 ff ff call memset 40a981 c6 44 24 27 00 mov byte ptr [rsp+0x27], 0x0 40a986 48 8d 3d c3 52 lea rdi, [0x44fc50] 04 00 40a98d be 0b 00 00 00 mov esi, 0xb 40a992 e8 b9 03 00 00 call <core::fmt::Arguments>::from_str 40a997 48 89 c7 mov rdi, rax 40a99a 48 89 d6 mov rsi, rdx 40a99d ff 15 35 95 05 call qword ptr [0x463ed8] 00 40a9a3 48 8d 7c 24 08 lea rdi, [rsp+0x8] 40a9a8 48 8d 74 24 17 lea rsi, [rsp+0x17] 40a9ad ba 08 00 00 00 mov edx, 0x8 40a9b2 ff 15 08 94 05 call qword ptr [0x463dc0] 00 40a9b8 48 89 44 24 28 mov qword ptr [rsp+0x28], rax 40a9bd 48 89 54 24 30 mov qword ptr [rsp+0x30], rdx 40a9c2 48 8d 7c 24 28 lea rdi, [rsp+0x28] 40a9c7 e8 94 f8 ff ff call core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>> 40a9cc 48 8d 7c 24 08 lea rdi, [rsp+0x8] 40a9d1 48 8d 74 24 27 lea rsi, [rsp+0x27] 40a9d6 ba 01 00 00 00 mov edx, 0x1 40a9db ff 15 df 93 05 call qword ptr [0x463dc0] 00 40a9e1 48 89 44 24 38 mov qword ptr [rsp+0x38], rax 40a9e6 48 89 54 24 40 mov qword ptr [rsp+0x40], rdx 40a9eb 48 8d 7c 24 38 lea rdi, [rsp+0x38] 40a9f0 e8 6b f8 ff ff call core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>> 40a9f5 48 8d 3d 5f 52 lea rdi, [0x44fc5b] 04 00 40a9fc be 0b 00 00 00 mov esi, 0xb 40aa01 e8 4a 03 00 00 call <core::fmt::Arguments>::from_str 40aa06 48 89 c7 mov rdi, rax 40aa09 48 89 d6 mov rsi, rdx 40aa0c ff 15 c6 94 05 call qword ptr [0x463ed8] 00 40aa12 48 8d 7c 24 08 lea rdi, [rsp+0x8] 40aa17 48 8d 74 24 1f lea rsi, [rsp+0x1f] 40aa1c ba 08 00 00 00 mov edx, 0x8 40aa21 ff 15 99 93 05 call qword ptr [0x463dc0] 00 40aa27 48 89 44 24 48 mov qword ptr [rsp+0x48], rax 40aa2c 48 89 54 24 50 mov qword ptr [rsp+0x50], rdx 40aa31 48 8d 7c 24 48 lea rdi, [rsp+0x48] 40aa36 e8 25 f8 ff ff call core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>> 40aa3b 48 8d 7c 24 08 lea rdi, [rsp+0x8] 40aa40 48 8d 74 24 27 lea rsi, [rsp+0x27] 40aa45 ba 01 00 00 00 mov edx, 0x1 40aa4a ff 15 70 93 05 call qword ptr [0x463dc0] 00 40aa50 48 89 44 24 58 mov qword ptr [rsp+0x58], rax 40aa55 48 89 54 24 60 mov qword ptr [rsp+0x60], rdx 40aa5a 48 8d 7c 24 58 lea rdi, [rsp+0x58] 40aa5f e8 fc f7 ff ff call core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>> 40aa64 48 8d 7c 24 17 lea rdi, [rsp+0x17] 40aa69 48 8d 74 24 1f lea rsi, [rsp+0x1f] 40aa6e e8 cd fd ff ff call fauxware::authenticate 40aa73 a8 01 test al, 0x1 ╭╴40aa75 75 05 jne 0x40aa7c │ │ 40aa77 e8 34 00 00 00 call fauxware::rejected │ ╰▸40aa7c e8 0f 00 00 00 call fauxware::accepted 40aa81 48 83 c4 68 add rsp, 0x68 40aa85 c3 ret _RNvCsfJzwR3Dz023_8fauxware12authenticate: 40a840 48 83 ec 68 sub rsp, 0x68 40a844 48 89 3c 24 mov qword ptr [rsp], rdi 40a848 48 89 74 24 08 mov qword ptr [rsp+0x8], rsi 40a84d 48 8d 7c 24 08 lea rdi, [rsp+0x8] 40a852 48 8d 35 5f 6b lea rsi, [0x4613b8] 05 00 40a859 e8 72 13 00 00 call <&[u8; 8] as core::cmp::PartialEq>::eq 40a85e a8 01 test al, 0x1 ╭────╴40a860 75 57 jne 0x40a8b9 │ │ 40a862 48 8d 7c 24 18 lea rdi, [rsp+0x18] │ 40a867 31 f6 xor esi, esi │ 40a869 ba 08 00 00 00 mov edx, 0x8 │ 40a86e e8 dd b7 ff ff call memset │ │ 40a873 48 8b 34 24 mov rsi, qword ptr [rsp] │ 40a877 48 8d 7c 24 20 lea rdi, [rsp+0x20] │ 40a87c ba 08 00 00 00 mov edx, 0x8 │ 40a881 ff 15 19 94 05 call qword ptr [0x463ca0] │ 00 │ │ 40a887 48 8d 7c 24 20 lea rdi, [rsp+0x20] │ 40a88c e8 9f 11 00 00 call <alloc::borrow::Cow<str> as core::ops::deref::Deref>::deref │ │ 40a891 48 89 c7 mov rdi, rax │ 40a894 48 89 d6 mov rsi, rdx │ 40a897 31 d2 xor edx, edx │ 40a899 e8 22 f7 ff ff call <str>::trim_end_matches::<char> │ │ 40a89e 48 89 c6 mov rsi, rax │ 40a8a1 48 8d 7c 24 38 lea rdi, [rsp+0x38] │ 40a8a6 e8 a5 f7 ff ff call <std::fs::File>::open::<&str> │ │ 40a8ab 8b 44 24 38 mov eax, dword ptr [rsp+0x38] │ 40a8af 48 a9 01 00 00 test rax, 0x1 │ 00 │ ╭╴40a8b5 75 09 jne 0x40a8c0 │ │ │ ╭╴│ 40a8b7 eb 15 jmp 0x40a8ce │ │ │ ╰▸│ │ 40a8b9 c6 44 24 17 01 mov byte ptr [rsp+0x17], 0x1 ╭──────╴│ │ 40a8be eb 7e jmp 0x40a93e │ │ │ │ ╭──▸│ ╰▸40a8c0 8b 44 24 38 mov eax, dword ptr [rsp+0x38] │ │ │ 40a8c4 48 a9 01 00 00 test rax, 0x1 │ │ │ 00 │ │ ╭╴│ 40a8ca 75 3f jne 0x40a90b │ │ │ │ │ ╭╴│ │ │ 40a8cc eb 47 jmp 0x40a915 │ │ │ │ │ │ │ │ │ ╰──▸40a8ce 8b 44 24 3c mov eax, dword ptr [rsp+0x3c] │ │ │ │ 40a8d2 89 44 24 4c mov dword ptr [rsp+0x4c], eax │ │ │ │ 40a8d6 48 8d 7c 24 4c lea rdi, [rsp+0x4c] │ │ │ │ 40a8db 48 8d 74 24 18 lea rsi, [rsp+0x18] │ │ │ │ 40a8e0 ba 08 00 00 00 mov edx, 0x8 │ │ │ │ 40a8e5 ff 15 95 90 05 call qword ptr [0x463980] │ │ │ │ 00 │ │ │ │ │ │ │ │ 40a8eb 48 89 44 24 50 mov qword ptr [rsp+0x50], rax │ │ │ │ 40a8f0 48 89 54 24 58 mov qword ptr [rsp+0x58], rdx │ │ │ │ 40a8f5 48 8d 7c 24 50 lea rdi, [rsp+0x50] │ │ │ │ 40a8fa e8 61 f9 ff ff call core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>> │ │ │ │ │ │ │ │ 40a8ff 48 8d 7c 24 4c lea rdi, [rsp+0x4c] │ │ │ │ 40a904 e8 37 fa ff ff call core::ptr::drop_glue::<std::fs::File> │ │ │ │ │ │ ╰╴│ 40a909 eb b5 jmp 0x40a8c0 │ │ │ │ │ ╰────▸40a90b 48 8d 7c 24 38 lea rdi, [rsp+0x38] │ │ 40a910 e8 1b f9 ff ff call core::ptr::drop_glue::<core::result::Result<std::fs::File, core::io::error::Error>> │ │ │ ╰────────▸40a915 48 8d 44 24 18 lea rax, [rsp+0x18] │ 40a91a 48 89 44 24 60 mov qword ptr [rsp+0x60], rax │ 40a91f 48 8d 7c 24 08 lea rdi, [rsp+0x8] │ 40a924 48 8d 74 24 60 lea rsi, [rsp+0x60] │ 40a929 e8 a2 12 00 00 call <&[u8; 8] as core::cmp::PartialEq>::eq │ │ 40a92e 24 01 and al, 0x1 │ 40a930 88 44 24 17 mov byte ptr [rsp+0x17], al │ 40a934 48 8d 7c 24 20 lea rdi, [rsp+0x20] │ 40a939 e8 92 f9 ff ff call core::ptr::drop_glue::<alloc::borrow::Cow<str>> │ ╰──────────▸40a93e 8a 44 24 17 mov al, byte ptr [rsp+0x17] 40a942 24 01 and al, 0x1 40a944 48 83 c4 68 add rsp, 0x68 40a948 c3 ret
# Find the input that gets accepted
import angr
proj = angr.Project("fauxware")
cfg = proj.analyses.CFGFast(normalize=True)
funcs = {f.demangled_name: f for f in cfg.functions.values()}
# skip the Rust runtime's startup: start right at fauxware::main
state = proj.factory.blank_state(addr=funcs["fauxware::main"].addr)
simgr = proj.factory.simgr(state)
simgr.explore(find=funcs["fauxware::accepted"].addr)
print(simgr.found[0].posix.dumps(0).rstrip(b"\x00"))b'\x00\x00\x00\x00\x00\x00\x00\x00\x00SOSNEAKY'
dec = proj.analyses.Decompiler("main")
print(dec.codegen.text)int main(unsigned int a0, unsigned long long a1)
{
unsigned long long v0; // [bp-0x48]
unsigned int v1; // [bp-0x3c]
char v2; // [bp-0x2c], Other Possible Types: unsigned int
char v3; // [bp-0x28]
char v4; // [bp-0x20]
char v5; // [bp-0x18]
char v6; // [bp-0x10]
v1 = a0;
v0 = a1;
v6 = 0;
v4 = 0;
puts("Username: ");
read(0, &v5, 8);
read(0, &v2, 1);
puts("Password: ");
read(0, &v3, 8);
read(0, &v2, 1);
v2 = authenticate(&v5, &v3, &v3);
if (!v2)
rejected(); /* do not return */
return accepted();
}# Disassemble a function with its CFG edges
import angr
proj = angr.Project("fauxware")
proj.analyses.CFGFast(normalize=True)
proj.kb.functions["authenticate"].pp()authenticate: 400664 push rbp 400665 mov rbp, rsp 400668 sub rsp, 0x20 40066c mov qword ptr [rbp-0x18], rdi 400670 mov qword ptr [rbp-0x20], rsi 400674 mov byte ptr [rbp-0x8], 0x0 400678 mov rdx, qword ptr [sneaky] 40067f mov rax, qword ptr [rbp-0x20] 400683 mov rsi, rdx 400686 mov rdi, rax 400689 call strcmp 40068e test eax, eax ╭╴400690 jne 0x400699 │ │ 400692 mov eax, 0x1 ╭──╴│ 400697 jmp 0x4006eb │ │ │ ╰▸400699 mov rax, qword ptr [rbp-0x18] │ 40069d mov esi, 0x0 │ 4006a2 mov rdi, rax │ 4006a5 mov eax, 0x0 │ 4006aa call open │ │ 4006af mov dword ptr [rbp-0x4], eax │ 4006b2 lea rcx, [rbp-0x10] │ 4006b6 mov eax, dword ptr [rbp-0x4] │ 4006b9 mov edx, 0x8 │ 4006be mov rsi, rcx │ 4006c1 mov edi, eax │ 4006c3 call read │ │ 4006c8 lea rdx, [rbp-0x10] │ 4006cc mov rax, qword ptr [rbp-0x20] │ 4006d0 mov rsi, rdx │ 4006d3 mov rdi, rax │ 4006d6 call strcmp │ │ 4006db test eax, eax │ ╭──╴4006dd jne 0x4006e6 │ │ │ │ 4006df mov eax, 0x1 │ │ ╭╴4006e4 jmp 0x4006eb │ │ │ │ ╰▸│ 4006e6 mov eax, 0x0 │ │ ╰──▸╰▸4006eb leave 4006ec ret
# Find the input that gets accepted
import angr
proj = angr.Project("fauxware")
simgr = proj.factory.simgr()accepted = proj.loader.find_symbol("accepted").rebased_addr
simgr.explore(find=accepted)<SimulationManager with 1 active, 1 found>
print(simgr.found[0].posix.dumps(0))b'\x00\x00\x00\x00\x00\x00\x00\x00\x00SOSNEAKY\x00'
# Decompile a Go binary's main.main — back to Go
import angr
proj = angr.Project("fauxware")
cfg = proj.analyses.CFGFast(normalize=True)proj.analyses.CompleteCallingConventions()
dec = proj.analyses.Decompiler("main.main", flavor="go")
print(dec.codegen.text)func main.main() {
v0 := 0
v1 := 0
v2 := 0
v3 := 0
v4 := 0
v10 := "Username: \nPassword: \nbad addressfile existsbroken pipebad messageassistQueuenetpollInitreflectOffsglobalAllocmSpanManualstart traceclobberfreegccheckmarkscheddetailunspecified"
syscall.RawSyscall(1, 1, "Username: \n", 11)
v9 := &v0
syscall.RawSyscall(0, 0, &v0, 8)
v8 := &v4
syscall.RawSyscall(0, 0, &v4, 1)
v7 := "Password: \nbad addressfile existsbroken pipebad messageassistQueuenetpollInitreflectOffsglobalAllocmSpanManualstart traceclobberfreegccheckmarkscheddetailunspecified"
syscall.RawSyscall(1, 1, "Password: \n", 11)
v6 := &v2
syscall.RawSyscall(0, 0, &v2, 8)
v5 := &v4
syscall.RawSyscall(0, 0, &v4, 1)
ok, v13 := main.authenticate(&v0, 9, 9, &v2, 8, 9)
if !ok {
main.rejected()
return
}
main.accepted()
return
}# Disassemble a Go function with its CFG edges
import angr
proj = angr.Project("fauxware")
proj.analyses.CFGFast(normalize=True)
proj.kb.functions["main.authenticate"].pp()main.authenticate: ╭────────▸47c5c0 cmp rsp, qword ptr [r14+0x10] │ ╭──────╴47c5c4 jbe 0x47c67a │ │ │ │ 47c5ca push rbp │ │ 47c5cb mov rbp, rsp │ │ 47c5ce sub rsp, 0x38 │ │ 47c5d2 mov qword ptr [rsp+0x48], rax │ │ 47c5d7 mov qword ptr [rsp+0x60], rdi │ │ 47c5dc nop dword ptr [rax] │ │ 47c5e0 cmp rsi, 0x8 │ │ ╭──╴47c5e4 jne 0x47c601 │ │ │ │ │ │ 47c5e6 movabs rdx, 0x594b41454e534f53 │ │ │ 47c5f0 cmp qword ptr [rdi], rdx │ │ │ ╭╴47c5f3 jne 0x47c601 │ │ │ │ │ │ │ │ 47c5f5 mov eax, 0x1 │ │ │ │ 47c5fa add rsp, 0x38 │ │ │ │ 47c5fe pop rbp │ │ │ │ 47c5ff nop │ │ │ │ 47c600 ret │ │ │ │ │ │ ╰▸╰▸47c601 mov qword ptr [rsp+0x20], 0x0 │ │ 47c60a nop │ │ 47c60b test rbx, rbx │ │ ╭────╴47c60e jbe 0x47c674 │ │ │ │ │ │ 47c610 mov qword ptr [rsp+0x68], rsi │ │ │ 47c615 mov qword ptr [rsp+0x60], rdi │ │ │ 47c61a mov qword ptr [rsp+0x30], rax │ │ │ 47c61f mov rbx, rax │ │ │ 47c622 xor ecx, ecx │ │ │ 47c624 mov rdi, rcx │ │ │ 47c627 mov eax, 0x2 │ │ │ 47c62c call syscall.RawSyscall │ │ │ │ │ │ 47c631 nop │ │ │ 47c632 lea rcx, [rsp+0x20] │ │ │ 47c637 mov qword ptr [rsp+0x28], rcx │ │ │ 47c63c mov rbx, rax │ │ │ 47c63f mov edi, 0x8 │ │ │ 47c644 xor eax, eax │ │ │ 47c646 call syscall.RawSyscall │ │ │ │ │ │ 47c64b mov rdx, qword ptr [rsp+0x68] │ │ │ 47c650 cmp rdx, 0x8 │ │ │ ╭╴47c654 je 0x47c65a │ │ │ │ │ │ │ │ 47c656 xor eax, eax │ │ │ ╭╴│ 47c658 jmp 0x47c66e │ │ │ │ │ │ │ │ │ ╰▸47c65a mov rax, qword ptr [rsp+0x60] │ │ │ │ 47c65f lea rbx, [rsp+0x20] │ │ │ │ 47c664 mov ecx, 0x8 │ │ │ │ 47c669 call runtime.memequal │ │ │ │ │ │ │ ╰──▸47c66e add rsp, 0x38 │ │ │ 47c672 pop rbp │ │ │ 47c673 ret │ │ │ │ │ ╰────▸47c674 call runtime.panicBounds │ │ │ ╰──────▸47c67a mov qword ptr [rsp+0x8], rax │ 47c67f mov qword ptr [rsp+0x10], rbx │ 47c684 mov qword ptr [rsp+0x18], rcx │ 47c689 mov qword ptr [rsp+0x20], rdi │ 47c68e mov qword ptr [rsp+0x28], rsi │ 47c693 mov qword ptr [rsp+0x30], r8 │ 47c698 call runtime.morestack_noctxt.abi0 │ │ 47c69d mov rax, qword ptr [rsp+0x8] │ 47c6a2 mov rbx, qword ptr [rsp+0x10] │ 47c6a7 mov rcx, qword ptr [rsp+0x18] │ 47c6ac mov rdi, qword ptr [rsp+0x20] │ 47c6b1 mov rsi, qword ptr [rsp+0x28] │ 47c6b6 mov r8, qword ptr [rsp+0x30] │ 47c6bb nop dword ptr [rax+rax] ╰────────╴47c6c0 jmp main.authenticate
# Find the input that gets accepted
import angr
proj = angr.Project("fauxware")
main = proj.loader.find_symbol("main.main").rebased_addr
accepted = proj.loader.find_symbol("main.accepted").rebased_addr
morestack = proj.loader.find_symbol("runtime.morestack_noctxt.abi0").rebased_addr# skip the Go runtime's bootstrap: start right at main.main
state = proj.factory.blank_state(addr=main)
simgr = proj.factory.simgr(state)
simgr.explore(find=accepted, avoid=morestack)<SimulationManager with 1 active, 1 found, 2 avoid>
print(simgr.found[0].posix.dumps(0))b'\x00\x00\x00\x00\x00\x00\x00\x00\x00SOSNEAKY\x00'
# Decompile a Rust binary's main — back to Rust
import angr
proj = angr.Project("fauxware")
cfg = proj.analyses.CFGFast(normalize=True)proj.analyses.CompleteCallingConventions()
proj.analyses.RustSymbolRecovery()
proj.analyses.TypeDBLoader()
funcs = {f.demangled_name: f for f in cfg.functions.values()}dec = proj.analyses.Decompiler(funcs["fauxware::main"], flavor="rust")
print(dec.codegen.text)fn fauxware::main() -> u0 {
let v0: std::io::stdio::Stdin; // [bp-0x60]
let v1: u8; // [bp-0x51]
let v2: u8; // [bp-0x49]
let v3: u8; // [bp-0x41]
let v4: u64; // [bp-0x38]
let v5: u64; // [bp-0x28]
let v6: u64; // [bp-0x18]
let v7: u64; // [bp-0x8]
let v10: struct16; // rax:rdx
let v11: core::result::Result<usize, std::io::error::Error>; // rax:rdx
let v12: core::result::Result<usize, std::io::error::Error>; // rax:rdx
let v13: core::result::Result<usize, std::io::error::Error>; // rax:rdx
let v14: core::result::Result<usize, std::io::error::Error>; // rax:rdx
let v15: struct16; // rax:rdx
v0 = std::io::stdio::stdin();
memset(&v1, 0, 8);
memset(&v2, 0, 8);
v3 = 0;
v10 = <core::fmt::Arguments>::from_str("Username: \n");
std::io::stdio::_print(v10 as u64);
v13 = <std::io::stdio::Stdin as std::io::Read>::read(&v0, &v1, 8);
v4 = *((&v13 as &char + 8) as &i64);
core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>>(&v13 as i64);
v14 = <std::io::stdio::Stdin as std::io::Read>::read(&v0, &v3, 1);
v5 = *((&v14 as &char + 8) as &i64);
core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>>(&v14 as i64);
v15 = <core::fmt::Arguments>::from_str("Password: \n");
std::io::stdio::_print(v15 as u64);
v12 = <std::io::stdio::Stdin as std::io::Read>::read(&v0, &v2, 8);
v6 = *((&v12 as &char + 8) as &i64);
core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>>(&v12 as i64);
v11 = <std::io::stdio::Stdin as std::io::Read>::read(&v0, &v3, 1);
v7 = *((&v11 as &char + 8) as &i64);
core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>>(&v11 as i64);
if fauxware::authenticate(&v1, &v2) as char {
fauxware::accepted();
return;
}
fauxware::rejected(); /* do not return */
}# Disassemble a Rust function — angr demangles the symbols
import angr
proj = angr.Project("fauxware")
cfg = proj.analyses.CFGFast(normalize=True)
funcs = {f.demangled_name: f for f in cfg.functions.values()}
funcs["fauxware::authenticate"].pp()_RNvCsfJzwR3Dz023_8fauxware12authenticate: 40a840 sub rsp, 0x68 40a844 mov qword ptr [rsp], rdi 40a848 mov qword ptr [rsp+0x8], rsi 40a84d lea rdi, [rsp+0x8] 40a852 lea rsi, [0x4613b8] 40a859 call <&[u8; 8] as core::cmp::PartialEq>::eq 40a85e test al, 0x1 ╭────╴40a860 jne 0x40a8b9 │ │ 40a862 lea rdi, [rsp+0x18] │ 40a867 xor esi, esi │ 40a869 mov edx, 0x8 │ 40a86e call memset │ │ 40a873 mov rsi, qword ptr [rsp] │ 40a877 lea rdi, [rsp+0x20] │ 40a87c mov edx, 0x8 │ 40a881 call qword ptr [0x463ca0] │ │ 40a887 lea rdi, [rsp+0x20] │ 40a88c call <alloc::borrow::Cow<str> as core::ops::deref::Deref>::deref │ │ 40a891 mov rdi, rax │ 40a894 mov rsi, rdx │ 40a897 xor edx, edx │ 40a899 call <str>::trim_end_matches::<char> │ │ 40a89e mov rsi, rax │ 40a8a1 lea rdi, [rsp+0x38] │ 40a8a6 call <std::fs::File>::open::<&str> │ │ 40a8ab mov eax, dword ptr [rsp+0x38] │ 40a8af test rax, 0x1 │ ╭╴40a8b5 jne 0x40a8c0 │ │ │ ╭╴│ 40a8b7 jmp 0x40a8ce │ │ │ ╰▸│ │ 40a8b9 mov byte ptr [rsp+0x17], 0x1 ╭──────╴│ │ 40a8be jmp 0x40a93e │ │ │ │ ╭──▸│ ╰▸40a8c0 mov eax, dword ptr [rsp+0x38] │ │ │ 40a8c4 test rax, 0x1 │ │ ╭╴│ 40a8ca jne 0x40a90b │ │ │ │ │ ╭╴│ │ │ 40a8cc jmp 0x40a915 │ │ │ │ │ │ │ │ │ ╰──▸40a8ce mov eax, dword ptr [rsp+0x3c] │ │ │ │ 40a8d2 mov dword ptr [rsp+0x4c], eax │ │ │ │ 40a8d6 lea rdi, [rsp+0x4c] │ │ │ │ 40a8db lea rsi, [rsp+0x18] │ │ │ │ 40a8e0 mov edx, 0x8 │ │ │ │ 40a8e5 call qword ptr [0x463980] │ │ │ │ │ │ │ │ 40a8eb mov qword ptr [rsp+0x50], rax │ │ │ │ 40a8f0 mov qword ptr [rsp+0x58], rdx │ │ │ │ 40a8f5 lea rdi, [rsp+0x50] │ │ │ │ 40a8fa call core::ptr::drop_glue::<core::result::Result<usize, core::io::error::Error>> │ │ │ │ │ │ │ │ 40a8ff lea rdi, [rsp+0x4c] │ │ │ │ 40a904 call core::ptr::drop_glue::<std::fs::File> │ │ │ │ │ │ ╰╴│ 40a909 jmp 0x40a8c0 │ │ │ │ │ ╰────▸40a90b lea rdi, [rsp+0x38] │ │ 40a910 call core::ptr::drop_glue::<core::result::Result<std::fs::File, core::io::error::Error>> │ │ │ ╰────────▸40a915 lea rax, [rsp+0x18] │ 40a91a mov qword ptr [rsp+0x60], rax │ 40a91f lea rdi, [rsp+0x8] │ 40a924 lea rsi, [rsp+0x60] │ 40a929 call <&[u8; 8] as core::cmp::PartialEq>::eq │ │ 40a92e and al, 0x1 │ 40a930 mov byte ptr [rsp+0x17], al │ 40a934 lea rdi, [rsp+0x20] │ 40a939 call core::ptr::drop_glue::<alloc::borrow::Cow<str>> │ ╰──────────▸40a93e mov al, byte ptr [rsp+0x17] 40a942 and al, 0x1 40a944 add rsp, 0x68 40a948 ret
# Find the input that gets accepted
import angr
proj = angr.Project("fauxware")
cfg = proj.analyses.CFGFast(normalize=True)
funcs = {f.demangled_name: f for f in cfg.functions.values()}# skip the Rust runtime's startup: start right at fauxware::main
state = proj.factory.blank_state(addr=funcs["fauxware::main"].addr)
simgr = proj.factory.simgr(state)
simgr.explore(find=funcs["fauxware::accepted"].addr)<SimulationManager with 1 active, 1 found>
print(simgr.found[0].posix.dumps(0).rstrip(b"\x00"))b'\x00\x00\x00\x00\x00\x00\x00\x00\x00SOSNEAKY'


















angr decompile fauxware --functions main authenticate rejected accepted// the toolkit
Your new swiss army knife
angr provides static and dynamic techniques in a single library. Mix and match to solve your problems.
Symbolic Execution
A powerful concolic engine: explore every path at once, solve constraints, and reason about inputs that reach any state.
Decompilation
Lift machine code to angr's AIL and recover readable pseudocode as C or Rust.
CFG Recovery
Reconstruct control-flow graphs and call graphs with advanced static analyses, even on stripped and obfuscated targets.
Disassembly & Lifting
Disassemble and lift to AIL, the angr intermediate language, giving every architecture one uniform analysis surface.
Multi-Architecture
x86 / x86-64, ARM & AArch64, MIPS, PowerPC, and more — any host can analyze any guest.
Extensible by Design
Hook anything, register custom analyses, SimProcedures, and exploration techniques. If you can script it in Python, angr can run it.
Pythonic API
A clean, scriptable Python interface. Drop into a REPL, wire angr into your tooling, or build something entirely new on top.
Free & Open Source
Released under the permissive BSD license and developed in the open. Battle-tested in research, CTFs, and the DARPA CGC.
// get started
Up and running in seconds
angr is a Python 3.12+ package. Install it into a virtual environment and you're ready to analyze. Works on Linux, macOS, and Windows.
$ pip install angr# then import angr and go
// angr-management
A full GUI, powered by angr
Prefer to point and click? angr-management is the official graphical interface. Control the whole platform, made visual and interactive. Disassemble, decompile to C or Rust, patch, and explore, all without leaving the window. It runs natively on Linux, macOS, and Windows.
- Customizable decompilation to C or Rust
- Linear and graph-based disassembly
- Hex editor and interactive binary patching
- Plugins, scripting, and more...
// model context protocol
angr for your AI assistant
angr ships an MCP server, so assistants like Claude can drive it directly — loading binaries, recovering control-flow graphs, decompiling functions, and chasing xrefs. It's not just a natural language control interface, it's a meaningful expansion to your toolkit. And that's special.
# expose angr over MCP (stdio — for Claude Desktop, etc.)
$ python -m angr.mcp
# ...or over HTTP / SSE for remote clients
$ python -m angr.mcp --transport httpTools it exposes
- Decompilation
- Control-flow graphs
- Disassembly
- Cross-references
- Strings
- Imports & exports
- Call graphs
- Function search
Works with any MCP client. Point yours at the server and ask it to reverse a binary.
// modular design
The Power of Composition
angr is built from focused subprojects, each one usable on its own. Take the whole stack, or just the piece you need.
- angr
The binary analysis platform itself.
- angr-management
The graphical interface for angr.
- srcdump
Like objdump, but dumps decompiled source code.
- CLE
Loads binaries and their libraries into memory.
- PyVEX
Python bindings to the VEX intermediate language.
- pypcode
Python bindings to Ghidra's P-code lifter.
- archinfo
A library of CPU architecture descriptions.
- angrop
Automatic ROP chain generation.
// join in
With and For Our Community
angr is developed by researchers and hackers around the world. Ask questions, share what you've built, or send your first pull request. Find community and make a difference!
// professional support
angr, backed by its core team
Emotion Labs is the company behind angr. We, the same maintainers who build it, offer support, development, and training to put binary analysis to work for your team.
Visit Emotion LabsSupport
Expert help and maintenance from the humans behind angr.
Development
Custom analyses, features, and integrations built on top of angr.
Training
Hands-on courses in binary analysis and reverse engineering.

