NetSPI / PESecurity

PowerShell module to check if a Windows binary (EXE/DLL) has been compiled with ASLR, DEP, SafeSEH, StrongNaming, and Authenticode.
https://blog.netspi.com/verifying-aslr-dep-and-safeseh-with-powershell/
MIT License
614 stars 152 forks source link

SafeSEH Result is unreliable #20

Closed AdrianIssott closed 3 years ago

AdrianIssott commented 3 years ago

Here's an example of this using the attached adoberfp.zip

> Import-Module .\Get-PESecurity.psm1
> $result = 1..100 |%{Get-PESecurity -File "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\adoberfp.dll" }
> ($result | ?{$_.SafeSEH -eq "False"}).length
54
> ($result | ?{$_.SafeSEH -eq "True"}).length
46

It appears to happen for all 32-bit binaries where SafeSEH really is OK on my machine. This adobe DLL is just the first one I tried that I could share.

Some details of my machine:

Dump of file C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\adoberfp.dll

File Type: DLL

Section contains the following load config:

        000000A0 size
               0 time date stamp
            0.00 Version
               0 GlobalFlags Clear
               0 GlobalFlags Set
               0 Critical Section Default Timeout
               0 Decommit Free Block Threshold
               0 Decommit Total Free Threshold
        00000000 Lock Prefix Table
               0 Maximum Allocation Size
               0 Virtual Memory Threshold
               0 Process Heap Flags
               0 Process Affinity Mask
               0 CSD Version
            0000 Dependent Load Flag
        00000000 Edit List
        1003F4B8 Security Cookie
        1003AD80 Safe Exception Handler Table
              6E Safe Exception Handler Count
        1002F4D0 Guard CF address of check-function pointer
        00000000 Guard CF address of dispatch-function pointer
        00000000 Guard CF function table
               0 Guard CF function count
        00000100 Guard Flags
                   CF Instrumented
            0000 Code Integrity Flags
            0000 Code Integrity Catalog
        00000000 Code Integrity Catalog Offset
        00000000 Code Integrity Reserved
        00000000 Guard CF address taken IAT entry table
               0 Guard CF address taken IAT entry count
        00000000 Guard CF long jump target table
               0 Guard CF long jump target count
        00000000 Dynamic value relocation table

Safe Exception Handler Table

      Address
      --------
      100186F5
      1001878F
      10018E30
      1001A8A0
      1001ACD1
      1002BDA0
      1002BDBB
      1002BDD6
      1002BDF1
      1002BE0C
      1002BE37
      1002BE7E
      1002BEBE
      1002BEE1
      1002BF04
      1002BF27
      1002BF52
      1002BF75
      1002BF90
      1002BFAB
      1002BFCE
      1002BFF1
      1002C014
      1002C03A
      1002C055
      1002C078
      1002C0D5
      1002C118
      1002C15D
      1002C192
      1002C1BD
      1002C1E8
      1002C213
      1002C23E
      1002C269
      1002C28C
      1002C2B9
      1002C2DC
      1002C307
      1002C367
      1002C3A4
      1002C3C7
      1002C3EA
      1002C40D
      1002C433
      1002C463
      1002C4BE
      1002C4E9
      1002C50C
      1002C53D
      1002C56D
      1002C5A8
      1002C5E6
      1002C616
      1002C641
      1002C6D4
      1002C6F7
      1002C71A
      1002C73D
      1002C768
      1002C78B
      1002C7B3
      1002C80E
      1002C891
      1002C8B4
      1002C8E7
      1002C912
      1002C935
      1002C968
      1002C983
      1002C9AE
      1002C9D1
      1002C9FC
      1002CA1F
      1002CA53
      1002CA7E
      1002CA99
      1002CAC4
      1002CAE7
      1002CB1B
      1002CB41
      1002CB69
      1002CB84
      1002CB9F
      1002CBCD
      1002CC00
      1002CC30
      1002CC58
      1002CC8C
      1002CCB7
      1002CCFA
      1002CD7D
      1002CDCF
      1002CDFF
      1002CE27
      1002CE72
      1002CE9D
      1002CEC0
      1002CEF1
      1002CF21
      1002CF5C
      1002CF8F
      1002CFBA
      1002D045
      1002D093
      1002D0BB
      1002D126
      1002D141
      1002D15C
      1002D17F

Summary

    4000 .data
    1000 .orpc
   10000 .rdata
    4000 .reloc
    3000 .rsrc
   2D000 .text
egru commented 3 years ago

Thanks for writing that up. It's very helpful. I think I see what the problem is in the code. It's not reading the IMAGE_LOAD_CONFIG_DIRECTORY structure in the PE correctly based on relative virtual address. So pointers to random bytes get parsed out and is causing the structure to give back garbage config directory sizes. I'm working on trying to get that read correctly, but it may be some time before I can figure it out.

egru commented 3 years ago

Actually, I just fixed it. The problem was how the module was reading the file into memory. It should work now, but it may end up crashing if you're reading really large binaries.

AdrianIssott commented 3 years ago

Well, that was quick, thanks @egru!

I've just confirmed current master @ https://github.com/NetSPI/PESecurity/commit/7f89e0050a1469ecdd7d262a54201e2b2f18ed7e now reliably tells me SafeSEH is True for that binary.

BTW, it looks like an accidental duplication of code got added. See https://github.com/NetSPI/PESecurity/blob/master/Get-PESecurity.psm1#L529-L535. Looks like merging master in https://github.com/NetSPI/PESecurity/commit/7f89e0050a1469ecdd7d262a54201e2b2f18ed7e went a bit awry.