Note how the value immediately following the syscall is still p64(0x0).
It looks like the next_pc is not populated until concretized and until another gadget is appended to the end of the chain.
It was our understanding that chains should always end in a state where the next value on the stack should be PC. This was throwing off some of our calculations, so we made this branch.
Since you already wrote some impressive logic to overwrite a next_pc value when chains are added together, we thought we would take advantage of this. We decided to add a simple rop.shift(arch.bytes) chain (which should be as simple as a single ret gadget) to the chain currently trying to be concretized, and then concretize the conglomerate chain instead.
This is chain1 after our modifications:
chain = b""
chain += p64(0x401137) # pop rax; pop rdi; ret
chain += p64(0x3)
chain += p64(0x0)
chain += p64(0x40113a) # syscall
chain += p64(0x401076) # nop word ptr cs:[rax + rax]; endbr64 ; ret
chain += p64(0x0)
chain += p64(0x0)
Bug: chains including x86_64
retn 0x10
instructions not terminated in a recoverable position.We used this python script against the
angrop_retn_test
binary:This is the resulting chain1:
Note how the value immediately following the syscall is still
p64(0x0)
.It looks like the
next_pc
is not populated until concretized and until another gadget is appended to the end of the chain.It was our understanding that chains should always end in a state where the next value on the stack should be PC. This was throwing off some of our calculations, so we made this branch.
Since you already wrote some impressive logic to overwrite a
next_pc
value when chains are added together, we thought we would take advantage of this. We decided to add a simple rop.shift(arch.bytes) chain (which should be as simple as a singleret
gadget) to the chain currently trying to be concretized, and then concretize the conglomerate chain instead.This is chain1 after our modifications: