Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bin2llvmir: Wrong translation for the sbb x86 instruction #401

Closed
palant opened this issue Sep 17, 2018 · 3 comments
Closed

bin2llvmir: Wrong translation for the sbb x86 instruction #401

palant opened this issue Sep 17, 2018 · 3 comments

Comments

@palant
Copy link
Contributor

palant commented Sep 17, 2018

Here is a minimized NASM application showing this issue:

  SECTION .text
  global main

main:
  call dummy
  neg eax
  sbb eax, eax
  add eax, 7
  ret

dummy:
  mov eax, edi
  ret

When compiled with nasm -f elf and decompiled with RetDec I get the following code:

    return dummy() != 0 ? 8 : 7;

According to https://reverseengineering.stackexchange.com/questions/14128/x86-sbb-with-same-register-as-first-and-second-operand this should have been:

    return dummy() != 0 ? 6 : 7;

Running bin2llvmir without any optimizations I see the following logic in the .ll file for the sbb instruction:

  %13 = load i32, i32* @eax
  %14 = load i32, i32* @eax
  %15 = load i1, i1* @cf
  %16 = zext i1 %15 to i32
  %17 = sub i32 %13, %14
  %18 = add i32 %17, %16

That's not what it should be: with the sbb instruction, CF is added to the source, not the result. So either:

  %17 = add i32 %14, %16
  %18 = sub i32 %13, %17

Or:

  %17 = sub i32 %13, %14
  %18 = sub i32 %17, %16
@palant
Copy link
Contributor Author

palant commented Sep 17, 2018

The issue is here:

https://github.com/avast-tl/retdec/blob/ec9ce19b754a31a003cf79751cc341dccbd1bf1f/src/capstone2llvmir/x86/x86.cpp#L2889

And I have to contradict the comment here: it's not an add.

@s3rvac
Copy link
Member

s3rvac commented Feb 5, 2019

@PeterMatula Can you please verify?

@PeterMatula
Copy link
Collaborator

Righ you are. Fixed to op0 = op0 - (op1 + CF) pattern.

The current result is:

return (int32_t)(dummy() != 0) ^ 7;

which I think is equivalent to:

return dummy() != 0 ? 6 : 7;

Because:

  • if dummy() != 0 is true (1) then 0b1 ^ 0b111 = 0b110 = 6
  • if dummy() != 0 is false (0) then 0b0 ^ 0b111 = 0b111 = 7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants