Thread: Jmp to procedur

    #1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2012
    Posts
    5
    Rep Power
    0

    Jmp to procedur


    Hi im trying to change a jump so it would point to my asm code but i got some problem



    This will write the jump
    Code:
    procedure Write_Bytes(Addy:integer; Bytes:array of byte);
    var
      OldProtect:DWORD;
    begin
      VirtualProtect(pointer(Addy), SizeOf(Bytes), PAGE_EXECUTE_READWRITE, @OldProtect); // Change Protection to writeable
      CopyMemory(pointer(Addy), @Bytes, SizeOf(Bytes));                                  // Change Bytes
      VirtualProtect(pointer(Addy), SizeOf(Bytes), OldProtect, @OldProtect);             // Reset protection
    end;
    
    
    procedure LongJump(DestAddy, SourceAddy, Size:integer);
    var
      jmp:array of byte;
      x:integer;
    begin
      SetLength(jmp, Size);
      jmp[0] := $E9;
      jmp[1] := byte(SourceAddy);
      jmp[2] := byte(SourceAddy shr 8);
      jmp[3] := byte(SourceAddy shr 16);
      jmp[4] := byte(SourceAddy shr 24);
    
      for x := 5 to Size do // Add Nops if nessecary
        jmp[x] := $90;
    
      Write_Bytes(DestAddy, jmp); // Write bytes
    end;
    so far so good now to the problem

    Code:
    procedure NakedTest;
    asm
      pop ebp // Delphi Fix
      call dword [$00B0F7B0]
      mov edx,[$01197E48]
      mov edx,[edx+$1AE0]
      mov edx,[edx+$0C]
      mov [esi+$298],edx
      jmp dword [$00B1DF92]
    end;
    
    
    procedure TMainForm.Button3Click(Sender: TObject);
    begin
    //redirect jmp on Address 00B1DF8D
    //Get the addy off "NakedTest"
    //only 5 bytes is needed (no nops will be added)
      LongJump($00B1DF8D, integer(addr(NakedTest)), 5);
    end;
    Here is the sucessfully changed jump


    http://i40.tinypic.com/2ai2261.jpg


    But it points to the wrong location


    http://i44.tinypic.com/a0i7w5.png


    Note it is an injected DLL so i guess i dont need to allocate the memory since it is already within the application, but i could be wrong.


    Hope someone could help me out have been strugling with the problem for a while now!


    ---------------------------------------------------
    in c++ it is done simular to this

    Code:
    #define jmp(frm, to) (int)(((int)to - (int)frm) - 5)
    
    DWORD myCodeCaveAddy = 0x00458777;
    DWORD myCodeCaveReturn = 0x0045877D;
    
    __declspec(naked) void __stdcall MyCodeCaveHack()
    {
    __asm
    {
      call dword [$00B0F7B0]
      mov edx,[$01197E48]
      mov edx,[edx+$1AE0]
      mov edx,[edx+$0C]
      mov [esi+$298],edx
      jmp dword [$00B1DF92]
            }
    }
    
    *(BYTE*)myCodeCaveAddy = 0xE9;
    *(DWORD*)(myCodeCaveAddy + 1) = jmp(myCodeCaveAddy, MyCodeCaveHack);
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Jan 2006
    Location
    Carlsbad, CA
    Posts
    2,057
    Rep Power
    383
    DISCLAIMER: I may be way off mark; but this looks suspect to me:
    Code:
    jmp[1] := byte(SourceAddy);
      jmp[2] := byte(SourceAddy shr 8);
      jmp[3] := byte(SourceAddy shr 16);
      jmp[4] := byte(SourceAddy shr 24);
    Are you sure that when casting a four byte integer to a single byte you are getting what
    you think you are getting?

    Something like this might be more defined:
    Code:
    procedure...
    type
      IntRec = record a, b, c, d : byte end;
    var
    ...
    begin
      jmp[1] := IntRec (SourceAddy).a;
      jmp[2] := IntRec (SourceAddy).b;
      jmp[3] := IntRec (SourceAddy).c;
      jmp[4] := IntRec (SourceAddy).d;
    Put a,b,c,d in which ever order you need for big/small endian etc.

    Clive
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2012
    Posts
    5
    Rep Power
    0
    Originally Posted by clivew
    DISCLAIMER: I may be way off mark; but this looks suspect to me:
    Code:
    jmp[1] := byte(SourceAddy);
      jmp[2] := byte(SourceAddy shr 8);
      jmp[3] := byte(SourceAddy shr 16);
      jmp[4] := byte(SourceAddy shr 24);
    Are you sure that when casting a four byte integer to a single byte you are getting what
    you think you are getting?

    Something like this might be more defined:
    Code:
    procedure...
    type
      IntRec = record a, b, c, d : byte end;
    var
    ...
    begin
      jmp[1] := IntRec (SourceAddy).a;
      jmp[2] := IntRec (SourceAddy).b;
      jmp[3] := IntRec (SourceAddy).c;
      jmp[4] := IntRec (SourceAddy).d;
    Put a,b,c,d in which ever order you need for big/small endian etc.

    Clive
    as i understand it, it works like this

    jmp[1] := byte(SourceAddy); Get the first 8 bits (1 byte)
    jmp[2] := byte(SourceAddy shr 8); Get the bits from 8 -16
    jmp[3] := byte(SourceAddy shr 16);Get the bits from 16 -24
    jmp[4] := byte(SourceAddy shr 24);Get the bits from 24 -30


    I will be using your methode because it looks way better and is easier to understand.


    but it still point to the wrong location (jmp 0921EB5E) it should be jumping close to 0D07C003

    ------------------------------------------------
    Edit6.Text := inttohex(integer(addr(NakedTest)), 8);
    This will get the correct location


    Addy - 096F0C60
    after convertion - E9 (jmp) 60 0C 6F 09

    Thats actually the bytes that is being written but thats also the problem

    the bytes should be E9 CE 2C BD 08 to point to the right location


    Im lost

    Im now sure i use the wrong bytes but unsure how i should do the convertion so it points right.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2012
    Posts
    5
    Rep Power
    0
    Got it working, the "jmp" function from the c++ example did the trick

    in case someone else got this problem i post the source

    Code:
    procedure Write_Bytes(Addy:integer; Bytes:array of byte);
    var
      OldProtect:DWORD;
    begin
      VirtualProtect(pointer(Addy), SizeOf(Bytes), PAGE_EXECUTE_READWRITE, @OldProtect); // Change Protection to writeable
      CopyMemory(pointer(Addy), @Bytes, SizeOf(Bytes));                                  // Change Bytes
      VirtualProtect(pointer(Addy), SizeOf(Bytes), OldProtect, @OldProtect);             // Reset protection
    end;
    
    
    function jump(from,too:DWORD): DWORD;
    var
      jmpto:dword;
    begin
      jmpto:=dword(from)-NativeInt(too)-5;
      Result := jmpto;
    end;
    
    
    
    procedure LongJump(DestAddy, SourceAddy, Size:integer);
    type
      IntRec = record a, b, c, d:byte;
    end;
    var
      jmp:array of byte;
      x:integer;
      JumpAddy:integer;
    begin
      JumpAddy := jump(SourceAddy, DestAddy);
    
      SetLength(jmp, Size);
      jmp[0] := $E9;
      jmp[1] := IntRec (JumpAddy).a;
      jmp[2] := IntRec (JumpAddy).b;
      jmp[3] := IntRec (JumpAddy).c;
      jmp[4] := IntRec (JumpAddy).d;
    
      for x := 5 to Size do // Add Nops
        jmp[x] := $90;
    
      Write_Bytes(DestAddy, jmp);
    end;
    
    
    procedure NakedTest;
    asm
    //Asm code here
    end;
    
    
    
    //Example of use
    // LongJump(AddyToChange, JumpTo, NumberOfBytes); more than 5 will add nops
    procedure TMainForm.Button3Click(Sender: TObject);
    begin
      LongJump($00B1DF8D, integer(addr(NakedTest)), 5);
    end;

IMN logo majestic logo threadwatch logo seochat tools logo