I'm still working through your reply XD as for falling into the strtoint function again the file i was posting from is just a temporary text file i use for creating and saving functions so I apologise for not exiting properly ^^
I'll definitely look at the string functions again because I'm going to need them pretty soon
We have this contest coming up that's hosted by our regional municapility ( regeering -> Usually my afrikaans to english is pretty good but I'm not sure about that particular word ) and I thought since we're allowed to submit practically anything I'd do something in nasm. The olympiades we have are all more math based and we're only allowed to use java , delphi and python ( not that I have anything against the languages it's just when I started with C and was introduced to memory allocation and pointers it just blew my mind on so many levels ). I was thinking along the lines of a RAT (remote access tool) although in this scenario I have a server and a few clients connecting to it. The server is sends commands to the clients which in turn execute something and return a value to the server.
A few nice and fun functions to implement that I thought of while my teacher was discussing exam papers XD
1.) Tracking the mouse movement to determine whether a user is active on the station or not ( got the idea from malware )
2.) Disabling/Enabling the shutdown of certain workstations ( using the registry )
3.) Process monitor that kills any processes that are in a blacklist
4.) Disabling/Enabling the network ( Although this seems impractical because obviously i'd lose connection to the client :/ )
Change that to network functions XD
5.) Some basic info about a client.
6.) A scripting engine for the client.
Then it hit me that if I made the server and had let's say ten clients connected to it I'd need 10 sockets for each client and well it'd slow down the program . I'm not THAT new to socket programming so I immediately thought of using threading to solve the problem. The idea was that I'd spawn one thread for every client connected. This is where things started to get interesting.
I started writing on the project yesterday and already managed to implement a server which handles a single connection and prints whatever is sent to it . Today I'm looking into the winapi's heaprealloc , heapalloc and heapfree functions aswell as createthread. I'm not familiar with any of the heap functions but I think I get them . As for createthread ... Obviously in delphi the arguments are
exactly the same similar my only problem is that I can't figure out where my address is that I pass. Being new to assembly and all. I thought it might have something to do with the esi,ebp and esp register but I'm still not certain. I think I'll solve that in an hour or so though ^^
This is what I have thusfar!
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;THIS IS AN EXAMPLE TO HANDLE A SINGLE CLIENT ONLY
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
BITS 32
extern _WSAStartup
extern _socket
extern _bind
extern _listen
extern _HeapReAlloc
extern _GetProcessHeap
extern _HeapAlloc
extern _HeapFree
extern _accept
extern _recv
extern _ExitProcess
extern __cprintf
extern _CreateThread
extern _bind
extern _ExitWindowsEx
extern _WSAGetLastError
extern __getch
extern _htons
global main
section .bss
WSADATA resb 400 ;Checked in C
sockaddr_inA resb 16 ;Checked in C
rcvBuffer resb 200
clientSockets resd 1
section .data
;ERRORS
errFormat db "ERRORCODE : %d",0ah,0
;ERRORS END
;DWORD
counterGeneral dd 0
counterSocket dd 0
ProcessHeap dd 0
socketServer dd 0
;DWORD END
;BYTES
strFormat db "%s",0
strConnected db "Client Connected!",0ah,0
strShutdown db "Shutdown",0
;BYTES END
section .text
main:
call _GetProcessHeap
mov dword [ProcessHeap],eax
;1.) Init WSA
push dword WSADATA
push 514 ;MakeWord(2,2)
call _WSAStartup
CMP eax,byte 0
JNE lblErrExit
;2.) Create A Socket
push 6 ; TCP
push 1 ; SOCK_STREAM
push 2 ; AF_INET
call _socket
cmp eax,-1 ;SOCK_ERROR
JE lblErrExit
mov dword [socketServer],eax
;3.) Bind The Socket
mov word [sockaddr_inA+0],2 ;AF_INET
push 968
call _htons
mov dword [sockaddr_inA+2],eax
mov dword [sockaddr_inA+6],0x0 ;ALL IP's
push 16
push sockaddr_inA
push dword [socketServer]
call _bind
CMP eax,0
JNE lblErrExit
;4.) Listen For A Connection
push 0
push dword [socketServer]
call _listen
CMP eax,0
JNE lblErrExit
;5.1) Spawn A Thread
;5.2.) Accept A Connection
push 0
push 0
push 0
push lblAccept
push 9
push 0
call _CreateThread
;5.3) Create a dynamic array for clientSockets
;LPVOID WINAPI HeapAlloc( _In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ SIZE_T dwBytes
push 1
push 0
push dword [ProcessHeap]
call _HeapAlloc
CMP eax,0
JE lblErrExit
lblAccept:
push 0
push 0
push dword [socketServer]
call _accept
cmp eax,-1
JE lblErrExit
mov edx,dword [Counter]
add edx,4
mov dword [clientSockets+edx],eax ;Save Client Handle
push 0
push 0
push 0
push lblRecv
push 9
push 0
call _CreateThread
push strConnected
push strFormat
call __cprintf
add esp , 8
JMP lblAccept
;6.) Recv data
lblRecv:
push 0
push 255
push rcvBuffer
mov edx,dword [Counter]
push dword [socketClient+edx]
call _recv
cmp eax,0
JE lblErrExit
cmp eax,-1
JE lblErrExit
push rcvBuffer
push strFormat
call __cprintf
mov ebx, rcvBuffer
mov ecx, strShutdown
call strCmp
cmp eax,-1
JE lblShutdown
add esp,8
mov dword [rcvBuffer],""
JMP lblRecv
lblErrExit:
call _WSAGetLastError
push eax
push errFormat
call __cprintf
add esp , 8
call __getch
call _ExitProcess
strCmp: ;Compare ebx to ecx
;>>Setup for the loop
mov edx,-1;We Want To Start By Comparing AStr[0] to BStr[0]
mov eax,-1
strCmp_Loop:
inc edx ;Increment Index
mov ah,[ebx+edx]
CMP ah,[ecx+edx]
JNE strCmp_NEQU
CMP ah,0
JE strCmp_Done
JMP strCmp_Loop
strCmp_NEQU:
mov eax,edx
strCmp_Done:
RET
lblShutdown:
push 0
push 0x00000001 ;Shutdown
call _ExitWindowsEx
I'll take a short break and quickly have a look see at what delphi does with the strtoint function. Great idea on setting the carry flag :/ I felt a little lost when you said that bit about the negative 1. What do you mean it doesn't play well with C though? ^^
I also thought I'd post delphi's version of it here if you'd like to have a look ^^
function _ValLong(const s: string; var code: Integer): Longint;
{$IFDEF PUREPASCAL}
var
I, Len, Digit: Integer;
Negative, Hex: Boolean;
begin
// U-OK
I := 1;
code := -1;
Result := 0;
Negative := False;
Hex := False;
Len := Length(s);
while (I <= Len) and (s[I] = ' ') do
Inc(I);
if I > Len then
Exit;
case s[I] of
'$',
'x',
'X':
begin
if I = Len then
begin
Code := I + 2; // Emulate Win32 _ValLong behaviour
Exit;
end;
Hex := True;
Inc(I);
end;
'0':
begin
Hex := (Len > I) and ((s[I+1] = 'X') or (s[I+1] = 'x'));
if Hex then
Inc(I, 2);
end;
'-':
begin
if I = Len then
begin
Code := I + 1; // Emulate Win32 _ValLong behaviour
Exit;
end;
Negative := True;
Inc(I);
end;
'+':
begin
if I = Len then
begin
Code := I + 1; // Emulate Win32 _ValLong behaviour
Exit;
end;
Inc(I);
end;
end;
if Hex then
while I <= Len do
begin
// check for overflow
if Result > (High(Result) shr 3) then
begin
code := I;
Exit;
end;
case s[I] of
'0'..'9': Result := Result * 16 + Ord(s[I]) - Ord('0');
'a'..'f': Result := Result * 16 + Ord(s[I]) - Ord('a') + 10;
'A'..'F': Result := Result * 16 + Ord(s[I]) - Ord('A') + 10;
else
code := I;
Exit;
end;
Inc(I);
end
else
while I <= Len do
begin
// check for overflow
if Result > (High(Result) div 10) then
begin
code := I;
Exit;
end;
Digit := Ord(s[I]) - Ord('0');
if (Digit < 0) or (Digit > 9) then begin
Code := I;
Exit;
end;
Result := Result * 10 + Ord(s[I]) - Ord('0');
Inc(I);
end;
if Negative then
Result := -Result;
code := 0;
end;
{$ELSE !PUREPASCAL}
asm
{ FUNCTION _ValLong( s: string; VAR code: Integer ) : Longint; }
{ ->EAX Pointer to string }
{ EDX Pointer to code result }
{ <-EAX Result }
PUSH EBX
PUSH ESI
PUSH EDI
MOV ESI,EAX
PUSH EAX { save for the error case }
TEST EAX,EAX
JE @@empty
XOR EAX,EAX
XOR EBX,EBX
MOV EDI,07FFFFFFFH / 10 { limit }
@@blankLoop:
MOV BX,[ESI]
ADD ESI, 2
CMP BX,' '
JE @@blankLoop
@@endBlanks:
MOV CH,0
CMP BX,'-'
JE @@minus
CMP BX,'+'
JE @@plus
@@checkDollar:
CMP BX,'$'
JE @@dollar
CMP BX, 'x'
JE @@dollar
CMP BX, 'X'
JE @@dollar
CMP BX, '0'
JNE @@firstDigit
MOV BX, [ESI]
ADD ESI, 2
CMP BX, 'x'
JE @@dollar
CMP BX, 'X'
JE @@dollar
TEST BX, BX
JE @@endDigits
JMP @@digLoop
@@firstDigit:
TEST BX,BX
JE @@error
@@digLoop:
SUB BX,'0'
CMP BX,9
JA @@error
CMP EAX,EDI { value > limit ? }
JA @@overFlow
LEA EAX,[EAX+EAX*4]
ADD EAX,EAX
ADD EAX,EBX { fortunately, we can't have a carry }
MOV BX,[ESI]
ADD ESI, 2
TEST BX,BX
JNE @@digLoop
@@endDigits:
DEC CH
JE @@negate
TEST EAX,EAX
JGE @@successExit
JMP @@overFlow
@@empty:
ADD ESI, 2
JMP @@error
@@negate:
NEG EAX
JLE @@successExit
JS @@successExit { to handle 2**31 correctly, where the negate overflows }
@@error:
@@overFlow:
POP EBX
SUB ESI,EBX
JMP @@exit
@@minus:
INC CH
@@plus:
MOV BX,[ESI]
ADD ESI, 2
JMP @@checkDollar
@@dollar:
MOV EDI,0FFFFFFFH
MOV BX,[ESI]
ADD ESI, 2
TEST BX,BX
JZ @@empty
@@hDigLoop:
CMP BX,'a'
JB @@upper
SUB BX,'a' - 'A'
@@upper:
SUB BX,'0'
CMP BX,9
JBE @@digOk
SUB BX,'A' - '0'
CMP BX,5
JA @@error
ADD BX,10
@@digOk:
CMP EAX,EDI
JA @@overFlow
SHL EAX,4
ADD EAX,EBX
MOV BX,[ESI]
ADD ESI, 2
TEST BX,BX
JNE @@hDigLoop
DEC CH
JNE @@successExit
NEG EAX
@@successExit:
POP ECX { saved copy of string pointer }
XOR ESI,ESI { signal no error to caller }
@@exit:
SHR ESI, 1
MOV [EDX],ESI
POP EDI
POP ESI
POP EBX
end;
The strtoint function calls Val which is short for Validate ^^
And please no don't apologise for late replies or anything like that, you have absolutely no obligation to help people out here ( unless it's like a moral thing being the developer - I wouldn't know because I've never done anything that huge :p - ).
I think it's really great that you do though not a lot of people would go to this amount of trouble ^^
Oh and please call me Connor :p