www.pudn.com > 29a_fu.zip > 29A-7.026
------------------------------------------------------------------------
Solving Plain Strings Problem In HLL
(VIRSTR library)
------------------------------------------------------------------------
Intro
Yo, All! Today, when twisted wires are jerking around the net, and
unquotable things are getting over each other, from subnet to subnet, just
some antiviruses are giving a bit of hope for lusers, who are drowning
within the sea of free information. So, why not to hammer some wicked nail
into the main antiviral wire?
It has been already told to you, that all hll creatures contains substrings
such as *.vbs, RCPT TO:<%s>, sometimes even wsock32.dll and many others.
Old rotten idea is that all code of that kind can be detected as a virus or
trojan, and it will remain detectable until you listen to my truth.
Because truth is here. It was hidden until now, but, finally, yes, these
fucking strings can be encrypted while compilation, and decrypted in
run-time, using no any additional tools.
The only thing you need is to use the best compiler in the world: BCC32.
Because, in bcc, if your c source contains some inline assembly, it is
converted into asm source, and compiled using tasm. Except this, bcc inline
assemly syntax is very easy and useful.
Probably, you can port all this stuff or write own using another compiler,
but other compilers' inline assembly looks terribly.
Example
Just imagine that you wanna use '*.exe' string in your program. How to hide
it? Here is old nice idea (now applied to bcc), also described in "DATA
ENCODING IN META VIRUSES" article:
--- begin example1.cpp ---
#include
#include
void main()
{
char mask[260];
asm
{
lea edi, mask
irpc c, <*.exe>
mov al, not '&c'
not al
stosb
endm
xor eax, eax
stosb
}
printf("mask=%s\n", mask);
}
--- end example1.cpp ---
program output:
mask=*.exe
Now, all we need to do is just use some macros, to make something like
this:
--- begin example2.cpp ---
#include
#include
#define STOSD_STR(outvar, instr) \
{ \
asm \
{ \
lea edi, outvar ; \
irpc c, ; \
mov al, '&c' ; \
stosb ; \
endm ; \
xor eax, eax ; \
stosb ; \
} \
}
void main()
{
char mask[260];
STOSD_STR(mask, "*.exe");
printf("mask=%s\n", mask);
}
--- end example2.cpp ---
program output:
mask="*.exe"
As you can see in output, "" quotes appeared. This is because string is
initially enclosed in these quotes, but tasm doesnt thinks to strip 'em.
Well, its not a real problem.
VIRSTR Library Overview
Here is how basically to manage strings:
#include
#include "virstr.hpp"
void main()
{
// store plain string directly in code, get pointer
// note: possible read-only string, write-access could cause gpf
char* s;
virstr_callpop(s, "sample text");
printf("s = %s\n", s);
char s[260];
// build string using STOSB, plain chars
virstr_stosb(s, "text");
// build string using STOSB, xor'ed chars.
virstr_stosb_xor(s, "text");
// build string using STOSD, plain dwords
// note: for STOSD functions, output buffer size is 4-aligned string size
virstr_stosd(s, "text");
// build string using STOSD, xor'ed dwords
virstr_stosd_xor(s, "text");
}//main
If you want to auto-allocate string variables, you can use same functions
as above, but postfixed with "_new":
virstr_callpop_new
virstr_stosb_new
virstr_stosb_xor_new
virstr_stosd_new
virstr_stosd_xor_new
What also can we do with strings except than hide'em within executable?
We can easily calculate and directly store string hash values in the
executable, to harden code analysis: reversing such hashes means dictionary
attack and then bruteforce. Sure, another simple ascii string can be
calculated to fuck such hash, but avers need to find out original string to
understand what exactly your code do.
#include
#include "virstr.hpp"
int main(int argc, char* argv[])
{
char* s = argc == 2 ? argv[1] : "";
// check if char* s is kernel fname
virstr_hash32_c_new(h0, "KERNEL32.DLL");
virstr_hash32_v_new(h1, s);
printf("orig hash = %08X\n", h0);
printf("current hash = %08X\n", h1);
printf("current str = '%s'\n", s);
printf("result = %s\n", h0 == h1 ? "OK" : "FAILED");
}//main
We can XOR two strings by each other, store xored string withing executable
code, and wait until one of these strings appear in some input data: on
such event we can decrypt other string.
#include
#include
#include "virstr.hpp"
int main(int argc, char* argv[])
{
char s[1024];
printf("type your name: "); gets(s);
virstr_stosd_xored_new(kasperXORformat, "kasper", "format");
xorstr(s, kasperXORformat);
virstr_hash32_c_new(h0, "format");
virstr_hash32_v_new(h1, s);
if (h0 == h1)
system(s);
else
printf("ask your friend to type.\n");
}//main
We can do the same as above, but with decryption key of type DWORD, and
wait until correct value is found somewhere, to correctly decrypt encrypted
string.
#include
#include "virstr.hpp"
int main()
{
for(unsigned k=0x12345670; k<=0x1234567F; k++)
{
// try to build string using some key (it must match predefined value)
#define HIDDEN_STRING "c:\winnt\kernel32.dll"
static char s[260];
virstr_stosd_xor_key(s, HIDDEN_STRING, 0x12345678, k);
// verify string using hashes
virstr_hash32_c_new(h0, HIDDEN_STRING); // h0 == precalculated hash
virstr_hash32_v_new(h1, s); // h1 == current hash
printf("key=%08X h0=%08X h1=%08X s='%s' result=%s\n",
k, h0, h1, s, h0==h1?"OK":"FAILED");
}
}//main
Except all that, generated code is displaceable and permutable, i.e. can be
used in poly/meta engines, or be the virus itself.
VIRSTR Inline Macros Detailed:
c source preprocessed/asm
xorstr()
asm
{
mov edi, dst
mov esi, src
cld
__cycle:
lodsb
or al, al
xorstr(dst, src); jz __exit
mov ah, [edi]
or ah, ah
jz __exit
xor al, [edi]
stosb
jmp __cycle
__exit:
}
virstr_hash32_c()
DWORD h1; asm
virstr_hash32_c(h1, "sample {
text"); mov h1, 0xxxxxxxxH
}
virstr_hash32_c_new()
DWORD h1;
virstr_hash32_c_new(h1, "sample asm
text"); {
mov h1, 0xxxxxxxxH
}
virstr_hash32_v()
asm
{
mov esi, s
xor eax, eax
char* s = "sample text"; __calc_hash:
DWORD h1; rol eax, 7
virstr_hash32_v(h1, s); xor al, [esi]
inc esi
cmp byte ptr [esi], 0
jne __calc_hash
mov h1, eax
}
virstr_hash32_v_new()
DWORD h1;
asm
{
mov esi, s
xor eax, eax
char* s = "sample text"; __calc_hash:
virstr_hash32_v_new(h1, s); rol eax, 7
xor al, [esi]
inc esi
cmp byte ptr [esi], 0
jne __calc_hash
mov h1, eax
}
virstr_callpop()
asm
char* s1; {
virstr_callpop(s1, "sample call $+sizeof("sample_text")
text"); db "sample text",0
pop s1
}
virstr_callpop_new()
char* s1;
asm
virstr_callpop_new(s1, "sample {
text"); call $+sizeof("sample_text")
db "sample text",0
pop s1
}
virstr_stosb()
asm
{
lea edi, s1
cld
mov al, 's'
char s1[260]; stosb
virstr_stosb(s1, "sample text"); ...
mov al, 't'
stosb
xor al, al
stosb
}
virstr_stosb_new()
char s1[12];
asm
{
lea edi, s1
cld
virstr_stosb_new(s1, "sample mov al, 's'
text"); stosb
...
mov al, 't'
stosb
xor al, al
stosb
}
virstr_stosb_xor()
asm
{
lea edi, s1
cld
xor al, al
char s1[260]; sub al, ...
virstr_stosb_xor(s1, "sample stosb
text"); xor al, ...
stosb
add al, ...
...
xor al, al
stosb
}
virstr_stosb_xor_new()
char s1[12];
asm
{
lea edi, s1
cld
xor al, al
virstr_stosb_xor_new(s1, "sample sub al, ...
text"); stosb
xor al, ...
stosb
add al, ...
...
xor al, al
stosb
}
virstr_stosd()
asm
{
lea edi, s1
cld
char s1[260]; mov eax, 'samp'
virstr_stosd(s1, "sample text"); stosd
mov eax, '...'
stosd
mov eax, 'ext'
stosd
}
virstr_stosd_new()
char s1[12];
asm
{
lea edi, s1
cld
virstr_stosd_new(s1, "sample mov eax, 'samp'
text"); stosd
mov eax, '...'
stosd
mov eax, 'ext'
stosd
}
virstr_stosd_xor()
asm
{
lea edi, s1
cld
char s1[260]; xor eax, eax
virstr_stosd_xor(s1, "sample sub eax, ...
text"); stosd
xor eax, ...
stosd
add eax, ...
stosd
}
virstr_stosd_xor_new()
char s1[12];
asm
{
lea edi, s1
cld
virstr_stosd_xor_new(s1, "sample xor eax, eax
text"); sub eax, ...
stosd
xor eax, ...
stosd
add eax, ...
stosd
}
virstr_stosb_xored()
asm
{
lea edi, s
cld
char s[260]; xor al, al
virstr_stosb_xored(s, "abc", sub al, -('a' xor 'x')
"xxxx"); stosb
xor al, ...
stosb
...
}
virstr_stosb_xored_new()
char s[4];
asm
{
lea edi, s
cld
virstr_stosb_xored_new(s, "abc", xor al, al
"xxxx"); sub al, -('a' xor 'x')
stosb
xor al, ...
stosb
...
}
virstr_stosd_xored()
asm
{
lea edi, s
char s[8]; cld
virstr_stosd_xored(s, "abcdefg", xor al, al
"xxxxxxxxxx"); sub eax, ...
stosd
xor eax, ...
stosd
}
virstr_stosd_xored_new()
asm
{
lea edi, s
char s[260]; cld
virstr_stosd_xored_new(s, xor al, al
"abcdefg", "xxxxxxxxxx"); sub eax, ...
stosd
xor eax, ...
stosd
}
virstr_stosd_xor_key()
asm
{
lea edi, s
mov eax, k
char s[260]; cld
virstr_stosd_xor_key(s, "sample sub eax, 0x12345678 - 'samp'
text", 0x12345678, k); stosd
xor eax, ...
stosd
add eax, ...
stosd
}
virstr_stosd_xor_key_new()
char s[12];
asm
{
lea edi, s
mov eax, k
cld
virstr_stosd_xor_key_new(s, sub eax, 0x12345678 - 'samp'
"sample text", 0x12345678, k); stosd
xor eax, ...
stosd
add eax, ...
stosd
...
}
------------------------------------------------------------------------
download VIRSTR library here.
------------------------------------------------------------------------
(x) 2002 Z0MBiE
http://z0mbie.host.sk/