ASM IRC Bot
An IRC bot coded in x86 assembly for linux.
The code isn't very clean; I did this back in 2008. It also doesn't do much other than sitting in a channel waiting for someone to make it quit. The bot does not pong the server back after the first pong so it eventually timeouts.
; This program is free software. It comes without any warranty, to ; the extent permitted by applicable law. You can redistribute it ; and/or modify it under the terms of the Do What The Fuck You Want ; To Public License, Version 2, as published by Sam Hocevar. See ; COPYING for more details. ; ;--------- ;INTRODUCTION ;--------- ;IRCBOT for Linux ;--------- ;COMMENTS ;--------- ;General information to recall: ;esi holds the socket descriptor ;edi points to the string received from the server (on stack) ;To call send, first push the length of the string to send, ;then a pointer to the string, and afterwards call send. ;--------- ;DATA ;--------- BITS 32 section .data logincmd db ': NICK asmbot',0xd,0xa,'USER asmbot asmbot irc.host.net :asmbot',0xd,0xa quit db 'QUIT :Did you hear that?',0xd,0xa joinchannels db 'JOIN #botground',0xd,0xa msg_priv db 'PRIVMSG ' msg_quit db 'quit' section .text global _start ;--------- ;CODE ;--------- ;Alright, code goes here. ;Basically, it is divided into three main parts: ; Initialisation -> setting up, connecting to the server, making space for buffer. ; Main loop -> receiving and parsing commands. ; Ending -> send quit message, disconnect from server, and exit. _start: xor eax, eax xor ebx, ebx xor ecx, ecx xor edx, edx ;Make space for variables. sub esp, 4 mov ebp, esp ;[ebp] int: 1 when channels have been joined, 0 otherwise. ;[ebp+4] int: holds the number of bytes received by recv(). ;Initialise variables. mov dword [ebp], 0 socket: push edx push 0x1 push 0x2 mov ecx, esp inc bl mov al, 102 int 0x80 mov esi, eax cmp eax, 0 jb near socket_fail connect: push edx push dword 0x4bb8b2c3 push dword 0x0B1A0002 mov ecx, esp push 0x10 push ecx push esi mov ecx, esp mov bl, 3 mov al, 102 int 0x80 test eax, eax jnz near connect_fail prepare_buffer: ;We will need a buffer later on ;to receive messages from the server. push edx sub esp, 127+28 mov edi, esp login: ;Send the login information to the server. push dword 0 ;Flags push dword 67 ;Length push logincmd ;String push esi call send recv: push dword 0 ;Flags push dword 128 ;Len push edi ;buf push esi ;socket mov ecx, esp mov ebx, 10 mov eax, 102 int 0x80 mov [ebp+4], eax test eax, eax jz near connection_closed jbe near recv_fail pop ecx pop ecx pop ecx pop ecx check_for_ping: ;String long enough to ;deal with parsing? cmp dword [ebp+4], 6 jbe recv mov edx, edi mov ecx, 124 check_ping_repeat: cmp dword [edx], 0x474E4950 ;GNIP je pong inc edx dec ecx jnz check_ping_repeat jmp check_channels pong: ;Now we need to substitute the I ;in PING for O, so that is reads ;PONG, and reply to the server with ;our new string. O = 0x47. mov byte [edx+1], 0x4F ;Send the reply push 16 push edx call send check_channels: ;Have channels already been joined? ;If so, jump straight into the message parsing block. mov eax, [ebp] test eax, eax jnz check_message join_channels: ;Prudential wait time. mov eax, 162 push dword 0 push dword 1 mov ebx, esp xor ecx, ecx int 0x80 ;Once the server has welcomed us, we can join channels. push dword 0 ;Flags push dword 17 push joinchannels push esi call send mov dword [ebp], 1 ;Channels have been joined. check_message: ;user@host PRIVMSG #botground :asmbot, quit ;String long enough to ;deal with parsing? mov ecx, [ebp+4] cmp ecx, 9 jb recv mov edx, edi check_message_next: ;PRIVMSG ? cmp dword [edx], 0x56495250 ;VIRP jne check_message_iterate cmp dword [edx+4], 0x2047534D ; GSM je check_message_continue check_message_iterate: inc edx dec ecx jz recv jmp check_message_next check_message_continue: ;Now find the : in the message. add edx, 8 recheck_msg: cmp byte [edx], 0x3A je parse_command inc edx dec ecx jz recv jmp recheck_msg parse_command: ;PRIVMSG #Botground :asmbot, quit ;Is edx pointing near the end of the buffer? ;If so, there is no need to parse the string. cmp ecx, 10 jb recv ;Get past the : inc edx ;Now we read whatever was said after ;the : and check for commands. ;Was our name said ? asmbot, (space) cmp dword [edx], 0x626D7361 ;bmsa cmp dword [edx+4], 0x202C746F ; ,to jne recv ;Get past the name add edx, 8 ;Was quit said? push 4 push msg_quit push edx call compare test eax, eax je bye_bye jmp recv ;cmp dword [edx], 0x74697571 ;tiuq ;jne recv bye_bye: ;We say good bye! push dword 0 ;Flags push dword 26 push quit push esi call send shutdown: ;Close the socket. ;SHUT_RDWR = 0x2 push 0x2 push esi mov ecx, esp mov ebx, 0xD mov eax, 102 int 0x80 test eax, eax jnz near shutdown_fail ;Set ebx to 0 for a clean exit call. xor ebx, ebx exit: mov eax, 1 int 0x80 send: mov ecx, esp add ecx, 4 mov ebx, 9 mov eax, 102 int 0x80 cmp eax, 0 jb near send_fail pop eax ;ret pop ecx ;socket pop ecx ;buf pop ecx ;len pop ecx ;flags push eax ret compare: pop eax ;ret pop edx ; ptr one pop ebx ; ptr two pop ecx ; Length push eax compare_loop: mov al, [edx] xor al, [ebx] test al, al jnz compare_return dec ecx test ecx, ecx jz compare_equal inc edx inc ebx jmp compare_loop compare_equal: xor eax, eax compare_return: ret fail: pop ecx pop edx mov ebx, 0x1 mov eax, 0x4 int 0x80 ;Set ebx to 1 as an error code. mov ebx, 1 jmp exit ;----------------- ;FAIL "FUNCTIONS" ;----------------- ;The fail functions are all listed here. ;The tags are pretty self explanatory. ;Remember to push the length of the string to print ;before calling fail. recv_fail: push 14 call fail db 'recv() failed',0xa socket_fail: push 16 call fail db 'socket() failed',0xa connection_closed: push 48 call fail db'The server closed the connection.',0xa connect_fail: push 17 call fail db 'connect() failed',0xa send_fail: push 14 call fail db 'send() failed',0xa shutdown_fail: push 18 call fail db 'shutdown() failed',0xa