-5

I'm trying to convert an integer value of 10 digits for byte, but the function only returns me 4 values, I need 6 points, how to solve?

function I'm using to convert integer in bytes

var
  i, j: integer;
  bbI : array[1.. sizeof(integer)] of byte;
begin
  i := 2337669003;
  Move(i, bbI[1], SizeOf(Integer));
  for j := Low(bbI) to High(bbI) do
  Memo1.Lines.Append(IntToHex(bbI[j],2))
end;

the function returns me

8B FF 55 8B

values that are returned enter image description here but i need more 2 values

EC 51

the function should return me

8B FF 55 8B EC 51

correct value according to cheat engine

enter image description here

LU RD
  • 34,438
  • 5
  • 88
  • 296
0x4
  • 21
  • 1
  • 6
  • 2
    Ints are 4-bytes long, [your conversion is fine](https://www.google.com/search?q=2337669003+to+hex), adjusted for the endianness of your computer. – Sergey Kalinichenko May 25 '16 at 11:22
  • 1
    where you get EC 51? 2337669003 (dec) is exactly 8B FF 55 8B (hex) – Zam May 25 '16 at 12:24
  • 1
    The problem is the value 2.337.669.003 is bigger than MaxInt (2.147.483.647), you have to use Int64. – mezen May 25 '16 at 13:25
  • 2
    @mezen 1) 2 337 669 003 fits within unsigned 32-bit integer. 2) Int64 is not 6 bytes, so there's still something missing in OP's question. – Disillusioned May 25 '16 at 14:25

3 Answers3

4

I'm trying to convert an integer value of 10 digits for byte, but the function only returns me 4 values, I need 6 points, how to solve?

You can't. An Integer is only 4 bytes in size. The Integer value 2337669003 is the byte sequence 8B FF 55 8B. There is no way you can get the extra EC 51 bytes from that.

An Int64 is 8 bytes in size. The byte sequence 8B FF 55 8B EC 51 would be an Int64 value of 5903246413051658240 with its high 2 bytes (00 00) truncated off.

From the screenshot, we can clearly see that the byte sequence 8B FF 55 8B EC 51 actually corresponds to the first 4 x86 assembly instructions of the Win32 BitBlt() function. Why are you using integer values to represent assembly instructions? That is not a good way to approach this. Do you understand how the x86 instruction set actually works? Do you understand how Integers work?

In this situation, I would suggest using an actual byte array instead of an integer array:

var
  Instructions: array[0..5] of byte;
  i: Integer;
begin
  // mov edi,edi
  Instructions[0] := $8B;
  Instructions[1] := $FF;

  // push ebp
  Instructions[2] := $55;

  // mov ebp,esp
  Instructions[3] := $8B;
  Instructions[4] := $EC;

  // push ecx
  Instructions[5] := $51;

  for i := Low(Instructions) to High(Instructions) do
    Memo1.Lines.Append(IntToHex(Instructions[i], 2));
end;

Or even use a record instead:

type
  BitBltInstructions = packed record
    MovEdiEdi: array[0..1] of byte; // $8B $FF
    PushEbp: byte; // $55
    MovEbpEsp: array[0..1] of byte; // $8B $EC
    PushEcx: byte; // $51
  end;

var
  Instructions: BitBltInstructions;
  bytes: array[0..Sizeof(BitBltInstructions)-1] of byte absolute Instructions;
  i: Integer;
begin
  Instructions.MovEdiEdi[0] := $8B;
  Instructions.MovEdiEdi[1] := $FF;
  Instructions.PushEbp      := $55;
  Instructions.MovEbpEsp[0] := $8B;
  Instructions.MovEbpEsp[1] := $EC;
  Instructions.PushEcx      := $51;

  for i := Low(bytes) to High(bytes) do
    Memo1.Lines.Append(IntToHex(bytes[i], 2));
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks for the explanation I think this time I got it at first I thought I would have to write the 6 bytes, but I was wrong, I need to write only 4, tell me one thing, all the x86 instruction have fixed bytes regardless of Windows version, right? – 0x4 May 25 '16 at 19:48
  • In this case, it doesn't make sense to write only 4 bytes, as then you would be writing only half of the `mov ebp,esp` instruction. What are you *really* trying to accomplish? As for the x86 instruction set, yes it uses fixed bytes for many of its instructions (and some instructions have variable bytes). x86 has nothing to with Windows at all. You do know what x86 even is, don't you? It is the instructions that run directly on the CPU itself, and that has nothing to do with the OS. – Remy Lebeau May 25 '16 at 19:56
  • A software makes a WINAPI Hook in my function (in this case BitBlt), I capture the original value in FormCreate (the other program takes a few seconds to hook) and then write the correct value at the address of my function. – 0x4 May 25 '16 at 20:05
  • If your goal is to prevent the hook from being installed, then why are you bothering with the approach you asked about? You already have the original bytes, just save them to a variable and then write them back to the function address when needed. Or, even better, use [`VirtualProtect()`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366898.aspx) to prevent the hook from being installed in the first place. – Remy Lebeau May 25 '16 at 20:22
  • I'm using an alternative function to write bytes, I'm not using WPM, you have some stuff that I can study to use VirtualProtect() to not allow the hook to be done? – 0x4 May 25 '16 at 20:26
  • You don't need to use WPM when writing to memory that belongs to your own process. As for VP, read the documentation. You know the address of the function, and the number of bytes you want to protect. Mark those bytes as `PAGE_EXECUTE` or `PAGE_EXECUTE_READ` so they cannot be overwritten. – Remy Lebeau May 25 '16 at 20:46
  • Thanks again for the explanation, you are very good! allahu akbar – 0x4 May 25 '16 at 20:48
1

You could use the directive absolute:

procedure Main;
var
  i: Integer;
  x: array[0..3] of Byte absolute i;
begin
  i := 123456;
  Writeln(x[0]);
  Writeln(x[1]);
  Writeln(x[2]);
  Writeln(x[3]);
end;
mezen
  • 198
  • 4
-1

You use variant record for that. In this case both fields of the record share the same memory:

program Test;
uses
  System.SysUtils;

type
  TInteger = record
    case Byte of
      0: (AsValue: Integer);
      1: (AsArray: array [0..3] of Byte);
  end;

var
  X: TInteger;
begin
  X.AsValue := 123456;
  Writeln(X.AsArray[0]);
  Writeln(X.AsArray[1]);
  Writeln(X.AsArray[2]);
  Writeln(X.AsArray[3]);
end.
Z.B.
  • 1,185
  • 9
  • 18
  • 1
    Don't re-declare this type. It's already declared in `SysUtils` as `LongRec`. It is also somewhat odd that you provide an answer that behaves identically to the code in the question. – David Heffernan May 25 '16 at 11:55
  • You cannot assign LongRec variable an integer value! I do not redeclare that type. LongRec = packed record case Integer of 0: (Lo, Hi: Word); 1: (Words: array [0..1] of Word); 2: (Bytes: array [0..3] of Byte); end; – Z.B. May 25 '16 at 11:58
  • 1
    And mainly I just showed him the possible approach which can be used for any fixed binary structure. – Z.B. May 25 '16 at 11:59
  • @ZesNAN You are quite wrong. You can perfectly well cast an `Integer` variable to `LongRec`, on both lhs and rhs. Otherwise why on earth does it exist? In your case the code looks like this: `var X: Integer; X := 123456; Writeln(LongRec(X).Bytes[0])l`. And again, why won't you address the fact that the code in your answer behaves identically to that in the question? – David Heffernan May 25 '16 at 12:08
  • @DavidHeffernan: Agreed. You are right. Haven't used LongRec like that because I never needed to do a task like the author of the question (I mean working with an integer). I just showed one of the simple ways to achieve that. Thanks for the comment. – Z.B. May 26 '16 at 07:31