Jump to content
Tuts 4 You

2 quick questions about C


amateur

Recommended Posts

Posted

Hi.

I was solving a keyfile me today, and most of the keymaker i made was with inline assembly, because straight in C i was getting wrong values. For now i have 2 questions.

I'm not on my laptop right now so i'll try to remember as much close as possible the values  :)

 

1) Is possible to achieve that with the (right) way, like i have it below? :

DWORD eax;

	eax = 0xF96A872D;

	/* I want the result: eax = 0xF96A78D2. Even if i "fixed" little the data types/macros i will get either eax: 0xFFFF78D2 
           or eax: 0x000078D2  */
	LOWORD(eax) = ~(WORD)eax;

 

2) As my comment says i'm getting ebx = 0x18de781b and not ebx = 0xf8de781b. How can i fix this?

DWORD ebx;

        ebx = 0xC6F3C0DE;
	ebx >>= 0x3;

/* After shifting  i get ebx = 0x18DE781B instead ebx = 0xF8DE781B, so i'm forced to use inline assembly to solve it */

-Thanks all!

Posted

For question 1, here's two ways to do it:

    // Using pointer casting..
    DWORD eax = 0xF96A872D;
    *(WORD*)&eax = ~(WORD)eax;

    // Using bitwise operations..
    DWORD eax = 0xF96A872D;
    eax = (eax & 0xFFFF0000) | (WORD)~(WORD)eax;

For question 2, you are seeing the wrong result because of using an unsigned type. The math being performed is expecting the value to be a signed type instead. Instead of using 'DWORD' use a signed type instead. (ie. 'long', 'int32_t', etc.)

  • Thanks 1
Posted (edited)

Thank you @atom0s, one more help :)!

int32_t eax = 0;
int32_t ebx = 0x288d6c47;

//_rotr(ebx ^ 0x9714, 0x2) = 0xca237ed4
	
eax = _rotr(ebx ^ 0x9714, 0x2) >> 0x3;

Output:   eax  =  0x19446fda

 

Here i'm declaring and i'm assigning the value from the start

int32_t eax = 0;
int32_t ebx = 0x288d6c47;
int32_t ecx = 0xca237ed4;
	
eax = ecx >> 0x3;

Output:   eax = 0xf9446fda

 

I want with the first approach to have the result of the second. Why is happening? Where is the mistake? Tried with other signed data types, but with no luck. Thank you!

Edited by amateur
Fixed because auto-merged
Posted

Be mindful of what types functions return. The intrinsic function '_rotr' returns an unsigned value, which goes against the signed types you are trying to use. Because of that, you need to cast its return back to a signed type or store it in a signed variable first.

    int32_t eax = 0;
    int32_t ebx = 0x288d6c47;
    //_rotr(ebx ^ 0x9714, 0x2) = 0xca237ed4
    eax = (int32_t)_rotr(ebx ^ 0x9714, 0x2) >> 0x3;

Should get what you want.

  • Like 1
  • Thanks 1
Posted (edited)

Thank you @atom0s! Everything working fine now. I will finish the keymaker with a proper way :)

I didn't know that '_rotr' return unsigned value. I found in last 2 days the "intrin.h" header, which has some assembly operations like those, and seems to me more convenient for rotate operations,  instead of doing it through bitwise or through inline asm.

Edited by amateur
Posted (edited)

Unsigned types are zero extended and signed types are sign extended with shift instructions.  C does not have efficient implementations of some hardware details.

For example, shifting left or right by 1 gives the removed bit in the carry flag CF.  Or addition/subtraction.  But in C you must do some bit twiddling expressions to turn a native efficient operation into something taking a few instructions.  I doubt the compiler actually optimizes it.

So if you want to shift a big integer stored in an integer array, it will be an annoyance especially since rotate with carry or double precision shifts are strictly necessary.  No idea if SIMD instructions can speed this up given it's a sequential memory op

Edited by Progman
  • Like 1
Posted

That's true C isn't so "flexible" in some cases. When i started learning C- i still do i'm not an expert -  i was searching if there is an "auto" way to reverse a string instead doing loops to reverse it. Then i found "strrev". It works great when you obtain the string with "gets_s", but not, when you use "fgets" because when it reverse the string it will add the '\0'. I mean C has some "weird" features :)

Same for the bit operations. I was trying to find an "auto" way to do rotation -left and right- at least for the ROL/ROR, not RCL, RCR, instead writing inline assembly or writing expressions like:  x = ((x & 0x80) ? 0x01 : 0x00) | (x << 1). Luckily i found the "intrin.h" header which has quite a few assembly functions.

Speaking of "not-flexible" C another question appeared, which i had forgotten (until now)! A lot of times coding keygens i have seen mismatches of the FPU values (in assembly) and the floating/double values i used (in C). What is going on with this case? Any ideas? - Again inline assembly helps on that :)

  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...