My OS is Windows 7 64-bit and my processor is an Intel Core i7-4700MQ running on the x64 architecture. My program is 32-bit.
Recently, I read an article here describing how it is possible and legal in C to write the main function simply as a constant array of integers, characters, floats, doubles, etc. The article went step-by-step in the process of writing assembly in linux and then transforming it into an array of constant integers in order to print "Hello world!\n\0". I had never seen such a program before, so I decided it would be cool to make one that works on Windows.
In my program, I display an ANSI style MessageBox with the title "Made by CaptainObvious!\n\0" and the the message "C and assembly are for real men\n\0". I have the working inline assembly code in my C program shown below :
int main( )
{
__asm__
(
"sub $0x10, %esp;\n"
"movl $0x0, 0x0(%esp);\n"
"lea message, %eax;\n"
"movl %eax, 0x4(%esp);\n"
"lea title, %eax;\n"
"movl %eax, 0x8(%esp);\n"
"movl $0x00000040, 0xc(%esp);\n"
"call _MessageBoxA@16;\n"
"movl $0, %eax;\n"
"leave;\n"
"ret;\n"
"message: .ascii \"C and assembly are for real men.\\n\\0\";"
"title: .ascii \"Made by CaptainObvious!\\n\\0\";"
);
return 0;
}
Also to ensure that I could implement the technique used by the article, I wrote a simple array of opcodes that functions to return the value of 10 immediately after execution. The test was successfull, and that array is shown below :
const char main[] = { 0x55, 0x89, 0xe5, 0x83, 0xe4, 0xf0, 0x83, 0xec, 0x10, 0xe8, 0, 0, 0, 0, 0xb8, 10, 0, 0, 0, 0xc9, 0xc3 };
Yet when I tried to convert my more complex program to a constant array of integers, my program failed to execute with SIGILL (Illegal Instruction). Here is the relavent disassembly output from gdb :
0x00403040 and $0xffffff89,%ebp
0x00403043 push %ebp
0x00403044 add %ch,%al
0x00403046 lock in $0x83,%al ; <--- SIGILL
; ...
Upon seeing the disassembly output from gdb, I suspected that my array of integers were wrong, but although I caught a few mistakes, it still throws the exact same SIGILL exception shown above. Here is what the current integer array is :
const unsigned int main[] =
{
0x5589e583, 0xe4f0e800, 0x00000083, 0xec10c704, 0x24000000,
0x008d053d, 0x00000089, 0x4424048d, 0x055f0000, 0x00894424,
0x08c74424, 0x0c400000, 0x00e80000, 0x0000b800, 0x000000c9,
0xc3432061, 0x6e642061, 0x7373656d, 0x626c7920, 0x61726520,
0x666f7220, 0x7265616c, 0x206d656e, 0x2e0a004d, 0x61646520,
0x62792043, 0x68726973, 0x204f2754, 0x6f6f6c65, 0x210a00b8,
0x00000000, 0xc9c39090
};
Currently to get the hexadecimal opcodes, I dump the .text section of my program using the objdump.exe program that comes with the MinGW package. Here is the output of my program upon dumping the .text section :
Disassembly of section .text:
00000000 <_main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: e8 00 00 00 00 call b <_main+0xb>
b: 83 ec 10 sub $0x10,%esp
e: c7 04 24 00 00 00 00 movl $0x0,(%esp)
15: 8d 05 3d 00 00 00 lea 0x3d,%eax
1b: 89 44 24 04 mov %eax,0x4(%esp)
1f: 8d 05 5f 00 00 00 lea 0x5f,%eax
25: 89 44 24 08 mov %eax,0x8(%esp)
29: c7 44 24 0c 40 00 00 movl $0x40,0xc(%esp)
30: 00
31: e8 00 00 00 00 call 36 <_main+0x36>
36: b8 00 00 00 00 mov $0x0,%eax
3b: c9 leave
3c: c3 ret
0000003d <message>:
3d: 43 inc %ebx
3e: 20 61 6e and %ah,0x6e(%ecx)
41: 64 20 61 73 and %ah,%fs:0x73(%ecx)
45: 73 65 jae ac <title+0x4d>
47: 6d insl (%dx),%es:(%edi)
48: 62 6c 79 20 bound %ebp,0x20(%ecx,%edi,2)
4c: 61 popa
4d: 72 65 jb b4 <title+0x55>
4f: 20 66 6f and %ah,0x6f(%esi)
52: 72 20 jb 74 <title+0x15>
54: 72 65 jb bb <title+0x5c>
56: 61 popa
57: 6c insb (%dx),%es:(%edi)
58: 20 6d 65 and %ch,0x65(%ebp)
5b: 6e outsb %ds:(%esi),(%dx)
5c: 2e 0a 00 or %cs:(%eax),%al
0000005f <title>:
5f: 4d dec %ebp
60: 61 popa
61: 64 65 20 62 79 fs and %ah,%fs:%gs:0x79(%edx)
66: 20 43 61 and %al,0x61(%ebx)
69: 70 74 jo df <title+0x80>
6b: 61 popa
6c: 69 6e 4f 62 76 69 6f imul $0x6f697662,0x4f(%esi),%ebp
73: 75 73 jne e8 <title+0x89>
75: 21 0a and %ecx,(%edx)
77: 00 b8 00 00 00 00 add %bh,0x0(%eax)
7d: c9 leave
7e: c3 ret
7f: 90 nop
This brings me back to my question, how do I convert assembly to a constant array of integer opcodes for my main function?