mttaggart/wtfbins

[New WTFBin]: IBM Personal Communications pcsnp.exe

59e5aaf4 opened this issue · 2 comments

  • Contributor Name: 59e5aaf4

  • Application/Executable: pcsnp.exe

  • SHA256 caa69ac524061e231b341b92995a9cbc2b4db81035cbef724695a175e9e6ae3f

  • WTF Behavior Description: Has a subprocess cmd.exe /c mkdir c:\Temp launched, possibly from other processes as S-1-5-18 like mpnotify.exe or lsass.exe.

    • mpnotify.exe will launch cmd.exe /c mkdir c:\Temp
    • lsass.exe will launch cmd.exe /c mkdir c:\Temp
  • Link to Documentation of Behavior:

1 - The tool.

I don't know where to start. This binary is part of some https://www.ibm.com/support/pages/ibm-personal-communications IBM "Personal Communications" tool, some sort of SSH.IBM.EXE relying on java and .exe to do script-like jobs.

  • As per vendor : "IBM® Personal Communications is a host communication and terminal emulation package for Microsoft™ Windows™. Now with full 64-bit architecture, it features virtual terminal (VT) emulation and systems network architecture (SNA) application support and provides a platform to access data and applications on different host systems. It is a component of IBM Host Access Client Package (HACP) and IBM Host Integration Solution."

It's commonly found on sysadmins workstations who work on any IBM thingies.

2 - The code.

pcsnp.exe ( has a lot of pcs*.exe friends in C:\Program Files (x86)\ibm\Personal Communications\ ) has a weird forced mkdir subcommand ( presumably written by Neelabh

int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
  char CurrentProcessId; // al
  char TickCount; // [esp+0h] [ebp-4h]

  TickCount = GetTickCount();
  GetEnvironmentVariable_PCOMM_Root();
  system_mkdir_c_Temp_pcsnp_init_log(); // Make that system("mkdir ...") call
  WriteLog((wchar_t *)L"cmdLine parse\n", TickCount);
  if ( ParseCommandLine(lpCmdLine) )
  {
    ReadFile_wrapper(&logfile);
    CryptProtectData_Neelabh_Credentials(&logfile); // Some fun
  }
  __RTDynamicCast();
  CreateProcessA_tpam_exe(); // More fun
  GetTickCount();
  CurrentProcessId = GetCurrentProcessId();
  WriteLog((wchar_t *)L"pcsnp(%d) %d sec\n\n", CurrentProcessId);
  SetLastError(0);
  return 0;
}

The first function does this : system("mkdir c:\\Temp");, effectively causing a subprocess cmd.exe /c mkdir c:\Temp to be launched.

wchar_t *system_mkdir_c_Temp_pcsnp_init_log()
{
  system("mkdir c:\\Temp");
  return wcscpy(pcsnp_init_log_path, L"c:\\Temp\\pcsnp_init.log");
}

3 - The behavior.

Sometimes, this is done from OTHER binaries than pcsnp.exe like mpnotify.exe ( at user login ? suspected since pcsnp parent is usually userinit.exe ), and on very rare occasions, by lsass.exe, causing CrowdStrike to pop a LsassToChild alert for valid reasons.

  • mpnotify.exe will launch cmd.exe /c mkdir c:\Temp
  • lsass.exe will launch cmd.exe /c mkdir c:\Temp

When this second, rare, behavior happens, CrowdStrike fires a LsassToChild alert stating : "Lsass launched a child process. If this child process is unexpected, it might indicate malware hijacked lsass to evade detection or dump credentials. Investigate the process tree."

  • Please provide any images for additional evidence.

Correlation between these mkdir commands and that tool being launched. Timestamps are missing but I swear it's really close.

image

IDA screenshot for fun and giggles; this appends forever to a log file (C:\Program Files (x86)\ibm\Personal Communications\private\pcsnp.log) without any timestamps fksdjhfqkljh. While we're at it, it has the capability (and forcibly tries) to launch tpam.exe, which I didn't find anywhere in my infra haha. So plant "tpam.exe" in system32 and boom, magic persistence whenever some admin launches that IBM thingy or just opens a session. BRB filing papers to open a crime consulting company.

image

int CreateProcessA_tpam_exe() { // redacted for brevity // read that churchill memo on brevity, it's good.
  WriteLog((wchar_t *)L"Tpam \n", v1);
  result = CreateProcessA(0, (LPSTR)"tpam.exe
    return WriteLog((wchar_t *)L"Tpam(%d) started\n", ProcessInformation.dwProcessId);

I still have NO idea why these mkdir commands appear as children of other processes, but I couldn't find another binary containing that specific string.


4 - Why Neelabh ?

Why Neelabh ? Here it is, that string is used as a test vector for encryption with Crypt(Un)ProtectData.

  v7 = RegCreateKeyExW(HKEY_CURRENT_USER, aSoftwareIbmPer, 0, 0, 1u, 0xF003Fu, 0, &hKey, &dwDisposition);// Software\IBM\Personal Communications\CurrentVersion\Credentials
    if ( !v7 && hKey && (dwDisposition == 1 || dwDisposition == 2) )
    {
      RegDeleteValueA(hKey, "Data");
                                        /* here */
      if ( CryptProtectData(&pDataIn, L"Neelabh", &pOptionalEntropy, 0, 0, 0, &pDataOut) )      {
        if ( !RegSetValueExA(hKey, "Data", 0, 3u, pDataOut.pbData, pDataOut.cbData) )        {
          if ( CryptUnprotectData(&pDataOut, 0, &pOptionalEntropy, 0, 0, 0, &v5) )          {
            if ( !memcmp(v5.pbData, pDataIn.pbData, v5.cbData) && v5.cbData == pDataIn.cbData )            {
              log((wchar_t *)L"Encryption validation success\n", v2);              v10 = 1;
            }            else            {
              log((wchar_t *)L"Encryption validation failed\n", v2);              v10 = 0;
            }            LocalFree(v5.pbData);
          }
          else
          {            RegDeleteValueA(hKey, "Data");            v10 = 0;

( also gg )

Holy wow, what a great writeup and a great find! Thanks for this! Added in b5b8815