; SMTP client. ; Sends an e-mail using the Outlook SMTP server specified in the registry. ; .386 .MODEL FLAT .DATA JUMPS ; So I don't have to mess around with JMPs. EXTRN ExitProcess:PROC EXTRN WSAStartup:PROC EXTRN WSACleanup:PROC EXTRN gethostbyname:PROC EXTRN socket:PROC EXTRN closesocket:PROC EXTRN connect:PROC EXTRN select:PROC EXTRN recv:PROC EXTRN send:PROC EXTRN RegCloseKey:PROC EXTRN RegQueryValueExA:PROC EXTRN RegOpenKeyExA:PROC SOCK_STREAM EQU 1 ; Stream socket. AF_INET EQU 2 ; Internetwork: UDP, TCP, etc. HKEY_CURRENT_USER EQU 80000001h KEY_QUERY_VALUE EQU 1 REG_SZ EQU 1 START: CALL Get_EIP ; Get delta offset, incase Get_EIP: POP EBP ; someone would want to stuff SUB EBP, (Get_EIP-START) ; this in a virus. XOR EBX, EBX LEA EDI, [EBP+(Reg_Handle-START)] LEA EAX, [EBP+(Reg_Handle-START)] PUSH EAX PUSH KEY_QUERY_VALUE PUSH EBX CALL @1 DB 'Software\Microsoft\Internet Account Manager', 0 @1: PUSH HKEY_CURRENT_USER CALL RegOpenKeyExA CALL @2 DD 9 @2: LEA EAX, [EBP+(Account_Index-START)] PUSH EAX PUSH EBX PUSH EBX CALL @3 DB 'Default Mail Account', 0 @3: PUSH DWORD PTR [EBP+(Reg_Handle-START)] CALL RegQueryValueExA PUSH DWORD PTR [EBP+(Reg_Handle-START)] CALL RegCloseKey PUSH OFFSET Reg_Handle PUSH KEY_QUERY_VALUE PUSH EBX CALL @4 DB 'Software\Microsoft\Internet Account Manager\Accounts\' Account_Index: DB '00000000', 0 @4: PUSH HKEY_CURRENT_USER CALL RegOpenKeyExA CALL @5 DD 30 @5: LEA EAX, [EBP+(SMTP_Name-START)] PUSH EAX PUSH EBX PUSH EBX CALL @6 DB 'SMTP Server', 0 @6: PUSH DWORD PTR [EBP+(Reg_Handle-START)] CALL RegQueryValueExA PUSH DWORD PTR [EBP+(Reg_Handle-START)] CALL RegCloseKey PUSH OFFSET WSA_Data ; Winsock data. PUSH 0101h ; Version 1.1 (Win95+). CALL WSAStartup OR EAX, EAX ; Error? JNZ Exit ; Convert the DNS name to an IP address. LEA EAX, [EBP+(SMTP_Name-START)] PUSH EAX CALL gethostbyname XCHG ECX, EAX ; Error? JECXZ Free_Winsock MOV ESI, [ECX+12] ; Fetch IP address. LODSD PUSH DWORD PTR [EAX] POP DWORD PTR [EBP+(Server_IP-START)] PUSH 0 ; Create a socket. PUSH SOCK_STREAM PUSH AF_INET CALL socket MOV [EBP+(Work_Socket-START)], EAX INC EAX ; Error? JZ Free_Winsock PUSH 16 ; Size of connect structure. CALL @7 ; Connect structure. DW AF_INET ; Family. DB 0, 25 ; Port number. Server_IP DD 0 ; IP of server. DB 8 DUP(0) ; Unused. @7: PUSH DWORD PTR [EBP+(Work_Socket-START)] CALL connect INC EAX ; Error? JZ Close_Socket LEA ESI, [EBP+(Send_Table-START)] MOV BL, 6 ; Wait up to 5 seconds for incoming data, ; or else close the connection. This is ; done to prevent an endless block. Command_Loop: XOR EAX, EAX CALL @8 ; Time-out: Time_Out: DD 5 ; - Seconds. DD 0 ; - Milliseconds. @8: PUSH EAX ; Error (not used). PUSH EAX ; Writeability (not used). CALL @9 ; Readability: Socket_Set: DD 1 ; - Socket count. Work_Socket DD 0 ; - Socket. @9: PUSH EAX ; Unused. CALL select DEC EAX ; Socket can be read? JNZ Close_Socket ; Else close up. LEA EDI, [EBP+(Buffer-START)] PUSH 0 ; Receive data from the PUSH 512 ; socket. PUSH EDI PUSH DWORD PTR [EBP+(Work_Socket-START)] CALL recv XCHG ECX, EAX ; Connection closed? JECXZ Close_Socket INC ECX ; Error? JZ Close_Socket OR EBX, EBX ; Received stuff was the QUIT JZ Close_Socket ; reply? Then close up. MOV AL, '2' ; "OK" reply. CMP BL, 2 ; Received stuff was the DATA JNE Check_Reply ; reply? INC EAX ; "OK, send the rest" reply. Check_Reply: SCASB ; Check for correct reply. JE Wait_Ready ; Yep, so go on. ; An error occurred, so we gracefully close down the ; connection by sending a QUIT command to the server. LEA ESI, [EBP+(Send_Table-START)+(5*4)] MOV BL, 1 ; Poll if the socket can be written ; to or bail after 5 seconds. Wait_Ready: XOR ECX, ECX LEA EAX, [EBP+(Time_Out-START)] PUSH EAX @10: PUSH ECX ; Error (not used). LEA EAX, [EBP+(Socket_Set-START)] PUSH EAX ; Writeability. @11: PUSH ECX ; Readability (not used). PUSH ECX ; Unused. CALL select DEC EAX ; Time-out? JNZ Close_Socket CLD ; Fetch offset + size of next LODSD ; SMTP command. MOVZX ECX, AX SHR EAX, 16 ADD EAX, EBP ; Add delta offset. ; Send command/data to the socket. PUSH ECX PUSH 0 PUSH ECX ; Size of buffer. PUSH EAX ; Buffer. PUSH DWORD PTR [EBP+(Work_Socket-START)] CALL send POP ECX CMP EAX, ECX ; All bytes were sent? JNE Close_Socket ; Else close connection. DEC EBX ; Did all commands so far? JNS Command_Loop ; If not, continue. Close_Socket: PUSH DWORD PTR [EBP+(Work_Socket-START)] CALL closesocket Free_Winsock: CALL WSACleanup Exit: PUSH 0 ; Back to Windoze. CALL ExitProcess Send_Table: DW (esHELO-sHELO), (sHELO-START) DW (esMAIL-sMAIL), (sMAIL-START) DW (esRCPT-sRCPT), (sRCPT-START) DW (esDATA-sDATA), (sDATA-START) DW (End_Body-Body), (Body-START) DW (esQUIT-sQUIT), (sQUIT-START) ; Identify us to the server, keep in mind that ; some servers check if this host is correct. sHELO DB 'HELO host.name.of.sender', 0Dh, 0Ah esHELO: ; This is the addy the mail gets returned to when it can't be delivered. ; If you don't want to get notified of failures, use a blank addy ('<>'). sMAIL DB 'MAIL FROM:', 0Dh, 0Ah esMAIL: ; To whom the mail should be delivered. sRCPT DB 'RCPT TO:', 0Dh, 0Ah esRCPT: sDATA DB 'DATA', 0Dh, 0Ah esDATA: ; Header of the body. Body: DB 'From: "Ben Dover" ', 0Dh, 0Ah DB 'Subject: Fuck You', 0Dh, 0Ah DB 0Dh, 0Ah ; Main body. DB 'This is the body of the e-mail', 0Dh, 0Ah DB 'bla bla bla die die bla bla', 0Dh, 0Ah DB '.', 0Dh, 0Ah ; End of data command. End_Body: sQUIT DB 'QUIT', 0Dh, 0Ah esQUIT: Reg_Handle DD 0 SMTP_Name DB 30 DUP(0) WSA_Data DB 400 DUP(0) Buffer DB 512 DUP(0) ; For more info consult RFC 821 (SMTP). END START