Introduction
This tool is used to collect information from the system by executing a command and then sending the information out to a specific destination through a network (via email through SMTP in this version. For information regarding SMTP, please ref. to: RFC821) even through Internet.
Background
Have you ever called your friend to help you comfort your PC but gave up from his willingness to teach you what an IP address is whilst he was trying to connect to your computer from his office? Did your ever call your IT support engineer to resolve a simple problem but he wants to fill your mind with useless information?
Have you ever been called to support your friends, parents, customers or boss who has very poor knowledge of computers? Maybe their only experience is in reading and composing email with their computer. Does this often happen when you are far from them and they will tell you that you are the only one they trust? Therefore you might like to resolve the problem by connecting to their computer. When you try to do this, did it often frustrate you to explain what an IP address is?
Did you ever want to monitor the time when a computer booted up? Maybe you also wanted it to send you an announcement, after a user logs in, through a network (such as via email) rather than check the boring event log. Did you want the announcement to contain more useful information, such as what the IP address it is getting from DHCP? Did you ever want to know who logs into the computer?
This tool is just for you :)
Did you want to get a simple example of how to execute a command, send data via network and use SMTP, query registry for information, etc., for your program?
The source code of this tool will provide you with a simple view of how to combine those technologies to complete a task. This is not the best, but I am giving a good try :)
How to Use
This tool will work as following process:
- Create a new process to run a console-based command provided by the system (such as ipconfig.exe).
- Redirect the standard output of the command execution and generate a message from this output information.
- Send the message to a specified destination.
To use this utility, simply run the executable program or run the program with some arguments (all arguments are optional).
usage: IPAnnounceByEmail [-p:X] [-s:IP] [-c:S] [-t:S] [-f:S] [-?]
-p:X Remote port to send to
-s:IP Server's IP address or host name
-c:S Command to execute
-t:S Target email address for the message to be send to
-f:S Source email address that the message is send from
-? Get this usage information
If the argument not be specified, the tool will execute the default command: "ipconfig /all". If the tool cannot find any default email account information from profile of current logon user also, the output will be send to default address: wesley_yang@sohu.com. These information can be changed in the source code:
#define COMMAND_TO_EXEC "ipconfig /all"
After you change these definitions, you can then rebuild an EXE file and send it to your friend, or your customer.
This tool does not request an email client application. It sends email messages by an embedded method. For the current version of this tool that only support message announce via SMTP email, an SMTP server is required on the environment of the executing side.
Points of Interest
1. Synchronization of process:
In the very first version of this utility, I create new process to execute the command "ipconfig.exe". This utility runs properly, that means the output pipe can get correct and complete output from this command.
After I completed the testing of other function, I tried to execute a new command as "ping www.microsoft.com", the utility will not completely send the output from this execution this time. I found out that the output pipe actuarially hadn't got the whole output as we could see in console. This is caused by the synchronization problem that the main process does not wait for the child process to be completed. Therefore, I made some enhancement.
At first, return a handle of the child process:
HANDLE createChildProcess(char* cmdName)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
ZeroMemory(&piProcInfo,sizeof(PROCESS_INFORMATION));
ZeroMemory(&siStartInfo,sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
CreateProcess(NULL,
cmdName,
NULL,
NULL,
true,
0,
NULL,
NULL,
&siStartInfo,
&piProcInfo);
return piProcInfo.hProcess;
}
Then, while create child process to execute the command, added a single to wait for the complication of command execution:
hChildProcess=createChildProcess(cmdName);
if (hChildProcess == NULL)
ErrorExit ("Command execution error", logFile);
if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdOut))
ErrorExit ("Restor Stdout handle error!", logFile);
if (WaitForSingleObject(hChildProcess, TIME_OUT_SETTING) ==
WAIT_TIMEOUT)
{
printf ("The command execution time out!\n");
TerminateProcess(hChildProcess, 0);
printf ("The command is terminated!\n");
writeLog(logFile, "Command execution time out!");
}
2. Transforming data through network:
In this utility, data transformation is very important. I'm using the socket2 API to send and receive data. Since the network communication capability is inside of the Windows system, the program can execute without other dependencies.
There will be 3 steps to send data through network:
- The very first step is to prepare the data to be send.
- After the data structure is filled and ready to be send, initialize the socket connection to the SMTP server will be the next.
- Then, send data to the server.
setSmtpMessage (cmdResult);
initConn (srv.address, srv.port, &ssmtp);
printf("Now sending the message. Please wait...\n");
sendSmtpAnnounce();
The basic networking function is in the header file: baseheader.h therefore the winsock2.h is needed to be included in the file.
3. Sending email message:
The email message is send based on SMTP protocol. This protocol is defined in the RFC821 (refer to:
ftp://ftp.rfc-editor.org/in-notes/rfc821.txt).
After the TCP/IP connection to the SMTP server (default port is 25) be established, the data can be send to the server with format defined by SMTP protocol.
bool sendSmtpAnnounce (void)
{
char Data2Srv;
char FeedBack;
char* CRLF = "\r\n";
ZeroMemory(Data2Srv, BUFFER_DEFAULT_SIZE);
strcpy (Data2Srv, "HELO ");
strcat (Data2Srv, srv.address);
strcat (Data2Srv, CRLF);
sendData (Data2Srv, ssmtp, FeedBack);
writeLog(logFile, FeedBack);
strcpy (Data2Srv, "MAIL FROM <");
strcat (Data2Srv, msg.FromAdd);
...
sendData (Data2Srv, ssmtp, FeedBack);
writeLog(logFile, FeedBack);
strcpy (Data2Srv, "RCPT TO <");
strcat (Data2Srv, msg.ToAdd);
...
sendData (Data2Srv, ssmtp, FeedBack);
writeLog(logFile, FeedBack);
strcpy (Data2Srv, "DATA ");
strcat (Data2Srv, CRLF);
sendData (Data2Srv, ssmtp, FeedBack);
writeLog(logFile, FeedBack);
strcpy (Data2Srv, "SUBJECT: ");
...
sendData (Data2Srv, ssmtp, FeedBack);
writeLog(logFile, FeedBack);
return true;
}
4. Retrieval default email account information:
At the very first version of this tool, the email account is defined in the source code. Although this will provide a channel for user that does not have SMTP email sending account, it will cause some inconvenience.
Therefore in this version, get email sending information from user profile be added in to code. The user profile that provide information of email account is stored in the registry key here:
HKEY_CURRENT_USER\Software\Microsoft\Internet Account Manager
To get those information, use these codes:
if (getRegInfo(STR_VALUE, "Software\\Microsoft\\Internet Account Manager",
"Default Mail Account", defMailAccount, NULL))
{
defSmtpInfo = true;
strcpy (KEY,
"Software\\Microsoft\\Internet Account Manager\\Accounts\\");
strcat (KEY, defMailAccount);
}
if (defSmtpInfo && getRegInfo(STR_VALUE, KEY,
"SMTP Email Address", msg.FromAdd = new char [REG_BUFF], NULL));
else msg.FromAdd = SOURCE_ADDRESS;
The function getRegInfo
is defined in the baseheader.h header file.
The predefined email information still exists; meanwhile the tool can also get information for email sending in this order:
- Arguments. Using the information specified by the command argument.
- User profile. If required information for email sending is not in the argument, the tool will use the email account information that get from registry setting or so called user profile. The default account will be used.
- Defaults in code. If the execution information that this tool required neither in specified by argument nor possible to be get from user profile (such as default account does not exists in the registry), the default predefined information will be used.