Some people say it is impossible to make smaller applications in C than in Assembly Language.
This is not totally true. Using as model the code from this message (http://masm32.com/board/index.php?topic=6524.msg69994#msg69994) I made a C .exe of the same size as the MASM one, i.e 3072 bytes. The output is the same, the difference is that the encrypted string is not in the middle of the code. That could have been done as well with inline asm, but I prefered to keep it all in C this time.
The compiler used was VS 2017 using the Windows SDK 7.1 toolset.
The code and .exe are attached.
I am taking unfair advantage of you here Jose, not only am I using MASM but I used Pelle's linker.
MASM the magnificent and modest at 1536 bytes. :P
I forgot to free the allocated memory. Main should look like this.
main proc
LOCAL ptxt:DWORD
call mangled
mov ptxt, eax
invoke StdOut, ptxt
free ptxt
ret
main endp
Builds at the same size.
deleted
ust looking at the code, it appears that neither of you guys are decrypting the data, it looks like you have just stored the text data in numeric form.
Quote from: hutch-- on September 09, 2017, 03:45:25 AM
Just looking at the code, it appears that neither of you guys are decrypting the data, it looks like you have just stored the text data in numeric form.
:biggrin:
Quote
1536 byte
If I use polink i get 1536 bytes as well. :t
\masm32\bin\polink /SUBSYSTEM:console /NODEFAULTLIB main.obj \masm32\lib\msvcrt.lib
Sometimes, my antivirus bark when look at polink linked files.
In the masm32 SDK there is this 1K example.
c:\masm32\examples\exampl07\masm1k\masm1k.exe
Sorry, I am a bit late, folks - the smally.vcxproj tried to open Visual Studio, and that took a while :greensml:
And the behemoth complains:Rebuild All: 0 succeeded, 1 failed, 0 skipped
No additional info why it fails - I assume it's because it's genuine Microsoft software :bgrin:
@nidud: fatal error A1000: cannot open file : alloc.inc
Re obfuscation, the reverse engineer should not have such an easy job imho:
Smally.exe:00D61011 ³. B9 0030D600 mov ecx, offset 00D63000
00D61016 ³. 8D50 64 lea edx, [eax+64]
00D61019 ³> 8B39 Úmov edi, [ecx]
00D6101B ³. 33FE ³xor edi, esi
00D6101D ³. 893A ³mov [edx], edi
00D6101F ³. 8B31 ³mov esi, [ecx]
00D61021 ³. 83C1 04 ³add ecx, 4
00D61024 ³. 83EA 04 ³sub edx, 4
00D61027 ³. 81F9 6830D600 ³cmp ecx, offset 00D63068
00D6102D ³. 7C EA Àjl short 00D61019
00D6102F ³. 50 push eax ; ³format
00D61030 ³. FF15 0020D600 call near [<&msvcrt.printf>] ; ÀMSVCRT.printf
ObfuscateString.exe:004011AA . E8 68000000 call 00401217 ; ÀObfuscateString.00401217
004011AF . 34 E5 xor al, E5
004011B1 . 11BB 51973FBB adc [ebx+BB3F9751], edi
004011B7 36 db 36 ; char '6'
004011B8 FE db FE ; char 'þ'
004011B9 51 db 51 ; char 'Q'
004011BA DE db DE ; char 'Þ'
004011BB 53 db 53 ; char 'S'
004011BC DE db DE ; char 'Þ'
004011BD 34 db 34 ; char '4'
004011BE B0 db B0
004011BF 25 db 25 ; char '%'
004011C0 BB db BB
004011C1 Ú. 46 inc esi
004011C2 À. C3 retn
...
00401217 Ú$ 5A pop edx ; here you land when using F7 - with F8 you'll never see this part ;-)
00401218 ³. 6A 1A push 1A
0040121A ³. 59 pop ecx
0040121B ³> 8B02 Úmov eax, [edx]
0040121D ³. 3342 FC ³xor eax, [edx-4]
00401220 ³. 83C2 04 ³add edx, 4
00401223 ³. 50 ³push eax
00401224 ³. 49 ³dec ecx
00401225 ³. 75 F4 Àjnz short 0040121B
00401227 ³. 54 push esp
00401228 ³. 6A 01 push 1
0040122A ³. 6A 02 push 2
0040122C ³. E8 06130000 call 00402537
I like Erol's code. The Pelles C IDE opens in 3 seconds, it builds in 2 seconds, and it doesn't complain about any errors :t
Besides, the clear text becomes visible only when the whole loop is finished, that is even better than my version :t
Hi aw27,
Nice example. Thanks. Source code built with Pelles C.
A small modification in your code to avoid problems with getchar :
The header file stdio.h supplied with Pelles C :
/* macro overrides */
#if !defined(__MT__) && !defined(_DLL)
#define getc(str) ((str)->ptr < (str)->getend ? *(str)->ptr++ : (fgetc)(str))
#define getchar() (__filetab[0]->ptr < __filetab[0]->getend ? *__filetab[0]->ptr++ : (fgetc)(__filetab[0]))
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#undef getchar
Reference :
http://www.masmforum.com/board/index.php?PHPSESSID=786dd40408172108b65a5a36b09c88c0&topic=14078.0
Nice tip Siekmanski. :t
Adding
#pragma comment(linker,"/merge:.rdata=.data")
#pragma comment(linker,"/merge:.data=.text")
Fixed base Address:YES and Randomized Base Address: NO under Linker Advanced
reduces the file linked with MS Link to 1024 bytes and the file linked with polink to 1024 bytes as well.
Thank you Vortex too.
What is being missed here is the MASM example stores 2 sequences of data that are XORRED together to produce the string. One in the code section, the other in the data section so to make a comparable example you need to add the code to do that otherwise you are not comparing the same thing.
The /MERGE option often drops the size by one 512 byte section but its not much use for any viable executable file.
Quote from: hutch-- on September 09, 2017, 03:54:46 PM
What is being missed here is the MASM example stores 2 sequences of data that are XORRED together to produce the string. One in the code section, the other in the data section so to make a comparable example you need to add the code to do that otherwise you are not comparing the same thing.
The /MERGE option often drops the size by one 512 byte section but its not much use for any viable executable file.
The MASM example creates a DATA section which was not used in the code. But even merging sections I can not go under 1536 bytes both with link.exe and polink.exe. :icon_confused:
The reason may be some overhead added by the SDK.
If I don't use the SDK I can indeed reach the 1024 bytes size.
.386
.model flat, stdcall
option casemap :None
includelib \masm32\lib\msvcrt.lib
getchar proto C
printf proto C :ptr, :vararg
STD_OUTPUT_HANDLE equ -11
.code
main proc C
call @F
@obs$ dd 0BB11E534h,0BB3F9751h,0DE51FE36h,0B034DE53h,0C346BB25h,0A6349B4Ah,0D214E92Fh,0B6668847h,09612E167h,0F17C880Ch,09011A820h,
0F165C944h,0D101AC20h,0B564CE4Dh,0D044AB39h,0B127D84Ch,0D745B76Ch,0B8319709h,0DC5EF429h,0B83F9C09h,0DD49F97Dh,
08E66911Eh,0FA13D93Eh,0D676B457h,0A256D139h,0CD76A578h
@@:
pop edx
mov ecx, sizeof @obs$/4
push 0
.Repeat
mov eax, [edx]
mov ebx, [edx-4]
xor eax, [edx-4]
add edx, 4
push eax
dec ecx
.Until Zero?
INVOKE printf, esp
INVOKE getchar
add esp, sizeof @obs$ +4
ret
main endp
end main
linked with POLINK as follows:
\masm32\bin\polink /MERGE:.rdata=.data /MERGE:.data=.text /SUBSYSTEM:console xor2.obj
Jose,
I think you have mis-understood what the code does. The code in the data section is loaded into the EDX register then XORRED against the address stored in ESI. This is how the string is decrypted and the result is returned in EAX.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
mangled proc
LOCAL pMem :DWORD
; --------------------------------------------------------
; Return value in EAX is the memory pointer to the result
; The data length is returned in ECX. Deallocate memory in
; EAX with the Windows API function GlobalFree() or the
; MASM32 macro "free".
; --------------------------------------------------------
push ebx
push esi
push edi
mov pMem, alloc(102)
mov esi, pMem
mov DWORD PTR [esi+52], 2701825359
mov DWORD PTR [esi+32], 4160494258
mov DWORD PTR [esi+68], 202942781
mov DWORD PTR [esi+16], 4294820983
mov DWORD PTR [esi+44], 4205567486
mov DWORD PTR [esi+0], 4017705100
mov DWORD PTR [esi+84], 3971489685
mov DWORD PTR [esi+4], 3496616615
mov DWORD PTR [esi+12], 2682706439
mov DWORD PTR [esi+92], 3083553528
mov DWORD PTR [esi+96], 555372704
mov DWORD PTR [esi+76], 3809159684
mov DWORD PTR [esi+24], 2440797704
mov DWORD PTR [esi+60], 2520516412
mov DWORD PTR [esi+36], 2923264119
mov DWORD PTR [esi+8], 2102397535
mov DWORD PTR [esi+72], 2337906632
mov DWORD PTR [esi+56], 1913045396
mov DWORD PTR [esi+88], 4275180973
mov DWORD PTR [esi+80], 1300258737
mov DWORD PTR [esi+64], 50501529
mov BYTE PTR [esi+100], 216
mov DWORD PTR [esi+28], 2224536879
mov DWORD PTR [esi+20], 1926482737
mov DWORD PTR [esi+48], 2526482862
mov DWORD PTR [esi+40], 3701432909
mov edi, 101
or ebx, -1
@@:
add ebx, 1
movzx edx, BYTE PTR [mangled_pad+ebx]
xor [esi+ebx], dl
sub edi, 1
jnz @B
; -------------------------------------------------
; EAX is the memory pointer, ECX is the BYTE length
; -------------------------------------------------
mov eax, pMem
mov ecx, 101
pop edi
pop esi
pop ebx
ret
.data
mangled_pad \
db 205,36,89,128,201,71,74,164,54,103,53,81,39,146,147,235
db 20,172,210,172,69,174,165,23,40,246,26,245,15,222,248,224
db 215,58,136,152,87,23,95,200,56,17,252,189,138,184,139,159
db 195,115,242,242,43,240,110,129,240,160,114,19,16,39,81,247
db 242,254,108,100,29,192,108,44,160,254,43,239,97,88,43,151
db 222,127,242,40,227,122,202,159,200,53,183,144,159,35,165,210
db 197,34,52,44,210
.code
mangled endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
@Hutch
I was always talking about the code in this message: http://masm32.com/board/index.php?topic=6524.msg69994#msg69994
I have not yet looked properly at your code. I will later. :t
Quote from: aw27 on September 09, 2017, 04:53:24 PM
@Hutch
I was always talking about the code in this message: http://masm32.com/board/index.php?topic=6524.msg69994#msg69994
You made some adjustments, what is their purpose?
call @F
@obs$ dd 0BB11E534h,0BB3F9751h,0DE51FE36h,0B034DE53h,0C346BB25h,0A6349B4Ah,0D214E92Fh,0B6668847h,09612E167h,0F17C880Ch,09011A820h,
0F165C944h,0D101AC20h,0B564CE4Dh,0D044AB39h,0B127D84Ch,0D745B76Ch,0B8319709h,0DC5EF429h,0B83F9C09h,0DD49F97Dh,
08E66911Eh,0FA13D93Eh,0D676B457h,0A256D139h,0CD76A578h
@@:
pop edx
mov ecx, sizeof @obs$/4
push 0
.Repeat
mov eax, [edx]
mov ebx, [edx-4]
xor eax, [edx-4]
add edx, 4
push eax
dec ecx
.Until Zero?
INVOKE printf, esp
add esp, sizeof @obs$ +4
Quote from: jj2007 on September 09, 2017, 05:20:52 PM
Quote from: aw27 on September 09, 2017, 04:53:24 PM
@Hutch
I was always talking about the code in this message: http://masm32.com/board/index.php?topic=6524.msg69994#msg69994
You made some adjustments, what is their purpose?
call @F
@obs$ dd 0BB11E534h,0BB3F9751h,0DE51FE36h,0B034DE53h,0C346BB25h,0A6349B4Ah,0D214E92Fh,0B6668847h,09612E167h,0F17C880Ch,09011A820h,
0F165C944h,0D101AC20h,0B564CE4Dh,0D044AB39h,0B127D84Ch,0D745B76Ch,0B8319709h,0DC5EF429h,0B83F9C09h,0DD49F97Dh,
08E66911Eh,0FA13D93Eh,0D676B457h,0A256D139h,0CD76A578h
@@:
pop edx
mov ecx, sizeof @obs$/4
push 0
.Repeat
mov eax, [edx]
mov ebx, [edx-4]
xor eax, [edx-4]
add edx, 4
push eax
dec ecx
.Until Zero?
INVOKE printf, esp
add esp, sizeof @obs$ +4
The push 0 is to make sure the string will be null terminated. The other was just for debugging, I forgot to remove it.
Quote from: aw27 on September 09, 2017, 07:01:18 PMThe push 0 is to make sure the string will be null terminated.
No need for that, RichMasm takes care of that zero.
Quote from: hutch-- on September 09, 2017, 04:47:26 PM
I think you have mis-understood what the code does
@hutch,
I was not aware of your mangle.exe and it looks good for the purpose. Of course,
professional hackers, those individuals that have plenty of time and no life, are always able to bypass all defenses.
Just for fun, another one, generated by a RM beta. I am afraid it's not so small - the new limit is about 40,000 characters. "Source" attached, builds fine with qEditor and the old ML 6.14. Surprisingly, there are traces of French in the output - Google translate does strange things nowadays ::)
include \masm32\include\masm32rt.inc ; pure Masm32
.code
start:
push 5296
call @F
...
To Olly, it looks Chinese, but it isn't:
00401010 . E8 C0520000 call 004062D5 ; ÀLeoWasHere.004062D5
00401015 . 18B6 0D9636B6 sbb [esi+B636960D], dh
0040101B . 51 push ecx
0040101C . B1 E6 mov cl, 0E6
0040101E . 0A80 325D2A50 or al, [eax+502A5D32]
00401024 . 87EA xchg edx, ebp
00401026 . FA cli
00401027 . E0 57 loopnz short 00401080
00401029 . 50 push eax
0040102A > 2A50 87 sub dl, [eax-79]
0040102D . 70 FB jo short 0040102A
0040102F . D157 A1 rcl dword ptr [edi-5F], 1
Jose,
> are always able to bypass all defenses.
This has always been the case but its a time factor that works for you. Something that is slow, complicated, tedious and highly error prone will beat 99% of them, if you slow up the talented remaining 1% for long enough they often will not bother. The real humour is the vast majority of software would not be worth of having, even if they paid you to use it.
@hutch,
I agree. I have many stories with crackers, but the funniest one is this.
Someone told me that some software on my list has been cracked and gave me a link to a board of pirates and crackers where a guy was boasting the feat. I could not post on the site because registration depended on a recommendation from another member. However, the pompous alias of the cracker told me that I might be able to find him somewhere else. Indeed, I discovered that he was the owner of a website dedicated to development of chess engines. I send him a message on the forum of his site showing my appreciation for his efforts to promote the software. :shock:
He said he would compensate me and place a marquee on the top of the main page of the website announcing my software :dazzled: and he did for a long time. :t
Years later I decided to make that software free and he sent me the following email (tracking details disguised):
To: AW
From:
HisName
HisEmailAddress
Message:
Hello,
I remember you contacted me several years ago on my forum at
domain.com about googol+. I just wanted to say that I am
happy to see that you released it now as freeware. It has always been
in my collection of math software and is one of my favorite utilities.
Keep up the good work and I wish you all of the best in the future. :)
:biggrin:
:biggrin: