Jump to content











Photo

If anyone is up for a challenge


  • Please log in to reply
73 replies to this topic

#51 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 23 August 2013 - 04:15 PM

Yeah, I know it's not a virus. Of course. And was not aware that mine was flagged too. Anyways, no I have not had time to test yours, yet.



#52 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 28 August 2013 - 10:33 AM

As I see it, the challenge is not over. :dubbio:

 

 

joakim is - no doubts - the winner of it, for several reasons:

  1. having convinced me of the volatility/foolishness of using Ordinal references :w00t:
  2. independently tested Winexec proving it to be a suitable approach, much more compact than CreateProcessA :)
  3. having provided the smallest possible PE @97 bytes :thumbsup:
  4. having provided also a handy example of ShellCode :thumbup:

:worship:

 

BUT he also :ph34r::

  • went ultra petita http://en.wikipedia....on_ultra_petita
  • by design provided a solution that would not work on NT6+ (and not on 2K because according to the mentioned page there is a need for a dll reference to kernel32.dll)
  • by design provided a solution that needs to be adapted on each XP/2003 version of Kernel32.dll

 

So IMHO there is still space to "shrink" the (theoretically working on *any* NT) solution @192 bytes (or my version @172 bytes or the one attached to this post @164 bytes) and to re-generalize the original challenge. 

 

Are there still margins to reduce the "generic" approach further?

Do actually these "generic" solutions work from 2K to 8 without needing specific changes?

 

Let's say that this has become a spin-off of the original challenge, and it is now:

How small can be made this little PE while keeping compatibility with *all* NT versions?

 

 

:cheers:

Wonko

Attached Files


  • Nuno Brito likes this

#53 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 28 August 2013 - 09:18 PM

I think the lower limit for a tinype on nt6.x is 256 bytes. Nice one (oskw164.exe) with imports directory moved into optional header and overlapping with the stack and heap fields.



#54 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 29 August 2013 - 08:16 AM

I think the lower limit for a tinype on nt6.x is 256 bytes. Nice one (oskw164.exe) with imports directory moved into optional header and overlapping with the stack and heap fields.

Well, something better can be done (though far from being "optimal" for other reasons).

 

148 bytes.

 

However it is to be found if the need is just to "pad" the file to reach the "minimum of 256 bytes".

 

I.e. if this "limit" needs to be "filled" with proper fields or we can use "random" data.

 

There is the issue - on NT 5.x also - of the Debug directory needing to be 0 with this approach.

 

:cheers:

Wonko

Attached Files



#55 Holmes.Sherlock

Holmes.Sherlock

    Gold Member

  • Team Reboot
  • 1444 posts
  • Location:Santa Barbara, California
  •  
    United States

Posted 29 August 2013 - 12:02 PM

I think the lower limit for a tinype on nt6.x is 256 bytes. Nice one (oskw164.exe) with imports directory moved into optional header and overlapping with the stack and heap fields.

 

According to my test result, the limit is 252 bytes on NT 6.1 (Windows 7). OSKW164.exe fails to run on Win 7 with the following error message: "Program too big to fit in memory". I stuffed (252-164)=88 NULL padding bytes at the end of OSKW164.exe and it works. Deletion of a single byte from the modified exe reverts back to old error message.

 

@Wonko

Should the suffix be 'W' or 'D' in case of OSKW164.exe and OSKW148.exe?



#56 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 29 August 2013 - 12:12 PM

According to my test result, the limit is 252 bytes on NT 6.1 (Windows 7). OSKW164.exe fails to run on Win 7 with the following error message: "Program too big to fit in memory". I stuffed (252-164)=88 NULL padding bytes at the end of OSKW164.exe and it works. Deletion of a single byte from the modified exe reverts back to old error message.

Good. :)
Now, what happens with the various versions if you stuff "random" bytes instead of zeroes?

 

@Wonko
Should the suffix be 'W' or 'D' in case of OSKW164.exe and OSKW148.exe?

I am not sure to understand which "suffix" do you mean?
 
:cheers:
Wonko

#57 Holmes.Sherlock

Holmes.Sherlock

    Gold Member

  • Team Reboot
  • 1444 posts
  • Location:Santa Barbara, California
  •  
    United States

Posted 29 August 2013 - 12:14 PM

I am not sure to understand which "suffix" do you mean?

 

OSKW164 opens a shell on regular desktop instead of Winlogon ones.



#58 Holmes.Sherlock

Holmes.Sherlock

    Gold Member

  • Team Reboot
  • 1444 posts
  • Location:Santa Barbara, California
  •  
    United States

Posted 29 August 2013 - 01:47 PM

Good. :)
Now, what happens with the various versions if you stuff "random" bytes instead of zeroes?

 

Not exactly what you want, though.

https://docs.google....VEE&usp=sharing

 

Wonko and any team reboot member should be able to edit.



#59 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 29 August 2013 - 06:11 PM

According to my test result, the limit is 252 bytes on NT 6.1 (Windows 7). OSKW164.exe fails to run on Win 7 with the following error message: "Program too big to fit in memory". I stuffed (252-164)=88 NULL padding bytes at the end of OSKW164.exe and it works. Deletion of a single byte from the modified exe reverts back to old error message.

@Wonko
Should the suffix be 'W' or 'D' in case of OSKW164.exe and OSKW148.exe?

I see it's 252 now. I just did not bother checking the last bytes when you anyway would have to add that much padding (I tried chunks of 16 bytes). Regarding the content of the padding, it seems to not matter much, so I guess random also would do.



#60 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 30 August 2013 - 03:42 PM

@Holmes.Sherlock
Anything posted here 192 bytes or less uses WinExec (and thus opens the cmd prompt on the SAME desktop it is launched from).
You need an "indirect" way to launch it, see posts #32:
http://reboot.pro/to...lenge/?p=176030
and #41:
http://reboot.pro/to...lenge/?p=176129
since powerprompt does not work on NT 6.x, you may want to try using joakim's correspondent little app runassystem:

http://reboot.pro/to...d-runfromtoken/

 

Anyway, if it works on the "default" desktop it will work also on the Winlogon one, with the only possible exception if - for any reason - it "goes astray" (the 148 bytes version due to having the number of  directories set to 0x30 will have issues with "random" data padding and may go beserk, in theory it is possible that there is a combination of padding that will work on default desktop and fail on Winlogon one, because it "eats" too much resources/memory/whatever and saturates the heap ).

 

@joakim

So, given that we *need* 252 bytes, your shellcode approach may still have merit.

We could say that the target is now the 252 bytes with the largest "free" code cave at the end.

A question, can we be sure (or reasonably sure) that kernel32.dll is actually loaded at it's declared address (ImageBase @offset e_lfanew+34 )? :unsure:

 

I.e., can we adapt this approach (adding to it a translation from fileoffset to RVA and viceversa where needed):

http://www.cyvera.co...rted-functions/

and use grub4dos pre-boot to write the correct address of the WinExec function (based on the selected \<Windows>\System32\kenel32.dll)?

 

I tested with my XP SP2 the load address is 0x7C800000, I can find the WinExec string @ fileoffset 0x8061 (just a quick draft/sketch):

 

0x8061 Winexec
0x8C61 Function Name RVA Winexec
Delta C00


e_lfa_new offset is fixed 3C
In kernel 32 it's value is E8

0xE8 + 0x78 = 160
Export Directory address value @160= 261C This is a RVA that corresponds to File Offset 1A1C

value 1A1C+0x1C = File Offset 1A38 Value@1A38=2644 is AddressOfFunctions CFF 2644 This is a RVA that corresponds to File Offset 1A44

Value 1A1C+0x20 = File Offset 1A3C Value@1A3C=35C1 is AddressOfNames CFF 351C This is a RVA that corresponds to File Offset 291C

Value 1A1C+0x24 = File Offset 1A40 Value@1A40=43F4 is AddressOfOrdinals CFF 43F4 This is a RVA that corresponds to File Offset 37F4


Value@1A44=A654

Value@291C=4B6D which corresponds to 3F6D and Value@3F6D=ActivateActCtx (first function)




WinExec is function 0x380, thus it must be @E00+1A44=2844 CFF 2844
Value@2844=6158D
String WinExec is at File Offset 8061.
0x8061+0x1000-0x400=8C61
String 0x618C is at File Offset 0x371C
0X371C-0x291C=E00
0xE00/4=380 <- we got the function Ordinal
If we search for 8003 we find it at File Offset 3EF4
0x3EF4-0x37F4=700
700/2=380 <- we got the function Ordinal again
We can now take the base offset for Functions 1A44 and plainly add to it E00 (or ordinal x 4) and get:
0x1A44+E00=2844 this is the file offset whose value is 8D150600, i.e. 0x0006158D, i.e. the wanted address of the function.
Since Kernel32.dll loads at 0x7C800000 we have 0x7C800000+0x0006158D=0x7C86158D

 

 

:cheers:

Wonko



#61 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 30 August 2013 - 10:03 PM

Actually I had to read your post 3 times before I got agrasp of the real question (I think). :)

 

The way I see it your grub4dos method would only work on nt5.x family because of ASLR introduced in nt6.x. But I don't quite see how the refrenced link and PEB method relates to that. That method must be performed when the target module is loaded (ie typically at shellcode execution time), however by the time grub4dos is executed not a single Windows module is loaded (except for ntldr/bootmgr in the case of chainloading) and definetely not kernel32.dll.

 

So, the grub4dos thing, if I understood it correctly, barely gives any advantage. It will give you smaller necessary code within the exe, that is hardcoded (without imports table), but saves you the time to manually modify the hardcoded address within the exe for every new target system, if that job can be "outsourced" to grub4dos. But it seems like a lot of work and limited gains.

 

But the PEB thing, which is entirely different, can be implemented withing the "shellcode" and the target memory address is resolved at runtime. Because of that it requires some more code to work. But the huge advantage is that it works without dependencies and is self contained.



#62 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 31 August 2013 - 11:20 AM

As I see it (sorry if I wasn't clear, but as said I just posted a quick sketch) the PEB method referenced is some code that needs to be added to the "shellcode".

 

Basically the method is simple:

  1. get *somehow* the address at which kernel32.dl is loaded
  2. find in it *any* function by "name" (specifically WinExec)
  3. do some calculations to find out the actual dll function address in memory
  4. write this address in your shellcode

This is done (obviously) "online".

 

I was wondering if this can be done also "offline" (from another OS, or miniOS, like grub4dos) using the kernel32.dll "base address" declared in the PE header.

 

In the test I made the PE header of kernel32.dll says that it will be loaded @ 0x7C800000.

 

My calculations using this as "base address" give the same results your little program give (I presume it is a quick workaround to the GetProocAddress), which means that on my system kernel32 is actually loaded at the declared address of 0x7C800000.

 

My questions are:

  1. will this happen "generally" or - better - always?
  2. or the kernel32.dll could be loaded to a different address?

if the base address is "reliable", it is possible to calculate the value to write in your "shellcode" PE before (or outside) booting the actual system.

The result could be a 252 byte PE with a larger "code cave" than current best "totally" independent result, which is the 164 bytes version (the 148 bytes doesn't count because it needs that at least 8, but more probably 16 bytes corresponding to the "debug directory" need to be 00, leaving the same code cave as the 164 version, only non-contiguous).

 

Conversely, the other question may be, how many bytes are needed to be added to the 97 bytes shellcode to make it recogniazble on NT 6 (apart the padding to 252 bytes) and how many bytes need to be added for the PEB code?

If more than 164-97=67 bytes, then - set aside the "fun" - the result won' t be any good.

 

 

:cheers:

Wonko 

 



#63 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 31 August 2013 - 02:19 PM

It can be done like you describe, but only on nt5.x. Therefore, if I was to give it another try, would probably do it PEB way.

 

Regarding the 97 byte exe, you can just add the required padding and it works (if you corrected the memory address).



#64 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 31 August 2013 - 03:13 PM

It can be done like you describe, but only on nt5.x.

What happens (different) on 6.x?
*Like* is the kernel32.dll loaded to a "random" address?
 
 
 

Therefore, if I was to give it another try, would probably do it PEB way.

Exactly :thumbsup:, but the question is, can the PEB way be implemented in less than 164-97=67 bytes of code (with all the known issues with "placement" of code?

Regarding the 97 byte exe, you can just add the required padding and it works (if you corrected the memory address).

Good, but only with 00 padding or with *any* padding?

:cheers:
Wonko

#65 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 31 August 2013 - 08:39 PM

What happens (different) on 6.x?
*Like* is the kernel32.dll loaded to a "random" address?
 
 
 
Exactly :thumbsup:, but the question is, can the PEB way be implemented in less than 164-97=67 bytes of code (with all the known issues with "placement" of code?

Good, but only with 00 padding or with *any* padding?

:cheers:
Wonko

On nt6.x with ASLR, the base address is random to an extent, at least within a certain range (don't know to which algorithm though). Just noticed that on my Windows 7 x86 the address value (4 bytes) only changes on byte position 1 (counting 0-3). Possibility is that someone has figured out the algorithm, but I don't and have no interest either.

 

I don't know if PEB method for x86 can be done in 67 bytes or less, but it sounds too little.

 

Regarding the the padding for the 97 bytes exe, yes it can be random too. But needs to start beyond offset of optional header.



#66 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 01 September 2013 - 08:58 AM

The PEB method on x86 can be done in 75 bytes for the actual machinecode. However, I just don't understand why cmd.exe can't be loaded directly using this method. Calling cmd1.exe (simpel loader for cmd.exe) works fine.....???

 

Edit: 73 bytes is the correct byte value. And the differing behaviour on different Windows version is really starting to annoy me..



#67 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 01 September 2013 - 10:36 AM

The PEB method on x86 can be done in 75 bytes for the actual machinecode.

Good.
 

However, I just don't understand why cmd.exe can't be loaded directly using this method. Calling cmd1.exe (simpel loader for cmd.exe) works fine.....???

I am sorry, I don't understand. Where does cmd1.exe come from? Calling it how?
 

Edit: 73 bytes is the correct byte value. And the differing behaviour on different Windows version is really starting to annoy me..

Well, I may be wrong, but those differences seem to me - to a certain extent - a part of the "fun".
I would say that taking part to this thread/challenge has been useful as we both (or at least myself) learned quite a few new things, that may come handy one day or the other. :) You never know when something can suddenly become useful.

:cheers:
Wonko
 
P.S.: Just looked for some info on ASLR:
http://skypher.com/i...slr-randomness/

https://web.archive....slr-randomness/
Interesting :).



#68 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 01 September 2013 - 09:23 PM

cmd1.exe is an application I compiled that simply just start cmd.exe. Launching an application that takes 3 characters instead of 4 actually takes more code.. The strange thing is that the same shellcode could launch original calc.exe, but not cmd.exe renamed to calc.exe. At first I thought it was the code to handle the 3 character string that was incorrect, but it was not. The 73 byte code does not cleanly exit. It was taken from here; http://code.google.c...calc-shellcode/

 

However I tested and modified several other codes too. And combined with different behaviour of XP and Windows 7, the mess is significant, and i am loosing interest.

 

Nice link about ASLR. So I see someone already thought about cracking the randomness of it :)



#69 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 02 September 2013 - 08:47 AM

Nice link about ASLR. So I see someone already thought about cracking the randomness of it :)

Yep, though at the light of that, I propose to change ASLR to FASLR (the F being for "fake"), it is hard to call "random" something that is among 750 or so possible values.

Care to share the cmd1.exe source?

:cheers:
Wonko



#70 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 02 September 2013 - 08:25 PM

Sure, it's just an au3 with:

Run("C:\Windows\system32\cmd.exe","", @SW_SHOW)

 

But if I'm not mistaken we already have other examples in this thread that is not as bloated as this one ;)



#71 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 03 September 2013 - 09:55 AM

I don't get it.

You were talking of a 73 bytes shelkcode taken (or derived) from here:

http://code.google.c...calc-shellcode/

 

:cheers:

Wonko



#72 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 03 September 2013 - 06:18 PM

I don't get it.

You were talking of a 73 bytes shelkcode taken (or derived) from here:

http://code.google.c...calc-shellcode/

 

:cheers:

Wonko

Yes, if you look at the code you will see that the last instruction (0xCC) can be removed, so we are left with 74-1=73 bytes.



#73 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13745 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 03 September 2013 - 06:49 PM

The AutoIT code seemingly compiles into a 301.886 bytes file.

 

 

Yes, if you look at the code you will see that the last instruction (0xCC) can be removed, so we are left with 74-1=73 bytes.

But what has the Auto-It code to do with this (and the reference to needing "more" code for a three character filename)?

 

Maybe it's just me, but I have no idea of what you mean about the above.

 

I take it now, that the shellcode on the given page : http://code.google.c...calc-shellcode/ cannot be used, UNmodiifed (if not replacing calc with cmd) to build a .exe that runs in*any* Windows NT system and can load cmd.exe? 

 

Since you seemingly already did this change, and it worked, but not evidently so easily, I asked you to provide that modified source code (if you are willing to share it, of course) in order to avoid the issues that you seemingly had.

 

Or you used the Autoit cmd1.exe (which is in relative terms a piece of bloat :w00t: :ph34r:) because you didn't manage to run the shellcode with the three characters filename directly? :unsure:

 

:cheers:

Wonko



#74 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 03 September 2013 - 07:45 PM

I tried many different PEB based shellcodes and also modified some, but still cmd.exe directly seems like an issue. It is not the 3 vs 4 character that makes a difference. It seems it is simply cmd.exe. Why would calc.exe work? Why would calc.exe work if renamed to cmd.exe? And why on earth don't cmd.exe work as is or renamed to anything?? All tired of it now. Leaving the subject..

 

Maybe someday when I'm all into shellcoding.

 

Good luck further.

 

Edit: My tests was primarily done on Windows 7 SP1 x86.






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users