flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > IP Overlay. A bug or not a bug? [NOT]

Author
Thread Post new topic Reply to topic
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Hi there. I'd like the reader to consider the following code:
Code:
format PE GUI 4.0
include 'win32a.inc'

entry start

remoteCodeOffset = 10008h-remoteCode.size
LDT_Entry:
dw 0FFFFh     ;lower 16 limit bits
.base1:
db 0h,0h,0h      ;lower 24 base bits
.type:
db 11111010b       ;P: 1, DPL: 11 (ring3), S: 1, Type: 1010
db 00000001b        ;G: 0 - limit in bytes, D/B: 0, L: 0, AVL: 0, 16-19 limit bits: 0001
.base2:
db 0                 ;upper base byte

start:
 invoke VirtualAlloc,NULL,20000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
           mov dword[mem_ptr],eax
              mov dword[eax],0FEEBh

           lea edi,[eax+remoteCodeOffset]
              mov esi,remoteCode
          mov ecx,remoteCode.size
             rep movsb

               mov edx,eax
         and eax,000FFFFFFh
          shr edx,24
          or dword[LDT_Entry.base1],eax
               or dword[LDT_Entry.base2],edx
               invoke NtSetLdtEntries,27h,dword[LDT_Entry],dword[LDT_Entry+4],0,0,0
                and byte[LDT_Entry.type], not 1000b
         invoke NtSetLdtEntries,2Fh,dword[LDT_Entry],dword[LDT_Entry+4],0,0,0
                mov bx,2Fh

              jmp 27h:remoteCodeOffset
                beBack:

             invoke MessageBox,0,gotBack,gotBack,MB_OK
   invoke VirtualFree,dword[mem_ptr],0,MEM_RELEASE
ret

data import
   library kernel32,'KERNEL32.DLL',\
                user32,'USER32.DLL',\
            ntdll,'NTDLL.DLL'
 import kernel32,\
          VirtualAlloc,'VirtualAlloc',\
            VirtualFree,'VirtualFree'
 import ntdll,\
             NtSetLdtEntries,'NtSetLdtEntries'
 import user32,\
            MessageBox,'MessageBoxA'
end data

gotBack           db 'Got back',0

align 16
mem_ptr      dd ?

align 16
remoteCode:
   USE16
       org remoteCodeOffset
        .start:
         mov ss,bx
                   mov ebx,esp
                 mov sp,100h
                 push 'ck'
                 push 'Fu'
                 call @F      ;db 0E8h,0,0
                   @@:
                     mov esp,ebx
         push 23h
            pop ss
              ;db 0EBh,00                             ;<-- Problem 1. Wanna have jmp $+2
       USE32
               db 66h                                  ;<-- Problem 2. Wanna have no need to use such workaround
                jmp 1Bh:beBack
  .end:
   .size = .end-.start    

This code just shows a message box and exits.
The line commented as "Problem 1" needs a special look. One could think, that if we uncomment the jmp $+2 instruction (well... it's HEX-equivalent), this will have no effect, causing the instruction flow simply go on. This is not true because of the actual destination address of the instruction, which is located at the first byte of an ip overlay. As long as the jmp $ instruction has been placed on the eip = 0 address (by the instruction mov dword[eax],0FEEBh), a thread executing this code will have an endless loop on eip = 0. Thus one will see no message box anymore.
Fasm recognizes this situation and doesn't allow me to write jmp $+2. Well... I could understand a warning in this case, because it's possible, that a programmer could expect another behavior, but (!) inasmuch as such instruction exists and one (me, for example Smile) could still need exactly what it does, I consider this to be a bug (same problem concerns the big real mode... I think... never used it Smile).
Or... is there any pro to leave the original fasm behavior for this case?

The second problem (referred in the comments as "Problem 2") is speaking for itself and IMHO doesn't need any additional explanation.
Post 06 Apr 2010, 23:15
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17473
Location: In your JS exploiting you and your system
revolution
1. You can't jump to address 0x10000 in 16-bit code. So jmp $+2 will never work. The CPU will force IP to 0x0000. In 16-bit code IP is always masked with 0xffff so executing past 0xffff will wrap back to 0x0000.

2. Remove "USE32" and put "jmp fword 1Bh:beBack".
Post 07 Apr 2010, 00:40
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
revolution
Quote:
You can't jump to address 0x10000 in 16-bit code. So jmp $+2 will never work.

Sure I can. The only thing I need in this case is a prefix (and surely sufficient segment limit in a descriptor). Anyway jmp $+2 is still a valid instruction on this place and it will surely work. Only in different ways depending on if there is a prefix or not.
But if you attentively read my post (well... I know you didn't Smile) you probably would understand, that eip-truncation is exactly the thing I need. And I'd like to have a possibility to write valid instructions with their mnemonics in fasm, not with a db-directive.
Quote:
In 16-bit code IP is always masked with 0xffff so executing past 0xffff will wrap back to 0x0000.

You obviously didn't try to run the code. Cause if you did, you would know, that eip is not always masked with 0FFFFh. Otherwise the code would never get back to the 32-bit segment and one would never see the message box.
Quote:
Remove "USE32" and put "jmp fword 1Bh:beBack".

Thanks. That worked fine.
Post 07 Apr 2010, 12:59
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17473
Location: In your JS exploiting you and your system
revolution
To generate a 32-bit jmp in 16-bit mode you need this:
Code:
jmp dword $+3    
I still stand by what I said, you can't jmp past 0xffff in 16-bit code, you have to switch to 32-code (with a prefix, like you mentioned).
Post 07 Apr 2010, 13:11
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
revolution
As I already twice said, I don't need a 32-bit jump. I need a short 16-bit jump, that goes 64K (or even more in some cases) backwards.
Post 07 Apr 2010, 13:19
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17473
Location: In your JS exploiting you and your system
revolution
If that is all you need then simply:
Code:
jmp 0    
The assembler will work it out for you. Wink

BTW: The talk about jmp $+2 is confusing the issue, you should just put the destination where you actually want to go.
Post 07 Apr 2010, 13:32
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
revolution
Thank you. Smile My fault. Didn't think about it. The conclusion is: "not a bug". Smile Fasm proved me again its flatness (in a good sense). Smile What you code is what you get.
Quote:
I still stand by what I said, you can't jmp past 0xffff in 16-bit code, you have to switch to 32-code (with a prefix, like you mentioned).

I think it's a definition question in this case. I still consider a prefixed code as 16-bit code with a redefined operand size. But at least I think you understand now, that even if we can't jump into an ip overlay with 16-bit code (we can't with your definition but we can with mine), we still can get to the ip overlay(with both definitions) if we don't use any call's or jumps.

Thanks again for the answer.
Post 07 Apr 2010, 13:51
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.