Ed's Blog

A PhD Student's Musings

Wiley Q

Q is the automated return oriented programming system (ROP) that I developed with my colleague, Thanassis Avgerinos. The basic idea behind ROP is to find small code fragments that do something useful in a binary that you are attacking. These code fragments are called gadgets. (Do you get the reference to Q now?) Later, the gadgets are strung together to accomplish something even more useful. (Hint: It can be Turing-complete.) ROP can be used to bypass program defenses such as Data Execution Prevention.

I’m not doing much personal work with Q these days, but it has become fairly popular as a tool for evaluating proposed ROP defenses. I just added a new option for such an evaluation. The new option forces Q to only consider gadgets at specified addresses. Naturally, to make sure it works, I specified a random gadget address, 0x80492d9, and checked the output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Printing Noop gadgets: 0
Printing Jumps gadgets: 0
Printing JumpConsts gadgets: 1
SET: JumpConst {}  Other +0  @0  (Addrset: @0 ) [This gadget is fake.]
Printing Move gadgets: 1
SET: MoveReg R_EBX_6:u32 -> R_EAX_5:u32 { R_EAX_5:u32 R_EBX_6:u32 R_EDI_3:u32 R_ESP_1:u32}  Ret +c  @80492d9  (Addrset: @80492d9 @80492da @80492db @80492dc @80492dd ) [; mov    %ebx,%eax; pop    %ebx; pop    %edi; ret    ]
Printing LoadConst gadgets: 3
SET: LoadConst const(+0) -> R_EAX_5:u32 { R_EAX_5:u32 R_EBX_6:u32 R_EDI_3:u32 R_ESP_1:u32}  Ret Ret +c +c  @80492d9 @80492d9  (Addrset: @80492d9 @80492da @80492db @80492dc @80492dd ) [; mov    %ebx,%eax; pop    %ebx; pop    %edi; ret    COMBINED; mov    %ebx,%eax; pop    %ebx; pop    %edi; ret    ]
SET: LoadConst const(+0) -> R_EBX_6:u32 { R_EAX_5:u32 R_EBX_6:u32 R_EDI_3:u32 R_ESP_1:u32}  Ret +c  @80492d9  (Addrset: @80492d9 @80492da @80492db @80492dc @80492dd ) [; mov    %ebx,%eax; pop    %ebx; pop    %edi; ret    ]
SET: LoadConst const(+4) -> R_EDI_3:u32 { R_EAX_5:u32 R_EBX_6:u32 R_EDI_3:u32 R_ESP_1:u32}  Ret +c  @80492d9  (Addrset: @80492d9 @80492da @80492db @80492dc @80492dd ) [; mov    %ebx,%eax; pop    %ebx; pop    %edi; ret    ]
Printing Arithmetic gadgets: 0
Printing ArithmeticConst gadgets: 0
Printing Loadmem gadgets: 0
Printing Storemem gadgets: 0
Printing ArithmeticLoad gadgets: 0
Printing ArithmeticStore gadgets: 0
Printing SwitchStack gadgets: 1
SET: SwitchStack(R_ESP_1:u32 + 8) { R_EAX_5:u32 R_EBX_6:u32 R_EDI_3:u32 R_ESP_1:u32}  Ret +c  @80492d9  (Addrset: @80492d9 @80492da @80492db @80492dc @80492dd ) [; mov    %ebx,%eax; pop    %ebx; pop    %edi; ret    ]
Printing MemPivot gadgets: 0
Printing Syscall gadgets: 0
Printing Super gadgets: 0

The code at this address is mov %ebx,%eax; pop %ebx; pop %edi; ret. Interestingly, Q figured out that it could load into %eax by simply executing the gadget twice. This allows you to put a value into %ebx during the first execution, and then move that value to %eax during the second execution. This is fairly cute, and I don’t know if I would have thought of the same trick myself.

Maybe it’s just me, but I am always surprised when automated systems out-smart us. With respect to security, this means that we really need provable and measurable defensive capabilities. The “I don’t see any attacks” defense strategy is simply not good enough against a sophisticated attacker. Just because we (as limited humans) cannot see an attack against our system does not mean that an attacker, who can create a sophisticated program to search for attacks, will not.

Comments