flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
rain_storm 30 Apr 2012, 13:45
Okay I know this works on XP SP3 but I need testers to verify if it works on Windows 7 / Vista.
If all goes well you should see a greyscale full screen image. It will exit as soon as you press any key. Features import by hash and minimalist gdi window setup, in 354 bytes. Edit - Also feel free to try your hand at byte crunching this even further.
|
|||||||||||
![]() |
|
bzdashek 30 Apr 2012, 14:16
Win 7 ultimate x64, runs ok, shows gray gradient screen, then exits on anykey
|
|||
![]() |
|
rain_storm 30 Apr 2012, 14:19
Does it have that circle that signifies not responding?
|
|||
![]() |
|
rain_storm 30 Apr 2012, 14:34
Excellent. Now if I can get someone on Vista to verify I'll be over the moon.
|
|||
![]() |
|
typedef 30 Apr 2012, 16:50
Nice stuff...How long did it take you to write such a small PE.
PS: Too bad I switched back to XP from VISTA. |
|||
![]() |
|
rugxulo 30 Apr 2012, 23:18
Sorry, my Vista laptop killed itself 2.5 years ago (not kidding). Actually it overheated, so probably? not Vista's fault.
![]() Anyways ... WINE 1.3.6 atop (Lucid Puppy 5.28 ) says this (I know, who cares? but for completeness ...): Quote:
|
|||
![]() |
|
rain_storm 01 May 2012, 01:06
On and off (mostly off) this took about 4 years of work. Studying crinklers header, tinype, and plenty of shellcode. Had a lot of help from some Demosceners Ferris, rbraz and mostly mentor (mentor is part of the team that created crinkler). It wouldn't have taken so long if I had direct access to a PC with Windows 7 and Vista. But such is life.
The entry point is the "MZ" signiture. LOL guese that's a no-no! |
|||
![]() |
|
revolution 01 May 2012, 01:29
A major problem with these types of non-standard exe files: Even if testing on current OSes shows it "works" this is still no guarantee that future iterations or updates of the OS will continue to allow it to "work". In short, you are asking for trouble and must be prepared for failure at any time.
|
|||
![]() |
|
r22 01 May 2012, 02:32
Quote:
I was looking at this snippet from @rain_storm's code and it just seemed excessive to me. Code: movzx eax, ch imul eax, 010101h Too bad though, still 9 bytes. "MOV al, ch" if you could get away with it would be 1 byte smaller. @Revolution - You've expressed that non-compatibility sentiment so often over the years, I find myself imagining a huge poster-board collage of all such posts made by you. This thought amuses me, kudos! |
|||
![]() |
|
typedef 01 May 2012, 05:00
^^He must know what he's talking about...
Offtopic: 354b trojan downloader..... ![]() ![]() Thanks for the code. ![]() |
|||
![]() |
|
revolution 01 May 2012, 05:08
r22 wrote: @Revolution - You've expressed that non-compatibility sentiment so often over the years, ... typedef wrote: ^^He, or she, must know what he's talking about... |
|||
![]() |
|
rain_storm 01 May 2012, 10:35
@revolution Once apon a time DOS was as standard as you could get. I've spent a lot of time writing 256 byte demos that run under DOS. Nowadays they don't work under Windows 7 or Vista. Some of them rely on undefined data which is always zero under DosBox so cannot be emulated easily.
The day will come when we will be saying the exact same thing about PE executables. But that sounds like a problem for future rain_storm and yep future rain_storm ain't gonna like that one bit. Shaved off three bytes by modifying the way I stored the hash. down to 351 bytes. Code: format binary as 'exe' ;include 'tiny.inc' macro tinycall proc,[arg] { common if ~ arg eq reverse pushd arg common end if call dword [ebx + proc] } VK_ESCAPE = (0x0000001B) SRCCOPY = (0x00CC0020) WS_POPUP = (0x80000000) WS_VISIBLE = (0x10000000) WS_MAXIMIZE = (0x01000000) PM_REMOVE = (0x00000001) WM_KEYDOWN = (0x00000100) WM_KEYUP = (0x00000101) SM_CXSCREEN = (0x00000000) SM_CYSCREEN = (0x00000001) RESX equ 256 RESY equ 192 ImageBase = 0x00400000 SizeOfHdr = 148 SizeOpHdr = SizeOfHdr - Op_Hdr SizeOfCode = 0x00040004 ; 0x00010000 + 196608 ; (196608 = 4*(RESX)*(RESY)) ;GetSystemMetrics dd 0xB9DAA600 use32 root: dec ebp ; 4D 'M' ; .e_magic pop edx ; 5A 'Z' ; jmp jump ; EB 4A ; .e_cblp NT_Hdr: dd 'PE' ; .Signature dw 0x014C ; .Machine dw 0x0000 ; .NumberOfSections LoadLibrary dd 0xE9826FC6 ; .TimeDateStamp GetWindowRect dd 0xF9AC1F38 ; .PointerToSymbolTable ShowCursor dd 0x19A434A8 ; .NumberOfSymbols dw SizeOpHdr ; .SizeOfOptionalHeader dw 0x010F ; .Characteristics (no relocations, executable, 32 bit) Op_Hdr: dw 0x010B ; .Magic db 0x00 ; .MajorLinkerVersion db 0x00 ; .MinorLinkerVersion PeekMessage dd 0xEA1682FE ; .SizeOfCode StretchDIBits dd 0x4ED54D5C ; .SizeOfInitializedData ExitProcess dd 0x38A66AE8 ; .SizeOfUninitializedData dd root ; .AddressOfEntryPoint CreateWindowEx dd 0xF8820ECC ; .BaseOfCode dd 'edit' ; .BaseOfData dd ImageBase ; .ImageBase dd 0x00000004 ; .SectionAlignment dd 0x00000004 ; .FileAlignment GetDC dd 0xA4D450D1 ; .MajorOperatingSystemVersion dd 0 ; .MinorOperatingSystemVersion .MajorImageVersion dw 0x0004 ; .MajorSubsystemVersion jump: push 0x30 ; 6A 30 ; .MinorSubsystemVersion pop ecx ; 59 ; .Win32VersionValue push edx ; jmp kern ; dd SizeOfCode ; .SizeOfImage dd SizeOfHdr ; .SizeOfHeaders libname: dd 'gdi3' ; .CheckSum dw 0x0002 ; .Subsystem dw 0x0000 ; .DllCharacteristics ; compressed stack (offset is relative to stack pointer after clearing the stack) SizeStackClear = 0x24 NumStackValues = 0x0F BitMapInfo = 0x68 PtrStack = (PackedStack-libname)+3 PackedStack: db 0x08, 0x34 ; <- &edit db 0x0A, 0x40 ; <- &edit+ImageBase db 0x13, 0x91 ; <- window style WS_POPUP|WS_MAXIMIZE|WS_VISIBLE db 0x60, 0x20 ; <- LOWORD(SRCCOPY); db 0x4D, 0x01 ; <- StretchDIBits->nSrcWidth = RESX db 0x68, 0x28 ; <- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); db 0x56, 0x41 ; <- 41 here is compressed 00410000 == &pixel[0] db 0x50, 0xC0 ; <- StretchDIBits->nSrcHeight = RESY db 0x62, 0xCC ; <- HIWORD(SRCCOPY); db 0x6D, 0x01 ; <- bmi.bmiHeader.biWidth = RESX; dd 0x00000000 ; .NumberOfRvaAndSizes db 0x76, 0x20 ; <- bmi.bmiHeader.biBitCount = 32; db 0x70, 0xC0 ; <- bmi.bmiHeader.biHeight = RESY; db 0x74, 0x01 ; <- bmi.bmiHeader.biPlanes = 1; ;edx = return to ntldr ;ecx = 0x00000030 kern: mov eax, [fs : ecx] ; 64 8B 01 mov eax, [eax + 0x0C] ; 8B 40 0C mov eax, [eax + 0x1C] ; 8B 40 1C base: mov edx, [eax + 0x20] ; 8B 50 20 mov ebp, [eax + 0x08] ; 8B 68 08 cmp [edx + 0x18], ch ; 38 6A 18 mov eax, [eax] ; 8B 00 jnz base ; 75 F3 mov esi, ImageBase + libname ; jmp imports ; ;ebp = imagebase of dll ;eax = imagebase + &NT_Hdr ;edx = imagebase + &DataDirectory ;esi = &libname ;edi = &hashed function name hash: mov ecx, [edx + 0x18] ; 8B 4A 18 ; ecx = Num Exports redo: jecxz done ; E3 2E ; ecx = 0 No More Exports dec ecx ; 49 ; ecx = Num Exports Decreased mov esi, [edx + 0x20] ; 8B 72 20 ; edi = RVA Exports Asciiz add esi, ebp ; 01 EE ; edi = RVA -> VA mov esi, [esi + ecx * 0x04] ; 8B 34 8E ; esi = RVA Export Asciiz Index add esi, ebp ; 01 EE ; esi = RVA -> VA mov ebx, 0x00000000 ; BB 00 00 00 00 ; .PointerToLinenumbers calc: lodsb ; AC ; al = Char Export Asciiz rol ebx, 0x06 ; C1 C3 06 ; ebx = Hash Preparation xor bl, al ; 30 C3 ; ebx = Hash Complete test al, al ; 84 C0 ; al = 0 Only For End of Asciiz jnz calc ; 75 F6 ; If Not Zero Keep Hashing cmp ebx, [edi] ; 3B 1F ; Check Hash Against Input jnz redo ; 75 E3 ; If Not Equal Hash Next Function mov ebx, [edx + 0x24] ; 8B 5A 24 ; edi = RVA Function Ordinal add ebx, ebp ; 01 EB ; edi = RVA -> VA movzx ecx, word [ebx + ecx * 0x02] ; 0F B7 0C 4B ; mov ebx, [edx + 0x1C] ; 8B 5A 1C ; edi = Function RVAS List add ebx, ebp ; 01 EB ; edi = RVA -> VA add ebp, [ebx + ecx * 0x04] ; 03 2C 8B ; eax = Function RVA ;xchg eax, ebp ; 95 ; ;stosd ; AB ; mov [edi], ebp ; 89 2F ;done: ret ; C3 ; jmp done ;esi = &libname ;ecx = 0x00000030 ;eax = imagebase kernel32.dll imports: or byte [esi+4], cl mov ebx, esi mov bl, ch scan: ;mov edi, ebx push 0x13 ; pop ecx ; LoadLibrary trashes ecx func: pusha lea edi, [ebx + ecx * 0x04] mov eax, [ebp + 0x3C] ; 8B 45 3C ; eax = RVA NT Header mov edx, [ebp + eax + 0x78] ; 8B 54 05 78 ; edx = RVA Data Directory add edx, ebp ; 01 EA ; edx = RVA -> VA ;call hash ; E8 AD FF FF FF ; jmp hash done: popa ; 61 ; Restore Registers loop func ; E2 EB libs: push esi ; 56 tinycall LoadLibrary ;, esi ; FF 53 0C dec esi ; 4E mov dword [esi], 'user' ; C7 06 75 73 65 72 xchg ebp, eax ; 95 or ebp, ebp ; 09 ED jnz scan ; 75 DE ; execution is allowed to fall through to main... start: ; eax = imagebase of user32.dll ebx = imagebase esi = 0040006A edi = 0040004C ebp = 00000000 ;memset(stack,0,sizeof(arguments)); push SizeStackClear ; 0x24 pop ecx push ebp loop $-1 ;decompress(stack, NonZeroValues); lea esi, [esi + PtrStack] mov cl, NumStackValues lodsw movzx edx, al mov [esp + edx], ah loop $-8 ;StretchDIBits->lpBitMapInfo = &BitMapInfo lea ebp, [esp + BitMapInfo] mov [esp + 0x58], ebp ;create the window... tinycall ShowCursor ;(FALSE); tinycall CreateWindowEx ;(0,"edit",0,WS_POPUP|WS_MAXIMIZE|WS_VISIBLE,0,0,0,0,0,0,0,0); mov edx, esp ; our RECT struct doubles as StretchDIBits arguments tinycall GetWindowRect, eax, edx, eax tinycall GetDC ;(hwnd); push eax ; StretchDIBits(hdc... mov ebp, esp ; preserve stackframe main: ; eax = hdc ebx = imagebase == &msg ebp = StackFrame esp = StackFrame ; these locals are already on the Stack as arguments to StretchDIBits RESX equ 256 ; const int RESY equ 192 ; const int ResX equ ebp + 0x1C ; local int ResY equ ebp + 0x20 ; local int Size equ ebp + 0x1F ; local int size = ResX<<8 Pixel equ ebp + 0x24 ; local int* mov edi, [Pixel] ; edi = &pixel[0] (is on the stack as an argument to StretchDIBits) mov ecx, [Size] ; ecx = RESX*RESY (RESY is on the stack we offset it by 1 byte as RESX == 256) draw: mov al, ch mov ah, al shl eax, 0x08 mov al, ah stosd ;dec ecx ;jns draw loop draw pump: ;ecx = 0x00000000 eax = 0x00000000 esp = ebp = StackFrame ebx = ImageBase = msg msg equ ebx tinycall PeekMessage, msg, eax, eax, eax, PM_REMOVE tinycall StretchDIBits ;(hdc,rc.left,rc.top,rc.right,rc.bottom,0,0,ResX,ResY,pixel,0,SRCCOPY); mov esp, ebp ; repair the stack frame (preserves StretchDIBits arguments) mov eax, [ResX] ; if ((eax = 0x00000100) == WM_KEYDOWN == msg.message) ExitProcess(0); cmp eax, [msg + 4] ; jnz main ; tinycall ExitProcess |
|||
![]() |
|
r22 01 May 2012, 14:51
Quote:
? Code:
XOR ebx, ebx
|
|||
![]() |
|
rain_storm 01 May 2012, 14:56
That's a hardcoded constant, PointerToLinenumbers must be 0 so this is actually a way of zeroing ebx in 1 byte
|
|||
![]() |
|
r22 01 May 2012, 15:32
@rain_storm - Does it really 'have' to be zero, seems like it just has to be a valid pointer. But I suppose you'd run into trouble with NumberOfLinesNumbers at that point. I thought there would be some potential because PointerToLineNumbers is a DWORD while NumberOfLineNumbers is only a WORD.
|
|||
![]() |
|
rugxulo 01 May 2012, 18:31
Code: mov esp, ebp ; repair the stack frame (preserves StretchDIBits arguments) This is way too hardcore for me, and it looks like you've done a very exhaustive job. I'm probably wrong, but maybe you can somehow?? use LEAVE instead here. LEAVE is semantically equal to this code below, but I don't know if "pop ebp" would hurt anything here in your case: Code:
mov esp,ebp
pop ebp
However, it would only save you one byte! (I'm not too optimistic, but I try anyways!) ![]() |
|||
![]() |
|
AsmGuru62 01 May 2012, 19:02
LEAVE is OK, but slower than fiddle with ESP.
|
|||
![]() |
|
rain_storm 02 May 2012, 03:55
To get leave to work you need to place ebp on the stack. which adds a push and makes it two bytes. Same size as mov esp, ebp.
Got it down to 347 bytes by taking another look at the drawing code, but to be honest this is the only piece of code I have no interest in crunching. This is a tiny framework for 512 byte demos and the drawing code will be replaced. Code: draw: mov al, ch ;mov ah, al ;shl eax, 0x08 ;mov al, ah ;stosd stosb stosb stosb stosb loop draw |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.