Something that is technically simple to do is store text directly into stack memory, its just a pain to have the reverse the text order in 4 byte blocks and you must correct the stack when you have finished.
It is useful to increase the workload of anyone who wants to open a binary file and hack the string data and while someone who knows what they are doing can work it out, it is still no joy to alter and it is time consuming to do. It becomes a lot messier to change if you interleave the pushes between other procedure calls and the pushes of the string data and te arguments for the procedure calls are harder to seperate.
The following displays "Copyright (c) The MAS32 Project 1998-2005"
push 0
push " 50"
push "02-8"
push "991 "
push "tcej"
push "orP "
push "23MS"
push "AM e"
push "hT )"
push "c( t"
push "hgir"
push "ypoC"
mov ecx, esp ; save esp in another register
fn MessageBox,0,ecx,"Notice",MB_OK
add esp, 48
At its simplest as above its easy to change but interleave it and it becomes a mess to alter.
TRUE CONFESSION : This was a task to wind my head down after midnight, I have been meaning to do one of these for a long time but never got around to it.
[attachment deleted by admin]
Sorry, could not resist.....
SafeMsgA PROC
push 0FFFFFFFFh
push 0DFDFCACFh
push 0CFCDD2C7h
push 0C6C6CEDFh
push 08B9C9A95h
push 0908DAFDFh
push 0CDCCB2ACh
push 0BEB2DF9Ah
push 097ABDFD6h
push 09CD7DF8Bh
push 09798968Dh
push 0868F90BCh
mov ecx,esp
mov edx,44
@@: not DWORD PTR [ecx+edx]
sub edx,4
jns @B
fn MessageBox,0,ecx,"Notice",MB_OK
add esp,48
ret
SafeMsgA EndP
...and this one to create copy'n'paste code:
NotStrA Proc
;-- Just a tool to generate code for SafeMsgA
;-- Should not be placed in final code :-)
Local tmp:DWORD
jmp @F
.DATA
szMsg DB "Copyright (c) The MASM32 Project 1998-2005 ",0,0,0,0
.CODE
@@: push ebx
lea ebx,szMsg
invoke StrLen,ebx
mov edx,eax
and dl,0FCh
sub edx,eax
jz @F
and al,0FCh
add al,4
@@: push eax
mov ecx,eax
@@: push ecx
mov edx,[ebx+ecx]
not edx
mov tmp,edx
print SADD(" push 0",0)
print uhex$(tmp)
print SADD("h",0)
print ADDR CRLF
pop ecx
sub ecx,4
jns @B
print SADD(13,10," mov ecx,esp",13,10,13,10,0)
print SADD(" mov edx,",0)
mov eax,[esp]
print ustr$(eax)
print SADD(13,10,"@@: not DWORD PTR [ecx+edx]",13,10,0)
print SADD(" sub edx,4",13,10,0)
print SADD(" jns @B",13,10,13,10,0)
print SADD(" fn MessageBox,0,ecx,",22h,"Notice",22h,",MB_OK",13,10,13,10,0)
print SADD(" add esp,",0)
pop eax
add eax,4
print ustr$(eax)
print SADD(13,10," ret",13,10,0)
pop ebx
ret
NotStrA EndP
Lousy code, I know but seems to work. :lol
[attachment deleted by admin]
Phoenix,
It looks like a piece of genius. :U
I used the stack string method in my GetProcOffset (http://www.masmforum.com/simple/index.php?topic=1144.0) - functions, where i had to make a null-terminated copy of the forwarder module. A lot better, than reserving 512 bytes of local space for a string, that length is not known.
Nice work guys, i find this very useful :U
Phoenix,
That looks very nice. I have always done something similar. The way I did it was by using XOR. I did not use the stack, though. I used a memory block and kept the pointer into the block in another variable. This allowed for very cool interleaving. I had instructions strewn throughout the code. What they did was get the pointer into the block, do an XOR with a predetermined value and store the result into the same address, update the block pointer and go back to sleep. I would eventually have a decoded string.
Another method I used that is probably simpler is to use is to take another string of the same size as the data to hide and use an encoding program to XOR the two strings together. I would then store the result in a data block and also store the encoder string in the program, also. Then, somewhere in the program, I would XOR the two together and write the result in a block so it can be displayed.
Paul E. Brennick.
Type /h for Help
I would XOR the two together. If someone uses a hex editor to view the file all they will see is 'Type /h for Help' and will not play with that. Misdirection and hiding the ASCII, pretty cool, don't you think?
Paul
hutch--,
Thanks a lot... :red
PBrennick,
Both ways you described are very good hiding the ASCII. XORing the string is the way i protect the Admin password of database applications (VB) using quite harmless looking strings like "Windows" or something like this as key...
hutch--'s idea of using the stack is a special way that is quite easy to use in ASM, and perhaps it would be a good idea to use a combination of both methods -- i'd like to see the workload of someone who tries to decode the ASCII that is protected by XOR with a key, NOT and placed in the stack!! :toothy The only thing to do is to change the proc that creates copy'n'paste code to reduce our workload, I'll give it a try.
Regards, Joerg
This is the variation mentioned above:
SafeMsgA Proc
push 0A90580CCh
push 08925B5FCh
push 09937ADF4h
push 0903CB1ECh
push 0DD66E5A6h
push 0C677D0ECh
push 09B36CD9Fh
push 0E848A0A9h
push 0C151A0E5h
push 0CA2DA0B8h
push 0C162E9BEh
push 0D075EF8Fh
mov ecx,esp
mov edx,44
@@: not DWORD PTR [ecx+edx]
sub edx,4
jns @B
mov ecx,esp
mov edx,44
@@: xor DWORD PTR [ecx+edx],056FA7F33h
sub edx,4
jns @B
fn MessageBox,0,ecx,"Notice",MB_OK
add esp,48
ret
SafeMsgA EndP
I think it is a good idea to do the decoding in different places, if you interleave it between other procedure calls.
This is the source for copy'n'paste code:
XorNotStrA Proc
Local tmp:DWORD
jmp @F
.DATA
szMsgA DB "Copyright (c) The MASM32 Project 1998-2005 ",0,0,0,0
dwKey DWORD 056fa7f33h
.CODE
@@: push ebx
lea ebx,szMsgA
invoke StrLen,ebx
mov edx,eax
and dl,0FCh
sub edx,eax
jz @F
and al,0FCh
add al,4
@@: push eax
mov ecx,eax
@@: push ecx
mov edx,[ebx+ecx]
xor edx,dwKey
not edx
mov tmp,edx
print SADD(" push 0",0)
print uhex$(tmp)
print SADD("h",0)
print ADDR CRLF
pop ecx
sub ecx,4
jns @B
print SADD(13,10," mov ecx,esp",13,10,0)
print SADD(" mov edx,",0)
mov eax,[esp]
print ustr$(eax)
print SADD(13,10,"@@: not DWORD PTR [ecx+edx]",13,10,0)
print SADD(" sub edx,4",13,10,0)
print SADD(" jns @B",13,10,13,10,0)
print SADD(" mov ecx,esp",13,10,0)
print SADD(" mov edx,",0)
mov eax,[esp]
print ustr$(eax)
print SADD(13,10,"@@: xor DWORD PTR [ecx+edx],0")
print uhex$(dwKey)
print SADD("h",13,10,0)
print SADD(" sub edx,4",13,10,0)
print SADD(" jns @B",13,10,13,10,0)
print SADD(" fn MessageBox,0,ecx,",22h,"Notice",22h,",MB_OK",13,10,13,10,0)
print SADD(" add esp,",0)
pop eax
add eax,4
print ustr$(eax)
print SADD(13,10," ret",13,10,0)
pop ebx
ret
XorNotStrA EndP
The key is only four bytes but i guess that does not matter... what do you think?
[attachment deleted by admin]
Phoenix, this is a very nice implementation to hide a sensitive string, but don't rely on that.
Reversers can obtain that string more or less easy, depending on what the string is used (password, refrence to a key file, etc), and using so to say "specific" methods :P
Anyway, nice work :wink
Ghirai,
Easy, perhaps, you are a smart guy? Just as a fun little test, I have a program that encrypts/decrypts files. It uses an XOR algorythm. It was written in 1990 using MASM 5.1 and it still remains in its original form today. I keep toying with the idea of changing it to a win32 application. Anyway, how about I encode a file and you decode it? Might be fun and we can see how easy it is to do. I suspect my part of the job will be easier. :U
Paul
Possibly, thought xor encryption is not very difficult, i'm no cryptographer.
I was referring to the fact that you use design features of the target application to obtain that string (messageboxes saying pw is wrong, bpx on GetDlgItemTexta, bpx on WM_GETTEXT, to list a few basics).
Those deisgn features are not implemented in your app, where you probably feed a password string, it performs an algo on a text file, and you can only tell that the password was wrong when the output text is garbage.
Though i have some experience at reading code dumps in general, and understanding some routines in particular, i doubt i can recreate your algo, and be able to decrypt your file... :P
Ghirai,
No problem, just thought it would be fun. It uses a progressive multipass encryption technology that employs an XOR algorythm. It also uses pattern overlays. Trust me, it is not easy. If anyone wants the source just say so.
Paul
Interestingly enough, its not the XOR part thats the problem, its the uniqueness of the pad that makes or breaks very powerful encryption. You can use ROL or ROR just as easily if you have a highly unique and ramdom pad to modify the string with. In the context of xorring a string to obscrure it, picking a piece of the code section would probably be the safest way to do it as it is usually dense binary with a wide range of characters in it. You stay away from areas that are full of zeros as this leaves the text in plain text form.
A good target would be the code section of a DLL that the exe uses as it will not change as the exe is changed to process the xorring.
Nice trick :U
Here's a similar one I knew of, but not as good:
call @F
db "This is the string",0
@@: pop eax
invoke MessageBox, hWnd, eax, eax, MB_OK
As for the XOR thing, please let me be picky for a moment ;) and say that any such algorithm is not encription, but encoding. So by definition it's not really safe - in fact XORed strings are trivially broken, there are programs that do it automatically. It does hide things from the average script kiddie though. :)
QvasiModo ,
XOR by itself is very weak, a friend of mine made a toy that automated the 256 combinations so it was very easy to decode it Where it becomes useful is when the text is xorred against a random pad of the same length where instead of it being broken in 256 combinations, there is the same statistical probability for every character.
The only weakness I know about with random pads is that occasionally you get a bit of plain txt showing though and this would justify using one of the simple block cyphers first just to mess up the character order.
Hutch,
That is correct and is the reason I use pattern overlays, just another term for what you are talking about. One of the things XOR encoding is useful for and was necessary in some of my jobs was after the data was unencrypted by the master cypher it was now in a position to be decoded after having been encoded by several people. In other words, each person would encode the data using their own private key (similar to logging in) and then the master encryption is performed. Using this method, it required several people to unlock the data (this was something THEY required). The point is, using the XOR encoding/decoding method, the result is not 'order dependant' which means the data could be encoded by users in the sequence of A,B,C,D but the decoding did not need to be D,C,B,A and could, in fact be in any order. This was VERY important because people are people and an order driven encoding using any other method would yield incomprehensible garbage if the decoding order was not rigidly followed. After losing one database, I decided to find a way that prevented this possible loss and XOR pattern encoding/decoding was the answer and in an environment where there are multiple encodings (these are pattern overlays) is going on, it is not easily broken. It was always broken using Cray computers with a lot of processing overhead but passed a certain level of difficulty that was established by the client.
People can say all they want about this is easily broken but as I said before in this thread, how about I encode a file and they decode it? I bet I don't get any takers.
Paul
M xor A xor B xor C xor D = M xor K
(where K is a single key = A xor B xor C xor D)
In other words, you only need to figure out one suitable key to be able to decrypt, not four.
And finding the key for encrypted plain english text is not as difficult as it might seem, as long as the key is some length shorter than the message ie. allows for a few repeats; without any repeats it's equivalent to a one-time pad, which is theoretically unbreakable.