# -*- Fundamental -*-
# smb_nt.inc 
# $Revision: 1.75 $
#


 global_var multiplex_id, g_mhi, g_mlo;

 multiplex_id = rand();
 g_mhi = multiplex_id / 256;
 g_mlo = multiplex_id % 256;

 function kb_smb_name(){
 	return string(get_kb_item("SMB/name"));
 }

 function kb_smb_domain(){
 	return string(get_kb_item("SMB/domain"));
 }

 function kb_smb_login(){
 	return string(get_kb_item("SMB/login"));
 }

 function kb_smb_password(){
 	return string(get_kb_item("SMB/password"));
 }

 function kb_smb_transport()
 {
 	local_var r;
 	r = get_kb_item("SMB/transport");
 	if(r){
		return int(r);
	}
 	else {
		return 445;
	}
 }


 #-----------------------------------------------------------------#
 # Reads a SMB packet						   #
 #-----------------------------------------------------------------#
 function smb_recv(socket, length)
 {
 	local_var header, len, trailer;

   	header = recv(socket:socket, length:4, min:4);
   	if(strlen(header) < 4){
		return(NULL);
	}
   	len = 256 * ord(header[2]);
   	len += ord(header[3]);
   	if(len == 0){
		return(header);
	}
   	trailer = recv(socket:socket, length:len, min:len);
   	if(strlen(trailer) < len){
		return(NULL);
	}
   	return strcat(header, trailer);
 }

 #-----------------------------------------------------------------#
 # Encode name and service to the netbios network format           #
 #-----------------------------------------------------------------#
 function netbios_encode(data,service)
 {
	local_var tmpdata, ret;

	ret = "";
 	tmpdata = data; 

	while(strlen(tmpdata) < 15){
 		tmpdata += " ";
 	}

 	tmpdata += raw_string(service);
 	for(i=0; i<16; i=i+1)
 	{
   		o = ord(tmpdata[i]);
   		odiv = o/16;
   		odiv = odiv + ord("A");
   		omod = o%16;
   		omod = omod + ord("A");
   		c = raw_string(odiv, omod);
		ret = ret+c;
 	}
	return(ret); 
 }

 #-----------------------------------------------------------------#
 # Convert a netbios name to the netbios network format            #
 #-----------------------------------------------------------------#
 function netbios_name(orig){
 	return netbios_encode(data:orig, service:0x20); 
 }

 #--------------------------------------------------------------#
 # Returns the netbios name of a redirector                     #
 #--------------------------------------------------------------#
 function netbios_redirector_name()
 {
 	ret = crap(data:"CA", length:30);
 	ret = ret+"AA";
 	return(ret); 
 }

 #-------------------------------------------------------------#
 # return a 28 + strlen(data) + (odd(data)?0:1) long string    #
 #-------------------------------------------------------------#
 function unicode(data)
 {
 	len = strlen(data);
 	ret = raw_string(ord(data[0]));
	for(i=1;i<len;i=i+1){
  		ret = string(ret, raw_string(0, ord(data[i])));
  	}
 
 	if(!(len & 1)){
		even = 1;
	}
 	else {
		even = 0;
	}
 
 	for(i=0;i<7;i=i+1){
  		ret = ret + raw_string(0);
	}
  
  	if(even){
		ret = ret + raw_string(0x00, 0x00);
	}
 	return(ret);
 }

 #----------------------------------------------------------#
 # Request a new SMB session                                #
 #----------------------------------------------------------#
 function smb_session_request(soc, remote)
 {
 	trp = kb_smb_transport();
 	# We don't need to request a session when talking on top of
 	# port 445
 	if(trp == 445){
  		return(TRUE);
	}
  
 	nb_remote = netbios_name(orig:remote);
 	nb_local  = netbios_redirector_name();
 
 	session_request = raw_string(0x81, 0x00, 0x00, 0x44) + 
			  raw_string(0x20) + nb_remote + raw_string(0x00, 0x20) + 
		  	  nb_local + raw_string(0x00);
	send(socket:soc, data:session_request);
 	r = smb_recv(socket:soc, length:4000);
 	if(ord(r[0])==0x82){
		return(r);
	}
 	else {
		return(FALSE);
	}
 }

 #------------------------------------------------------------#
 # Extract the UID from the result of smb_session_setup()     #
 #------------------------------------------------------------#
 function session_extract_uid(reply)
 {
 	low = ord(reply[32]);
 	high = ord(reply[33]);
 	ret = high * 256;
 	ret = ret + low;
 	return(ret);
 }

 #-----------------------------------------------------------#
 # Negociate (pseudo-negociate actually) the protocol        #
 # of the session                                            #
 #-----------------------------------------------------------#
 function smb_neg_prot_cleartext(soc)
 {
 	neg_prot = raw_string(0x00,0x00,
	 		      0x00, 0x89, 0xFF, 0x53, 0x4D, 0x42, 0x72, 0x00,
	 		      0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
	 		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		              0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
	 		      g_mlo, g_mhi, 0x00, 0x66, 0x00, 0x02, 0x50, 0x43,
	 		      0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B,
	 		      0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D,
	 	              0x20, 0x31, 0x2E, 0x30, 0x00, 0x02, 0x4D, 0x49,
	 		      0x43, 0x52, 0x4F, 0x53, 0x4F, 0x46, 0x54, 0x20,
			      0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B, 0x53,
			      0x20, 0x31, 0x2E, 0x30, 0x33, 0x00, 0x02, 0x4D,
			      0x49, 0x43, 0x52, 0x4F, 0x53, 0x4F, 0x46, 0x54,
			      0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B,
			      0x53, 0x20, 0x33, 0x2e, 0x30, 0x00, 0x02, 0x4c,
			      0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e, 0x30,
			      0x00, 0x02, 0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58,
			      0x30, 0x30, 0x32, 0x00, 0x02, 0x53, 0x61, 0x6d,
			      0x62, 0x61, 0x00);
 	send(socket:soc, data:neg_prot);
 	r = smb_recv(socket:soc, length:4000);
 	if(strlen(r) < 10){
		return(FALSE);
	}
 	if(ord(r[9])==0){
		return(r);
	}
 	else {
		return(FALSE);
	}
 }

 function smb_neg_prot_NTLMv1(soc)
 {
 	local_var neg_prot, r;
 
 	neg_prot = raw_string(0x00, 0x00, 0x00, 0xA4, 0xFF, 0x53,
	 		      0x4D, 0x42, 0x72, 0x00, 0x00, 0x00, 0x00, 0x08,
	 		      0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	 		      0x4D, 0x0B, 0x00, 0x00, g_mlo, g_mhi, 0x00, 0x81,
	                      0x00, 0x02) + "PC NETWORK PROGRAM 1.0" +
		   raw_string(0x00, 0x02) + "MICROSOFT NETWORKS 1.03" +
		   raw_string(0x00, 0x02) + "MICROSOFT NETWORKS 3.0"  +
		   raw_string(0x00, 0x02) + "LANMAN1.0" +
		   raw_string(0x00, 0x02) + "LM1.2X002" +
		   raw_string(0x00, 0x02) + "Samba" +
		   raw_string(0x00, 0x02) + "NT LANMAN 1.0" +
 		   raw_string(0x00, 0x02) + "NT LM 0.12" +
		   raw_string(0x00);

 	send(socket:soc, data:neg_prot);
 	r = smb_recv(socket:soc, length:4000);
 	if(strlen(r) < 38){
		return(NULL);
	}
	if(ord(r[9])==0){
		return(string(r));
	}
	else {
		return(NULL);
	}
 }

 function smb_neg_prot_anonymous(soc)
 {
        if(defined_func("nt_owf_gen")){
                return smb_neg_prot_NTLMv1(soc:soc);
        }
        else {
                return smb_neg_prot_cleartext(soc:soc);
        }
 }

 function smb_neg_prot(soc){
  	return smb_neg_prot_cleartext(soc:soc);
 }

 function smb_neg_prot_value(prot){
 	return(ord(prot[37]));
 }

 function smb_neg_prot_cs(prot){
 	if(smb_neg_prot_value(prot:prot) < 7){
  		return NULL;
	}
  	return substr(prot, 73, 73 + 8);
 }
 
 function smb_neg_prot_domain(prot)
 {
 	local_var i, ret;
 	ret = NULL;
 	for(i=81; i<strlen(prot); i+=2)
 	{
  		if(ord(prot[i]) == 0) break;
  		else ret += prot[i];
 	}
 	return ret;
 }

 #------------------------------------------------------#
 # Set up a session                                     #
 #------------------------------------------------------#
 function smb_session_setup_cleartext(soc, login, password, domain)
 {
  	local_var extra, native_os, native_lanmanager, len, bcc;
  	local_var len_hi, len_lo, bcc_hi_n, bcc_lo;
  	local_var pass_len_hi, pass_len_lo;
  	extra = 0;
  	native_os = "Unix";
  	native_lanmanager = "Nessus";

  	if(!domain){
		domain = "MYGROUP";
	}

  	if(domain){
		extra = 3 + strlen(domain) + strlen(native_os) +
			    strlen(native_lanmanager);
	}
  	else {
		extra = strlen(native_os) + strlen(native_lanmanager) + 2;
	}

  	len = strlen(login) + strlen(password) + 57 + extra;
 	bcc = 2 + strlen(login) + strlen(password) + extra;
  
 	len_hi = len / 256;
 	len_low = len % 256;
  
	bcc_hi = bcc / 256;
	bcc_lo = bcc % 256;
  
	pass_len = strlen(password) + 1 ;
	pass_len_hi = pass_len / 256;
	pass_len_lo = pass_len % 256;

  	#if (typeof(login) == "int")    display("HORROR! login=", login, "\n");
  	#if (typeof(password) == "int") display("HORROR! password=", password, "\n");
  	if(!login){
		login="";
	}
	if(!password){
		password="";
	}
  
  	st = raw_string(0x00,0x00,
    	  		len_hi, len_low, 0xFF, 0x53, 0x4D, 0x42, 0x73, 0x00,
			0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
			0x00, 0x00, 0x0A, 0xFF, 0x00, 0x00, 0x00, 0x04,
			0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, pass_len_lo,  pass_len_hi, 0x00, 0x00, 0x00, 0x00,
			bcc_lo, bcc_hi) + password +
	     raw_string(0) + login + raw_string(0x00);
	  
  	if(domain){
  		st = st + domain + raw_string(0x00);
	}
	
	st = st + native_os + raw_string(0x00) + native_lanmanager + raw_string(0x00);
  	send(socket:soc, data:st);
  	r = smb_recv(socket:soc, length:1024); 
  	if(strlen(r) < 9){
		return(NULL);
	}
	if(ord(r[9])==0){
		return(r);
	}
 	else {
		return(NULL);
	}
 }

 function smb_session_setup_NTLMvN(soc, login, password, domain, cs, version)
 {
 	local_var extra, native_os, native_lanmanager, len, bcc;
 	local_var len_hi, len_lo, bcc_hi_n, bcc_lo;
	local_var plen;
  
	local_var NT_H, LM_H, lm, nt;
	local_var ntlmv2_hash;

	if(version == 1)
  	{
  		if(password)
  		{
  			NT_H = nt_owf_gen(password);
  			LM_H = lm_owf_gen(password);
  
			lm = NTLMv1_HASH(cryptkey:cs, passhash:LM_H);
  			nt = NTLMv1_HASH(cryptkey:cs, passhash:NT_H);
  		}
  	}
  	else 
  	{
    		if(password)
		{
	 		NT_H = nt_owf_gen(password);
	 		ntlmv2_hash = ntv2_owf_gen(owf:NT_H, login:login, domain:domain);
	 		lm = NTLMv2_HASH(cryptkey:cs, passhash:ntlmv2_hash, length:8);
			nt = NTLMv2_HASH(cryptkey:cs, passhash:ntlmv2_hash, length:64);
		}
  	}
  
  	extra = 0;
  	native_os = "Unix";
  	native_lanmanager = "Nessus";
  	if(!domain)domain = "WORKGROUP";

  	if(domain){
		extra = 3 + strlen(domain) + strlen(native_os) +
			    strlen(native_lanmanager);
	}
  	else {
		extra = strlen(native_os) + strlen(native_lanmanager) + 2;
	}

  	len = strlen(login) + strlen(lm) + strlen(nt) + 62 + extra;
  	bcc = 1 + strlen(login) + strlen(lm) + strlen(nt) + extra;
  
  	len_hi = len / 256;
  	len_low = len % 256;
  
	bcc_hi = bcc / 256;
	bcc_lo = bcc % 256;
  
	if(password)
	{
  		plen_lm = strlen(lm);
		plen_nt = strlen(nt);
  	}
	else
	{
		plen_lm = 0;
		plen_nt = 0;
		plen = 0;
	}
  
  	pass_len_hi = pass_len / 256;
  	pass_len_lo = pass_len % 256;
  
  	if(!login){
		login="";
	}
	if(!password){
		password="";
	}
  
  	st = raw_string(0x00,0x00,
    	  		len_hi, len_low, 0xFF, 0x53,
	  		0x4D, 0x42, 0x73, 0x00, 0x00, 0x00, 0x00, 0x08,
	  		0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	 		0x00, 0x28, 0x00, 0x00, g_mlo, g_mhi, 0x0D, 0xFF,
			0x00, 0x00, 0x00, 0x00, 0x44, 0x02, 0x00, 0xA0,
			0xF5, 0x00, 0x00, 0x00, 0x00, plen_lm, 0x00, plen_nt,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, bcc_lo, bcc_hi) + lm + nt + toupper(login) + 
	     raw_string(0);

	if(domain){
		st += domain + raw_string(0x00);
	}
	
  	st += native_os + raw_string(0x00) + native_lanmanager + raw_string(0x00);
  	  
  	send(socket:soc, data:st);
	r = smb_recv(socket:soc, length:1024); 
  	if(strlen(r) < 9){
		return(FALSE);
	}
  	if(ord(r[9])==0){
		return(r);
	}
	else {
		return(FALSE);
	}
 }

 function smb_session_setup(soc, login, password, domain, prot)
 {
 	local_var ct, ret, ntlmv1;
 
 	ct = get_kb_item("SMB/dont_send_in_cleartext");
	ntlmv1 = get_kb_item("SMB/dont_send_ntlmv1");
 
	if(smb_neg_prot_value(prot:prot) < 7 )
  	{
  		if(ct == "yes"){
			return NULL;
		}
		else {
			return smb_session_setup_cleartext(soc:soc, login:login,
							   password:password, domain:domain);
		}
  	}
 	else
  	{
  		ret = smb_session_setup_NTLMvN(soc:soc, login:login, password:password,
				               domain:domain, cs:smb_neg_prot_cs(prot:prot), version:2);
  		if(!ret && !ntlmv1){
			ret = smb_session_setup_NTLMvN(soc:soc, login:login, password:password,
						       domain:domain, cs:smb_neg_prot_cs(prot:prot), version:1);
		}
  		return ret;
  	}
 }

 #------------------------------------------------------#
 # connection to a remote share                         #
 #------------------------------------------------------#		
 #
 # connection to the remote IPC share
 #		
 function smb_tconx(soc,name,uid, share)
 {
	high = uid / 256;
	low = uid % 256;
	len = 48 + strlen(name) + strlen(share) + 6;
	ulen = 5 + strlen(name) + strlen(share) + 6;
 
 	req = raw_string(0x00, 0x00,
 		 	 0x00, len, 0xFF, 0x53, 0x4D, 0x42, 0x75, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, low, high,
			 0x00, 0x00, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00,
		 	 0x00, 0x01, 0x00, ulen, 0x00, 0x00, 0x5C, 0x5C) + name +
	      raw_string(0x5C) + share +raw_string(0x00) + "?????"  +
	      raw_string(0x00);

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:1024);
	if(strlen(r) < 10){
		return(FALSE);
	}
	if(ord(r[9])==0){
		return(r);
	}
 	else {
		return(FALSE);
	}
 }

 #------------------------------------------------------#
 # Extract the TID from the result of smb_tconx()       #
 #------------------------------------------------------#
 function tconx_extract_tid(reply)
 {
 	if(strlen(reply) < 30){
		return(FALSE);
	}

	low = ord(reply[28]);
	high = ord(reply[29]);
	ret = high * 256;
	ret = ret + low;
	return(ret);
 }

 #--------------------------------------------------------#
 # Request the creation of a pipe to name. Name must      #
 # contain '\'.                                           #
 #--------------------------------------------------------#
 function smbntcreatex(soc, uid, tid, name, always_return_blob)
 {
 	tid_high = tid / 256;
	tid_low  = tid % 256;
 
	uid_high = uid / 256;
	uid_low  = uid % 256;
 
	req = raw_string(0xFF, 0x53, 0x4D, 0x42, 0xA2, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x50, 0x81,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00,
			 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x9F, 0x01, 0x02, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
			 0x00, 0x00, 0x00, (strlen(name)+1) % 256, 0x00) + name +
	      raw_string(0x00);

	req = raw_string(0x00, 0x00, 0x00, (strlen(req)%256)) + req;

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4000);
	if(always_return_blob){
		return r;
	}
	if(strlen(r) < 10){
		return(FALSE);
	}
 	if(ord(r[9])==0x00){
		return(r);
	}
 	else {
		return(FALSE);
	}
 }


 #--------------------------------------------------------#
 # Extract the ID of our pipe from the result             #
 # of smbntcreatex()                                      #
 #--------------------------------------------------------#

 function smbntcreatex_extract_pipe(reply)
 {
 	if(strlen(reply) < 44){
		return(FALSE);
	}

	low = ord(reply[42]);
	high = ord(reply[43]);
 
	ret = high * 256;
	ret = ret + low;
	return(ret);
 }

 #---------------------------------------------------------#
 # Determines whether the registry is accessible           #
 #---------------------------------------------------------#
		
 function pipe_accessible_registry(soc, uid, tid, pipe)
 {
 	tid_low = tid % 256;
 	tid_high = tid / 256;
 	uid_low = uid % 256;
 	uid_high = uid / 256;
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	req = raw_string(0x00, 0x00,
 		 	 0x00, 0x94, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x1B, 0x81,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C,
			 0x00, 0x48, 0x00, 0x4C, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, 0x51, 0x00, 0x5C, 0x50, 0x49,
			 0x50, 0x45, 0x5C, 0x00, 0x00, 0x00, 0x05, 0x00,
			 0x0B, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x16,
			 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xd0,
			 0x8c, 0x33, 0x44, 0x22, 0xF1, 0x31, 0xAA, 0xAA,
			 0x90, 0x00, 0x38, 0x00, 0x10, 0x03, 0x01, 0x00,
			 0x00, 0x00, 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C,
			 0xc9, 0x11, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10,
			 0x48, 0x60, 0x02, 0x00, 0x00, 0x00);

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
 	if(strlen(r) < 10){
		return(FALSE);
	}
	if(ord(r[9])==0){
		return(r);
	}
	else {
		return(FALSE);
	}
 }

 #----------------------------------------------------------#
 # RegOpenHKLM()                                            #
 #----------------------------------------------------------#
 function registry_open_hklm(soc, uid, tid, pipe)
 {
 	local_var req, tid_low, tid_high, uid_low, uid_high, pipe_low, pipe_high, r;

 	tid_low = tid % 256;
 	tid_high = tid / 256;
	uid_low = uid % 256;
	uid_high = uid / 256;
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	req = raw_string(0x00, 0x00,
 			 0x00, 0x78, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x1D, 0x83,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x24, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x24, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, 0x35, 0x00, 0x00, 0x5c, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x05, 0x00,
		 	 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00,
			 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0xFF,
			 0x12, 0x00, 0x30, 0x39, 0x01, 0x00, 0x00, 0x00,
			 0x00, 0x02);
		  
 	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 10){
		return(FALSE);
	}
	if(ord(r[9])==0){
		return(r);
	}
	else {
		return(FALSE);
	}
 }

 #----------------------------------------------------------#
 # RegOpenHKU()                                             #
 #----------------------------------------------------------#
 function registry_open_hku(soc, uid, tid, pipe)
 {
 	local_var req, tid_low, tid_high, uid_low, uid_high, pipe_low, pipe_high, r;

	tid_low = tid % 256;
	tid_high = tid / 256;
	uid_low = uid % 256;
	uid_high = uid / 256;
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	req = raw_string(0x00, 0x00,
 		 	 0x00, 0x78, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x1D, 0x83,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x24, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x24, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, 0x35, 0x00, 0x00, 0x5c, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00,
			 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0xFF,
			 0x12, 0x00, 0x30, 0x39, 0x01, 0x00, 0x00, 0x00,
			 0x00, 0x02);
		  
 	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 10){
		return(FALSE);
	}
 	if(ord(r[9])==0){
		return(r);
	}
	else {
		return(FALSE);
	}
 }

 #----------------------------------------------------------#
 # RegFlush()						    #
 #----------------------------------------------------------#
 function registry_flush(soc, uid, tid, pipe, reply)
 {
 	local_var magic, req, r, tid_low, tid_high, uid_low, uid_high, pipe_low, pipe_high, name, data, i, len;
 
 	tid_low = tid % 256;
	tid_high = tid / 256;
 
	uid_low = uid % 256;
	uid_high = uid / 256;
 
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	magic = raw_string(ord(reply[84]));		  
	for(i=1; i<20; i=i+1){
  		magic = magic + raw_string(ord(reply[84+i]));
 	}

 	req = raw_string(0x00, 0x00, 0x00, 0x78, 0xFF, 0x53, 
			 0x4D, 0x42, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08,
			 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, tid_low, tid_high,
			 0x00, 0x28, uid_low, uid_high, g_mlo, g_mhi, 0x10, 0x00,
			 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x4c,
			 0x00, 0x02, 0x00, 0x26, 0x00, pipe_low, pipe_high, 0x35,
			 0x00, 0x5c, 0x50, 0x49, 0x50, 0x45, 0x5c, 0x00,
			 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x10, 0x00,
			 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xcf, 0x01,
			 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x0b, 0x00) + magic;
		  
 	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:65535);
 	if(r){
		return substr(r, strlen(r) - 4, strlen(r) - 1);
 	}
 }
  
 #----------------------------------------------------------#
 # RegClose()                                               #
 #----------------------------------------------------------#

 function registry_close(soc, uid, tid, pipe, reply)
 {
 	local_var magic, req, r, tid_low, tid_high, uid_low, uid_high, pipe_low, pipe_high, name, data, i, len;
 
	tid_low = tid % 256;
	tid_high = tid / 256;
 
	uid_low = uid % 256;
	uid_high = uid / 256;
 
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	magic = raw_string(ord(reply[84]));		  
	for(i=1; i<20; i=i+1){
  		magic = magic + raw_string(ord(reply[84+i]));
  	}

 	req = raw_string(0x00, 0x00, 0x00, 0x78, 0xFF, 0x53, 
			 0x4D, 0x42, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08,
			 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, tid_low, tid_high,
			 0x00, 0x28, uid_low, uid_high, g_mlo, g_mhi, 0x10, 0x00,
			 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x4c,
			 0x00, 0x02, 0x00, 0x26, 0x00, pipe_low, pipe_high, 0x35,
			 0x00, 0x5c, 0x50, 0x49, 0x50, 0x45, 0x5c, 0x00,
			 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x10, 0x00,
			 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xcf, 0x01,
			 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x05, 0x00) + magic;
		  
 	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:65535);
	if(r){
		return substr(r, strlen(r) - 4, strlen(r) - 1);
 	}
 }

 #----------------------------------------------------------#
 # RegDelKey()						    #
 #----------------------------------------------------------#
 function registry_delete_key(soc, uid, tid, pipe, key, reply )
 {
 	local_var _na_start, i, error;

	key_len = strlen(key) + 1;
	key_len_hi = key_len / 256;
	key_len_lo = key_len % 256;
 
	tid_low = tid % 256;
	tid_high = tid / 256;
	uid_low = uid % 256;
	uid_high = uid / 256;
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
	uc = unicode3(data:key);
 
	len = 148 + strlen(uc);
 
	len_hi = len / 256;
	len_lo = len % 256;
 
 	z = 40 + strlen(uc);
	z_lo = z % 256;
	z_hi = z / 256;
 
	y = 81 + strlen(uc);
	y_lo = y % 256;
	y_hi = y / 256;
 
	x = 64 + strlen(uc);
	x_lo = x % 256;
	x_hi = x / 256;
 
	if(strlen(reply) < 17){
		return NULL;
	}
	magic1 = raw_string(ord(reply[16]), ord(reply[17]));
 
	req = raw_string(0x00, 0x00,
			 len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80) + magic1 +
	      raw_string(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00,tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, x_lo, x_hi, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, x_lo, x_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, y_lo, y_hi, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, x_lo, x_hi,
			 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, z_lo, z_hi,
			 0x00, 0x00, 0x00, 0x00, 0x07, 0x00);
		  
	magic = raw_string(ord(reply[84]));
	for(i=1; i<20; i=i+1){
  		magic = magic + raw_string(ord(reply[84+i]));
 	}

	x = strlen(key) + strlen(key) + 2;
	x_lo = x % 256;
	x_hi = x / 256;
 
	req = req + magic +
	      raw_string(x_lo, x_hi, x_lo, x_hi, 0x01, 0x00,
 			 0x00, 0x00, key_len_lo, key_len_hi, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, key_len_lo, key_len_hi, 0x00) + uc +
	      raw_string(0);
		  
 	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 10){
		return(1);
	}
 	error = substr(r, strlen(r) - 4, strlen(r) - 1);
 	return ((int(ord(error[3])) * 256 + int(ord(error[2]))) * 256 +
		 int(ord(error[1])) * 256) + int(ord(error[0]));
 }

 #----------------------------------------------------------#
 # RegDelValue()					    #
 #----------------------------------------------------------#
 function registry_delete_value(soc, uid, tid, pipe, value, reply )
 {
 	local_var _na_start, i, error;

	key_len = strlen(value) + 1;
	key_len_hi = key_len / 256;
	key_len_lo = key_len % 256;
 
 	tid_low = tid % 256;
	tid_high = tid / 256;
	uid_low = uid % 256;
	uid_high = uid / 256;
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
	uc = unicode3(data:value);
 
	len = 148 + strlen(uc);
 
	len_hi = len / 256;
	len_lo = len % 256;
 
 	z = 40 + strlen(uc);
	z_lo = z % 256;
	z_hi = z / 256;
 
	y = 81 + strlen(uc);
	y_lo = y % 256;
	y_hi = y / 256;
 
	x = 64 + strlen(uc);
	x_lo = x % 256;
	x_hi = x / 256;
 
	if(strlen(reply) < 17){
		return NULL;
	}

 	magic1 = raw_string(ord(reply[16]), ord(reply[17]));
 
	req = raw_string(0x00, 0x00,
 			 len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80) + magic1 +
	      raw_string(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00,tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, x_lo, x_hi, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, x_lo, x_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, y_lo, y_hi, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, x_lo, x_hi,
			 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, z_lo, z_hi,
			 0x00, 0x00, 0x00, 0x00, 0x08, 0x00);
		  
	magic = raw_string(ord(reply[84]));
	for(i=1; i<20; i=i+1){
  		magic = magic + raw_string(ord(reply[84+i]));
 	}

	x = strlen(value) + strlen(value) + 2;
	x_lo = x % 256;
	x_hi = x / 256;
 
	req = req + magic +
	      raw_string(x_lo, x_hi, x_lo, x_hi, 0x01, 0x00,
 			 0x00, 0x00, key_len_lo, key_len_hi, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, key_len_lo, key_len_hi, 0x00) + uc +
	      raw_string(0);

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 10){
		return(1);
	}
	error = substr(r, strlen(r) - 4, strlen(r) - 1);
 
	return ((int(ord(error[3])) * 256 + int(ord(error[2]))) * 256 +
		 int(ord(error[1])) * 256) + int(ord(error[0]));
 }

 #--------------------------------------------------------------#
 # RegShutdown()                                                #
 #--------------------------------------------------------------#
 function registry_shutdown(soc, uid, tid, pipe, message, timeout, reboot, closeapps)
 {
 	local_var _na_start, i, error, msg_len, msg_len_hi, msg_len_lo, tid_low, tid_high, uid_low, uid_high, pipe_low, pipe_high, uc;

	msg_len = strlen(message) + 1;
	msg_len_hi = msg_len / 256;
	msg_len_lo = msg_len % 256;
 
 	tid_low = tid % 256;
	tid_high = tid / 256;
	uid_low = uid % 256;
	uid_high = uid / 256;
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
	uc = unicode4(data:message);
 
	len = 146 + strlen(uc);
 
	len_hi = len / 256;
	len_lo = len % 256;
 
 	z = 38 + strlen(uc);
	z_lo = z % 256;
	z_hi = z / 256;
 
	y = 79 + strlen(uc);
	y_lo = y % 256;
	y_hi = y / 256;
 
	x = 62 + strlen(uc);
	x_lo = x % 256;
	x_hi = x / 256;
 
 	req = raw_string(0x00, 0x00,
 		         len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x00, 0x00 ) +
	      raw_string(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00,tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, x_lo, x_hi, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, x_lo, x_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, y_lo, y_hi, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, x_lo, x_hi,
			 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, z_lo, z_hi,
			 0x00, 0x00, 0x00, 0x00, 0x18, 0x00);

	x = strlen(message) + strlen(message);
	x_lo = x % 256;
	x_hi = x / 256;
	y = x + 2;
	y_lo = y % 256;
	y_hi = y / 256;

	msg_len2 = msg_len - 1;
	msg_len2_lo = msg_len2 % 256;
	msg_len2_hi = msg_len2 / 256;

	req += raw_string(0x01, 0x00, 0x00, 0x00,  # ptr_1
			  0x01, 0x00, 0x00, 0x00,  # ptr_2
			  0x01, 0x00, 0x00, 0x00,  # ptr_3
			  x_lo, x_hi,		     # uni_str_len
			  y_lo, y_hi,		     # max_str_len
			  0x01, 0x00, 0x00, 0x00,  # buffer
			  msg_len_lo, msg_len_hi, 0x00, 0x00,  # uni_max_len
			  0x00, 0x00, 0x00, 0x00 , # undoc
			  msg_len2_lo, msg_len2_hi, 0x00, 0x00);  # str_max_len
 	req += uc;
	req += raw_string(timeout % 256, (timeout/256) % 256, (timeout/(256*256)) % 256,
			  timeout / (256*256*256));
 	if(closeapps){
		req += raw_string(0x01);
	}
	else {
		req += raw_string(0x00);
	}
 
	if(reboot){
		req += raw_string(0x01);
	}
	else {
		req += raw_string(0x00);
	}

 	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 10){
		return(1);
	}
	error = substr(r, strlen(r) - 4, strlen(r) - 1);
 	return ((int(ord(error[3])) * 256 + int(ord(error[2]))) * 256 +
		 int(ord(error[1])) * 256 ) + int(ord(error[0]));
 }

 #----------------------------------------------------------#
 # RegEnumKey()                                             #
 #----------------------------------------------------------#
 function registry_enum_key(soc, uid, tid, pipe, reply)
 {
	local_var magic, req, r, tid_low, tid_high, uid_low, uid_high, pipe_low, pipe_high, name, data, list, i, j;
 
	list = make_list();
	tid_low = tid % 256;
	tid_high = tid / 256;
 
	uid_low = uid % 256;
	uid_high = uid / 256;
 
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	magic = raw_string(ord(reply[84]));		  
	for(i=1; i<20; i=i+1){
  		magic = magic + raw_string(ord(reply[84+i]));
  	}

 	for(j=0; j>=0; j++)
 	{
		req = raw_string(0x00, 0x00, 0x00, 0xa8, 0xFF, 0x53, 
				 0x4D, 0x42, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08,
				 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, tid_low, tid_high,
				 0x00, 0x28, uid_low, uid_high, g_mlo, g_mhi, 0x10, 0x00,
				 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x4c, 0x00, 0x5c, 0x00, 0x4c,
				 0x00, 0x02, 0x00, 0x26, 0x00, pipe_low, pipe_high, 0x65,
				 0x00, 0x5c, 0x50, 0x49, 0x50, 0x45, 0x5c, 0x00,
				 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x10, 0x00,
				 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xff, 0x00,
				 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x09, 0x00);

		req2= magic + raw_string(j % 256, j / 256, 0x00, 0x00,  # key ID
					 0x00, 0x00, 		    # key name len
					 0x14, 0x04,  		    # unknown
					 0x01, 0x00, 0x00, 0x00,   # ptr
					 0x0a, 0x02, 0x00, 0x00,   # unknown_2
					 0x00, 0x00, 0x00, 0x00,   # padding
					 0x00, 0x00, 0x00, 0x00,   # padding
					 0x01, 0x00, 0x00, 0x00,   # ptr2
					 0x00, 0x00, 0x00, 0x00,   # padding2
					 0x00, 0x00, 0x00, 0x00,   # padding2
					 0x01, 0x00, 0x00, 0x00,   # ptr3 
					 0xff, 0xff, 0xff, 0xff,   # smb_io_time low
					 0xff, 0xff, 0xff, 0x7f);   # smb_io_time high

	 	req += req2;
 		send(socket:soc, data:req);
		r = smb_recv(socket:soc, length:65535);
		if(strlen(r) < 80){
			return(NULL);
		}

		len = ord(r[60+24+16]);
		if(!len){
			break;
		}

		name = "";
		for(i=0; i<len - 1; i++){
			name += r[60+43+i*2+1];
		}
		list = make_list(list, name);
	}
	return list;
 }

 #----------------------------------------------------------#
 # RegEnumValue()                                           #
 #----------------------------------------------------------#
 # Author: Nicolas Pouvesle
 function registry_enum_value(soc, uid, tid, pipe, reply)
 {
 	local_var magic, req, r, tid_low, tid_high, uid_low, uid_high, pipe_low, pipe_high, name, data, list, i, j;
 
	tid_low = tid % 256;
	tid_high = tid / 256;
 
	uid_low = uid % 256;
	uid_high = uid / 256;
 
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	magic = raw_string(ord(reply[84]));		  
	for(i=1; i<20; i=i+1){
  		magic = magic + raw_string(ord(reply[84+i]));
	}

	for(j=0; j>=0; j++)
 	{
		req = raw_string(0x00, 0x00,
 				 0x00, 0xC0, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
				 0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x00, 0x83,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
				 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x6C, 0x00, 0x00,
				 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
				 0x00, 0x6C, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
				 0x00, pipe_low, pipe_high, 0x59, 0x00, 0x00, 0x5C, 0x00,
				 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
				 0x5C, 0x00, 0x00, 0x00, 0xEE, 0xD5, 0x05, 0x00,
				 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x6C, 0x00,
				 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00);

  		req = req + magic +
		      raw_string(j % 256, j / 256, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
				 0xcc, 0xf9, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0xa0, 0xf9, 0x06, 0x00, 0x59, 0xe6, 0x07, 0x00,
				 0x00, 0xc4, 0x04, 0x01, 0x00, 0x80, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0xb0, 0xf9, 0x06, 0x00, 0x00, 0x80, 0x00, 0x00,
				 0x94, 0xf9, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00); 

 		send(socket:soc, data:req);
		r = smb_recv(socket:soc, length:65535);
		if(strlen(r) < 80){
			return(NULL);
		}

		len = ord(r[60+24]);
		if(!len){
			break;
		}

		name = "";
		for(i=0; i<len; i=i+2){
			name += r[60+43+i+1];
		}

		if(!ord(r[60+43+len+2])){
			len+=2;
		}

		dlen = ord(r[60+43+len+21]);

		data = "";
		for(i=0;i<dlen;i = i+2){
			data += r[60+43+len+24+i+1];
		}

		list[j*2] = name;
		list[j*2+1] = data;
	}
	return list;
}

 #---------------------------------------------------------------------#
 # RegOpenKey()							      #
 #---------------------------------------------------------------------#
 function registry_get_key(soc, uid, tid, pipe, key, reply, write)
 {
 	local_var _na_start, i, error, access_mask;

	key_len = strlen(key) + 1;
	key_len_hi = key_len / 256;
	key_len_lo = key_len % 256;
 
 	tid_low = tid % 256;
	tid_high = tid / 256;
	uid_low = uid % 256;
	uid_high = uid / 256;
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
	uc = unicode(data:key);

	if(write){
		access_mask = raw_string(0x19, 0x00, 0x02, 0x02);
	}
	else {
		access_mask = raw_string(0x19, 0x00, 0x02, 0x00);
	}
 
	uc += access_mask;
	len = 148 + strlen(uc);
 
	len_hi = len / 256;
	len_lo = len % 256;
 
 	z = 40 + strlen(uc);
	z_lo = z % 256;
	z_hi = z / 256;
 
	y = 81 + strlen(uc);
	y_lo = y % 256;
	y_hi = y / 256;
 
	x = 64 + strlen(uc);
	x_lo = x % 256;
	x_hi = x / 256;
 
	if(strlen(reply) < 17){
		return NULL;
	}
	magic1 = raw_string(ord(reply[16]), ord(reply[17]));
 
	req = raw_string(0x00, 0x00,
 			 len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80) + magic1 +
	      raw_string(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00,tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, x_lo, x_hi, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, x_lo, x_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, y_lo, y_hi, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, x_lo, x_hi,
			 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, z_lo, z_hi,
			 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00);
		  
	magic = raw_string(ord(reply[84]));
	for(i=1; i<20; i=i+1){
  		magic = magic + raw_string(ord(reply[84+i]));
	}

	x = strlen(key) + strlen(key) + 2;
	x_lo = x % 256;
	x_hi = x / 256;
 
	req = req + magic +
	      raw_string(x_lo, x_hi, 0x0A, 0x02, 0x00, 0xEC,
 			 0xFD, 0x7F, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, key_len_lo, key_len_hi, 0x00, 0x00) + uc;

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 10){
		return(FALSE);
	}
 
	len = ord(r[2])*256;
	len = len + ord(r[3]);
	if(len < 100){
		return(FALSE);
	}

	# pull the last 4 bytes off the end
	_na_start = (strlen(r) - 4);
	for (_na_cnt = 0; _na_cnt < 4; _na_cnt++){
		_na_data = _na_data + r[_na_start + _na_cnt];
	}

	# access denied, returned by Windows XP+
	if(_na_data == raw_string(0x05,0x00,0x00,0x00) ||
	   _na_data == raw_string(0x02, 0x00, 0x00, 0x00)){
		return(FALSE);
	}
	if(ord(r[9])==0){
		return(r);
	}
	else {
		return(FALSE);
	}
 }

 #------------------------------------------------------------------#
 # Return TRUE if someone else than the admin group, the owner      #
 # and the local system can modify the key                          #
 #------------------------------------------------------------------#
 function registry_key_writeable_by_non_admin(security_descriptor)
 {
 	local_var r, num_aces, size, start, s, i, mask, z, id_auth, num_auth, sub_auth, k, n, sid;
	local_var WRITE, ADMIN_SID, LOCAL_SYSTEM_SID, CREATOR_OWNER_SID; 
 
	if(isnull(security_descriptor)){
		return(NULL);
	}
	
	# write mask
	WRITE = 0x00010000 | 0x00040000 | 0x00080000 | 0x00000002 | 0x000004;

	# sids - written the nessus way

	ADMIN_SID = "1-000005-32-544";
	LOCAL_SYSTEM_SID = "1-000005-18";
	CREATOR_OWNER_SID = "1-000003-0";

 	r = security_descriptor;
	num_aces = 0;
	num_aces = ord(r[135]);
	num_aces = ord(r[134])+ num_aces*256;
	num_aces = ord(r[133])+ num_aces*256;
	num_aces = ord(r[132])+ num_aces*256;
	start = 137;
 	size = 0;
	s = start;

	for(i=0;i<num_aces;i=i+1)
 	{
		z = ord(r[s+2]);
		z = ord(r[s+1])+z*256;
		mask = ord(r[s+6]);
		mask = ord(r[s+5])+mask*256;
		mask = ord(r[s+4])+mask*256;
		mask = ord(r[s+3])+mask*256;
  
		id_auth = ord(r[s+14]);
		id_auth = string(ord(r[s+13]), id_auth);
		id_auth = string(ord(r[s+12]), id_auth);
		id_auth = string(ord(r[s+11]), id_auth);
		id_auth = string(ord(r[s+10]), id_auth);
		id_auth = string(ord(r[s+9]), id_auth);
  
		num_auths = ord(r[s+8]);
		sub_auths = "";
		k = 15;
		for(c = 0;c < num_auths; c = c+1)
		{
			n = ord(r[s+k+3]);
			n = ord(r[s+k+2])+n*256;
			n = ord(r[s+k+1])+n*256;
			n = ord(r[s+k])+n*256;
			k = k + 4;
			sub_auths = string(sub_auths,"-",n);
		}
  
		sid = string(ord(r[s+7]), "-", id_auth, sub_auths);
		# display("sid = ", sid, "\n");
		if(mask & WRITE)
		{
			#     display("writeable by ", sid, "\n");
			#	  display(mask & WRITE, "\n");
	
			if((sid != ADMIN_SID) && (sid != LOCAL_SYSTEM_SID) &&
	    		   (sid != CREATOR_OWNER_SID))
			{
				#display("sid != ", CREATOR_OWNER_SID, "\n");
				#display(mask, "\n");
				return(TRUE);
			}
      		}
		s = s + z;
 	} 
	return(FALSE);
 }

 #---------------------------------------------------------------------#
 # Get the security descriptor for a key                               #
 #---------------------------------------------------------------------#
 function registry_get_key_security(soc, uid, tid, pipe, reply)
 {
 	local_var magic, req, r, tid_low, tid_high, uid_low, uid_high, pipe_low, pipe_high;
 
	tid_low = tid % 256;
	tid_high = tid / 256;
 
	uid_low = uid % 256;
	uid_high = uid / 256;
 
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	req = raw_string(0x00, 0x00,
 			 0x00, 0x90, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x00, 0x83,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x3C, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x3C, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, 0x4D, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0xEE, 0xD5, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x3C, 0x00,
			 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x24, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00);

	if(strlen(reply) < 104){
		return(FALSE);
	}
 
	magic = raw_string(ord(reply[84]));		  
	for(i=1;i<20;i=i+1){
		magic = magic + raw_string(ord(reply[84+i]));
	}
 
	req = req + magic + raw_string(0x04) + crap(data:raw_string(0), length:15);
 
	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:65535);
 
	len1 =  ord(r[strlen(r) - 12]);
	len2 = ord(r[strlen(r) - 11]);
	len3 = ord(r[strlen(r) - 10]);
	len4 = ord(r[strlen(r) - 9]);
	req = raw_string(0x00, 0x00,
 			 0x00, 0x9C, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x00, 0x83,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x48, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, 0x59, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0xEE, 0xD5, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00,
			 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00);
		  
 	req = req + magic +
	      raw_string(0x04, 0x00, 0x00, 0x00, 0x38, 0x8d,
			 0x07, 0x00, len1, len2, len3, len4, 0x00, 0x00,
			 0x00, 0x00, len1, len2, len3, len4, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:65535);
	if(strlen(r) < 150){
		return(NULL);
	}
	return(r);
 }

 #---------------------------------------------------------------------#
 # returns 'TRUE' if <key> exists				       #
 #---------------------------------------------------------------------#
 function registry_key_exists(key)
 {
 	local_var name, domain, _smb_port, login, pass, soc, r, uid, tid, pipe, ret, prot;
	local_var magic, flag, i;
 
	name =  kb_smb_name();
	if(!name){
		return NULL;
	}

	domain = kb_smb_domain();
	_smb_port = kb_smb_transport();
	if(!_smb_port){
		return NULL;
	}

	if(!get_port_state(_smb_port)){
		return(FALSE);
	}

	login = kb_smb_login();
	pass  = kb_smb_password();

	if(!login){
		login = "";
	}
	if(!pass){
		pass = "";
	}

	soc = open_sock_tcp(_smb_port);
	if(!soc){
		return NULL;
	}

	# Request the session
	r = smb_session_request(soc:soc,  remote:name);
	if(!r){
		return(FALSE);
	}

	# Negociate the protocol
	prot = smb_neg_prot(soc:soc);
	if(!prot){
		return(FALSE);
	}

	# Set up our session
	r = smb_session_setup(soc:soc, login:login, password:pass, domain:domain, prot:prot);
	if(!r){
		return(FALSE);
	}
	# and extract our uid
	uid = session_extract_uid(reply:r);
	if(!uid){
		return(FALSE);
	}

	# Connect to the remote IPC and extract the TID
	# we are attributed
	r = smb_tconx(soc:soc, name:name, uid:uid, share:"IPC$");
	# and extract our tree id
	tid = tconx_extract_tid(reply:r);
	if(!tid){
		return(NULL);
	}

	#
	# Create a pipe to \winreg
	#
	r = smbntcreatex(soc:soc, uid:uid, tid:tid, name:"\winreg");
	if(!r){
		return(NULL);
	}
	# and extract its ID
	pipe = smbntcreatex_extract_pipe(reply:r);

	#
	# Setup things
	#

	r = pipe_accessible_registry(soc:soc, uid:uid, tid:tid, pipe:pipe);
	if(!r){
		return(FALSE);
	}
	r = registry_open_hklm(soc:soc, uid:uid, tid:tid, pipe:pipe);
	r2 = registry_get_key(soc:soc, uid:uid, tid:tid, pipe:pipe, key:key, reply:r);
	close(soc);
	if(!r2 && strlen(r2) < 104){
		return NULL;
	}
	#flag = 0;
	for(i=1; i<20; i=i+1)
 	{
		if(ord(r2[84+i]) != 0)
  		{
			return TRUE; 
			#flag = 1;
		}
	}

	#if ( flag ) return TRUE;
	#else return NULL;
	return NULL;
 }

 #---------------------------------------------------------------------#
 # returns 'TRUE' if <key> is writeable				       #
 #---------------------------------------------------------------------#
 function registry_get_acl(key)
 {
 	local_var name, domain, _smb_port, login, pass, soc, r, uid, tid, pipe, ret, prot;
 
	name = kb_smb_name();
	if(!name){
		return NULL;
	}

	domain = kb_smb_domain();
	_smb_port = kb_smb_transport();
	if(!_smb_port){
		return NULL;
	}

	if(!get_port_state(_smb_port)){
		return(FALSE);
	}

	login = kb_smb_login();
	pass  = kb_smb_password();

	if(!login){
		login = "";
	}
	if(!pass){
		pass = "";
	}

	soc = open_sock_tcp(_smb_port);
	if(!soc){
		return NULL;
	}

	# Request the session
	r = smb_session_request(soc:soc,  remote:name);
	if(!r){
		return(FALSE);
	}

	# Negociate the protocol
	prot = smb_neg_prot(soc:soc);
	if(!prot){
		return(FALSE);
	}

	# Set up our session
	r = smb_session_setup(soc:soc, login:login, password:pass, domain:domain, prot:prot);
	if(!r){
		return(FALSE);
	}
	# and extract our uid
	uid = session_extract_uid(reply:r);
	if(!uid){
		return(NULL);
	}

	# Connect to the remote IPC and extract the TID
	# we are attributed
	r = smb_tconx(soc:soc, name:name, uid:uid, share:"IPC$");
	if(!r){
		return(NULL);
	}
	# and extract our tree id
	tid = tconx_extract_tid(reply:r);
	if(!tid){
		return(NULL);
	}

	# Create a pipe to \winreg
	r = smbntcreatex(soc:soc, uid:uid, tid:tid, name:"\winreg");
	if(!r){
		return(NULL);
	}
	# and extract its ID
	pipe = smbntcreatex_extract_pipe(reply:r);
	if(!pipe){
		return(FALSE);
	}

	# Setup things
	r = pipe_accessible_registry(soc:soc, uid:uid, tid:tid, pipe:pipe);
	if(!r){
		return(FALSE);
	}
	r = registry_open_hklm(soc:soc, uid:uid, tid:tid, pipe:pipe);
	if(!r){
		return(FALSE);
	}

	if(key){
		 r2 = registry_get_key(soc:soc, uid:uid, tid:tid, pipe:pipe, key:key, reply:r);
	}
	else {
		r2 = r;
	}

	if(r2)
 	{
		r3 = registry_get_key_security(soc:soc, uid:uid, tid:tid, pipe:pipe, reply:r2);
		if(!r3){
			return(FALSE);
		}
		registry_close(soc:soc, uid:uid, tid:tid, pipe:pipe, reply:r2);
		registry_close(soc:soc, uid:uid, tid:tid, pipe:pipe, reply:r);
		close(soc);
 
		if(strlen(r3) < 100){
			return(NULL);
		}
		return(r3);
	}
	return(NULL);
 }

 #---------------------------------------------------------------------#
 # Get an item of type reg_sz from the key                             #
 #---------------------------------------------------------------------#
 function unicode2(data)
 {
 	len = strlen(data);
	ret = raw_string(0, ord(data[0]));
 
	for(i=1; i<len; i=i+1){
  		ret = ret + raw_string(0, ord(data[i]));
	}
	if(len & 1){
		ret = ret + raw_string(0x00, 0x00);
	}
	else {
		ret = ret + raw_string(0x00, 0x00, 0x00, 0x63);
	}
	return(ret);
 }

 function unicode3(data)
 {
 	len = strlen(data);
	ret = raw_string(0, ord(data[0]));
 
	for(i=1; i<len; i=i+1){
  		ret = ret + raw_string(0, ord(data[i]));
	}
	if(len & 1){
		ret = ret + raw_string(0x00, 0x00);
	}
	else {
		ret = ret + raw_string(0x00, 0x00, 0x00, 0x00);
	}
	return(ret);
 }

 function unicode4(data)
 {
 	len = strlen(data);
	ret = raw_string(0, ord(data[0]));
 
	for(i=1; i<len; i=i+1){
		ret = ret + raw_string(ord(data[i]),0);
	}
	if(len & 1){
		ret = ret + raw_string(0x00);
	}
	return(ret);
 }

 function registry_get_item_sz(soc, uid, tid, pipe, item, reply)
 {
 	local_var i;
	item_len = strlen(item) + 1;
	item_len_lo = item_len % 256;
	item_len_hi = item_len / 256;
 
	uc2 = unicode2(data:item);
	len = 188 + strlen(uc2);
	len_lo = len % 256;
	len_hi = len / 256;
 
	tid_low = tid % 256;
	tid_high = tid / 256;
	uid_low = uid % 256;
	uid_high = uid / 256;
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	bcc = 121 + strlen(uc2);
	bcc_lo = bcc % 256;
	bcc_hi = bcc / 256;
 
	y = 80 + strlen(uc2);
	y_lo = y % 256;
	y_hi = y / 256;
 
	z = 104 + strlen(uc2);
	z_lo = z % 256;
	z_hi = z / 256;
	req = raw_string(0x00, 0x00,
 			 len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x1D, 0x83,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, z_lo, z_hi, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, z_lo, z_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, bcc_lo, bcc_hi, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, z_lo, z_hi,
			 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, y_lo, y_hi,
			 0x00, 0x00, 0x00, 0x00, 0x11, 0x00);
		  
	if(strlen(reply) < 104){
		return(FALSE);
	}
	magic = raw_string(ord(reply[84]));
	for(i=1;i<20;i=i+1){
  		magic = magic + raw_string(ord(reply[84+i]));
	}

	x = 2 + strlen(item) + strlen(item);
	x_lo = x % 256;
	x_hi = x / 256;
  
	y = y + 3;
	y_lo = y % 256;
	y_hi = y / 256;
 
	req = req + magic +
	      raw_string(x_lo, x_hi, 0x0A, 0x02, 0x00, 0xEC,
  			 0xFD, 0x7F, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, item_len_lo, item_len_hi, 0x00) + uc2 + 
	      raw_string(0x00, 0x34, 0xFF,
			 0x12, 0x00, 0xEF, 0x10, 0x40, 0x00, 0x18, 0x1E,
			 0x7c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xFF,
			 0x12, 0x00, 0x00, 0x04, 0x00, 0x00, 0x30, 0xFF,
			 0x12, 0x00, 0x00, 0x00, 0x00, 0x00);
 	send(socket:soc, data:req);
	req = smb_recv(socket:soc, length:4000);		
	return(req);
 }

 #------------------------------------------------------#
 # Decode the reply from the registry                   #
 #------------------------------------------------------#
 function registry_decode_binary(data)
 {
 	local_var i, o, len, index;

	len = ord(data[2])*256;
	len = len + ord(data[3]);
	if(len < 130){
		return(NULL);
	}
 
	data_offset = ord(data[52])*256;
	data_offset = data_offset + ord(data[51]) + 4;
	data_len = ord(data[data_offset+43]);
	data_len = data_len * 256;
	data_len = data_len + ord(data[data_offset+44]);
	index = data_offset + 48;
	o = "";
	data_len = data_len - 2;
	for(i=0; i<data_len; i=i+1){
   		o = string(o, raw_string(ord(data[index+i])));
	}
	return(o);
 }

 function registry_decode_sz(data)
 {
 	local_var i, o, len, index;

	len = ord(data[2])*256;
	len = len + ord(data[3]);
	if(len < 128){
		return(NULL);
	}
 
	data_offset = ord(data[52])*256;
	data_offset = data_offset + ord(data[51]) + 4;
	data_len = ord(data[data_offset+47]);
	data_len = data_len * 256 + ord(data[data_offset+46]);
	data_len = data_len * 256 + ord(data[data_offset+45]);
	data_len = data_len * 256 + ord(data[data_offset+44]);
	index = data_offset + 48;
	o = "";
	data_len = data_len - 2;
 
	for(i=0; i<data_len; i=i+2){
		o = string(o, raw_string(ord(data[index+i])));
	}
	return(o);
 }

 #---------------------------------------------------------------------#
 #---------------------------------------------------------------------#
 # Get an item of type reg_dword from the key                          #
 #---------------------------------------------------------------------#
 function registry_get_item_dword(soc, uid, tid, pipe, item, reply)
 {
 	local_var item_len, item_len_lo, item_len_hi, uc2, len, len_lo, len_hi, tid_low, tid_high, uid_low, uid_high;
	local_var pipe_low, pipe_high, bcc, bcc_lo, bcc_hi, y, y_lo, y_hi, z, z_lo, z_hi, req;
	local_var magic, x, x_lo, x_hi;
	item_len = strlen(item) + 1;
	item_len_lo = item_len % 256;
	item_len_hi = item_len / 256;
 
	uc2 = unicode2(data:item);
	len = 188 + strlen(uc2);
	len_lo = len % 256;
	len_hi = len / 256;
 
	tid_low = tid % 256;
	tid_high = tid / 256;
	uid_low = uid % 256;
	uid_high = uid / 256;
	pipe_low = pipe % 256;
	pipe_high = pipe / 256;
 
	bcc = 121 + strlen(uc2);
	bcc_lo = bcc % 256;
	bcc_hi = bcc / 256;
 
	y = 80 + strlen(uc2);
	y_lo = y % 256;
	y_hi = y / 256;
 
	z = 104 + strlen(uc2);
	z_lo = z % 256;
	z_hi = z / 256;

	req = raw_string(0x00, 0x00,
 			 len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x1D, 0x83,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, z_lo, z_hi, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, z_lo, z_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_low, pipe_high, bcc_lo, bcc_hi, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, z_lo, z_hi,
			 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, y_lo, y_hi,
			 0x00, 0x00, 0x00, 0x00, 0x11, 0x00);
		  
	magic = raw_string(ord(reply[84]));
	for(i=1; i<20; i=i+1){
   		magic = magic + raw_string(ord(reply[84+i]));
	}

 	x = 2 + strlen(item) + strlen(item);
	x_lo = x % 256;
	x_hi = x / 256;
  
	y = y + 3;
	y_lo = y % 256;
	y_hi = y / 256;
 
	req = req + magic +
	      raw_string(x_lo, x_hi, 0x0A, 0x02, 0x00, 0xEC,
			 0xFD, 0x7F, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, item_len_lo, item_len_hi, 0x00) + uc2 + 
	      raw_string(0x00, 0x34, 0xFF,
			 0x12, 0x00, 0xEF, 0x10, 0x40, 0x00, 0x18, 0x1E,
			 0x7c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xFF,
			 0x12, 0x00, 0x00, 0x04, 0x00, 0x00, 0x30, 0xFF,
			 0x12, 0x00, 0x00, 0x00, 0x00, 0x00);
		
	send(socket:soc, data:req);
	req = smb_recv(socket:soc, length:4000);		
	return(req);
 }	  

 #------------------------------------------------------#
 # Decode the reply from the registry                   #
 #------------------------------------------------------#
 function registry_decode_dword(data)
 {
 	len = ord(data[2])*256;
	len = len + ord(data[3]);
	if(len < 126)return(NULL);
 
	data_offset = ord(data[52])*256;
	data_offset = data_offset + ord(data[51]) + 4;
	data_len = ord(data[data_offset+43]);
	data_len = data_len * 256;
	data_len = data_len + ord(data[data_offset+44]);
	index = data_offset + 48;
	o = "";
	for(i=data_len; i>0; i=i-1)
	{
		t *= 256;
		t += ord(data[index+i-1]);
	}
	return(t);
 }
			  
		 
 #---------------------------------------------------------------------#
 # registry_get_dword()						      #
 #---------------------------------------------------------------------#
 function registry_get_dword(key, item)
 {
 	local_var name, port, login, pass, soc, dom, r, prot, value;
 
	if(get_kb_item("SMB/samba")){
		return NULL;
	}
 
	port = kb_smb_transport();
	if(!port){
		return NULL;
	}

	name = kb_smb_name();
	if(!name){
		return NULL;
	}

	if(!get_port_state(port)){
		return(FALSE);
	}

	login = kb_smb_login();
	pass  = kb_smb_password();

	if(!login){
		login = "";
	}
	if(!pass){
		pass = "";
	}

	dom = kb_smb_domain();
	  
	soc = open_sock_tcp(port);
	if(!soc){
		return NULL;
	}

 	# Request the session
 	r = smb_session_request(soc:soc,  remote:name);
	if(!r)
	{
		close(soc);
		return NULL;
	}

 	# Negociate the protocol
	prot = smb_neg_prot(soc:soc);
	if(!prot)
	{
		close(soc);
		return NULL;
	}

 	# Set up our session
	r = smb_session_setup(soc:soc, login:login, password:pass, domain:dom, prot:prot);
	if(!r)
	{
		close(soc);
		return NULL;
	}

	# and extract our uid
	uid = session_extract_uid(reply:r);
	if(!uid)
	{
		close(soc);
		return NULL;
	}

 	# Connect to the remote IPC and extract the TID
	# we are attributed
 	r = smb_tconx(soc:soc, name:name, uid:uid, share:"IPC$");
	if(!r)
	{
		close(soc);
		return NULL;
	}

	# and extract our tree id
	tid = tconx_extract_tid(reply:r);
	if(!tid)
	{
		close(soc);
		return NULL;
	}

	# Create a pipe to \winreg
 	r = smbntcreatex(soc:soc, uid:uid, tid:tid, name:"\winreg");
	if(!r)
	{
		close(soc);
		return(NULL);
	}

	 # and extract its ID
	pipe = smbntcreatex_extract_pipe(reply:r);
	if(!pipe)
	{
		close(soc);
		return NULL;
	}

	# Setup things
 	r = pipe_accessible_registry(soc:soc, uid:uid, tid:tid, pipe:pipe);
	if(!r)
	{
		close(soc);
		return(NULL);
	}
	r = registry_open_hklm(soc:soc, uid:uid, tid:tid, pipe:pipe);
	if(!r)
	{
		close(soc);
		return NULL;
	}

	r2 = registry_get_key(soc:soc, uid:uid, tid:tid, pipe:pipe, key:key, reply:r);
	if(r2)
 	{
		r3 = registry_get_item_dword(soc:soc, uid:uid, tid:tid, pipe:pipe, item:item, reply:r2);
 		registry_close(soc:soc, uid:uid, tid:tid, pipe:pipe, reply:r2);
		registry_close(soc:soc, uid:uid, tid:tid, pipe:pipe, reply:r);
		value = registry_decode_dword(data:r3);
		close(soc);
		return(value); 
	}
	close(soc);
	return NULL;
 }

 #---------------------------------------------------------------------#
 # registry_get_binary()					       #
 #---------------------------------------------------------------------#
 function registry_get_binary(key, item)
 {
 	local_var name, _smb_port, login, pass, domain, soc, uid, tid, r, prot, pipe;

	if(get_kb_item("SMB/samba")){
		return NULL;
	}

	name = kb_smb_name();
	if(!name){
		return NULL;
	}

	_smb_port = kb_smb_transport();
	if(!_smb_port){
		return NULL;
	}

	if(!get_port_state(_smb_port)){
		return(FALSE);
	}

	login = kb_smb_login();
	pass  = kb_smb_password();
	domain = kb_smb_domain();

	if(!login){
		login = "";
	}
	if(!pass){
		pass = "";
	}

	soc = open_sock_tcp(_smb_port);
	if(!soc){
		return(FALSE);
	}

	# Request the session
	r = smb_session_request(soc:soc,  remote:name);
	if(!r)
	{
		close(soc);
		return(FALSE);
	}

	# Negociate the protocol
	prot = smb_neg_prot(soc:soc);
	if(!prot)
	{
		close(soc);
		return(FALSE);
	}

	# Set up our session
	r = smb_session_setup(soc:soc, login:login, password:pass, domain:domain, prot:prot);
	if(!r)
	{
		close(soc);
		return(FALSE);
	}

	# and extract our uid
	uid = session_extract_uid(reply:r);
	if(!uid)
        {
                close(soc);
                return NULL;
        }

	# Connect to the remote IPC and extract the TID
	# we are attributed
	r = smb_tconx(soc:soc, name:name, uid:uid, share:"IPC$");
	if(!r)
        {
                close(soc);
                return NULL;
        }

	# and extract our tree id
	tid = tconx_extract_tid(reply:r);
	if(!tid)
	{
		close(soc);
		return(FALSE);
	}

	# Create a pipe to \winreg
	r = smbntcreatex(soc:soc, uid:uid, tid:tid, name:"\winreg");
	if(!r)
	{
		close(soc);
		return(FALSE);
	}
	# and extract its ID
	pipe = smbntcreatex_extract_pipe(reply:r);

	# Setup things
	r = pipe_accessible_registry(soc:soc, uid:uid, tid:tid, pipe:pipe);
	if(!r)
	{
		close(soc);
		return(FALSE);
	}
	r = registry_open_hklm(soc:soc, uid:uid, tid:tid, pipe:pipe);
	if(!r)
        {
                close(soc);
                return NULL;
        }

	r2 = registry_get_key(soc:soc, uid:uid, tid:tid, pipe:pipe, key:key, reply:r);
	if(r2)
	{
		r3 =  registry_get_item_sz(soc:soc, uid:uid, tid:tid, pipe:pipe, item:item, reply:r2);
		registry_close(soc:soc, uid:uid, tid:tid, pipe:pipe, reply:r2);
		registry_close(soc:soc, uid:uid, tid:tid, pipe:pipe, reply:r);
		value = registry_decode_binary(data:r3);
		close(soc);
		return(value);
	}
	close(soc);
	return(FALSE);
 }
		 
 #---------------------------------------------------------------------#
 # registry_get_sz()						      #
 #---------------------------------------------------------------------#
 function registry_get_sz(key, item)
 {
 	local_var name, _smb_port, login, pass, domain, soc, uid, tid, r, prot, pipe;
	if(get_kb_item("SMB/samba")){
		return NULL;
	}

	name = kb_smb_name();
	if(!name){
		return NULL;
	}

	_smb_port = kb_smb_transport();
	if(!_smb_port){
		return NULL;
	}

	if(!get_port_state(_smb_port)){
		return(FALSE);
	}

	login = kb_smb_login();
	pass  = kb_smb_password();
	domain = kb_smb_domain();

	if(!login){
		login = "";
	}
	if(!pass){
		pass = "";
	}

	soc = open_sock_tcp(_smb_port);
	if(!soc){
		return(FALSE);
	}

	# Request the session
	r = smb_session_request(soc:soc,  remote:name);
	if(!r)
	{
		close(soc);
		return(FALSE);
	}

	# Negociate the protocol
	prot = smb_neg_prot(soc:soc);
	if(!prot)
	{
		close(soc);
		return(FALSE);
	}

	# Set up our session
	r = smb_session_setup(soc:soc, login:login, password:pass, domain:domain, prot:prot);
	if(!r)
	{
		close(soc);
		return(FALSE);
	 }
	# and extract our uid
	uid = session_extract_uid(reply:r);
	if(!uid)
	{
		close(soc);
		return(FALSE);
	}

	# Connect to the remote IPC and extract the TID
	# we are attributed
	r = smb_tconx(soc:soc, name:name, uid:uid, share:"IPC$");
	if(!r)
	{
		close(soc);
		return(FALSE);
	}

	# and extract our tree id
	tid = tconx_extract_tid(reply:r);
	if(!tid)
	{
		close(soc);
		return(FALSE);
	}

	# Create a pipe to \winreg
	r = smbntcreatex(soc:soc, uid:uid, tid:tid, name:"\winreg");
	if(!r)
	{
		close(soc);
		return(FALSE);
	}
	# and extract its ID
	pipe = smbntcreatex_extract_pipe(reply:r);
	if(!pipe)
	{
		close(soc);
		return(FALSE);
	}

	# Setup things
	r = pipe_accessible_registry(soc:soc, uid:uid, tid:tid, pipe:pipe);
	if(!r)
	{
		close(soc);
		return(FALSE);
	}
	r = registry_open_hklm(soc:soc, uid:uid, tid:tid, pipe:pipe);
	if(!r)
	{
		close(soc);
		return(FALSE);
	}

	r2 = registry_get_key(soc:soc, uid:uid, tid:tid, pipe:pipe, key:key, reply:r);
	if(r2)
	{
		r3 =  registry_get_item_sz(soc:soc, uid:uid, tid:tid, pipe:pipe, item:item, reply:r2);
		registry_close(soc:soc, uid:uid, tid:tid, pipe:pipe, reply:r2);
		registry_close(soc:soc, uid:uid, tid:tid, pipe:pipe, reply:r);
		if(r3){
			value = registry_decode_sz(data:r3);
		}
		close(soc);
		return(value);
	}
	close(soc);
	return(FALSE);
 }

 #---------------------------------------------------------------------------#
 # SAM related functions							    #
 #---------------------------------------------------------------------------#

 #------------------------------------------------------#
 # Open a pipe to \samr                                 #
 #------------------------------------------------------#
 function OpenPipeToSamr(soc, uid, tid)
 {
	tid_hi = tid / 256;
	tid_lo = tid % 256;
 
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
 	req = raw_string(0x00, 0x00,
 			 0x00, 0x60, 0xFF, 0x53, 0x4D, 0x42, 0xA2, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x18, 0xFF, 0x00, 0xDE, 0xDE, 0x00,
			 0x0A, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 
			 0x00, 0x00, 0x9F, 0x01, 0x02, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
			 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00,
			 0x00, 0x00, 0x03, 0x0D, 0x00, 0x00, 0x5C, 0x00,
			 0x73, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x72, 0x00,
			 0x00, 0x00);
		  
 	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 42){
		return(FALSE);
	}
	else
	{
		low = ord(r[42]);
		hi  = ord(r[43]);
		ret = hi * 256;
		ret = ret + low;
		return(ret);
	}
 }

 function samr_smbwritex(soc, tid, uid, pipe)
 {
 	tid_hi = tid / 256;
	tid_lo = tid % 256;
 
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
	req = raw_string(0x00, 0x00,
 			 0x00, 0x88, 0xFF, 0x53, 0x4D, 0x42, 0x2F, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x0E, 0xFF, 0x00, 0xDE, 0xDE, pipe_lo,
			 pipe_hi, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
			 0xFF, 0x08, 0x00, 0x48, 0x00, 0x00, 0x00, 0x48,
			 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
			 0x00, 0xEE, 0x05, 0x00, 0x0B, 0x03, 0x10, 0x00,
			 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00,
			 0x00, 0x00, 0xB8, 0x10, 0xB8, 0x10, 0x00, 0x00,
			 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x01, 0x00, 0x78, 0x57, 0x34, 0x12, 0x34, 0x12,
			 0xCD, 0xAB, 0xEF, 0x00, 0x01, 0x23, 0x45, 0x67,
			 0x89, 0xAC, 0x01, 0x00, 0x00, 0x00, 0x04, 0x5D,
			 0x88, 0x8A, 0xEB, 0x1C, 0xC9, 0x11, 0x9F, 0xE8,
			 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60, 0x02, 0x00,
			 0x00, 0x00);
		  
	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
 }		

 function samr_smbreadx(soc, tid, uid, pipe)
 {
 	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
	req = raw_string(0x00, 0x00,
 			 0x00, 0x3B, 0xFF, 0x53, 0x4D, 0x42, 0x2E, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x0C, 0xFF, 0x00, 0xDE, 0xDE, pipe_lo,
			 pipe_hi, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
			 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x04, 0x00, 
			 0x00, 0x00, 0x00, 0x00, 0x00);
		  
	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
 }		    

 #------------------------------------------------------#
 # Returns the unicode representation of <name>         #
 #------------------------------------------------------#
 function samr_uc(name)
 {
 	ret = "";
	for(i=0; i<strlen(name); i=i+1){
  		ret = ret + raw_string(0) + name[i];
 	}
	return(ret);
 }

 #------------------------------------------------------#
 # Connects to the remote SAM                           #
 #------------------------------------------------------#
 function SamrConnect2(soc, tid, uid, pipe, name)
 {
 	samr_smbwritex(soc:soc, tid:tid, uid:uid, pipe:pipe);
	samr_smbreadx(soc:soc, tid:tid, uid:uid, pipe:pipe);
 
	l = strlen(name);
	odd = l % 2;
 
	if(odd){
		p = 0;
	}
	else {
		p = 2;
	}
 
	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
 	l = 3 + strlen(name);
	l_h = l / 256;
	l_l = l % 256;

	tot_len = 134 + strlen(name) + strlen(name) + p;
	tot_len_h = tot_len / 256;
	tot_len_l = tot_len % 256;
 
	bcc = 67 + strlen(name) + strlen(name) + p;
	bcc_lo = bcc % 256;
	bcc_hi = bcc / 256;
 
	total_data_count = 50 + strlen(name) + strlen(name) + p;
	total_data_count_lo = total_data_count % 256;
	total_data_count_hi = total_data_count / 256;
 
	req = raw_string(0x00, 0x00,
 			 tot_len_h, tot_len_l, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00,total_data_count_lo, total_data_count_hi, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, total_data_count_lo, total_data_count_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, bcc_lo, bcc_hi, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0xAF, 0x47, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, total_data_count_lo, total_data_count_hi,
			 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x60, 0x60,
			 0x13, 0x00, l_l, l_h, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, l_l, l_h, 0x00, 0x00, 0x5C, 0x00,
			 0x5C) + samr_uc(name:name) + raw_string(0x00, 0x00, 0x00);
		  
	if(p){
		req = req + raw_string(0xC9, 0x11); # 0x02, 0x00, 0x00, 0x00);
	}
  
	req = req +  raw_string(0x30, 0x00, 0x00, 0x00);
	#display(strlen(req), "\n");		  
	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);		  
	#display("--->", strlen(r), "\n");

 	# We return a handle to the remote SAM
	samrhdl = "";
	_len = strlen(r);
	if(_len < 24){
		return(FALSE);
	}
	
	_len = _len - 24;
	for(i=0; i<20; i=i+1)
	{
		samrhdl = samrhdl + raw_string(ord(r[i+_len]));
		#display(hex(ord(r[i+_len])), " ");
	}
	#display("\n");
	#display("samhdl : ", strlen(samrhdl), "\n");
	return (samrhdl);
 }

 #--------------------------------------------------------------#
 # This function is probably SamrEnumerateDomainsInSamServer()  #
 # but I'm not sure of that, so I changed its name to           #
 # _SamrEnumDomains()                                           #
 #                                                              #
 # This function only returns the first domain it obtains       #
 #--------------------------------------------------------------#
 function _SamrEnumDomains(soc, uid, tid, pipe, samrhdl)
 {
 	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
	req = raw_string(0x00, 0x00,
 			 0x00, 0x88, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x34, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x34, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, 0x45, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0xAF, 0x47, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x34, 0x00,
			 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1C, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x06, 0x00) + samrhdl +
	      raw_string(0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00);
		  
	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);		  
	if(strlen(r) < 137){
		return(FALSE);
	}
 
	len_lo = ord(r[136]);
	len_hi = ord(r[137]);
 
	len = len_hi * 256;
	len = len + len_lo;
	dom = "";
	len = len*2;
	maxlen = strlen(r);
	if(maxlen < len)return(FALSE);
	for(i=0; i<len; i=i+2)
	{
  		if(maxlen < 139+i){
			return(FALSE);
		}
		dom = dom + raw_string(ord(r[139+i]), ord(r[140+i]));
 	}
	#display(dom, "\n");
	return(dom);  
 }


 #------------------------------------------------------#
 # Returns the sid from the domain <dom>                #
 #------------------------------------------------------#
 function SamrDom2Sid(soc, tid, uid, pipe, samrhdl, dom)
 {
 	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
	#display(strlen(dom), "<-dom\n");
	tot_len = 148 + strlen(dom);
	tot_len_hi = tot_len / 256;
	tot_len_lo = tot_len % 256;
 
	bcc = 81 + strlen(dom);
	bcc_lo = bcc % 256;
	bcc_hi = bcc / 256;
 
	tot_dat_count = 64 + strlen(dom);
	tot_dat_count_lo = tot_dat_count % 256;
	tot_dat_count_hi = tot_dat_count / 256;
 
	dom_len = strlen(dom);
	dom_len = dom_len / 2;
	dom_len_lo = dom_len % 256;
	dom_len_hi = dom_len / 256;
  
	dom_t_len =  dom_len + 1;
	dom_t_len_lo = dom_t_len % 256;
	dom_t_len_hi = dom_t_len / 256;
 
	dom_m_len = dom_len * 2;
	dom_m_len_lo = dom_m_len % 256;
	dom_m_len_hi = dom_m_len / 256;
 
	dom_mm_len = dom_m_len + 2;
	dom_mm_len_lo = dom_mm_len % 256;
	dom_mm_len_hi = dom_mm_len / 256;
 
 	req = raw_string(0x00, 0x00,
 			 tot_len_hi, tot_len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, tot_dat_count_lo, tot_dat_count_hi, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, tot_dat_count_lo, tot_dat_count_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, bcc_lo, bcc_hi, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0xAF, 0x47, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, tot_dat_count_lo, tot_dat_count_hi,
			 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x05, 0x00) + samrhdl + 
	      raw_string(dom_m_len_lo, dom_m_len_hi, dom_mm_len_lo, dom_mm_len_hi, 0x40, 0x7B,
			 0x13, 0x00, dom_t_len_lo, dom_t_len_hi, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, dom_len_lo, dom_len_hi, 0x00) + dom + raw_string(0x00);
		 
	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 88){
		return(FALSE);
	}
	#display(ord(r[88]), "\n");  
  	_sid = "";
  	for(i=0; i<28; i=i+1)
	{
		_sid = _sid + raw_string(ord(r[88+i]));
		 #display(hex(ord(r[88+i])),  " ");
  	}
	#display("\n");
	return (_sid);
 }

 #------------------------------------------------------#
 # Opens a policy handle to a given domain              #
 #------------------------------------------------------#
 function SamrOpenDomain(soc, tid, uid, pipe, samrhdl, sid)
 {
 	#display("sid = ", strlen(sid), "\n");
	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
 	len = 132 + strlen(sid);
	len_h = len / 256;
	len_l = len % 256;

	tdc = 48 + strlen(sid);
	tdc_l = tdc % 256;
	tdc_h = tdc / 256;
 
	bcc = tdc + 17;
	bcc_l = bcc % 256;
	bcc_h = bcc / 256;
	req = raw_string(0x00, 0x00,
 			 0x00, 0xA0, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x4C, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x4C, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, 0x5D, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x33, 0x00, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x4C, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x07, 0x00) + samrhdl +
	      raw_string(0x00, 0x02, 0x00, 0x00) + sid;
	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 30){
		return(FALSE);
	}
 	#display(strlen(r),"\n");
	samrhdl = "";
	_len = strlen(r);
	_len = _len - 24;
	_z = 0;
	for(i=0; i<20; i=i+1)
 	{
		if(ord(r[i+_len]) == 0)_z = _z + 1;
		samrhdl = samrhdl + raw_string(ord(r[i+_len]));
		#display(hex(ord(r[i+_len])), " ");
	}
	#display("\n");
	#display("samhdl : ", strlen(samrhdl), "\n");
	if(_z == 20){
		return(NULL);
	}
 	return(samrhdl);
 }

 #------------------------------------------------------#
 # NetUserModalsGet - does not work yet		       #
 #------------------------------------------------------#
 function SamrQueryDomainInfo(soc, tid, uid, pipe, samrhdl, level)
 {
 	#display("sid = ", strlen(sid), "\n");
	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
 	req = raw_string(0x00, 0x00,
 			 0x00, 0x82, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x2e, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x2e, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, 0x3f, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x45, 0x00, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2E, 0x00,
			 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x16, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x08, 0x00) + samrhdl +
	      raw_string(level % 256, level / 256);

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 30){
		return(FALSE);
	}
	return r;	
 }


 function SamrOpenBuiltin(soc, tid, uid, pipe, samrhdl)
 {
 	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;

	req = raw_string(0x00, 0x00,
 			 0x00, 0x94, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x40, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, 0x51, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00,
			 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x28, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x07, 0x00) + samrhdl +
	      raw_string(0x80, 0x02, 0x00, 0x00, 0x01, 0x00,
			 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x05, 0x20, 0x00, 0x00, 0x00);
		  
	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	builtinhdl = "";
	_len = strlen(r);
	_len = _len - 24;
	_z  = 0;
	for(i=0; i<20; i=i+1)
 	{
		if(ord(r[i+_len]) == 0){
			_z = _z + 1;
		}
		builtinhdl = builtinhdl + raw_string(ord(r[i+_len]));
		#display(hex(ord(r[i+_len])), " ");
 	}
	if(_z == 20){
		return(NULL);
	}
	#display("\n");
	#display("builtinhdl : ", strlen(builtinhdl), "\n");
	return(builtinhdl);
 }

 #------------------------------------------------------#
 # Converts a username to its rid                       #
 #------------------------------------------------------#
 function SamrLookupNames(soc, uid, tid, pipe, name, domhdl)
 {
 	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
	usr = samr_uc(name:name);
	len = 164 + strlen(usr);
	len_hi = len / 256;
	len_lo = len % 256;
 
	tdc = 80 + strlen(usr);
	tdc_l = tdc % 256;
	tdc_h = tdc / 256;
 
	bcc = tdc + 17;
	bcc_l = bcc % 256;
	bcc_h = bcc / 256;
 
	x = strlen(usr) / 2;
	x_h = x / 256;
	x_l = x % 256;
 
	y = x + 1;
	y_h = y / 256;
	y_l = y % 256;
 
	z = strlen(usr);
	z_l = z % 256;
	z_h = z / 256;
 
	t = z + 2;
	t_l = t % 256;
	t_h = t / 256;
 
	req = raw_string(0x00, 0x00, 
 			 len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, tdc_l, tdc_h, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, tdc_l, tdc_h, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, bcc_l, bcc_h, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0xAF, 0x47, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, tdc_l, tdc_h,
			 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x11, 0x00) + domhdl +
	      raw_string(0x01, 0x00, 0x00, 0x00, 0xE8, 0x03,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
			 0x00, 0x00, z_l, z_h, t_l, t_h, 0xD8, 0x0E, 
			 0x41, 0x00, y_l, y_h, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, x_l, x_h, 0x00) + usr + 
              raw_string(0x00);

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);		
 
	if(strlen(r) < 100){
		return(FALSE);
	}
 
	_rid = "";
	#display("RID : ");
	_z = 0;
	for(i=0; i<4; i=i+1)
	{
		if(ord(r[96+i]) == 0){	
			_z = _z + 1;
		}
		#display(hex(ord(r[96+i])), " ");
		_rid = _rid + raw_string(ord(r[96+i]));
	}
	#display("\n");
	if(_z == 4){
		return(NULL);
	} 
	return(_rid);
 }

 #--------------------------------------------------------#
 # Opens a policy handle to a given user                  #
 #--------------------------------------------------------#
 function SamrOpenUser(soc, uid, tid, pipe, samrhdl, rid)
 {
 	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
	len = 176;
	len_hi = len / 256;
	len_lo = len % 256;
 
	req = raw_string(0x00, 0x00,
 			 0x00, 0x88, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x34, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x34, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, 0x45, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x33, 0x00, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x34, 0x00,
			 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x22, 0x00) + samrhdl +
	      raw_string(0x1B, 0x01, 0x02, 0x00) + rid;

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
	if(strlen(r) < 100){
		return(FALSE);
	}
 
	_usrhdl = "";
	_len = strlen(r);
	_len = _len - 24;
	#display("usrhdl = ");
	_z = 0;
	for(i=0; i<20; i=i+1)
	{
		if(ord(r[i+_len]) == 0){
			_z = _z + 1;
		}
		_usrhdl = _usrhdl + raw_string(ord(r[i+_len]));
		#display(hex(ord(r[i+_len])), " ");
 	}
 	if(_z == 20){
		return(NULL);
	}
	#display("\n");
	return(_usrhdl);
 }

 #----------------------------------------------------------#
 # Requests the list of groups to which the user belongs to #
 #----------------------------------------------------------#
 function SamrQueryUserGroups(soc, uid, tid, pipe, usrhdl)
 {
 	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
	req = raw_string(0x00, 0x00,
 			 0x00, 0x80, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x2C, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x2C, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26, 
			 0x00, pipe_lo, pipe_hi, 0x3D, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00,
			 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x27, 0x00) + usrhdl;
 	send(socket:soc, data:req);
	r = recv(socket:soc, length:4096); 
 
 	num_lo = ord(r[88]);
	num_hi = ord(r[89]);
 
	num = num_hi * 256;
	num = num + num_lo;
 
	# Ok. Our user is in <num> groups. Let's decode their RID
 
	if(strlen(r) < 103){
		return(FALSE);
	}
	base = 100;
	rids = "";
	for(i=0; i<num; i=i+1)
	{
		g_rid = string(hex(ord(r[base+3])), "-", 
		hex(ord(r[base+2])), "-",
		hex(ord(r[base+1])), "-",
		hex(ord(r[base])));
	   
		base = base + 8;
		rids = rids + g_rid + string("\n");
 	}	
	return(rids);
 }

 #------------------------------------------------------#
 # Queries information about a given user               #
 #------------------------------------------------------#
 function SamrQueryUserInfo(soc, uid, tid, pipe, usrhdl)
 {
	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
	req = raw_string(0x00, 0x00,
 			 0x00, 0x82, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x2E, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x2E, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, 0x3F, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x33, 0x00, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2E, 0x00,
			 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x24, 0x00) + usrhdl +
	      raw_string(0x15, 0x00);

	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);

	return (r);
 }

 #-----------------------------------------------------------#
 # Requests the list of aliases to which the user belongs to #
 #-----------------------------------------------------------#
 function SamrQueryUserAliases(soc, uid, tid, pipe, usrhdl, sid, rid)
 {
 	tid_hi = tid / 256;
	tid_lo = tid % 256;
	uid_hi = uid / 256;
	uid_lo = uid % 256;
 
	pipe_hi = pipe / 256;
	pipe_lo = pipe % 256;
 
	subsid = "";
 
	for(i=0; i<20; i=i+1)
	{
		subsid = subsid + raw_string(ord(sid[8+i]));
		#display(hex(ord(sid[8+i])), " ");
	}
	#display("\n");
 
	req = raw_string(0x00, 0x00, 
 			 0x00, 0xB0, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
			 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28, uid_lo, uid_hi,
			 g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00,
			 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
			 0x00, 0x5C, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
			 0x00, pipe_lo, pipe_hi, 0x6D, 0x00, 0x00, 0x5C, 0x00,
			 0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
			 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
			 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x5C, 0x00,
			 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x44, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x10, 0x00) + usrhdl +
	      raw_string(0x01, 0x00, 0x00, 0x00, 0x88, 0x7C,
       	 		 0x13, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x7C,
			 0x13, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x05,
			 0x00, 0x00) + subsid + rid;
		  
	send(socket:soc, data:req);
	r = smb_recv(socket:soc, length:4096);
 
	if(strlen(r) < 100)
	{
 		#display("=====>", strlen(r), "<====\n");
		return(FALSE);
	}
 
 	num_lo = ord(r[92]);
	num_hi = ord(r[93]);
 
	num = num_hi * 256;
	num = num + num_lo;
	#display("NUM EGAL : ", num, "\n");
	base = 96;
	rids = "";
	for(i=0; i<num; i=i+1)
 	{
		_rid = string(hex(ord(r[base+3])), "-",
  			      hex(ord(r[base+2])), "-",
			      hex(ord(r[base+1])), "-",
			      hex(ord(r[base])));
  		rids = rids + _rid + string("\n");		
		base = base + 4;		
	}
	return(rids);
 }

 function _ExtractTime(buffer, base)
 {
	if(strlen(buffer) < base + 8){
		return(FALSE);
	}

	return(string(hex(ord(buffer[base+7])), "-",
 		      hex(ord(buffer[base+6])), "-",
		      hex(ord(buffer[base+5])), "-",
		      hex(ord(buffer[base+4])), "-",
		      hex(ord(buffer[base+3])), "-",
		      hex(ord(buffer[base+2])), "-",
		      hex(ord(buffer[base+1])), "-",
		      hex(ord(buffer[base]))));
 }

 #------------------------------------------------------#
 # Decodes the informations received about a given usr  #
 # This function is not part of MSDN, hence the under-  #
 # score in front of it                                 #
 #------------------------------------------------------#
 function _SamrDecodeUserInfo(info, count, type)
 {
 	lim = strlen(info);

	if(strlen(info) < 100){
 		return(FALSE);
	}
	
	# Various times
 	logon = _ExtractTime(buffer:info, base:92);
	#display("Logon time : ", logon, "\n");
 
	set_kb_item(name:string("SMB/", type, "/", count, "/Info/LogonTime"),
 		    value:logon);
	     
 	logoff = _ExtractTime(buffer:info, base:100);
	#display("Logoff time : ", logoff, "\n");
	set_kb_item(name:string("SMB/", type, "/", count, "/Info/LogoffTime"),
 		    value:logoff);

	if(strlen(info) < 116){
		return(FALSE);
	}
 
 	kickoff = _ExtractTime(buffer:info, base:108);
	#display("Kickoff time : ", kickoff, "\n");
	set_kb_item(name:string("SMB/", type, "/", count, "/Info/KickoffTime"),
 		    value:kickoff);

	base = 116;
	pass_last_set = _ExtractTime(buffer:info, base:116);

	if(strlen(info) < 124){
 		return(FALSE);
 	}

	#display("Pass last set : ", pass_last_set, "\n");		     
	set_kb_item(name:string("SMB/", type, "/", count, "/Info/PassLastSet"),
 		    value:pass_last_set); 

	pass_can_change = _ExtractTime(buffer:info, base:124);
	#display("Pass can change : ", pass_can_change,"\n");
	set_kb_item(name:string("SMB/", type, "/", count, "/Info/PassCanChange"),
 		    value:pass_can_change);
 
	pass_must_change = _ExtractTime(buffer:info, base:132);
 
	#display("Pass must change : ", pass_must_change, "\n");
	set_kb_item(name:string("SMB/", type, "/", count, "/Info/PassMustChange"),
 		    value:pass_must_change);
 
	# ACB
 	if(strlen(info) < 260){
		return(FALSE);
 	}
 
	acb_lo = ord(info[260]);
	acb_hi = ord(info[261]);
	acb = acb_hi * 256;
	acb = acb + acb_lo;
	#display("ACB : ", hex(acb), "\n");
 
	set_kb_item(name:string("SMB/", type, "/", count, "/Info/ACB"), value:acb);
	     
 	#if(acb & 0x01)display("  Account is disabled\n");
	#if(acb & 0x04)display("  Password not required\n");
	#if(acb & 0x10)display("  Normal account\n");
	#if(acb & 0x0200)display("  Password does not expire\n");
	#if(acb & 0x0400)display("  Account auto-locked\n");
	#if(acb & 0x0800)display("  Password can't be changed\n");
  
	#if(acb & 0x1000)display("  Smart card is required for interactive log on\n");
	#if(acb & 0x2000)display("  Account is trusted for delegation\n");
	#if(acb & 0x4000)display("  Account is sensitive an can not be delegated\n");
	#if(acb & 0x8000)display("  Use DES encryption type for this account\n");
 }

 #
 # Open file <file>
 #
 function OpenAndX(socket, uid, tid, file)
 {
 	local_var req, tid_lo, tid_hi, uid_lo, uid_hi, len_lo, len_hi, rep;
	local_var fid_lo, fid_hi;

	len_lo = (66 + strlen(file)) % 256;
	len_hi = (66 + strlen(file)) / 256;
 
	tid_lo = tid % 256;
	tid_hi = tid / 256;
 
	uid_lo = uid % 256;
	uid_hi = uid / 256;
 
	bcc_lo = strlen(file) % 256;
	bcc_hi = strlen(file) / 256;
 
 	req = raw_string(0x00, 0x00, len_hi, len_lo,   0xFF, 0x53,
 			 0x4D, 0x42, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x08,
			 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, tid_lo, tid_hi,
			 0x00, 0x28, uid_lo, uid_hi, g_mlo, g_mhi, 0x0F, 0xFF,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x06,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, bcc_lo, bcc_hi) + file +
	      raw_string(0x00);

	send(socket:socket, data:req);
	rep = smb_recv(socket:socket, length:4096);
	if(strlen(rep) < 65){
		return(NULL);
	}

	else
 	{
 		fid_lo = ord(rep[41]);
		fid_hi = ord(rep[42]);
		return(fid_lo + (fid_hi * 256));
	}
 }

 #
 # Read <count> bytes at offset <off>
 #
 function ReadAndX(socket, uid, tid, fid, count, off)
 {
 	local_var r, req, uid_lo, uid_hi, tid_lo, tid_hi, fid_lo, fid_hi, off_hi, off_lo, ret, i;
 
	uid_lo = uid % 256; uid_hi = uid / 256;
	tid_lo = tid % 256; tid_hi = tid / 256;
	fid_lo = fid % 256; fid_hi = fid / 256;
	cnt_lo = count % 256; cnt_hi = count / 256;
 
	off_lo_lo = off % 256;  off /= 256;
	off_lo_hi = off % 256;  off /= 256;
	off_hi_lo = off % 256;  off /= 256;
	off_hi_hi = off;
 
	req = raw_string(0x00, 0x00, 0x00, 0x37, 0xFF, 0x53,
 			 0x4D, 0x42, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x08,
			 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, tid_lo, tid_hi,
			 0x00, 0x28, uid_lo, uid_hi, g_mlo, g_mhi, 0x0A, 0xFF,
			 0x00, 0x00, 0x00, fid_lo, fid_hi, off_lo_lo, off_lo_hi, off_hi_lo, 
			 off_hi_hi, cnt_lo, cnt_hi, cnt_lo, cnt_hi, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
 
	send(socket:socket, data:req);
	r = smb_recv(socket:socket, length:65535);
	ret = "";
	if(strlen(r) < 37 + 28){
		return(NULL);
	}
	return substr(r, 36+28, strlen(r) - 1);	   
 }

 # Returns the size of the file pointed by <fid>
 function smb_get_file_size(socket, uid, tid, fid)
 {
 	local_var r, req, uid_lo, uid_hi, tid_lo, tid_hi, fid_lo, fid_hi, ret;
 
	uid_lo = uid % 256; uid_hi = uid / 256;
	tid_lo = tid % 256; tid_hi = tid / 256;
	fid_lo = fid % 256; fid_hi = fid / 256;
 
 	req = raw_string(0x00, 0x00, 0x00, 0x48, 0xFF, 0x53,
 			 0x4D, 0x42, 0x32, 0x00, 0x00, 0x00, 0x00, 0x08,
			 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, tid_lo, tid_hi,
			 0x00, 0x28, uid_lo, uid_hi, g_mlo, g_mhi, 0x0F, 0x04,
			 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x11, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x00, 0x48,
			 0x00, 0x01, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
			 0x44, 0x20, fid_lo, fid_hi, 0x07, 0x01);

	send(socket:socket, data:req);
	r = smb_recv(socket:socket, length:4096);
	if(strlen(r) < 112){
		return -1;
	}
 
	ret = ord(r[115]);			
	ret = ret * 256 + ord(r[114]);		
	ret = ret * 256 + ord(r[113]);
	ret = ret * 256 + ord(r[112]);		
 	return ret;
 }

 #
 # Gives the listing in the pattern <pattern> 
 # If pattern is set to NULL, then we return the
 # content of the root (\*)
 #
 function FindFirst2(socket, uid, tid, pattern)
 {
 	local_var uid_lo, uid_hi, tid_lo, tid_hi, r, r2;
	local_var t, nxt, off, name, ret, bcc, bcc_lo, bcc_hi;
	local_var len, len_lo, len_hi;
	local_var unicode_pattern, i;
	local_var data_off, data_off_lo, data_off_hi, bcc2, bcc2_lo, bcc2_hi;
	local_var eof, search_id, err;
 
 	if(isnull(pattern))pattern = "\*";
 
	for(i=0; i<strlen(pattern); i++){
		unicode_pattern += pattern[i] + raw_string(0);
  	}
	unicode_pattern += raw_string(0, 0);
 	ret = NULL;
  
	bcc = 15 + strlen(unicode_pattern);
	bcc2 = bcc - 3;
	len  = 80 + strlen(unicode_pattern);
 
	uid_lo = uid % 256; uid_hi = uid / 256;
	tid_lo = tid % 256; tid_hi = tid / 256;
	bcc_lo = bcc % 256; bcc_hi = bcc / 256;
	bcc2_lo = bcc2 % 256; bcc2_hi = bcc2 / 256;
	len_lo = len % 256; len_hi = len / 256;
 
	data_off = 80 + strlen(unicode_pattern);
	data_off_lo = data_off % 256; data_off_hi = data_off / 256;
 
	req = raw_string(0x00, 0x00, len_hi, len_lo,   0xFF, 0x53,
 			 0x4D, 0x42, 0x32, 0x00, 0x00, 0x00, 0x00, 0x08,
			 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, tid_lo, tid_hi,
			 0x00, 0x28, uid_lo, uid_hi, g_mlo, g_mhi, 0x0F, bcc2_lo,
			 bcc2_hi, 0x00, 0x00, 0x0A, 0x00, 0x04, 0x11, 0x00,
			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			 0x00, bcc2_lo, bcc2_hi, 0x44, 0x00, 0x00, 0x00, data_off_lo,
			 data_off_hi, 0x01, 0x00, 0x01, 0x00, bcc_lo, bcc_hi, 0x00,
			 0x44, 0x20, 0x16, 0x00, 0x00, 0x02, 0x06, 0x00,
			 0x04, 0x01, 0x00, 0x00, 0x00, 0x00) + unicode_pattern;

	send(socket:socket, data:req);
	r = smb_recv(socket:socket, length:65535);
	if(strlen(r) < 80){
		return(NULL);
	}

	err = substr(r, 11, 12);
	if(hexstr(err) != "0000"){
		return NULL;
	}
 
	search_id = substr(r, 60, 61);
	off = 72;
	while(TRUE)
	{
		eof = ord(r[64]);
		while(TRUE)
		{
			t = 1;
			nxt = 0;

			if(off + i + 4 >= strlen(r)){
				break;
			}
 
			for(i=0; i<4; i++)
 			{
				nxt += ord(r[off+i]) * t;
				t *= 256;
 			}
 
 			t = 1;
			len = 0;
 
			if(off+4+4+8+8+8+8+8+8+4+i+4 >= strlen(r)){
				break;
			}
 
			for(i=0; i<4; i++)
			{
				len += ord(r[off+4+4+8+8+8+8+8+8+4+i]) * t;
				t *= 256;
 			}

			if(len >= strlen(r)){
				break;
			}
 			name = NULL;
 
			if(off+4+4+8+8+8+8+8+8+4+4+1+1+24+i+len > strlen(r)){
				break;
			}

			for(i=0; i<len; i+=2){
 				name += r[off+4+4+8+8+8+8+8+8+4+4+4+1+1+24+i];
			}
 
			if(!isnull(name))
			{
				if(isnull(ret)){
					ret = make_list(name);
				}
				else {
					ret = make_list(ret, name);
				}
 			}
 
			off = off + nxt;
			if(nxt == 0)break;
			if((off >= strlen(r)) || off < 0 ){
				return ret;
			}
		 }
		if(eof){
			break;
		}
		else
		{
			req = raw_string(0x00, 0x00, 0x00, 0x52, 0xff, 0x53, 0x4d, 0x42,
					 0x32, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xC0,
					 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
					 0x00, 0x00, 0x00, 0x00, tid_lo, tid_hi, 0x00, 0x28,
					 uid_lo, uid_hi, g_mlo, g_mhi, 0x0f, 0x0e, 0x00, 0x00,
					 0x00, 0x0a, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00, 
					 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
					 0x00, 0x44, 0x00, 0x00, 0x00, 0x52, 0x00, 0x01,
					 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x44, 0x20) + search_id +
			      raw_string(0x00, 0x02, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00);

			send(socket:socket, data:req);
			r = smb_recv(socket:socket, length:65535);
			if(r){
				err = substr(r, 11, 12);
			}
			if(hexstr(err) != "0000"){
				return NULL;
			}
			if(strlen(r) <= 64  && hexstr(substr(r, 9, 12)) == "00000000"){
				r = smb_recv(socket:soc, length:65535);
			}
			else if(strlen(r) <= 64){
				break;
			}
			off = 68;
		}
 	}
	return ret;
 }

 #
 # GetFileVersion() returns the version of the file.
 #
 function GetFileVersion(socket, uid, tid, fid)
 {
 	local_var i, fsize, data, off, tmp, version, v, len;

	fsize = smb_get_file_size(socket:socket, uid:uid, tid:tid, fid:fid);
	if(fsize < 180224){
		off = 0;
	}
	else {
		off = fsize - 180224;
	}

 	for(i = 0; off < fsize; i ++ )
	{
		tmp = ReadAndX(socket:socket, uid:uid, tid:tid, fid:fid, count:16384, off:off);
		if(tmp)
   		{ 
			tmp = str_replace(find:raw_string(0), replace:"", string:tmp);
			data += tmp;
			version = strstr(data, "ProductVersion");
			if(version)
   			{
				len = strlen(version);
				for(i=strlen("ProductVersion"); i<len; i++)
				{
					if((ord(version[i]) < ord("0") ||
					    ord(version[i]) > ord("9")) && 
					    version[i] != ".") {
						return (v);
					}
					else {
						v += version[i];
					}
     				}
   			}
   			off += 16384;
   		}
 	}
	return NULL;
 }
