@@ -63,6 +63,119 @@ lazy_static! {
6363 static ref COUNT_RECV : Mutex <u32 > = Mutex :: new( 0 ) ;
6464}
6565
66+ fn getaddrinfo ( emu : & mut emu:: Emu ) {
67+ let node_name_ptr = emu
68+ . maps
69+ . read_dword ( emu. regs ( ) . get_esp ( ) + 4 )
70+ . expect ( "ws2_32!getaddrinfo cannot read node_name_ptr" ) ;
71+ let service_name_ptr = emu
72+ . maps
73+ . read_dword ( emu. regs ( ) . get_esp ( ) + 8 )
74+ . expect ( "ws2_32!getaddrinfo cannot read service_name_ptr" ) ;
75+ let hints_ptr = emu
76+ . maps
77+ . read_dword ( emu. regs ( ) . get_esp ( ) + 12 )
78+ . expect ( "ws2_32!getaddrinfo cannot read hints_ptr" ) ;
79+ let result_ptr_ptr = emu
80+ . maps
81+ . read_dword ( emu. regs ( ) . get_esp ( ) + 16 )
82+ . expect ( "ws2_32!getaddrinfo cannot read result_ptr_ptr" ) ;
83+
84+ let node_name = if node_name_ptr != 0 {
85+ emu. maps . read_string ( node_name_ptr)
86+ } else {
87+ "NULL" . to_string ( )
88+ } ;
89+
90+ let service_name = if service_name_ptr != 0 {
91+ emu. maps . read_string ( service_name_ptr)
92+ } else {
93+ "NULL" . to_string ( )
94+ } ;
95+
96+ log_red ! ( emu, "ws2_32!getaddrinfo node: `{}` service: `{}`" , node_name, service_name) ;
97+
98+ // Read hints if provided
99+ let mut hints_flags = 0 ;
100+ let mut hints_family = 0 ;
101+ let mut hints_socktype = 0 ;
102+ let mut hints_protocol = 0 ;
103+
104+ if hints_ptr != 0 {
105+ hints_flags = emu. maps . read_dword ( hints_ptr) . unwrap_or ( 0 ) as i32 ;
106+ hints_family = emu. maps . read_dword ( hints_ptr + 4 ) . unwrap_or ( 0 ) as i32 ;
107+ hints_socktype = emu. maps . read_dword ( hints_ptr + 8 ) . unwrap_or ( 0 ) as i32 ;
108+ hints_protocol = emu. maps . read_dword ( hints_ptr + 12 ) . unwrap_or ( 0 ) as i32 ;
109+ }
110+
111+ // Create a dummy ADDRINFO structure
112+ let addrinfo_size = 48 ; // Size of ADDRINFOA structure (approximate)
113+ let sockaddr_in_size = 16 ; // Size of sockaddr_in structure
114+
115+ // Allocate memory for the result
116+ let heap_management = emu. heap_management . as_mut ( ) . unwrap ( ) ;
117+ let addrinfo_addr = heap_management. allocate ( ( addrinfo_size + sockaddr_in_size + 100 ) as usize ) . unwrap ( ) ;
118+ let sockaddr_addr = addrinfo_addr + addrinfo_size;
119+ let canonname_addr = sockaddr_addr + sockaddr_in_size;
120+
121+ // Create a dummy sockaddr_in (IPv4 address 127.0.0.1, port based on service)
122+ let ip_addr = 0x0100007f ; // 127.0.0.1 in network byte order
123+
124+ // Determine port based on service name
125+ let port = if service_name == "http" || service_name == "80" {
126+ 80u16
127+ } else if service_name == "https" || service_name == "443" {
128+ 443u16
129+ } else if service_name == "ftp" || service_name == "21" {
130+ 21u16
131+ } else if service_name == "ssh" || service_name == "22" {
132+ 22u16
133+ } else if service_name == "smtp" || service_name == "25" {
134+ 25u16
135+ } else if service_name == "dns" || service_name == "53" {
136+ 53u16
137+ } else {
138+ service_name. parse ( ) . unwrap_or ( 80u16 )
139+ } ;
140+
141+ // Write sockaddr_in structure
142+ emu. maps . write_word ( sockaddr_addr, 2 ) ; // AF_INET = 2
143+ emu. maps . write_word ( sockaddr_addr + 2 , port. to_be ( ) ) ; // Port in network byte order
144+ emu. maps . write_dword ( sockaddr_addr + 4 , ip_addr) ; // IP address (127.0.0.1)
145+ emu. maps . memset ( sockaddr_addr + 8 , 0 , 8 ) ; // Zero out the rest
146+
147+ // Write ADDRINFO structure
148+ emu. maps . write_dword ( addrinfo_addr, hints_flags as u32 ) ; // ai_flags
149+ emu. maps . write_dword ( addrinfo_addr + 4 , if hints_family != 0 { hints_family as u32 } else { 2 } ) ; // ai_family (AF_INET)
150+ emu. maps . write_dword ( addrinfo_addr + 8 , if hints_socktype != 0 { hints_socktype as u32 } else { 1 } ) ; // ai_socktype (SOCK_STREAM)
151+ emu. maps . write_dword ( addrinfo_addr + 12 , if hints_protocol != 0 { hints_protocol as u32 } else { 6 } ) ; // ai_protocol (IPPROTO_TCP)
152+ emu. maps . write_qword ( addrinfo_addr + 16 , sockaddr_in_size as u64 ) ; // ai_addrlen
153+ emu. maps . write_qword ( addrinfo_addr + 24 , canonname_addr) ; // ai_canonname
154+ emu. maps . write_qword ( addrinfo_addr + 32 , sockaddr_addr) ; // ai_addr
155+
156+ // Set ai_canonname to the node name or "localhost"
157+ let canon_name = if node_name == "NULL" || node_name. is_empty ( ) || node_name == "localhost" {
158+ "localhost.localdomain" . to_string ( )
159+ } else if node_name == "127.0.0.1" {
160+ "localhost" . to_string ( )
161+ } else {
162+ format ! ( "{}.localdomain" , node_name)
163+ } ;
164+ emu. maps . write_string ( canonname_addr, & canon_name) ;
165+
166+ // ai_next is NULL (end of list)
167+ emu. maps . write_qword ( addrinfo_addr + 40 , 0 ) ;
168+
169+ // Store the result pointer in the ppResult parameter
170+ emu. maps . write_qword ( result_ptr_ptr, addrinfo_addr) ;
171+
172+ log:: info!( "\t created dummy ADDRINFO for {}:{} at 0x{:x}" , node_name, service_name, addrinfo_addr) ;
173+ log:: info!( "\t sockaddr at 0x{:x}, canonname at 0x{:x}" , sockaddr_addr, canonname_addr) ;
174+
175+ // Return 0 for success (WSA error code)
176+ emu. regs_mut ( ) . rax = 0 ;
177+ }
178+
66179fn WsaStartup ( emu : & mut emu:: Emu ) {
67180 log_red ! ( emu, "ws2_32!WsaStartup" ) ;
68181
0 commit comments