3

I have a simple program:

int main(){
    int t = 12 + 34;
    return t;
}

The executable of this program is signed and the sign data altered with this disitool utility as described in in this thread: Codesign an executable and allow the modification of some bytes with command:

python.exe disitool.py inject --paddata HelloWorld.exe id.txt HelloWorld_altered.exe

The contents of id.txt:

super_id=test9a0

If I understand it correctly this utility adds desired data into certificate section at the end of the file and recalulates hash of the sign. How can I read this added data from within my program, that is to read string super_id=test9a0.

1
  • My understanding is that the size of the signature data is expanded and additional data is added to the extra space following the original signature data. In that case, you can determine the size of the extra space by subtracting the actual size of the signature data from the size of the signature data specified in the PE headers. Commented Dec 26, 2023 at 11:54

1 Answer 1

3

The injected data is located after the Authenticode signature, which is located in the The Attribute Certificate Table of the file (PE Format). Here is some sample code to read it from the file:

#include <windows.h>
#include <wintrust.h>

void ReadAuthenticodeTail(PCWSTR path, LPBYTE* tailData, LPDWORD tailSize)
{
  *tailData = nullptr;
  *tailSize = 0;

  // open file & map it in memory
  auto file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
  if (file != INVALID_HANDLE_VALUE)
  {
    auto mapping = CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr);
    if (mapping)
    {
      auto map = (LPBYTE)MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
      if (map)
      {
        // do some checks
        auto dosHeader = (PIMAGE_DOS_HEADER)map;
        if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE)
        {
          auto headers = (PIMAGE_NT_HEADERS)(map + dosHeader->e_lfanew);
          if (headers->Signature == IMAGE_NT_SIGNATURE)
          {
            // get to Attribute Certificate Table
            auto va = headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
            auto size = headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
            if (va && size)
            {
              // va is in fact a file offset
              // cf https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#the-attribute-certificate-table-image-only
              auto cert = (LPWIN_CERTIFICATE)(map + va);

              // check it's authenticode signature and there's a tail
              if (cert->wRevision == WIN_CERT_REVISION_2_0 &&
                cert->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA &&
                cert->dwLength < size)
              {
                // read what's after certificate (the tail)
                *tailSize = size - cert->dwLength;
                *tailData = new BYTE[*tailSize];
                CopyMemory(*tailData, map + va + cert->dwLength, *tailSize);
              }
            }
          }
        }
        UnmapViewOfFile(map);
      }
      CloseHandle(mapping);
    }
    CloseHandle(file);
  }
}

int main()
{
  LPBYTE tail;
  DWORD size;
  ReadAuthenticodeTail(L"c:\\somepath\\SomeSignedFileWithInjectedData.exe", &tail, &size);
  if (tail)
  {
    // TODO: do something with it...

    delete[] tail;
  }
  return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! The only thing I've found is that this method also reads trailing '\0's of data, so I had to trim them.
@qloq - I'm not suprised, it's probably allocated by chunks of data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.