I found this code while browsing through the examples that come with the masm32 package.

; =======================================
; NO_IMPORT by mob aka drcmda
; this program demonstrates how to write
; portable code... this code could be
; added to other executables with no prob.
; i'm over that virus shit so don't waste
; your time... i'm working on something
; like a executable patcher right now so
; portable code was very interesting for
; me...................................
; if you want to use other apis or other
; dll's then use this structure:
;
; 00      db ?? ;lenght of name
; 01 - ?? db ?? ;API name
; ??      dd ?? ;pointer
;
; then use 'GetApis' to find their
; pointers so you don't have to search
; the pointers with GetModuleHandle
; write to drcmda@gmx.de
; =======================================

; ---------------------------------------------------
; Build with MAKEIT.BAT to merge the .text and .data
; sections. Result is a 1024 byte length EXE file.
; ---------------------------------------------------

.486
.Model      Flat, Stdcall
Option      Casemap:None

.Data

; kernel32.dll api's
___Kernel32        db 14,"GetProcAddress"
_Getprocaddress    dd 0
                    db 11,"LoadLibrary"
_Loadlibrary        dd 0
                    db 11,"ExitProcess"
_Exitprocess        dd 0

; user32.dll api's
___User32          db 11,"MessageBeep"
_Messagebeep        dd 0
                    db 10,"MessageBox"
_MessageBox        dd 0                   

_Kernel            Dd 0
_User32            db "USER32",0
_Default            Dd 0 

.Code     
   
Start:
            Call    Delta
Delta:
            Pop    Ebp                                ; get deltaofs   
            Sub    Ebp,Offset Delta                    ; for portability       
           
            Call    Get_Kernel                          ; get kernel base/set default
           
            Push    3                                  ; 3 api's in the kernel32 struc
            pop    Ecx
            Lea    Esi,                                         
            Call    Get_Apis                            ; get kernel apis
                     
            Lea    Eax,            ; load user32.dll
            Push    Eax
            Call               
           
            test    Eax,Eax
            jz      Error_Exit

            Mov    ,Eax          ; store result in 'default'

            push    2                                  ; 4 api's in the user32 struc
            pop    Ecx
            Lea    Esi,                                          
            Call    Get_Apis                            ; get user32 apis         
                                 
            Push    -1
            Call                      ; beep
           
            Push    0
            Call    _t02
            db      "little test",0
_t02:      Call    _t01
            db      "MessageBox without imports, funny eh?",0
_t01:      Push    0
            Call                      ; messagebox

Error_Exit:                               
            Push    0
            Call                      ; get out


; ######################## get kernel ########################
; returns kernelbase and stores it in 'default' and 'kernel'
Get_Kernel:
            Mov    Ecx, ; get kerneladdr from stack
           
Kernel_Loop:
            Xor    Edx,Edx
            Dec    Ecx
            Mov    Dx,
            Test    Dx,0F800H
            Jnz    Kernel_Loop
            Cmp    Ecx,
            Jnz    Kernel_Loop           
            Mov    ,Ecx
            Mov    ,Ecx                                           
            Ret

; ######################## get apis  ########################
; default  = dll base
; ecx      = number of api's in the structure
; esi      = pointer to structure
Get_Apis: 
            Xor    Ebx,Ebx
Api_Loop:
            Inc    Esi        ; scan through the api
            Push    Ecx        ; table and try to
            Movzx  ecx, byte ptr ; addresses...               
            Push    Ecx
            Call    Get_Api
            Pop    Ebx
            Pop    Ecx
            Add    Esi,Ebx           
            Mov    ,Eax
            Add    Esi,4
            Loop    Api_Loop
            Ret     

; ######################## get api    ########################
; default = dll base
; ecx    = structure entry
Get_Api: 
            Mov    Edx,
            Add    Edx, ; get default module       
            Mov    Edx,
            Add    Edx,

            Mov    Edi, ;Get Addrofnames
            Add    Edi,
            Mov    Edi, ;Get Addrofnames
            Add    Edi,
            Mov    Eax, ;Get Numberofnames                                 
            Xor    Ebx,Ebx
Next_One:           
            Push    Ecx
            Inc    Ebx         
            Push    Esi
            Push    Edi
            Repz    Cmpsb ; compare api with export
            Pop    Edi
            Pop    Esi
            Jnz    Not_Found           
            Pop    Ecx
            Mov    Ecx, ;Get Addrnameord
            Add    Ecx,
            Dec    Ebx
            Movzx  eax, word ptr                        
            Mov    Ebx, ;Get Addroffunctions
            Add    Ebx,
            Mov    Eax,                
            Add    Eax,
            Ret
Not_Found: 
            Dec    Edi           
Loop_1:
            Inc    Edi
            Cmp    Byte Ptr ,0
            Jnz    Loop_1

            Inc    Edi           
            Dec    Eax
            Jz      Exit_Search           
            Pop    Ecx
            Jmp    Next_One
Exit_Search: 
            Jmp    Error_Exit
            Ret                       
       
End        Start

The problem is that i have some problems understanding it.Although I know about the PE file structure and this program is just getting the handle for the api from the dll handling that api.But still there is some consusion.
can somebody please give some hint.
Posted on 2007-10-16 07:58:36 by shakuni
Gee, that code looks familiar.

This kind of code verges on breaching our Rules.
Please don't post this sort of code here again, at least not as a complete unit.
If you must, quote a few lines, ask specific questions, one at a time.
Don't expect anyone to explain the complete sourcecode to you.
You can get help, we just don't want to encourage (or be seen to encourage) malicious code and/or malicious coders.

Posted on 2007-10-16 10:11:09 by Homer
Sir
this code is NOT malicious(if it's malicious why it is distributed with the masm7 package that I downloaded a few months back).
it just displays a message box and nothing else but it does this WITHOUT importing any libraries and that is what I want to understand.
What I understand about this code is that it find out the address of the message box api in the place where dll is loaded when the OS is loaded,but I don't understand that how this code finds the address where the dll is loaded.So just point out to me how THAT part of code works.
Posted on 2007-10-16 10:56:24 by shakuni

Sir
this code is NOT malicious(if it's malicious why it is distributed with the masm7 package that I downloaded a few months back).


That is not saying much. The legality of the package itself is questionable, at best.


it just displays a message box and nothing else but it does this WITHOUT importing any libraries and that is what I want to understand.


On that point I would not consider it malicious. However, please do adhere to Homer's warning and don't post whole chunks of code like that when it obviously originates from a current/former malware developer.

Search engines are fickle creatures ;)


What I understand about this code is that it find out the address of the message box api in the place where dll is loaded when the OS is loaded,but I don't understand that how this code finds the address where the dll is loaded.So just point out to me how THAT part of code works.


You'll need intimate knowledge of the Portable Executable format to understand what is going on here. The code is using the base address of the program itself to find the hard-coded import locations... which is actually not an entirely accurate explanation... but it should point you in the right direction.

FYI: That code method will probably be tagged by any decent anti-virus software, since there is a good deal of malware-based methods being utilized. If you really want to do a Library-less call in ASM, look into INT 0x2E and the Windows System Call mechanism :)
Posted on 2007-10-16 11:40:46 by SpooK
shakuni,

You are right that the code is not malicious, the problem is that this code uses a technique that borders on the edge of malicious coding. "Portable coding" is very rarely used in anything other than viruses or shellcode, both of which are against the rules of this forum. There are legitimate uses but too few to overlook malicious ones. If you read the comment, Mob even states what he was using this code in relation to, "i'm working on something like a executable patcher right now so portable code was very interesting for me". This would fall under reverse engineering and is also not allowed. This is why Homer asked for you not to post the complete source here again. Mob was a well known virus/trojan author and as for why hutch decided to include code by him in his package I can't answer that, you'd have to ask him.

Regards,
Bryant Keller
Posted on 2007-10-16 11:48:57 by Synfire
The method for finding the functions consists in getting KERNEL32.DLL address from the stack (the return address), and later doing some memory traversing to find out where the kernel32's export table is located and take LoadLibrary address from there.

Note however that this method is unreliable, Windows 2000 needs KERNEL32.DLL imported directly or indirectly by another API that you import from the import table, otherwise the EXE is not executed at all. This method actually is ancient, I can't remember where I see it the first time (iczelion?). Well, there is a difference with the method I saw, while your example seems to get all addressess on its own, the other just used it to get LoadLibary&GetProcAddress but this one abuses the fact that the instance returned by LoadLibrary is in fact a pointer to the loaded library location.

PS: Sorry SpooK, I'm repeating you in some aspects but to lazy to edit :P. BTW, what slow I am today :S "Warning - while you were typing 2 new replies have been posted. You may wish to review your post."
Posted on 2007-10-16 11:57:18 by LocoDelAssembly
Please don't post this sort of code here again, at least not as a complete unit.

I am sorry to post the whole code,I'll not do it again.

This kind of code verges on breaching our Rules.

the problem is that this code uses a technique that borders on the edge of malicious coding.

Regarding the malicious background of the author and his code,I did'nt knew about it.
Next time I will do proper research before posting anything.

"Portable coding"

Sir,Can you please tell me more abut this?I've been reading that assembly language is NOT portable.

This method actually is ancient

Sir,What are the "new" methods of writing "portable" assembly code?

there is a difference with the method I saw

Sir,Can you please tell me what was the other methods?

Sorry for so much questioning,but please try to understand my situation because I am still in the learning phase.
Posted on 2007-10-16 12:55:14 by shakuni
Don't know what new methods are available, I just said that trick was published long time ago (the variation I saw at least).

About portability (I talked about it apart of the Windows 2000 remark?), the problem with this method is that is not reliable across Windows versions (here the loss of portability comes). ASM is not portable, but by using these technics you are making your executable even less portable while executables that imports "in the right way"TM works on more versions and even in future versions (unless Microsoft decide in future to break compatibility with software designed for earlier versions of Windows).

To sumarize, this method is not documented by Microsoft and hence you have no warranties that it will work OK always. Import APIs in the usual way. If you use fasm, by just doing
include 'win32ax.inc'

.code
start:
  invoke MessageBox, 0, "Hello", "Hello", 0
  invoke ExitProcess, 0

.end start 

Automatically builds the import table for you. You can use a sightly lower level if you want or really constructing your import table by yourself, check the examples inside the package.
Posted on 2007-10-16 13:25:54 by LocoDelAssembly
The fix for win2k systems (assuming you can detect the OS without any api, which I can) is, as sp00k suggested, to use an int 2e call to get k32 loaded, and then everything is peachy.
Again, the key here is the ability to detect which OS the code is running on WITHOUT using any api.
Posted on 2007-10-23 00:23:36 by Homer
What's the point in no-imports-whatever, anyway? You need to import (or end up importing) from kernel32, otherwise your app will silently fail to load on win2k.

Using int2e/syscall doesn't sound like a too great idea to me either, there's no guarantee that syscall numbers won't be swapped around on a service pack or whatever.
Posted on 2007-10-23 03:40:45 by f0dder

What's the point in no-imports-whatever, anyway? You need to import (or end up importing) from kernel32, otherwise your app will silently fail to load on win2k.

Using int2e/syscall doesn't sound like a too great idea to me either, there's no guarantee that syscall numbers won't be swapped around on a service pack or whatever.



That's the whole point of having such DLL wrappers :P
Posted on 2007-10-23 13:34:06 by SpooK


What's the point in no-imports-whatever, anyway? You need to import (or end up importing) from kernel32, otherwise your app will silently fail to load on win2k.

Using int2e/syscall doesn't sound like a too great idea to me either, there's no guarantee that syscall numbers won't be swapped around on a service pack or whatever.



That's the whole point of having such DLL wrappers :P

Exactly - and using them :)
Posted on 2007-10-24 06:22:32 by f0dder
Again, the key here is the ability to detect which OS the code is running on WITHOUT using any api.


To detect NT based systems (ignoring NT4 you will get 2K+)

fs mov eax, [18h] ; Test for NT
cmp eax, 7FFDE000h
setne B ; set the 9x flag based on the EFLAGS register


Donkey
Posted on 2007-12-29 10:12:49 by donkey
Iirc you can also check for 9x vs. NT by checking if you have LDT or GDT segments...

But again, this is pretty dirty stuff, might fail running under emulation, etc.
Posted on 2007-12-29 10:17:24 by f0dder