Backing up Outlook .pst files while in use

By dose | December 18, 2018
Under: Uncategorized
Comments: No Comments »

Microsoft Outlook is a very popular e-mail client nowadays.
Though cloud based services are becoming more popular, it’s still the case that i.e. e-mail storage at service providers is very limited. Therefore, there are a lot of people out there who are forced to download their e-mail and archive it in their e-mail client, i.e. in Microsoft Outlook .pst files.
Now we all know the problem of ransomware or physical disk damage that can kill the data storage location of the outlook .pst files.
For performance reasons, it’s better to keep the files locally on a possibly fast SSD drive and not to store them on a slow network drive.
Even though when files are stored on a network drive, there still is a problem that files are in an inconsistent state when being backed up from that location.
There are tools like SafePST that address this problem and promise to offer functions to do a background backup of a .pst file while the file is open and in use by the e-mail application.
Even though, they backup works, it is still not working well, as the destination file grows significally without getting compacted, as it seems (i.e. I had 20GB of Outlook .pst files which grw to 1TB in Size at the backup location – ridiculous).
There are plugins for outlook like Personal folder backup from Microsoft, that copy the .pst files on Outlook exit, but this also isn’t a solution for very large files, as it would take far too long and maybe ppl don’t close their Outlook for weeks.

So, why not use a simple backup strategy and do what all these disk imaging applications do:
Make a Volume shadow copy snapshot of the drive that contains the Outlook data files, so that the .pst file is in an at least somewhat consitant state and then copy it to the backup location?
It turns out that this can be accomplished very easily with the tools that are already shipped with Windows 7 or above. Therefore we can create a simple batch file in order to do this job.

First, Outlook profiles of the current user are collected, then volume snapshots are taken for all local drives that contain Outlook data files, next files are copied from the snapshot and finally the snapshot gets released. When copying from the snapshot to the Backup destination, we have to ensure that file is first copied completely before the old file gets overwritten, therefore taking up at least twice the size of the largest .pst file on the backup drive.
From the backup drive, you then can have a backup routine like rsnapshot which pulls off the files from the drive and stores it at a safe location.
Here is my batch file that does exactly that with descriptive comments, I hope you find it as useful as I do:

@echo off
REM Outlook .pst file backup script for Outlook 2007 or above and Windows 7 or above
REM (c)   12/2018
REM ---------- Configuration
REM Set this to the Microsoft office internal version number you are using
REM Works with Outlook 2007 or above:
REM Outlook 2007	12.0
REM Outlook 2010	14.0
REM Outlook 2013	15.0
REM Outlook 2016	16.0
REM Outlook 2019	16.0
set OFFICEVER=12.0
REM If you want logging to a file, set logfile here, otherwise leave it blank
set LOG=
REM Temporary file that records the volume shadow copied created.
REM Needed for removal on next run, if there is no clean exit.
REM Normally, you should keep it as it is
set SHADOWSF=%TEMP%\backup_pst.lst
REM Destination directory.. Taken as cmdline arg, modify if needed
set DEST=%1
REM ---------- Implementation
if "%DEST%"=="" (
  echo Usage: %0 [Backup Destination directory]
  exit /b
REM 1) Check for admin rights, we need them to run properly
net session >nul 2>&1
if errorlevel 2 (
  call :tee "ERROR: This script has to be run with administrative rights for VSS copying."
  exit /b 1
REM 2) Collect .pst files we need to process preserving spaces into PSTS
call :log ".pst file backup started"
set LW=
set PSTS=
for /f "tokens=1 delims=*" %%s in ('reg query HKCU\Software\Microsoft\Office\%OFFICEVER%\Outlook\Catalog /s ^| findstr "REG_BINARY"') do (
  set KEY=%%s
  for /F "tokens=1 delims=^|" %%t in ("!KEY!") do (
    set KEY=%%t
    for /L %%a in (1,1,260) do (
        if "!KEY:~-1!"==" " set KEY=!KEY:~0,-1!
        if "!KEY:~0,1!"==" " set KEY=!KEY:~1!
    set PSTS=!PSTS! "!KEY!"
REM 3) Collect local drives we need to make a snapshot for
for %%s in (!PSTS!) do (
  set FOUND=
  for %%i in (!LW!) do if "%%i"=="%%~ds" set FOUND=1
  if not !FOUND!==1 (
    for /F "delims=" %%L in ('
        2^>^&1 ^> nul wmic LogicalDisk where ^(DeviceID^="%%~ds" AND DriveType^=3^)
    ') do set FOUND=1
    if not !FOUND!==1 set LW=!LW! %%~ds
REM 4) If there are already volume shadow copies available, delete them first
if exist %SHADOWSF% (
  for /f "tokens=2 delims= " %%s in (%SHADOWSF%) do (
    call :log "Removing stale volume shadow copy %%s"
    vssadmin delete Shadows /Shadow=%%s /quiet >nul
REM 5) Create shadow copy of local drives to work with and collect GUIDs
del %SHADOWSF% 2>nul 
for %%s in (%LW%) do (
  for /f "tokens=3" %%i in ('"Wmic shadowcopy call create ClientAccessible,"%%s\""^|Findstr ShadowID') Do (
    call :log "Created volume shadow copy %%i for drive %%s"
    set VSSID=%%i
    echo %%s !VSSID:~1,-2! >>%SHADOWSF%
REM 6) Backup files from snapshot to backup location
for %%s in (!PSTS!) do (
  set FOUND=
  for /f "tokens=*" %%i in (%SHADOWSF%) do (
    set VSS=%%i
    For /f "tokens=2 delims=:" %%j in ('"vssadmin list shadows /Shadow=!VSS:~3!"^|FindStr GLOBALROOT') Do Set VSSVOL=%%j
    if "!VSS:~0,2!"=="%%~ds" (
      call :tee "Saving %%~ns%%~xs"
      copy /y !VSSVOL!%%~ps%%~ns%%~xs %DEST%\
      if errorlevel 0 move /y %DEST%\ %DEST%\%%~ns%%~xs >nul
      set FOUND=1
  if "%%~ds"=="\\" set FOUND=1
  if not !FOUND! == 1 (
    call :tee "echo Saving %%~ns%%~xs"
    copy /y %%s %DEST%\
    if errorlevel 0 move /y %DEST%\ %DEST%\%%~ns%%~xs >nul
REM 7) Delete shadow copies again, no longer needed
for /f "tokens=2 delims= " %%s in (%SHADOWSF%) do (
  vssadmin delete Shadows /Shadow=%%s /quiet >nul
  call :log "Removed shadow copy %%s"
call :log ".pst file Backup finished"
IF NOT "%LOG%"=="" ECHO !DATE! !TIME! %* >>!LOG!
CALL :log %*

Protocol of a Wavecom 2C2 GSM module

By dose | December 6, 2018
Under: Uncategorized
Comments: No Comments »

As I recently wrote, I had a Wavecom FastTrak M1306B compatible GSM-Modem from China (branded as Ostent Q2303A modem) where I flashed a new firmware from Wavecom to it, as it didn’t receive any SMS, which finally broke it.
I found a good amount of documentation for the modem and mirrored it here for archival, in case the chinese sites serving the documentation go offline.

From what I have read in the documentation, there is a BOOT pin that you have to pull down to GND with a resistor in order to place the defunct modem in a Firmware upload Boot-mode.
After doing so, it really gets into download mode, but due to the fact that I have a board with an Prolific PL2303 USB->Serial converter on it and the RTS/CTS signals were not connected to the Wavecom 2C2 module, the downloader mode doesn’t work as expected.
Normally, the firmware upgrade should be done with the DwlWin application, which one can obtain from the Sierrawireless site, because they bought Wavecom.
I unfortunately was never able to flash the module with it, because the module always NACKed the initial Bootstrap command 0x28. Not sure if it has something to do with the unconnected RTS/CTS lines, because documentation states that these lines are necessary, but I finally gave up on it, it’s not worth the effort.
Nevertheless during my research, I found out a bit about the Downloader-protocol which I want to share with you.
As the DwlWin application is C++ with a lot of classes, it is a pain to reverse-engineer. Fortunately the company M-Star also mad a DwlWin-application for their chips, which seems to be loosely based on the WaveCom DwlWin, but with very verbose debug output and seemingly C-code, so I first had a look at this to find the general principle of the Recovery-procedure. Note that this is not related to the wavecom chip:

Download Bootstrap to chip:
1) Open port with 2400 baud.
2) GetChipID
3) Send SendAndRecvStartFrame
4) Send PacketLengthSettingFrame
5) Change to requested baudrate
6) Send DataFrame until Bootloader is transmitted
7) Send ExitFrame

Then run Bootstrapper:
1) Set Baudrate to 2400 baud
2) Send BootstrapStartFrame
3) Change to requested baudrate

Next is to send Downloader to Bootstrap, which is a seperate protocol spoken
by bootstrapper.

M-Star command frames
Here are the corresponding commands used by M-Star (I don’t explain them any further, i.e. how to calc CRC, because it’s not relevant for Wavecom chips anyway):

#define ACK 0x06
#define NACK 0x15

Frame data is organized as {Command, [Data...], CKSHi CKSLo}
So it has a 16bit frame checksum and specific commands:

PacketLengthSettingFrame = {0x01, LenHi, LenLo, 0x00, 0x00, CKSHi, CKSLo}
Max. 28 bytes
SendAndRecvStartFrame = {0x02, Baudrate, 0x00, 0x00, 0x00, CKSHi, CKSLo}
1 - 2400
2 - 4800
3 - 9600
4 - 19200
5 - 38400
6 - 57600
7 - 115200
8 - 230400
9 - 460800
10 - 921600
-> ACK
DataFrame = {0x16, ....Framedata..., CKSHi, CKSLo}
-> ACK (0x06)
ExitFrame = {0x04, CRC4, CRC3, CRC2, CRC1, CKSHi, CKSLo}
-> ACK
GetChipID = {0x07, 0x04, 0x00, 0x00, 0x00, CKSHi, CKSLo}
-> ACK (0x06), 4 Bytes chip ID
BootstrapStartFrame = {0x28, 0x02, 0x53, Baudrate, CKSHi, CKSLo}
-> ACK

CKS..Frame Checksum
CRC..CRC over sent application

The Wismo 2C2 protocol

Now the WISMO 2C speak a different protocol. You can use the same baudrate table as above with the M-Star protocol.
CKS (Frame checksum) is always an XORed sum over the previous bytes of the frame, so very easy to calc.

Every data frame is organized as {Len, [Data…], CKS}

SendAndRecvStartFrame = {0x04, 0x53, Baudrate, 0x43, 0x01, CKS}
-> ACK
DataFrame = {Len, [Data...], CKS}
ExitFrame = {0x00, 0x00}
-> ACK
SetBaudrate = {0x02, 0x53, Baudrate, CKS}

0x53 = 'S' = Baudrate
0x50 = 'P' = Parity (0...None)
0x54 = 'T' = Stopbits (1..1 Stopbit)

Introduce downloader:
= {0x09, Ver_Maj, Ver_min, Ver_release, Ver_build, ?Baudrate?, Unixtime1, Unixtime2, Unixtime3, Unixtime4, CKS}
Ver_*.......Version octets of DWLWin Version
Unixtime*...Current time_t Unixtime timestamp as DWORD

I guess, nobody really has a use for this, but I just wanted to dump the information here in case there is interest in it and to save other ppl the effort of reversing it.

Word 2013 – “Dieses Feature scheint leider defekt zu sein”

By dose | December 6, 2018
Under: Uncategorized
Comments: No Comments »

Heute hatte ich auf einem PC das Problem, dass bei einem bestimmten Benutzer auf einer PC das Word 2013 beim Starten immer vermeldete: “Dieses Feature scheint leider defekt zu sein”
Auch eine Reparaturinstallation brachte nichts. Deaktivieren von Add-Ons führte auch nicht zum Erfolg.
winword /safe funktionierte aber, ebenso war kein Fehler zu sehen, wenn man Word als Administrator startet.

Daher habe ich mich mit dem Process Monitor von Sysinternals auf die Lauer gelegt, einen Filter gesetzt auf winword.exe und beim Ergebnis einen Filter auf “DENIED” gelegt.
Dies ergab dann, dass Word auf einen Registry-Schlüssel im WOW3264Node zugreifen wollte, welcher die .doc Dokumentenklasse als CLSID definiert. Auf diesem System hatte aus irgendeinem Grund der Benutzer “Benutzer” keine Zugriffsrechnte auf den Schlüssel.
Also Registry Editor geöffnet, “Benutzer” Zugriffsrechte auf den Schlüssel erteilt und siehe da – kein Fehler mehr beim Start von Word.

UPC Wi-Free with Linksys WRT54G

By dose | November 23, 2018
Under: Uncategorized
Comments: No Comments »

Recently I had the idea that I could use an old WRT54G als a Gateway to UPC Wi-Free. The reason was that the Owner was a customer of UPC and that he had a second site where he sporadically also wanted to use Internet on his old PC. So to save money, why pay for a second Internet line if you can have UPC Wi-Free for free?
Speed of WRT-54G is enough, so this is a cheap solution for Internet access.
I found out that it is not possible to use EAP in Client Mode on dd-wrt firmware, but OpenWRT should be possible.
I verified that and it worked fine. For further reference, here are the steps:

1) Install OpenWRT on the WRT54G
2) Logon to OpenWRT WebGUI
3) In the System-> Software tab, find the “wpad-mini” at the end – click remove
4) At the top of the page, click update lists (the router must have Internet access via the wan port temporarily)
5) In Filter, enter wpad, and install the package.
6) Go to the Network tab -> Wifi
7) Click Scan
8) Select the network to which you want to connect (UPC Wi-Free)
9) On the next page click Submit
10) On the next page in Interface Configuration select Wireless Security
11) Choose WPA2-EAP and enter: Cipher auto, EAP-PEAM method, MSCHAPv2, UPC username, UPC password
12) Save & Apply, Maybe reboot

Tadaa, now you have a cheap wireless Client for you home network and reused the old WRT54G router.

GSM Modems for SMS sending

By dose | November 14, 2018
Under: Uncategorized
Comments: No Comments »

We have a bunch of Falcom A2 modems here for automatic sending of SMS-messages to customers.
These modems have a weird firmware bug i nversion 01.93.07 that causes the modem to stop working when the +CMGS message counter overflows after sending 255 messages. Back in 2010, I asked Faclom support if there was a firmware update for the modems and they just lied to me and said, there was only one Firmware version, they are not supporting it anyway and I should buy a new modem.
So I found out that I could reset the modem with

and the counter gets reset.

However during the years, the GSM modems still showed some bugs and became a bit unreliable over time, which caused quite some annoyance.
So we checked the marked of GSM modems and found some OSTENT Wavecom Q2303A/2C/2C2 based GSM modems. They seem to be sold by Chinese manufacturers. Se we bought a serial and an USB-variant of the modem.
It turned out that they come with no support, are really old rebranded Wavecom-hardware (which was overtaken by Sierrawireless company, which doesn’t offer any support for old wavecom Hardware) and no firmware updates are available.
This was especially annoying, as these modems (both RS-232 and USB-variant) seem to have a major defect:
Sending SMS works great, but receiving SMS only works once and then it never receives SMS messages again, whatever you try to do. So these modems are rubbish, don’t buy them!

So I was back with my Faclom A2 modems. Turned out that there were Firmware updates for these modems indeed. Thankfully the wonderful Wayback machine archived them from the old manufacturer’s site!
Unfortunately, the other interesting documentation is gone forever, but I preserved what I was able to get (including most recent firmware) here. The a2_flash.exe is a WinZip selfextracting archive containing the most recent firmware.
When applying the most recent firmware to the A2, the SMS counter bug vanished and modems are currently working stable (crossing fingers that it stays that way).
Now updating these modems seems very complicated, as the manual just says that you need to short some PIN, you probably don’t even have access to. But it turned out, that it works this way:
1) Start the FlashBurner.exe, select COM port
2) Unplug the modem from power.
3) Hit the “Start download” button in the FlashBurner application
4) Hold down the RESET button of the modem (in the pinhole) while plugging in the power cord
5) Release the RESET button
The FlashUpdater should start downloading the firmware. If it doesn’t work, you can try a few times, it works after a few attempts.

So hopefully, this hint helps those who are still having these old Falcom A2 modems.

I set up another site with SMS functionality. As these was no modem available and these OSTENT are trash, we bought an old used TC65 Java Terminal, which seems to have been attached to a printer for communication with manufacturer. These Java modem Terminals seem to be able to run some embedded software on them and then communicate over serial line with the host.
However we wanted to use it as a normal modem executing AT-commands. So I did some research and found out that there is a way to disable the embedded application. For this, you need the SDK of the modem which contains an application wtk\bin\autostart_off.exe
Start the application, tell it to disable autostart and the nquickly unplug and replug the modem. After a few attempts, it should work and modem can be used in normal operation mode.
As the SDK doesn’t seem to be easy to find, I mirrored a copy of it here.

So far for my adventures with GSM modems. Hopefully, the information here is useful for some ppl.

FreePBX with Hylafax and Avantfax on Debian Jessie

By dose | April 5, 2018
Under: Uncategorized
Comments: 2 Comments »

I recently had to install a fax2mail and pcfax solution for outbound faxes using a FreePBX. Thee most convenient way to do this is using Hylafax, as it has some decent clients for sending faxes like the Winprint HylaFAX Reloaded Windows printer driver.
For managing and searching inbound faxes, Avantfax is a nice solution that not only covers sending Fax2mail (that could also be done with FreePBX directly with just a few settings), but also has a fax archive which can be made searchable using OCR.

So here is how I did it:
1) Install iaxmodem

apt-get install iaxmodem hylafax-server
vi /etc/iaxmodem/ttyIAX0

device /dev/ttyIAX0
owner uucp:uucp
mode 660
port 4570
refresh 60
peername 71
secret 111password
codec ulaw
cidname Fax
cidnumber 4311234567

2) Create extension in FreePBX:
Here we assume extension number 71
Applications / Extensions / Add New IAX2 Extension

secret 12345
notransfer yes
context from-internal
host dynamic
type friend
port 4571
qualify yes
disallow all
allow alaw
requirecalltoken no

3) Setup hylafax with iaxmodem

chown uucp:uucp /etc/iaxmodem/ttyIAX0
/etc/init.d/iaxmodem start

Do you want to run faxaddmodem to configure a modem [yes]?
Serial port that modem is connected to [ttyS0]? ttyIAX0

Country code [1]? 43
Area code [415]? 1
Phone number of fax modem [+1.999.555.1212]? +43.1.1234567
Local identification string (for TSI/CIG) ["NothingSetup"]?
Long distance dialing prefix [1]? 0
International dialing prefix [011]? 00
Dial string rules file (relative to /var/spool/hylafax) [etc/dialrules]?
Tracing during normal server operation [1]?
Tracing during send and receive sessions [11]?
Protection mode for received facsimile [0600]?
Protection mode for session logs [0600]?
Protection mode for ttyS0 [0600]?
Rings to wait before answering [1]?
Modem speaker volume [off]?
Command line arguments to getty program ["-h %l dx_%s"]?
Pathname of TSI access control list file (relative to /var/spool/hylafax) [""]?
Pathname of Caller-ID access control list file (relative to /var/spool/hylafax) [""]?
Tag line font file (relative to /var/spool/hylafax) [etc/lutRS18.pcf]?
Tag line format string ["From %%l|%c|Page %%P of %%T"]?
Time before purging a stale UUCP lock file (secs) [30]?
Hold UUCP lockfile during inbound data calls [Yes]?
Hold UUCP lockfile during inbound voice calls [Yes]?
Percent good lines to accept during copy quality checking [95]?
Max consecutive bad lines to accept during copy quality checking [5]?
Max number of pages to accept in a received facsimile [25]?
Syslog facility name for ServerTracing messages [daemon]?
Set UID to 0 to manipulate CLOCAL [""]?
Use available priority job scheduling mechanism [""]?

The non-default server configuration parameters are:

CountryCode:            43
AreaCode:               1
FAXNumber:              +43.1.1234567
LongDistancePrefix:     0
InternationalPrefix:    00
DialStringRules:        etc/dialrules
SessionTracing:         11
RingsBeforeAnswer:      1
SpeakerVolume:          off
GettyArgs:              "-h %l dx_%s"
LocalIdentifier:        "NothingSetup"
TagLineFont:            etc/lutRS18.pcf
TagLineFormat:          "From %%l|%c|Page %%P of %%T"
MaxRecvPages:           25

Are these ok [yes]?

Now we are going to probe the tty port to figure out the type
of modem that is attached.  This takes a few seconds, so be patient.
Note that if you do not have the modem cabled to the port, or the
modem is turned off, this may hang (just go and cable up the modem
or turn it on, or whatever).

Probing for best speed to talk to modem: 38400 OK.

About fax classes:

The difference between fax classes has to do with how HylaFAX interacts
with the modem and the fax protocol features that are used when sending
or receiving faxes.  One class isn't inherently better than another;
however, one probably will suit a user's needs better than others.

Class 1 relies on HylaFAX to perform the bulk of the fax protocol.
Class 2 relies on the modem to perform the bulk of the fax protocol.
Class 2.0 is similar to Class 2 but may include more features.
Class 1.0 is similar to Class 1 but may add V.34-fax capability.
Class 2.1 is similar to Class 2.0 but adds V.34-fax capability.

HylaFAX generally will have more features when using Class 1/1.0 than
when using most modems' Class 2 or Class 2.0 implementations.  Generally
any problems encountered in Class 1/1.0 can be resolved by modifications
to HylaFAX, but usually any problems encountered in Class 2/2.0/2.1 will
require the modem manufacturer to resolve it.

Use Class 1 unless you have a good reason not to.

This modem looks to have support for Class 1.0 and 1.
How should it be configured [1.0]?

Hmm, this looks like a Class 1.0 modem.
Product code (ATI0) is "spandsp".
Other information (ATI3) is "".
DTE-DCE flow control scheme [default]?
Modem manufacturer is "Unknown".
Modem model is "Unknown".

Using prototype configuration file class1.0...

There is no prototype configuration file for your modem, so we will
have to fill in the appropriate parameters by hand.  You will need the
manual for how to program your modem to do this task.  In case you are
uncertain of the meaning of a configuration parameter you should
consult the config(5) manual page for an explanation.

Note that modem commands must be specified exactly as they are to be
sent to the modem.  Note also that quote marks (") will not be displayed
and will automatically be deleted.  You can use this facility to supply
null parameters as "".

Finally, beware that the set of parameters is long.  If you prefer to
use your favorite editor instead of this script you should fill things
in here as best you can and then edit the configuration file


after completing this procedure.

Command to enter Class 1 [AT+FCLASS=1.0]?
Command to stop and wait prior to sending PPM [AT+FTS=7]?
Command to stop and wait prior to sending TCF [AT+FTS=7]?
Command to stop and wait prior to sending EOP [AT+FTS=9]?
Extra bytes in a received HDLC frame [4]?
Maximum time to wait for OK after aborting a receive (ms) [200]?
Maximum wait for initial identification frame (ms) [40000]?
Command to ensure silence after receiving HDLC and before sending [AT+FRS=7]?

The modem configuration parameters are:

Class1Cmd:              AT+FCLASS=1.0
Class1PPMWaitCmd:       AT+FTS=7
Class1TCFWaitCmd:       AT+FTS=7
Class1EOPWaitCmd:       AT+FTS=9
Class1FrameOverhead:    4
Class1RecvAbortOK:      200
Class1RecvIdentTimer:   40000
Class1SwitchingCmd:     AT+FRS=7
Class1TCFMaxNonZero:    10
Class1TCFMinRun:        1000

Are these ok [yes]?

Creating new configuration file /var/spool/hylafax/etc/config.ttyIAX0...
Creating fifo /var/spool/hylafax/FIFO.ttyIAX0 for faxgetty... done.
Done setting up the modem configuration.

Checking /var/spool/hylafax/etc/config for consistency...
...everything looks ok; leaving existing file unchanged.

Don't forget to restart hylafax in order to run faxgetty on this new modem
Do you want to run faxaddmodem to configure another modem [yes]? no

You do not appear to be using faxgetty to notify the HylaFAX scheduler
about new modems and/or their status.  This means that you must use the
faxmodem program to inform the new faxq process about the modems you
want to have scheduled by HylaFAX.  Beware that if you have modems that
require non-default capabilities specified to faxmodem then you should
read faxmodem(8) manual page and do this work yourself (since this
script is not intelligent enough to automatically figure out the modem
capabilities and supply the appropriate arguments).

Should I run faxmodem for each configured modem [yes]?
/usr/sbin/faxmodem ttyIAX0

Done verifying system setup.

4) Setup avantfax

cd /usr/src
tar -xzvf avantfax-3.3.5.tgz
rm avantfax-3.3.5.tgz
cd avantfax-3.3.5/
vi debian-prefs.txt

ROOTMYSQLPWD=[your DB root pw]

Here I set user of HTTPD to asterisk, as running FreePBX with a user other than asterisk usually is causing troubles. Of course, this needs to be adapted to your host enironment

mv /etc/apache2/sites-enabled/000-default /etc/apache2/sites-available/002-avatfax.conf
vi /etc/apache2/sites-available/002-avatfax.conf

<VirtualHost *:80>
    DocumentRoot /var/www/avantfax
    ErrorLog ${APACHE_LOG_DIR}/avantfax-error_log
    CustomLog ${APACHE_LOG_DIR}/avantfax-access_log common
    <Directory "/var/www/avantfax">
      AllowOverride All

a2ensite 002-avatfax
service apache2 reload
faxadduser -p changepasswd fax

5) Enable and install tesseract OCR for avantfax

apt-get install tesseract-ocr tesseract-ocr-deu tesseract-ocr-deu-frak tesseract-ocr-eng tesseract-ocr-fra
vi /var/www/avantfax/includes/local_config.php

define('ENABLE_OCR_SUPPORT', true);

6) Configure Avantfax
Admin menu -> Configure Modems -> ttypIAX0 -> Contact:
Write e-mail address where incoming mails need to be forwarded to

With these simple steps, I was able to get FreePBX running with Hylafax and Avantfax web interfae.

CIDLookup in FreePbx on SOGO

By dose | March 17, 2018
Under: Uncategorized
Comments: No Comments »

As SOGo is a very nice collaboration suite for the office, like I already showed in one of my earlier blog entries, why not also usa a free phone box like the Asterisk-based FreePBX project?
For good interaction with your SOGo-Installation, you can try to make your PBX lookup the incoming phone numbers in the SOGo address book. This article shows you how to do this.

First off, you need to install the CIDLookup FreePBX plugin into it.

Next, look up the MySQL-tables of SOGo that contain the address data of interest. As you may have multiple users, you may want to search in all address books or just specific address books, you need to configure this in a first step to have base data available. We do this my creating a MySQL view in the database that can easily be modified lateron according to your needs.

So logon to your sogo database and check the tables in there:
mysql -u sogo -p sogo
show tables;

You may notice the tables named in the style: sogo[username][uid]_quick
Some of these tables are for calendar data, but others are for address book data. Just select them to check if they are address book data tables, which exhibit a column called c_telephonenumber.
After you have collected all the tables with interesting address data in it, create the view `abooks` that join all of these into one, for example:

CREATE VIEW abooks AS SELECT * FROM sogouname0012c6fb387_quick UNION SELECT * FROM sogooffice0020231de93_quick;

Now we need to sanitize the phne numbers in there by removing unneccessary chracters from it and put them in the new view `phonenos`

CREATE VIEW phonenos AS SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(CONVERT(`c_telephonenumber` USING ascii),' ',''),'(',''),')',''),'-',''),'?','') phone, c_cn FROM abooks WHERE `c_telephonenumber`<>'';

Now that we sanitized it a bit, we finally need to make the numbers available in the correct format used by the PBX. In my example, the phone numer is always in international format without leading + character. This is then put in view `phoneno_f`. The reason why we don’t combine it with phonenos view in one query is that Views in MySQL don’t support subselects.

CREATE OR REPLACE VIEW phoneno_f AS SELECT CASE WHEN LEFT(phone,1)='+' THEN SUBSTR(phone,2) WHEN LEFT(phone,2)='00' THEN SUBSTR(phone,3) WHEN LEFT(phone,1)='0' THEN CONCAT( '43',SUBSTR(phone,2)) ELSE phone END phone, c_cn FROM phonenos;

Now we have a view containing all names and their respecive phone numbers in a unified format that can then be used to select in the CIDlookup module in FreePBX.
So now go to “Admin/Called ID lookup sources” in FreePBX GUI, Add a CIDLookup Source and set:

Source description: SOGo
Source type: MySQL
Host: localhost
Database: sogo
Query: SELECT c_cn FROM phoneno_f WHERE phone='[NUMBER]’
Username: sogo
Pass: sogopasswd

That’s it!

Advokat als CID-Quelle in FreePBX einbinden

By dose | March 17, 2018
Under: Uncategorized
Comments: No Comments »

Die FreePBX Telefonanlage ist eine
Konfigurationoberfläche zur einfachen Konfiguration einer Asterisk-basierenden
Sie beinhaltet auch ein interessantes Modul zur Caller ID Bestimmung, über
welches man verschiedene Methoden zur Reversnummernabfrage verwenden kann.

In Österreich ist das Anwaltskanzleipaket Advokat recht populär. Es wäre also
nicht unpraktisch, gleich den Namen des Mandanten am Display durch die Telefon-
Anlage angezeigt zu bekommen ganz ohne TAPI am Schirm.
Dies ist gar nicht so schwer zu realisieren, sofern die .MDB Datenbank am
Server liegt, wovon wir einmal ausgehen.

Die mdbtools sind hierfür ein nützliches Paket und können über unixodbc
einfach abgefragt werden.
Leider sind die Paketversionen der mdbtools buggy, sodas wir eine
fehlerberenigte Version der Bibliothek manuell installieren müssen:

apt-get install unixodbc php5-odbc libglib2.0-dev txt2man
cd /usr/src
cd mdbtools-master
autoreconf -fi
./configure --with-unixodbc=/usr/lib/odbc
make install

Nun die Datenquelle für die Advokat.mdb eintragen (Pfad anpassen):
vi /etc/odbc.ini

Description = Advokat
Driver = MDBTools
Servername = localhost
Database = /home/data/advokat/Advokat/Daten/ADVOKAT.MDB
UserName =
Password =
port = 5432

Jetzt noch den MDB-Treiber, den wir kompiliert haben mit ODBC registrieren:
vi /etc/odbcinst.ini

Description = MDBTools Driver
Driver = /usr/local/lib/

Nun benötigen wir noch ein kleines PHP-Script, welches die Nummern
normalisiert, damit diese mit der eingehenden Nummer auf der Telefonanlage
verglichen werden können.
Die Normalisierung der Nummer muss man sich entsprechend der Anlagenparameter
anpassen, da diese wohl je nach Provider in unterschiedlicher Form kommt.
Das Script z.B. in den root der FreePBX-Installation kopieren oder an einen
Ort, wo es das CIDLookup Script finden kann:


define('DSN_ADVOKAT', 'Advokat');
function GetName($odbc, $NNr)
    if ($result = odbc_exec($odbc, 'select Titel, Vorname, Name1 from Namen Where NNr='.$NNr))
        if (odbc_fetch_row($result))
            $titel = odbc_result($result,1);
            $ret=($titel?$titel.' ':'').odbc_result($result,2).' '.odbc_result($result,3);
    return $ret;
$odbc = odbc_connect(DSN_ADVOKAT, '', '');
if ($result = odbc_exec($odbc, "select NNr, Vorwahl, Telefon from Telefon Where Art='Telefon' or Art='Handy'"))
    while (odbc_fetch_row($result))
        $tel = trim(odbc_result($result,2).odbc_result($result,3));
        if ($tel[0]=='+') $tel='00'.substr($tel, 1);
        $tel = preg_replace("/[^0-9,.]/", "", $tel);
        if ($tel[0] == '0') $tel='43'.substr($tel,$tel[1]=='0'?2:1);
        if ($tel==$_REQUEST['nr'])
            echo GetName($odbc, odbc_result($result,1));

Danach müssen wir nur noch eine neue Quelle im CIDLookup definieren.
Source type: HTTP
Host: localhost
Port: 80 oder wo immer der Webserver läuft
Path: /tel.php
Query: nr=[NUMBER]

Das sollte es gewesen sein.

league.exe trojan

By dose | February 22, 2018
Under: Uncategorized
Comments: No Comments »

I recently stumbled over an infected setup application from dubious sources in the internet on a victim’s machine that contained a little obfuscated trojan which was interestingly written in .NET language, so it was pretty easy to reverse engineer.
The trojan contantly downloads itself from so you can download your own sample from there.

The trojan itself is crypted with AES encryption with a static key, which is very easy to unpack with a debugger like dnSpy. The code’s function names are obfuscated, so it doesn’t make much sense to read, but you just need to set a breakpoint before the unpacked .NET executable gets invoked and dump the decrypted memory buffer (in variable array) to disk, which can in turn be analyzed.

object obj = ze6WLzdqTLKVYk8yNb.qbpi2wrp4C09();
ze6WLzdqTLKVYk8yNb.Ssp0paUgqt("Key", obj, tqcF9712cQGgO);
ze6WLzdqTLKVYk8yNb.Ssp0paUgqt("IV", obj, tqcF9712cQGgO2);
object rXmEJKEg1Mp2m = ze6WLzdqTLKVYk8yNb.XYHLcqkA7W(obj);
array = ze6WLzdqTLKVYk8yNb.yGbemlFTZJdQjrX(rXmEJKEg1Mp2m, array);
object 6XaGtsti8u = ze6WLzdqTLKVYk8yNb.dXvj2MauvNk7t();

 Now you get an executable file named stub which in turn can be analyzed with dnSpy.
The executable is “obfuscated” with ConfuserEx v1.0.0.0.
This results in code that is difficult an annoying to read, like:

private static void Main(string[] args)
stub.res = stub.\u202D\u200D\u206B\u202C\u202B\u206D\u206E\u202A\u206C\u200E\u200F\u206D\u202B\u206E\u202B\u206A\u206F\u206C\u200B\u202E\u202E\u200D\u206E\u200D\u202E\u202B\u202A\u206D\u206E\u202B\u200C\u200E\u202B\u206F\u202E\u206E\u200D\u206D\u206A\u202E\u202E(<Module>.\u206D\u200B\u206B\u206C\u200D\u200E\u202E\u202E\u202B\u202A\u200D\u202C\u202A\u206A\u206B\u206B\u206A\u202C\u200C\u200F\u206F\u206E\u200E\u206C\u206C\u206B\u206F\u206B\u200F\u206E\u200D\u202E\u206B\u206D\u202C\u202C\u200C\u202D\u200D\u206A\u202E<string>(1666502779u), stub.\u202E\u202D\u200D\u200D\u206D\u206E\u206F\u206A\u202D\u206A\u200F\u202B\u202A\u206B\u200F\u206A\u202C\u206B\u206B\u200C\u206C\u206A\u202E\u200D\u202A\u206B\u200B\u206C\u206C\u206A\u200D\u200B\u206E\u200B\u200E\u202D\u200C\u200C\u206D\u202E\u202E());
for (;;)
uint num = 3253124917u;
for (;;)
uint num2;
switch ((num2 = (num ^ 2504117526u)) % 3u)
case 0u:
goto IL_19;
case 1u:
stub.\u202B\u200E\u206E\u206B\u206C\u202C\u206C\u206C\u200D\u202B\u202B\u200C\u206F\u206F\u206A\u200F\u206D\u200F\u200B\u200C\u206B\u202A\u200F\u206C\u206D\u200E\u206E\u206D\u206D\u200E\u202C\u202E\u206F\u206C\u206A\u200E\u206B\u206F\u206F\u202A\u202E(stub.\u200C\u206C\u206D\u206A\u202C\u200E\u206B\u200E\u202C\u202A\u200F\u202D\u206C\u200E\u200C\u200B\u206B\u202C\u202C\u200B\u200D\u206A\u200D\u200E\u202D\u200D\u202E\u202A\u206D\u206D\u200C\u202B\u200C\u206F\u200D\u206A\u202B\u200E\u206E\u202A\u202E(), new ResolveEventHandler(stub.CurrentDomain_AssemblyResolve));
num = (num2 * 307612828u ^ 2864558313u);
goto Block_1;

Fortunately, there are tools out there for deobfuscating this Confuser stuff. Tools for doing so are linked here.
Afterwards, you get a pretty readable copy of the trojan.

Judging from that, the trojan has multiple settings for injection,propagation, download, etc. Everything seems to be configurable via the resources-Section of the executable.
By looking at this specific trojan, it seems to be pretty dump and just downloads itself all over again and again and again. I suspect that the author may swap out the executable, possiby targeting different victim machines, by providing a copy of the trojan with a different configuration on a case-by-case basis, but this is just speculative.
Here is the resource section of the above mentioned trojan:

// 0x0001BE74: STUB.resources‎ (4868276 Bytes, Embedded, Public)

// 0x0001C75E: AdminRights‎ = False
// 0x0001C760: AntiDump‎ = False
// 0x0001C762: AntiSandboxie‎ = False
// 0x0001C764: AttributeHidden‎ = False
// 0x0001C766: AttributeSystem‎ = False
// 0x0001C768: BinderItems‎ = Object[][]-Array
// 0x00433FF9: CMDArgsFixed‎ = ""
// 0x00433FFB: CMDArgsType‎ = 0
// 0x00434000: CompressionGZIP‎ = False
// 0x00434002: CompressionLZMA‎ = False
// 0x00434004: CreationDateEnabled‎ = False
// 0x00434006: CreationDateValue‎ = 10.08.2016 17:36:12
// 0x0043400F: DisableCMD‎ = False
// 0x00434011: DisableSafeMode‎ = False
// 0x00434013: DisableSystemRestore‎ = False
// 0x00434015: DisableTaskManager‎ = False
// 0x00434017: DownloaderItems‎ = Object[][]-Array: ["", "CommonApplicationData"]
// 0x00434039: InjectionType‎ = 0
// 0x0043404E: MainFile‎ = 567808 Bytes
// 0x004BEA53: MessageButton‎ = 0
// 0x004BEA58: MessageEnabled‎ = False
// 0x004BEA5A: MessageIcon‎ = 0
// 0x004BEA5F: MessageOnlyOnce‎ = False
// 0x004BEA61: MessageText‎ = "Text"
// 0x004BEA67: MessageTitle‎ = "Title"
// 0x0043403E: MUTEX‎ = "TPfQHumqPQ5RUn"
// 0x004BEA6E: PersistenceStartup‎ = False
// 0x004BEA70: PersistenceSystemWide‎ = False
// 0x004BEA72: PersistenceWatchingProcess‎ = False
// 0x004BEA74: ProcessKiller‎ = String[]-Array
// 0x004BEA90: ProtectionAntiMemory‎ = False
// 0x004BEA92: ProtectionBSOD‎ = False
// 0x004BEA94: ProtectionDisableUAC‎ = False
// 0x004BEA96: ProtectionElevatedProcess‎ = False
// 0x004BEA98: RunPEDll‎ = 5658 Bytes
// 0x004C00B7: StartupAdvanced‎ = False
// 0x004C00B9: StartupEnabled‎ = False
// 0x004C00BB: StartupFileName‎ = "filename.exe"
// 0x004C00C9: StartupFolderName‎ = ""
// 0x004C00CB: StartupForceRestart‎ = False
// 0x004C00CD: StartupLocation‎ = "Desktop"
// 0x004C00D6: StartupMelt‎ = False
// 0x004C00D8: StartupName‎ = "Update"
// 0x004C00E0: StartupTask‎ = "...code for task XML file, removed for readbility..."
// 0x004C0724: ZoneIDDelete‎ = True
// 0x004C0726: ZoneIDEnabled‎ = False

If someone knows more about this trojan, please let me know.

Finding CHS-Values for HDD of an old 486-DX2/50 Highscreen notebook

By dose | December 23, 2017
Under: Uncategorized
Comments: No Comments »

Last week, I received a call for help from someone who inherited an old Highscreen 486-DX2/50 notebook from her father that contained some important documents that she wanted to recover.
Now as the Notebook hadn’t been in operation for approx. 10 years, CMOS battery was empty and the Notebook refused to boot DOS, as the CHS-Values for the Harddisk in BIOS got lost.
Now as there was no manual available anymore, I just unscrewed the 2 screws in the back of the Notebook, lifted the Keyboard and had a look at the harddisk.
So I discovered that it contained a Connor Peripherals CP30174E harddisk with approx. 160MB in size.
Now I thought that this is going to be easy, found a manual on the Internet that showed me the correct CHS values:

903 Cylinders
8 Heads
46 Sectors
0 Precomp
903 Landing zone

So I entered the information in BIOS, attempted to boot and…. Nothing, the Boot loader code in the MBR still showed me that the OS cannot be found.
Therefore I booted up with a floppy disk and was able to access the internal drive. But of course, I wanted to find out the right settings in the BIOS to let the Notebook boot again.
So I started up Norton Disk Editor:
Object -> Drive -> [x] Physical -> Hard drive 0
ALT+A (Object -> Partition table), F6 (View / As partition table)
There I was able to see the following table:

  Starting Location Ending Location Relative Number of
System Boot Side Cylinder Sector Side Cylinder Sector Sectors Sectors
BIGDOS Yes 1 0 1 5 1004 55 55 331595

Conclusion #1: Cylinder count must be >= 1004
Conclusion #2: Sectors may be 55
Conclusion #3: It has at least 5 Heads

Next, checking the Boot sector:
Object -> Drive -> [x] Logical -> C:
ALT + B (Object -> Boot Record)

There is showed:
Sides: 6
Sectors per track: 55

So we know that we have 6 Heads and 55 Sectors and >= 1004 Cylinders
Now judging from the CHS values of the Harddisk vendor, we know that the drive has a capacity of 162.257 MB
Therefore we can approximate the value of the Cylinders to closely match that value and find out that it has to be approx. 1007 Cylinders.
Therefore, I ended up with these values:

1007 Cylinders
6 Heads
55 Sectors
0 Precomp
1007 Landing zone

Entered them in the BIOS and it booted up fine.