-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathhh1.nasm
More file actions
198 lines (185 loc) · 6.61 KB
/
Copy pathhh1.nasm
File metadata and controls
198 lines (185 loc) · 6.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
;
; hh1.nasm
; by pts@fazekas.hu at Sat Jan 13 11:53:58 CET 2018
;
; How to compile hh1.exe:
;
; $ nasm -f bin -o hh1.exe hh1.nasm
; $ chmod 755 hh1.exe # For QEMU Samba server.
; $ ndisasm -b 32 -e 0x8c -o 0x40008c hh1.exe
;
; hh1.asm was inspired by the 268-byte .exe on
; https://www.codejuggle.dj/creating-the-smallest-possible-windows-executable-using-assembly-language/
; . The fundamental difference is that hh1.exe works on Windows XP ... Windows
; 10, while the program above doesn't work on Windows NT 3.1, Windows, 95 and
; Windows XP (but works on Windows 7).
;
; The reason why it doesn't work on Windows XP and earlier is that these
; versions of Windows require a file alignment larger than 4 bytes, e.g. in
; on Windows XP it's at least 512 bytes. (This has been verified: recompiling
; hh3.c with -Wl,--section-alignment,16,--file-alignment,16 made it stop
; working on Windows NT 3.51, Windows 95 and Windows XP, but it continued
; working on Windows 7 and Wine. hh1.nasm never worked
; on these systems for other header-related reasons.)
; (TODO(pts): Make hhwa4.exe work on Wine, which has 4 as alignment.)
;
; The generated hh1.exe works on:
;
; * Wine 1.6.2 on Linux.
; * It doesn't work on
; Windows XP SP3, 32-bit: Microsoft Windows XP [Version 5.1.2600]
; The application failed to initialize properly (0xc000007b).
; Click on OK to terminate the application.
; * Windows 7: Microsoft Windows [Version 6.1.7600]
; * ?? Windows 10 64-bit: Microsoft Windows [Version 10.0.16299.192]
;
bits 32
imagebase equ 0x400000
bits 32
org 0 ; Can be anything, this file doesn't depend on it.
_filestart:
IMAGE_DOS_HEADER: ; Truncated, breaks file(1) etc.
dw 'MZ', 0
IMAGE_NT_HEADERS:
Signature: dw 'PE', 0
IMAGE_FILE_HEADER:
Machine: dw 0x14c ; IMAGE_FILE_MACHINE_I386
NumberOfSections:
;dw 0
IMAGE_IMPORT_BY_NAME_ExitProcess:
.Hint: dw 0
TimeDateStamp:
;dd 0x00000000
;PointerToSymbolTable: dd 0x00000000
;NumberOfSymbols: dd 0x00000000
;db 'xxxxxxxxxxxx'
.Name: db 'ExitProcess', 0
SizeOfOptionalHeader: dw _datadir_end - _opthd
IMAGE_FILE_RELOCS_STRIPPED equ 1
IMAGE_FILE_EXECUTABLE_IMAGE equ 2
IMAGE_FILE_LINE_NUMS_STRIPPED equ 4
IMAGE_FILE_LOCAL_SYMS_STRIPPED equ 8
IMAGE_FILE_BYTES_REVERSED_LO equ 0x80 ; Deprecated, shouldn't be specified.
IMAGE_FILE_32BIT_MACHINE equ 0x100
IMAGE_FILE_DEBUG_STRIPPED equ 0x200
IMAGE_FILE_DLL equ 0x2000 ; Shouldn't be specified for .exe.
Characteristics: dw IMAGE_FILE_EXECUTABLE_IMAGE
_opthd:
IMAGE_OPTIONAL_HEADER32:
Magic: dw 0x10b ; IMAGE_NT_OPTIONAL_HDR32_MAGIC
MajorLinkerVersion:
;db 0
;MinorLinkerVersion: db 0
;SizeOfCode: dd 0x00000000
;SizeOfInitializedData: dd 0x00000000
;SizeOfUninitializedData: dd 0x00000000
;db 'xxxxxxxxxxxxxx'
IMAGE_IMPORT_BY_NAME_WriteFile:
.Hint: dw 0
.Name: db 'WriteFile', 0
dw 0 ; Padding, unusued.
AddressOfEntryPoint: dd (_entry - _filestart)
BaseOfCode:
;dd 0x00000000
;BaseOfData: dd (IMAGE_NT_HEADERS - _filestart) ; Overlaps with: IMAGE_DOS_HEADER.e_lfanew.
;db 'xxxxxxxx'
_KERNEL32_str: db 'kernel32' ; NUL-terminated below. 'KERNEL32' and 'KERNEL32.dll' also work.
ImageBase: dd imagebase ; First (LSB) byte is 0, terminates the string above
SectionAlignment: dd 4
FileAlignment: dd 4
MajorOperatingSystemVersion:
;dw 0
;MinorOperatingSystemVersion: dw 0
;MajorImageVersion: dw 0
;MinorImageVersion: dw 0
db 'xxxxxxxx'
MajorSubsystemVersion: dw 4
MinorSubsystemVersion:
;dw 0
;Win32VersionValue: dd 0 ; Nonzero values can break D3D.
db 'xxxxxx'
SizeOfImage: dd (_eof + bss_size - _filestart) ; Wine rounds it up to a multiple of 0x1000, and loads and maps that much.
SizeOfHeaders: dd 0x2c ; Must be at least 0x2c on Windows 7, and <= AddressOfEntryPoint on Windows 8.
CheckSum:
;dd 0
db 'xxxx'
Subsystem: dw 3 ; IMAGE_SUBSYSTEM_WINDOWS_CUI; gcc -mconsole
DllCharacteristics: dw 0
SizeOfStackReserve: dd 0x00100000
SizeOfStackCommit: dd 0x00001000
SizeOfHeapReserve: dd 0
SizeOfHeapCommit: dd 0
LoaderFlags: dd 0
NumberOfRvaAndSizes: dd 2
_datadir:
DataDirectory:
IMAGE_DIRECTORY_ENTRY_EXPORT:
.VirtualAddress: dd 0x00000000
.Size: dd 0x00000000
IMAGE_DIRECTORY_ENTRY_IMPORT:
.VirtualAddress: dd (_idescs - _filestart)
.Size: dd 0 ; Ignored.
_datadir_end:
_headers_end:
_entry:
; Arguments pushed in reverse order, popped by the callee.
; WINBASEAPI HANDLE WINAPI GetStdHandle (DWORD nStdHandle);
; HANDLE hfile = GetStdHandle(STD_OUTPUT_HANDLE);
push byte -11 ; STD_OUTPUT_HANDLE
call [imagebase + (__imp__GetStdHandle@4 - _filestart)]
; Arguments pushed in reverse order, popped by the callee.
; WINBASEAPI WINBOOL WINAPI WriteFile (HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
; DWORD bw;
push eax ; Value does't matter.
mov ecx, esp
push byte 0 ; lpOverlapped
push ecx ; lpNumberOfBytesWritten = &dw
push byte (_msg_end - _msg) ; nNumberOfBytesToWrite
push imagebase + (_msg - _filestart) ; lpBuffer
push eax ; hFile = hfile
call [imagebase + (__imp__WriteFile@20 - _filestart)]
;pop eax ; This would pop dw. Needed for cleanup.
; Arguments pushed in reverse order, popped by the callee.
; WINBASEAPI DECLSPEC_NORETURN VOID WINAPI ExitProcess(UINT uExitCode);
push byte 0 ; uExitCode
call [imagebase + (__imp__ExitProcess@4 - _filestart)]
_data:
_msg:
db 'Hello, World!', 13, 10
_msg_end:
; This can be before of after _entry, it doesn't matter.
_idata: ; Relocations, IMAGE_DIRECTORY_ENTRY_IMPORT data.
_hintnames:
dd (IMAGE_IMPORT_BY_NAME_ExitProcess - _filestart)
dd (IMAGE_IMPORT_BY_NAME_GetStdHandle - _filestart)
dd (IMAGE_IMPORT_BY_NAME_WriteFile - _filestart)
dd 0 ; Marks end-of-list.
_iat: ; Modified by the PE loader before jumping to _entry.
__imp__ExitProcess@4: dd (IMAGE_IMPORT_BY_NAME_ExitProcess - _filestart)
__imp__GetStdHandle@4: dd (IMAGE_IMPORT_BY_NAME_GetStdHandle - _filestart)
__imp__WriteFile@20: dd (IMAGE_IMPORT_BY_NAME_WriteFile - _filestart)
dw 0 ; Marks end-of-list, 2nd half of the dd is the dw below.
IMAGE_IMPORT_BY_NAME_GetStdHandle:
.Hint: dw 0
.Name: db 'GetStdHandle', 0
_idescs:
IMAGE_IMPORT_DESCRIPTOR__0:
.OriginalFirstThunk: dd (_hintnames - _filestart)
.TimeDateStamp: dd 0
.ForwarderChain: dd 0
.Name: dd (_KERNEL32_str - _filestart)
.FirstThunk: dd (_iat - _filestart)
_idata_data_end:
_eof:
;bss_size equ 0
;IMAGE_IMPORT_DESCRIPTOR__1: ; Empty, marks end-of-list.
;.OriginalFirstThunk: dd 0
;.TimeDateStamp: dd 0
;.ForwarderChain: dd 0
;.Name: dd 0
;.FirstThunk: dd 0
;_idata_end:
bss_size equ 20 ; _idata_end - _eof
; Padding to reach minimum file size of 268 bytes on 64-bit Windows 7.
; This padding is not needed on 32-bit Windows 7.
times 268 - ($-$$) db 0