flat assembler
Message board for the users of flat assembler.

Index > Windows > 'Import' proc.

Author
Thread Post new topic Reply to topic
okasvi



Joined: 18 Aug 2005
Posts: 382
Location: Finland
okasvi 17 Jun 2006, 18:30
Hi, I coded this import-proc for my current project, and it works and all,
But I'd like to hear if you who have better knowledge could say how to optimize(make better in overall) this.

If you like it, feel free to use it Smile

Code:
;__________________             _import
;- okasvi
;ecx=in
;edx=out
_import:
  push  ebp
  mov   ebp, esp
  sub   esp, 4h
  push  ebx edi esi
  mov   esi, ecx
  mov   edi, esi
  mov   ebx, edx
 .import_loop:
  mov   al, byte [esi]
  cmp   al, 0xFF
  je    .import_loadlibrary
  cmp   al, 0xFE
  je    .import_getprocaddr
  cmp   al, 0xFD
  je    .import_done
  inc   esi
  jmp   .import_loop
 .import_loadlibrary:
  mov   byte [esi], 0x00
  inc   esi
;loadlibrary
  push  edi
  call  [LoadLibrary]
  mov   [ebp-4h], eax
  jmp   .import_post
 .import_getprocaddr:
  mov   byte [esi], 0x00
  inc   esi
;getprocaddress
  push  edi
  push  dword [ebp-4h]
  call  [GetProcAddress]
 .import_post:
  mov   [ebx], eax
  add   ebx, 4h
  mov   edi, esi
  jmp   .import_loop
 .import_done:
  pop   ebx edi esi
  mov   esp, ebp
  pop   ebp
  ret    


Code:
;__________________
;example for input
_imports_table:
;kernel32
db 'KERNEL32'           ,0xFF
db 'CopyFileA'                  ,0xFE
db 'CreateProcessA'             ,0xFE
db 'CreateThread'               ,0xFE
db 'CreateRemoteThread'         ,0xFE
db 'ExitProcess'                ,0xFE
db 'GetCurrentProcessId'        ,0xFE
db 'GetEnvironmentVariableA'    ,0xFE
db 'GetModuleFileNameA'         ,0xFE
db 'GetShortPathNameA'          ,0xFE
db 'GetSystemDirectoryA'        ,0xFE
db 'HeapCreate'                 ,0xFE
db 'HeapAlloc'                  ,0xFE
db 'lstrcatA'                   ,0xFE
db 'lstrcmpiA'                  ,0xFE
db 'VirtualAllocEx'             ,0xFE
db 'WaitForSingleObjectEx'      ,0xFE
db 'WinExec'                    ,0xFE
db 'WriteProcessMemory'         ,0xFE
;shell32
db 'SHELL32'            ,0xFF
db 'ShellExecuteA'              ,0xFE
;advapi32
db 'ADVAPI32'           ,0xFF
db 'OpenProcessToken'           ,0xFE
db 'LookupPrivilegeValueA'      ,0xFE
db 'AdjustTokenPrivileges'      ,0xFE
db 'RegQueryValueExA'           ,0xFE
db 'RegOpenKeyExA'              ,0xFE
db 'RegSetValueExA'             ,0xFE
db 'RegCloseKey'                ,0xFE
db 0xFD    


Code:
;__________________
;example for output
_imports:
;kernel32
kernel32                rd 1
CopyFile                rd 1
CreateProcess           rd 1
CreateThread            rd 1
CreateRemoteThread      rd 1
ExitProcess             rd 1
GetCurrentProcessId     rd 1
GetEnvironmentVariable  rd 1
GetModuleFileName       rd 1
GetShortPathName        rd 1
GetSystemDirectory      rd 1
HeapCreate              rd 1
HeapAlloc               rd 1
lstrcat                 rd 1
lstrcmpi                rd 1
VirtualAllocEx          rd 1
WaitForSingleObjectEx   rd 1
WinExec                 rd 1
WriteProcessMemory      rd 1
;shell32
shell32                 rd 1
ShellExecute            rd 1
;advapi32
advapi32                rd 1
OpenProcessToken        rd 1
LookupPrivilegeValue    rd 1
AdjustTokenPrivileges   rd 1
RegQueryValueEx         rd 1
RegOpenKeyEx            rd 1
RegSetValueEx           rd 1
RegCloseKey             rd 1
;__________________    

_________________
When We Ride On Our Enemies
support reverse smileys |:


Last edited by okasvi on 18 Jun 2006, 10:09; edited 1 time in total
Post 17 Jun 2006, 18:30
View user's profile Send private message MSN Messenger Reply with quote
velox



Joined: 06 Jan 2006
Posts: 14
velox 18 Jun 2006, 09:57
hi,

i'm using this snippet for finding api addresses:


Code:
init_apis:
        mov esi,first_dll
        mov edi,esi
imp_loop:
        lodsd
        cmp dword [eax],0 ; reached end?
        jz imp_fin
        cmp byte [eax],0xFF ; is dll?
        jz @F
        jmp getaddr
@@:
        inc eax
        invoke LoadLibrary,eax
        mov ebx,eax
        stosd
        jmp imp_loop
getaddr:
        invoke GetProcAddress,ebx,eax
        stosd
        jmp imp_loop
imp_fin:

        dll1 db 0xFF,'1.DLL',0
        api1 db 'func1',0
        api2 db 'func2',0
        api3 db 'func3',0
        dll2 db 0xFF,'2.DLL',0
        api4 db 'func4',0
        endm dd 0
first_dll:
        _hdll1 dd dll1
        _func1 dd api1
        _func2 dd api2
        _func3 dd api3
        _hdll2 dd dll2  
        _func4 dd api4
        _endmark dd endm    
[/code]
Post 18 Jun 2006, 09:57
View user's profile Send private message Reply with quote
okasvi



Joined: 18 Aug 2005
Posts: 382
Location: Finland
okasvi 18 Jun 2006, 10:08
Really nice, never thought of prefixing DLL, btw. you dont need '.DLL' ending Wink

I just realised that I had few extra instructions left in my proc.
Edited it.


edit: hmm... I thought of using ebx for module handle of library too but my procs cant touch ebx as my calls are really [ebx+SOMESTRUCTURE.Api] so decided to use stack.
Post 18 Jun 2006, 10:08
View user's profile Send private message MSN Messenger Reply with quote
dreamhack



Joined: 02 Jul 2006
Posts: 14
dreamhack 03 Jul 2006, 09:37


Last edited by dreamhack on 16 Jul 2006, 21:59; edited 1 time in total
Post 03 Jul 2006, 09:37
View user's profile Send private message Reply with quote
Reverend



Joined: 24 Aug 2004
Posts: 408
Location: Poland
Reverend 06 Jul 2006, 09:25
Here is the smallest code for getting GetProcAddress address Smile
Code:
;       noimport.asm (c) Northfox, rambo, Reverend
;       52 bytes.

use32

start:

        pop     ecx
        push    ecx

      @@:
        cmp     word [ecx - 1], 'MZ'
        loopnz  @b

        mov     ebp, ecx

        add     ecx, dword [ecx+60]
        mov     eax, dword [ecx+120]
        mov     esi, dword [ebp+eax+28]
        add     esi, ebp
        mov     eax, dword [ebp+eax+32]
        mov     edi, dword [ebp+eax]
        add     edi, ebp

      @@:
        salc

      .1:
        cmp     word [edi], 'cA'
        jz      @f

        scasb
        jnz     .1

        lodsd
        jmp     @b

     @@:
        lodsd
        add     eax, ebp

;       eax - GetProcAddress
;       ebp - kernel32.dll

        ret    
Post 06 Jul 2006, 09:25
View user's profile Send private message Visit poster's website Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 06 Jul 2006, 09:32
Whoa that looks like safe code, Reverend... but I guess it's useful if you're into shellcode >_<
Post 06 Jul 2006, 09:32
View user's profile Send private message Visit poster's website Reply with quote
Reverend



Joined: 24 Aug 2004
Posts: 408
Location: Poland
Reverend 06 Jul 2006, 20:16
The code was heavily tested. I know it may look weird, as instead of PE specific structures there are just constants, but everything works.
Or maybe I misunderstood sth? What did you mean by saying "if you're into shellcode"?
Post 06 Jul 2006, 20:16
View user's profile Send private message Visit poster's website Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 06 Jul 2006, 20:45
Well, one thing is that you're not using PE structures - for my PE protector level1 stub loader I chose to use direct offsets as well (but with comments) - no need to set up structures for stuff that's only used once.

What I mean is that you're only testing for 'cA', which COULD give a false positive some day... and you're not taking into account that GetProcAddress could be forwarded (granted, I've never seen this on an actual system, but if it happens you're screwed majorly).

So well, this code is fine if you're doing 4k intros or shellcode, but I hope nobody would use it for "production" programs.
Post 06 Jul 2006, 20:45
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 06 Jul 2006, 21:06
f0dder: knowledge itself can't be restricted because it can be misused. then all the assembly should be banned Wink
Post 06 Jul 2006, 21:06
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 06 Jul 2006, 21:08
vid wrote:
f0dder: knowledge itself can't be restricted because it can be misused. then all the assembly should be banned Wink


Not saying it should, just saying you should know WHEN to use this kind of code... and especially WHEN NOT Smile

_________________
Image - carpe noctem
Post 06 Jul 2006, 21:08
View user's profile Send private message Visit poster's website Reply with quote
Reverend



Joined: 24 Aug 2004
Posts: 408
Location: Poland
Reverend 07 Jul 2006, 19:54
f0dder: Now I see what you mean. So let me explain. The code I pasted was originally created by Northfox - the creator of MEW exe packer (also the constants instead of PE structures). Rambo and I optimized it.
The trick with 'cA' worked in all tests I made, but of course it's not a perfect solution for all variants.
The forwarding of GetProcAddress is rather impossible. But you are right that a 100% correct loader should take it into account.

But remember, that it was done to be the SMALLEST possible solution. And it's a feature of all most optimized solutions that they work in specific opportunities. It's not a code working in every circumstances

BTW. Is your PE Protector public? I'm interested in the subjects of packers/protectors
Post 07 Jul 2006, 19:54
View user's profile Send private message Visit poster's website Reply with quote
dreamhack



Joined: 02 Jul 2006
Posts: 14
dreamhack 07 Jul 2006, 22:55
that northfox's code is something like using:

mov eax,[esp]
and eax,$FFFF0000
add eax,$1000
@@:
sub eax,$1000
cmp dword[eax],$00905A4D
jnz @b

to get kernel32 'handle'

or

xor esp,esp

to exit the program Wink

by the way, northfox's mew packer rulez Smile
Post 07 Jul 2006, 22:55
View user's profile Send private message Reply with quote
RedGhost



Joined: 18 May 2005
Posts: 443
Location: BC, Canada
RedGhost 08 Jul 2006, 01:29
i use this to hide my imports from anti-cheat clients and etc, works for ordinal/name like GetProcAddress and finds the correct addresses for mixed export tables (had a problem with some winsock lib iirc), also it uses no imports itself allowing for 0 imports on XP, the win2000 loader requires one valid import though

(sorry i wrote it in C)

Code:
unsigned long __stdcall GetProcedureAddress( unsigned long module_base, char *procedure_name ) {
    if( module_base == 0 || (unsigned short *)procedure_name == 0 ) {
        return 0;
    }

    IMAGE_DOS_HEADER *idh;
    IMAGE_NT_HEADERS *inth;
    IMAGE_EXPORT_DIRECTORY *ied;
    unsigned long *export_addresses_table;
    unsigned short *export_ordinals_table;

    idh = (IMAGE_DOS_HEADER *)module_base;
    
    if( idh->e_magic != IMAGE_DOS_SIGNATURE ) {
        return 0;
    }

    inth = (IMAGE_NT_HEADERS *)( module_base+idh->e_lfanew );
    
    if( inth->Signature != IMAGE_NT_SIGNATURE ) {
        return 0;
    }

    ied = (IMAGE_EXPORT_DIRECTORY *)( module_base+inth->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress );

    export_ordinals_table = (unsigned short *)( module_base+ied->AddressOfNameOrdinals );
    export_addresses_table = (unsigned long *)( module_base+ied->AddressOfFunctions ); 

    if( (unsigned short)( (unsigned long)procedure_name >> 16 ) == 0 ) {
        goto _ordinal;
    } 
    
    unsigned long *export_names_table = (unsigned long *)( module_base+ied->AddressOfNames ); 
 
    for( short i = 0; i < ied->NumberOfNames; i++ ) {
        if( strcmp( (char *)( export_names_table[ i ]+module_base ), procedure_name ) == 0 ) {              
            //use ordinal not loop counter to get proper address on mixed export tables
            return (unsigned long)( module_base+export_addresses_table[ (unsigned short)( module_base+export_ordinals_table[ i ] ) ] ); 
        }          
    }

    return 0;

_ordinal: 
    for( short i = 0; i < ied->NumberOfFunctions; i++ ) {
        if( (unsigned short)( export_ordinals_table[ i ]+module_base ) == (unsigned short)( (unsigned long)procedure_name & 0xFFFF ) ) {   
            return (unsigned long)( module_base+export_addresses_table[ (unsigned short)( module_base+export_ordinals_table[ i-1 ] ) ] ); 
        }          
    }

    return 0;
}
//---
    

_________________
redghost.ca
Post 08 Jul 2006, 01:29
View user's profile Send private message AIM Address MSN Messenger Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 08 Jul 2006, 11:36
Reverend wrote:

BTW. Is your PE Protector public? I'm interested in the subjects of packers/protectors


No, sorry - and the sources are currently in a state where I don't even know if it'll compile :/ - haven't worked on it for ~4 years or so.

_________________
Image - carpe noctem
Post 08 Jul 2006, 11:36
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.