cmu-sei / pharos

Automated static analysis tools for binary programs
Other
1.57k stars 192 forks source link

Prolog sanity check failed - multiple inheritance offsets #275

Open Detectronic-PB opened 4 days ago

Detectronic-PB commented 4 days ago

I'm getting this error trying to run OOProlog on a Kensington firmware update utility:

Consistency checks failed.
Class 0x587970 inherits from 0x569a4c at offsets 0 and 0x244
Initial sanity check failed, indicating the OO rules are incorrect.

There are several warnings/errors at the OOAnalyzer stage which may be related. \ \ Container Version: seipharos/pharos:latest (sha256:fe09ad8e492115b7a1cfe0899995fa37057089d695d73332aa633b7f696f33bd)

Input file: KensingtonUpdate.exe

API database JSON files: ApiJson.zip

Logs: Logs.zip

Partition command:

partition
    --serialize=kensington/kensington-sem.ser
    --maximum-memory=10240
    kensington/KensingtonUpdate.exe

Analyzer command:

ooanalyzer
    --serialize=kensington/kensington-sem.ser
    --new-method=0x4116a6
    --new-method=0x4116d8
    --new-method=0x42f692
    --delete-method=0x42f6ae
    --delete-method=0x53b4c0
    --maximum-memory 18000
    --per-function-maximum-memory=0
    --prolog-facts=kensington/kensington-facts.pl
    --threads=1
    --per-function-timeout=600
    --apidb=/usr/local/share/pharos/contrib/winspool.json
    --apidb=kensington/hid.xml.json
    --apidb=kensington/gdiplus.xml.json
    --apidb=kensington/SetupAPI.xml.json
    --apidb=kensington/UxTheme.xml.json
    --apidb=kensington/Imm32.xml.json
    --apidb=kensington/Msimg32.xml.json
    --apidb=kensington/Oleacc.xml.json
    --apidb=kensington/User32.xml.json
    --apidb=kensington/OleDlg.xml.json
    kensington/KensingtonUpdate.exe

Note: --threads=1 is to avoid a multithread issue that I'll submit/add to another issue for.

Prolog command:

ooprolog
    --facts kensington/kensington-facts.pl
    --results kensington/kensington-results.pl
    --log-level=6
Detectronic-PB commented 4 days ago

Forgot the facts: Facts.zip

sei-eschwartz commented 4 days ago

Thanks, I will take a look at this. The threading problem is probably #267.

sei-eschwartz commented 3 days ago

Working backwards...

Consistency checks failed.
Class 0x587970 inherits from 0x569a4c at offsets 0 and 0x244
Merging class 0x50b8db into 0x587970 ...
reasonMergeVFTables_A(constructor, 0x587970, 0x50b8db, 0x587970, 0, factVFTableWrite(0x50b8f8, 0x50b8db, 0, 0x587970)).
sei-eschwartz commented 3 days ago
[eschwartz@pd4 ooanalyzer-tests]$ /home/mwd/git/plogtrace/plogtrace.py ./code/testcases/kensington/kensington.exe.results.log 'factObjectInObject(0x587970, 0x569a4c, 0x244)'
1487178: Retracting factObjectInObject(0x50b8db, 0x569a4c, 0x244) and asserting factObjectInObject(0x587970, 0x569a4c, 0x244) ...
1487060: Merging class 0x50b8db into 0x587970 ...
895020: Retracting factObjectInObject(0x50b8db, 0x426738, 0x244) and asserting factObjectInObject(0x50b8db, 0x569a4c, 0x244) ...
894951: Merging class 0x426738 into 0x569a4c ...
152343: Concluding factObjectInObject(0x50b8db, 0x426738, 0x244).
reasonObjectInObject_D(0x50b8db, 0x426738, 0x244, validMethodCallAtOffset(0x50b92d, 0x50b8db, 0x426738, 0x244)).
% This rule is a special case of the reasonObjectInObject_E, that relies on the fact that it
% does not matter whether the InnerClass and OuterClass are provably different or whether
% they're just currently not assigned to the same class.  The key observation is that the
% distinction only matters when offset is non-zero, because that fact alone rules out the
% possibility that the two classes are in fact the same class.
sei-eschwartz commented 3 days ago

0x587970 is the vftable for .?AVCMFCPropertyGridCtrl@@ and 0x569a4c is the vftable for .?AVCWnd@@

sei-eschwartz commented 3 days ago

According to this:

class CMFCPropertyGridCtrl : public CWnd

So what is going on with the offset at 0x244?

Detectronic-PB commented 3 days ago

Just to add some more information in case it's relevant.

I identified 3 new operators and 2 delete operators, in a potentially strange configuration:

Having double checked these just now I've found a wrapper for the main delete operator as well, I will try running again with that one defined.

sei-eschwartz commented 3 days ago

At 0x50b92d of 0x50b8db (probably MFCPropertyGridCtrl's constructor), we call 0x426738 at offset 0x244.

sei-eschwartz commented 3 days ago
sub_426738 proc near
push    esi
mov     esi, ecx
call    sub_42305A
xor     eax, eax
mov     dword ptr [esi], offset ??_7CWnd@@6B@ ; const CWnd::`vftable'
mov     dword ptr [esi+30h], offset ??_7XAccessible@CWnd@@6B@ ; const CWnd::XAccessible::`vftable'
mov     dword ptr [esi+34h], offset ??_7XAccessibleServer@CWnd@@6B@ ; const CWnd::XAccessibleServer::`vftable'
mov     [esi+3Ch], eax
mov     [esi+40h], eax
or      dword ptr [esi+3Ch], 0FFFFFFFFh
or      dword ptr [esi+40h], 0FFFFFFFFh
mov     [esi+20h], eax
mov     [esi+24h], al
mov     [esi+38h], eax
mov     [esi+2Ch], eax
mov     [esi+28h], eax
mov     [esi+54h], eax
mov     [esi+58h], eax
mov     [esi+5Ch], eax
mov     [esi+60h], eax
mov     [esi+64h], eax
mov     [esi+68h], eax
mov     [esi+6Ch], eax
mov     [esi+70h], eax
mov     [esi+44h], eax
mov     [esi+48h], eax
mov     [esi+4Ch], eax
mov     [esi+50h], eax
mov     eax, esi
pop     esi
retn
sub_426738 endp
sei-eschwartz commented 3 days ago

According to OOAnalyzer, 0x426738 is CWnd::CWnd.

sei-eschwartz commented 3 days ago

https://github.com/pvpgn/pvpgn-magic-builder/blob/master/module/include/atlmfc/afxpropertygridctrl.h#L382

sei-eschwartz commented 3 days ago

I think the MFC classes in this program are triggered a rare-but-not-unknown problem in a sanity rule, insanityInheritTwice. Comment out this line and try to run again.

Detectronic-PB commented 3 days ago

Initial results are promising, it's on to the guess phase.

As an aside, are any of the errors in the analysis log concerning? I'm assuming it will just result in slightly less information extracted than otherwise.

sei-eschwartz commented 3 days ago

Nothing too concerning, especially for a program of that size

Detectronic-PB commented 1 day ago

After a few adjustments to memory and swap on the container I'm now getting:

reasoningLoop: post-reason sanityChecks
failed.
Consistency checks failed.
Contradictory information about constructor: factConstructor(0x426738) but reasonNOTConstructor(0x426738)
Constraint checks failed, retracting guess!
....
Fail-Retracting factNOTConstructor(0x4f7de3)...
setting numGroup to 0x2 failed so setting to 1
Fail-Retracting guessedNOTConstructor(0x52b9d4)...
Fail-Retracting factNOTConstructor(0x52b9d4)...
tryBinarySearch completely failed on [0x52b9d4] and will now backtrack to fix an upstream problem.
guess: We have back-tracked to the call of tryBinarySearch(tryConstructor, tryNOTConstructor, [0x52b9d4, 0x4c96e7, 0x424cde, 0x415931, 0x536cb0, 0x5357ff, 0x52d483, 0x52d050, 0x52867f, 0x52856d, 0x527ea9, 0x527ae7, 0x521244, 0x5142c3, 0x50813f, 0x502989, 0x4f8465, 0x4dcf68, 0x4d193e, 0x4cfe49, 0x4ccd22, 0x4ca61a, 0x4bfb3e, 0x4aa46f, 0x4a9fc1, 0x4a7719, 0x4a0e6c, 0x499ec9, 0x471a5b, 0x45786b, 0x43cf62, 0x43a0a2, 0x4302d3, 0x425e15, 0x425d6d, 0x4153f0, 0x41467c, 0x4133ec, 0x4133c5])
Refusing to backtrack into reasoningLoop to fix an upstream problem because backtrackForUpstream/0 is not set.

Full log: prolog.zip

sei-eschwartz commented 21 hours ago

This is pretty unusual. Most times it happens it is a problem with fact generation. I'll try to look on Monday.