Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Byte To code procedure

byte code procedure codecave

Best Answer Luthfi, 26 January 2013 - 10:20 AM

Unfortunately I don't have ready-to-use codes at hand. But like I have said, it's not difficult. Why don't you start coding and I will help you should you feel stuck.

Basically you would do these (this is just one approach, not the only one):

  • Load the bytes into a TStream instance (I recommend TMemoryStream, with the help of TFileStream if the bytes stored in a file).
  • Read a byte from the TStream instance.
  • By using the translation table, decode the byte into correct TMnemonic class and instantiate the class.
  • Feed the stream to the just created TMnemonic instance so it be able to decode the parameters.
  • Go to step #2, repeat until all the bytes processed.

EDIT:
I found some free time and wrote sample implementation using OOP approach I've suggested. Check out the attached source code. Note that I only implemented "PUSH" class. And also I changed the Label property of TMnemonic class into Code because previously I forgot that Label was reserved word.

Enjoy! Go to the full post


This topic has been archived. This means that you cannot reply to this topic.
14 replies to this topic

#1 leecan

leecan

    CC Newcomer

  • Member
  • PipPip
  • 16 posts

Posted 21 January 2013 - 01:28 PM

Hi,

How can i convert byte to codes in delphi language.
For example:
From

6A 70 68 98 18 00 01 E8 BF 01 00 00 33 DB 53

To:
PUSH 70
PUSH app.01001898
CALL app.01007568
XOR EBX,EBX
PUSH EBX


The reason of such procedure is to know which bytes need to move to codecave.

I can do that in Ollydbg, but i need to make it in delphi.

Any advise?

Best Regards

Edited by Roger, 21 February 2013 - 08:06 AM.


#2 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts

Posted 22 January 2013 - 11:54 PM

Actually that's not difficult. You just need a translation table that translates a byte value into corresponding mnemonic. And each mnemonic must know how it should read its "parameters" from subsequent bytes.

If you interested in implement the codes with OOP, I suggest to use these basic classes.

type
  TMnemonic=class
  public
    procedure StreamToParams(AStream: TStream); virtual; abstract;

    class function Label : string; virtual; abstract;

    property Params: string;
  end;

  // this class is to hold collection of TMnenomic instances
  TMnemonics=class
  private
    FItems: TList;
  public
    function Add(AMnemonic: TMnemonic): Integer;

    property Count: Integer read GetCount;
    property Items[Index: Integer]: TMnemonic read GetItem; default;
  end;

  // this class is to read a stream of bytes and translate them into proper mnemonics
  TMnemonicFactory=class
  public
    procedure StreamToMnemonics(AStream: TStream; AMnemonics: TMnemonics);
  end;

AStream used in TMnemonic and TMnemonicFactory contains the bytes you want to translate.


Edited by LuthfiHakim, 10 February 2013 - 12:13 PM.


#3 leecan

leecan

    CC Newcomer

  • Member
  • PipPip
  • 16 posts

Posted 24 January 2013 - 12:27 PM

Luthfi,
You are very kind, thank you very much cause you are always offering me the help.

in according to the above, is there any source code in your hand? cause honestly i didnt understand much :)

Thank you man,

Regards

#4 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts

Posted 26 January 2013 - 10:20 AM   Best Answer

Unfortunately I don't have ready-to-use codes at hand. But like I have said, it's not difficult. Why don't you start coding and I will help you should you feel stuck.

Basically you would do these (this is just one approach, not the only one):
  • Load the bytes into a TStream instance (I recommend TMemoryStream, with the help of TFileStream if the bytes stored in a file).
  • Read a byte from the TStream instance.
  • By using the translation table, decode the byte into correct TMnemonic class and instantiate the class.
  • Feed the stream to the just created TMnemonic instance so it be able to decode the parameters.
  • Go to step #2, repeat until all the bytes processed.

EDIT:
I found some free time and wrote sample implementation using OOP approach I've suggested. Check out the attached source code. Note that I only implemented "PUSH" class. And also I changed the Label property of TMnemonic class into Code because previously I forgot that Label was reserved word.

Enjoy!

Attached Files


Edited by LuthfiHakim, 27 January 2013 - 01:25 AM.


#5 leecan

leecan

    CC Newcomer

  • Member
  • PipPip
  • 16 posts

Posted 27 January 2013 - 01:19 AM

Thank you very much Luthfi :)
It is very good starting point for me.

i will post the results soon,

Best regards

#6 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts

Posted 30 January 2013 - 08:20 AM

Okay. Great if I could be of any help. Don't hesitate to report your progress.

#7 leecan

leecan

    CC Newcomer

  • Member
  • PipPip
  • 16 posts

Posted 17 February 2013 - 05:36 AM

Hi Lutfi,

 

I dont think i can proceed without your advise and help as usual.

Regarding Push class, I have to take in consideration the following opcode:

50                         PUSH EAX
66:50                   PUSH AX
51                         PUSH ECX
66:51                   PUSH CX
52                         PUSH EDX
66:52                   PUSH DX
53                         PUSH EBX
66:53                   PUSH BX
54                         PUSH ESP
55                         PUSH EBP
56                         PUSH ESI
57                         PUSH EDI
6A 70                   PUSH 70
68 80 00 00 00  PUSH 80

 

Shall i add the following code for each of the above?

class function TPushEAX.Code: string;
begin
  Result := 'PUSH EAX';
end;

procedure TPushEAX.StreamToParams(AStream: TStream);
var
  B: Byte;
  T: string;
begin
  if AStream.Read(B, 1)=1 then
  begin
    SetLength(T, 0);
    BinToHex(@B, PChar(T), 1);
    SetParams(T);
  end;
end;

procedure TMnemonicFactory.StreamToMnemonics(AStream: TStream;
  AMnemonics: TMnemonics);
var
  vCode: Byte;
  vMnemonic: TMnemonic;
begin
  repeat
    if AStream.Read(vCode, 1) < 1 then Break;
    case vCode of
      $6A: vMnemonic := TPush.Create;
      $50: vMnemonic := TPushEAX.Create;

If so, i have to add just for Push class the above 14 times.

 

Thanks and Regards


Edited by leecan, 17 February 2013 - 05:45 AM.


#8 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts

Posted 17 February 2013 - 06:31 AM

Basically you need a class for each opcode. Since "PUSH EAX", "PUSH ECX", and "PUSH EDX" have different opcodes (50, 51, 52 respectively), you have to implement them in different classes. So your approach with TPushEAX class is correct. Use the same approach for "PUSH ECX", "PUSH EDX", and others similar with them. But since in this case the opcode already defines the data/parameter, your implementation of StreamToParams method was wrong. This time you don't read anything from the stream. Empty method is enough.

It is a different story with "PUSH AX", "PUSH CX", and "PUSH BX". I see that they are using the same opcode (66) and to decide whether the data/parameter was AX or BX or CX you need to analyze the next byte. If the next byte was 50 then "AX" was the parameter, if it was 51 then the parameter was "CX", and so on. In this case you need only one class with Code of "PUSH" and in its StreamToParams you need to read the next byte from the supplied stream, and from the value you decide what the actual parameter is.


Edited by LuthfiHakim, 17 February 2013 - 06:33 AM.


#9 leecan

leecan

    CC Newcomer

  • Member
  • PipPip
  • 16 posts

Posted 18 February 2013 - 02:28 AM

Thanks for your help as usual,

I think so far, everything will be okay, but still i have one small problem.

class function TPushOther.Code: string;
begin
  Result := 'PUSH';
end;

procedure TPushOther.StreamToParams(AStream: TStream);
var
  B: Byte;
  T: string;
begin
  if AStream.Read(B, 1)=1 then
  begin
    SetLength(T, 8);
    BinToHex(@B, PChar(T), 1);
    SetParams(T);
  end;
end;

If i need to push the value 80 to the stack, i will have the following opcode 68 8F 00 00 00.

By the above code, it will read 8 bytes after 68?

it didnt work properly.

Only if you have time, any advise how can i read the followin 8 bytes in reverse order?

 

I am sorry for all these questions, as you are doing everything instead of me.

 

Thanks and regards
 



#10 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts

Posted 18 February 2013 - 08:33 AM

Thanks for your help as usual,

I think so far, everything will be okay, but still i have one small problem.

class function TPushOther.Code: string;
begin
  Result := 'PUSH';
end;

procedure TPushOther.StreamToParams(AStream: TStream);
var
  B: Byte;
  T: string;
begin
  if AStream.Read(B, 1)=1 then
  begin
    SetLength(T, 8);
    BinToHex(@B, PChar(T), 1);
    SetParams(T);
  end;
end;

If i need to push the value 80 to the stack, i will have the following opcode 68 8F 00 00 00.

By the above code, it will read 8 bytes after 68?

it didnt work properly.

 

No. For this I really suggest to look Delphi help for TStream.Read, so you would understand what the following line means:

if AStream.Read(B, 1)=1

 

Also look for HexToBin to see the reason for the following line:

SetLength(T, 8);

 

They will be a good exercise for you. :)


Edited by LuthfiHakim, 18 February 2013 - 08:34 AM.


#11 leecan

leecan

    CC Newcomer

  • Member
  • PipPip
  • 16 posts

Posted 20 February 2013 - 11:09 AM

What you have mentioned above is very important, but little diffcult.

So, as I dont have enough expereince, i tried the traditional method and i think it will work.

 
type
  TDisas = class
  private
    { Private declarations }
  public
    { Public declarations }
      Procedure PUSH_AX(B1:Byte; B2:Byte; MemoDisas:TMemo; VA:String);

  end;

Every thing work fine till Push AX (opcode 66:50)

 

      case B[II] of
        $50 : Disass.PUSHEAX(B[II], MemoDisas, IntToHex(Loc,8));
        $66 :
              case B[II + 1] of
                 $50 :
                    begin
                      Disass.PUSH_AX(B[II], B[II + 1], MemoDisas, IntToHex(Loc,8));
                      II := II + 1;
                    end;
              else

When i run the above code, and when it reach II := II + 1, it gave me the following error:

[DCC Error] Unit9.pas(275): E2081 Assignment to FOR-Loop variable 'II'

 

Any idea how can i increase the value of II by one inside the case of?

 

Thanks and Regards



#12 leecan

leecan

    CC Newcomer

  • Member
  • PipPip
  • 16 posts

Posted 21 February 2013 - 03:49 AM


[DCC Error] Unit9.pas(275): E2081 Assignment to FOR-Loop variable 'II'

 

This issue is already solved, instead of using FOR, i use while and everything work fine so far,

 

thanks anyway,






Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download