Just out of curiosity i downloaded crinkler
compiled this code with visual c++
#include <windows.h>
int WINAPI WinMain(__in HINSTANCE,__in_opt HINSTANCE,__in LPSTR,__in int) {
MessageBox(NULL, "Testing Crinky", "CRINKLE", MB_OK);
ExitProcess(NULL);
}
and linked the object file with crinkler20.exe
with
cl -c /nologo /W4 /O1 /Zi /analyze *.cpp
crinkler.exe /ENTRY:WinMain crinky.obj kernel32.lib user32.lib /CRINKLER /HASHTRIES:300 /COMPMODE:SLOW /ORDERTRIES:4000 /SUBSYSTEM:windows /out:crinky.exe
it created a 459 byte exe which runs fine
ls -la crinky.exe
-rwxrwxrwx 1 HP 0 459 2016-11-15 15:25 crinky.exe

opened it in a hexeditor to see whats inside it appears crinkler employs
pe header damaging techniques (it seems to use the peheader to stuff code )
here is a hexedit view (from hxd)
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 4D 5A 32 30 50 45 00 00 4C 01 00 00 01 DB 61 7F MZ20PE..L....Ûa.
00000010 10 D0 17 73 75 47 EB F9 08 00 02 00 0B 01 11 C9 .Ð.suGëù.......É
00000020 45 85 C0 79 1F 01 D3 50 F7 E2 90 3D 5C 00 00 00 E…Ày..ÓP÷â.=\...
00000030 F7 F3 39 C1 19 DB EB 48 00 00 40 00 04 00 00 00 ÷ó9Á.ÛëH..@.....
00000040 04 00 00 00 0F A3 2D 29 01 40 00 8D 04 00 EB CE .....£-).@....ëÎ
00000050 00 00 00 00 EB B6 42 06 40 00 00 00 53 31 ED BB ....ë¶[email protected]í»
00000060 02 00 00 00 90 BE 14 01 40 00 6A 01 58 BF 00 00 .....¾[email protected]¿..
00000070 42 00 B1 00 90 57 EB 12 00 00 00 00 00 00 00 00 B.±..Wë.........
00000080 5A 72 07 92 29 D1 04 00 29 D0 60 AD 01 F8 74 2C Zr.’)Ñ..)Ð`..øt,
00000090 6A 0A 5A 89 14 54 89 54 24 10 AD 31 ED 4D 45 01 j.Z‰.T‰T$..1íME.
000000A0 C0 72 FB 74 AF 60 AC 88 C2 32 07 6B C0 6F 02 87 Àrût¯`¬ˆÂ2.kÀo.‡
000000B0 00 00 00 00 48 4F 00 D2 72 EF 75 F9 BF CE 00 42 ....HO.Òrïuù¿Î.B
000000C0 00 B9 F5 E9 1F 03 73 0C F3 66 AB 0A 06 61 8D 76 .¹õé..s.óf«..a.v
000000D0 0C 7B B7 C3 F7 F1 8D 3C 57 89 E9 31 C0 AE 74 04 .{·Ã÷ñ.<W‰é1À®t.
000000E0 00 07 75 02 41 41 0F B6 14 07 D3 E2 01 54 84 34 ..u.AA.¶..Óâ.T„4
000000F0 48 7A F3 85 DB 7F 0D D0 2C 1F 75 03 D0 14 1F F7 Hzó…Û..Ð,.u.Ð..÷
00000100 D3 FE 04 1F 61 46 EB 95 E8 6A A6 38 C6 6F 82 E9 Óþ..aFë•èj¦8Æo‚é
00000110 1B 13 09 4F 55 FF BD FF FE FF FF 9A 00 20 80 90 ...OUÿ½ÿþÿÿš. €.
00000120 32 FF BD FF FF FF FF DF 00 44 BE 63 EE 28 9E 30 2ÿ½ÿÿÿÿß.D¾cî(ž0
00000130 07 9C 4B 16 0D 6B A8 05 A4 65 86 46 50 14 FE B3 .œK..k¨.¤e†FP.þ³
00000140 42 F6 F7 88 0C 1A 94 68 7D 22 BF 3C 30 2F DD C7 Bö÷ˆ..”h}"¿<0/ÝÇ
00000150 6B F9 26 24 83 12 7D A2 3A 05 85 FE B3 D2 B1 CF kù&$ƒ.}¢:.…þ³Ò±Ï
00000160 0F B2 80 7D 9A 49 1C 61 97 36 9F 22 F6 54 CD 3F .²€}šI.a—6Ÿ"öTÍ?
00000170 3B 0E 4B 81 F7 A3 6D 3C 54 89 06 C3 37 51 99 E0 ;.K.÷£m<T‰.Ã7Q™à
00000180 E6 1E D8 B1 E4 7C 73 D4 9C 36 78 DA 27 8C 39 F3 æ.رä|sÔœ6xÚ'Œ9ó
00000190 BD BF 42 6B F3 1C D9 B1 E7 A5 E7 60 1F C6 5B DF ½¿Bkó.Ù±ç¥ç`.Æ[ß
000001A0 8F A6 47 E0 B5 A7 DD 3D D6 4A CA 91 3C 35 B3 74 .¦G൧Ý=ÖJÊ‘<5³t
000001B0 CB A1 81 90 90 32 39 E4 B0 0F 4D EA E4 EA 2F 0A Ë¡...29ä°.Mêäê/.
000001C0 6C 06 7C 8F E8 9B B1 50 6E 55 0B l.|.è›±PnU.
linux file utility says it is a ms dos exe
dumpbin complains no COFF header
dumpbin /nologo crinky.exe
Dump of file crinky.exe
File Type: EXECUTABLE IMAGE
LINK : fatal error LNK1235: corrupt or invalid COFF symbol table
file crinky.exe
crinky.exe; MS-DOS executable, MZ for MS-DOS
loaded it into windbg and looked at header
appears to be completely corrupt
cdb -c ".foreach /pS 4 /ps 100 (place { lm }) { !dh place };q" crinky.exe | grep quit: -B 53
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (i386)
0 number of sections
7F61DB01 time date stamp Mon Sep 21 09:48:09 2037
7317D010 file pointer to symbol table
F9EB4775 number of symbols
8 size of optional header
2 characteristics
Executable
OPTIONAL HEADER VALUES
10B magic #
17.201 linker version
79C08545 size of code
50D3011F size of initialized data
3D90E2F7 size of uninitialized data
5C address of entry point
C139F3F7 base of code
----- new -----
00400000 image base
4 section alignment
4 file alignment
2 subsystem (Windows GUI)
41743.10541 operating system version
16385.36096 image version
4.52971 subsystem version
642B6EB size of image
40 size of headers
BBED3153 checksum
0114be90 size of stack reserve
016a0040 size of stack commit
0000bf58 size of heap reserve
00b10042 size of heap commit
0 DLL characteristics
0 [9207725A] address [size] of Export Directory
4D129 [AD60D029] address [size] of Import Directory
2C74F801 [895A0A6A] address [size] of Resource Directory
54895414 [31AD1024] address [size] of Exception Directory
1454DED [74FB72C0] address [size] of Security Directory
88AC60AF [6B0732C2] address [size] of Base Relocation Directory
87026FC0 [ 0] address [size] of Debug Directory
D2004F48 [F975EF72] address [size] of Description Directory
4200CEBF [E9F5B900] address [size] of Special Directory
C73031F [ AAB66F3] address [size] of Thread Storage Directory
768D6106 [C3B77B0C] address [size] of Load Configuration Directory
3C8DF1F7 [31E98957] address [size] of Bound Import Directory
474AEC0 [ 2750700] address [size] of Import Address Table Directory
B60F4141 [E2D30714] address [size] of Delay Import Directory
34845401 [85F37A48] address [size] of COR20 Header Directory
D00D7FDB [ 3751F2C] address [size] of Reserved Directory
quit:
tested if the entry point function is a function with single exit using cdb
there were no indirect calls / jmps and it contained only one exit a single return
cdb -c "g @$exentry;uf @eip;q" crinky.exe | grep -iE "call|ret"
004000d3 c3 ret
so set a bp there and executed and dumped the decryted area
cdb -c "g 4000d3;t \"dc @eip l38;q\"" crinky.exe | grep quit: -B 17
0:000> cdb: Reading initial command 'g 4000d3;t "dc @eip l38;q"'
*** WARNING: Unable to verify timestamp for image00400000
*** ERROR: Module load completed but symbols could not be loaded for image00400000
00420000 400108bb 00abbe00 00bf0042 58004300 [email protected]
00420010 8b0c408b 008b0c40 688b008b 75ed8518 .@[email protected]
00420020 6a006a0e 006a5200 000815ff 31c30043 .j.j.Rj.....C..1
00420030 6091acc0 013c458b 78508be8 4a8bea01 ...`.E<...Px...J
00420040 20428b18 748be801 ee01fc88 c7c1ff31 ..B ...t....1...
00420050 acc03106 7d48c731 e03b3bf5 24428be4 .1..1.H}.;;...B$
00420060 8b66e801 428b480c 8be8011c 44898804 ..f..H.B.......D
00420070 01611c24 c383abe8 56b8e204 000415ff $.a........V....
00420080 89950043 c8feacf2 c0fefb79 006a8f74 C.......y...t.j.
00420090 4200b868 00c06800 006a0042 000815ff h..B.h..B.j.....
004200a0 006a0043 000015ff 02cc0043 72657375 C.j.....C...user
004200b0 01003233 000000ff 4e495243 00454c4b 32......CRINKLE.
004200c0 74736554 20676e69 6e697243 0000796b Testing Crinky..
004200d0 00000000 00000000 00000000 00000000 ................
quit:
it appears the data has been decrypted but imports are resolved here
any way we can reach our code in three calls
cdb -c "g 4000d3;rm 0;pct 3" crinky.exe
0:000> cdb: Reading initial command 'g 4000d3;rm 0;pct 3'
0042007c ff1504004300 call dword ptr [(00430004)] ={kernel32!LoadLibraryA (7676395c)}
0042007c ff1504004300 call dword ptr [(00430004)] ={kernel32!LoadLibraryA (7676395c)}
0042009c ff1508004300 call dword ptr [(00430008)] ={user32!MessageBoxA (75e6ea11)}
0:000> ub @eip
image00400000+0x20086:
00420086 fec8 dec al
00420088 79fb jns image00400000+0x20085 (00420085)
0042008a fec0 inc al
0042008c 748f je image00400000+0x2001d (0042001d)
0042008e 6a00 push 0
00420090 68b8004200 push offset image00400000+0x200b8 (004200b8)
00420095 68c0004200 push offset image00400000+0x200c0 (004200c0)
0042009a 6a00 push 0
0:000> da 4200b8
004200b8 "CRINKLE"
0:000> da 4200c0
004200c0 "Testing Crinky"
0:000>
based on these the uncompressed executable may be impossible to dump without serious code ( it doesn't have any import table / nor pe header to work with )
you may have to prepend a pe header and append an import section to the raw memory
as to ollydumpex it is a tool with lots of options
pebase
you can either select any module , memory range , address range
list section will list the found section based on the pebase selection
for example if you choose memory list sections will list the whole virtual address range from 0x10000 to 0x7fffffff (32 bit 2 gb va range )
when you rescan search pe searches for pe header in the range
dump mode rebuild tries to rebuild the imports if possible (possibly runnable exe)
raw dumps what is in memory (usefull for forensics not fro running the exe)
but you can see ollydumpex complaining corrupt header in status bar
so dumping with ollydumpex is not a viable option as of now
well you can dump the contents if you start coding a special dumper
fill the pe headers imports etc it might be serious work maybe
s small start
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>
int dumpdos (char * filepath){
IMAGE_DOS_HEADER imdos = {0};
FILE * fp = fopen(filepath,"r");
if(fp) { fseek(fp,0,SEEK_SET);
fread(&imdos,sizeof(BYTE),sizeof(IMAGE_DOS_HEADER),fp); fclose(fp);
}
printf("%08x\n",imdos.e_magic);
printf("%08x\n",imdos.e_lfanew);
return imdos.e_lfanew;
}
void dumpnt (char * filepath , int off_pehead){
IMAGE_NT_HEADERS imnt = {0};
FILE * fp = fopen(filepath,"r");
if(fp) { fseek(fp,off_pehead,SEEK_SET);
fread(&imnt,sizeof(BYTE),sizeof(IMAGE_NT_HEADERS),fp); fclose(fp);
}
printf("%08x\n",imnt.Signature);
printf("%08x\n",imnt.FileHeader.Machine);
printf("%08x\n",imnt.FileHeader.NumberOfSections);
printf("%08x\n",imnt.FileHeader.SizeOfOptionalHeader);
printf("%08x\n",imnt.OptionalHeader.Magic);
printf("%08x\n",imnt.OptionalHeader.AddressOfEntryPoint);
printf("%08x\n",imnt.OptionalHeader.ImageBase);
}
void main (int argc,char* argv[]){
if(argc !=2){ printf("usage %s <path to binary>",argv[0] ); exit(-1); }
printf ("dumping e_magic and e_lfanew from header of %s\n" , argv[1]);
int pehead = dumpdos(argv[1]);
printf("dumping NtSig , M/c, sect_nos, sizeopt_hdr, opthdrmagic, &EP, imgbase\n");
dumpnt(argv[1],pehead);
}
executing it
dumpcrink.exe ..\crinky.exe
dumping e_magic and e_lfanew from header of ..\crinky.exe
00005a4d
00000004
dumping NtSig , M/c, sect_nos, sizeopt_hdr, opthdrmagic, &EP, imgbase
00004550
0000014c
00000000
00000008
0000010b
0000005c
00400000
the custom import resolver is cute
CPU Disasm
Address Command Comments
00420000 MOV EBX, OFFSET 00400108 ; hashtable
00420005 MOV ESI, OFFSET 004200AB ; no of imports to resolve in k32
0042000A MOV EDI, OFFSET 00430000 ; destination for resolved imports
0042000F POP EAX ; peb
00420010 MOV EAX, DWORD PTR DS:[EAX+0C] ; Peb.Ldr
00420013 MOV EAX, DWORD PTR DS:[EAX+0C] ; inLoadorderModuleList
00420016 MOV EAX, DWORD PTR DS:[EAX] ; flink ntdll
00420018 MOV EAX, DWORD PTR DS:[EAX] ; flink k32
0042001A MOV EBP, DWORD PTR DS:[EAX+18] ; kernel32.dllbaseAddr
0042001D TEST EBP, EBP
; dx ((ntdll!_LDR_DATA_TABLE_ENTRY *)((int )((ntdll!_PEB *) @$peb)->Ldr->
;InLoadOrderModuleList.Flink->Flink->Flink))->DllBase
0042001F JNE SHORT 0042002F ; if this is not k32base exit
00420021 PUSH 0
00420023 PUSH 0
00420025 PUSH EDX
00420026 PUSH 0
00420028 CALL NEAR DWORD PTR DS:[430008] ; will never reach here
;if reaches here in case of no k32 it will crash with null dereference
0042002E RETN
0042002F XOR EAX, EAX
00420031 LODS BYTE PTR DS:[ESI] ; no of imports from k32
00420032 XCHG EAX, ECX ; save no of imports from k32
00420033 PUSHAD
00420034 MOV EAX, DWORD PTR SS:[EBP+3C] ; k32peheaderptr (e_lfanew)
00420037 ADD EAX, EBP ; k32peheaderptr PE
00420039 MOV EDX, DWORD PTR DS:[EAX+78] ; exporttable of k32
0042003C ADD EDX, EBP ; k32_imageexportdir
0042003E MOV ECX, DWORD PTR DS:[EDX+18] ; noofname
00420041 MOV EAX, DWORD PTR DS:[EDX+20] ; addressofnamerva
00420044 ADD EAX, EBP ; virtualaddrof export names
00420046 MOV ESI, DWORD PTR DS:[ECX*4+EAX-4] ; last export rva
0042004A ADD ESI, EBP ; last export addr name
0042004C XOR EDI, EDI ; 0
0042004E ROL EDI, 6 ; creating hash
00420051 XOR EAX, EAX
00420053 LODS BYTE PTR DS:[ESI] ; first/nth letter of export name
00420054 XOR EDI, EAX
00420056 DEC EAX
00420057 JGE SHORT 0042004E ; null termin seek
00420059 CMP EDI, DWORD PTR DS:[EBX] ; comparehash with [400108]
0042005B LOOPNZ SHORT 00420041 ; reloop
0042005D MOV EAX, DWORD PTR DS:[EDX+24] ; matched hash end of iit
00420060 ADD EAX, EBP
00420062 MOV CX, WORD PTR DS:[ECX*2+EAX]
00420066 MOV EAX, DWORD PTR DS:[EDX+1C] ; addroffunctions
00420069 ADD EAX, EBP
0042006B MOV EAX, DWORD PTR DS:[ECX*4+EAX]
0042006E MOV DWORD PTR SS:[ESP+1C], EAX
; modify register eax so popad will hold the rva of k32 export
00420072 POPAD ; eax stays same as addr of
;functions
00420073 ADD EAX, EBP ; rva+ base = addr of proc
00420075 STOS DWORD PTR ES:[EDI] ; getprocaddr achieved
00420076 ADD EBX, 4 ; store at 430000
00420079 LOOP SHORT 00420033
; resolves all exports from k32 + loadlibrary
0042007B PUSH ESI ; ASCII "user32"
0042007C CALL NEAR DWORD PTR DS:[430004] ; loadlibs user32 or whatever dll
00420082 XCHG EAX, EBP
00420083 MOV EDX, ESI ; ASCII "user32"
00420085 LODS BYTE PTR DS:[ESI] ; again null term for dll name
00420086 DEC AL
00420088 JNS SHORT 00420085
0042008A INC AL
0042008C JE SHORT 0042001D ;
; so this is standard sized custom import resolver
so i created another exe with more api calls and checked it and
set a hardware exec bp on 42008e and f9nned i landed on actual code
CPU Disasm
Address Hex dump Command Comments
004000BC BF 3A014200 MOV EDI, OFFSET 0042013A <---------
004000C1 B9 23E91F03 MOV ECX, OFFSET 031FE923
004000C6 73 0C JAE SHORT 004000D4
004000C8 F3:66:AB REP STOS WORD PTR ES:[EDI]
so 42008e is start of actual code and spans upto the hard coded address
430000 is resolved imports
CPU Dump
Address Hex dump ASCII
0042008E 53 56 8B 35|08 00 43 00|33 DB 57 53|BF E4 00 42| SV‹5 C 3ÛWS¿ä B
0042009E 00 57 68 1C|01 42 00 53|FF D6 53 57|68 0C 01 42| WhB SÿÖSWhB
004200AE 00 53 FF D6|53 57 68 2C|01 42 00 53|FF D6 53 57| SÿÖSWh,B SÿÖSW
004200BE 68 FC 00 42|00 53 FF D6|53 57 68 EC|00 42 00 53| hü B SÿÖSWhì B S
004200CE FF D6 53 FF|15 00 00 43|00 5F 5E 5B|02 75 73 65| ÿÖSÿ C _^[use
004200DE 72 33 32 00|01 FF 43 52|49 4E 4B 4C|45 00 54 65| r32 ÿCRINKLE Te
004200EE 73 74 69 6E|67 20 43 72|6F 6E 6B 79|00 00 54 65| sting Cronky Te
004200FE 73 74 69 6E|67 20 43 72|65 6E 6B 79|00 00 54 65| sting Crenky Te
0042010E 73 74 69 6E|67 20 43 72|61 6E 6B 79|00 00 54 65| sting Cranky Te
0042011E 73 74 69 6E|67 20 43 72|69 6E 6B 79|00 00 54 65| sting Crinky Te
0042012E 73 74 69 6E|67 20 43 72|75 6E 6B 79|00 00 00 00| sting Crunky
if i binary copy and dump it to a bin file i can easily analyze it with ida
by rebasing it 0x40008e creating an xtern segment a, d etc
josh wrote a lengthy post below with patching instructions one doesnt have to go patching instructions all that is needed is hw bp 0x42008e -> f9 _>
change addr of entry point to 2008e instead of 5c in the original pe header
create backup and save backup
this mem dump can be loaded as is in idapro and it will be dandy enough like a pristine exe
ollydbg crinkledexe -> ctrl+g 42008e -> right click-> exec hw bpt -> f9 _> patch ADDROF ENTRYPOINT TO 0X2008E INSTEAD OF 0X5C ->right click_> createbackup _> right click _> save backup-> load in ida demo 6.9 bingo it is as nice as it get