It seems to me that joern doesn't handle try{}catch{} correctly.
I'm now using the following code:
query = (""
"getArguments('ProbeForRead', '0')"
".match{ it.type == 'Identifier' && it.childNum == '0' }" # This gets the 'identifier' node
".sideEffect { paramName = it.code }"
".reachableCfgNodes()"
)
You can see from the output (below) running against the demo code below that reachableCfgNodes doesn't return either the statements after ProbeForRead that are inside the "try" statement, and it also doesn't return the statements after the "catch" statement. So all that Joern seems to think is reachable when you start from a node inside a "try" statement are the nodes in the "catch" statement.
This prevents Joern from being used against many Windows driver scenarios.
Output:
(n68 {childNum:"0",code:"ntStatus = GetExceptionCode ( )",functionId:14,isCFGNode:"True",location:"24:2:480:509",type:"ExpressionStatement"})
(n118 {code:"EXIT",functionId:14,isCFGNode:"True",type:"CFGExitNode"})
(n66 {childNum:"1",code:"goto Cleanup ;",functionId:14,isCFGNode:"True",location:"25:2:513:525",type:"GotoStatement"})
(n76 {childNum:"6",code:"EXCEPTION_EXECUTE_HANDLER",functionId:14,isCFGNode:"True",location:"21:8:447:471",type:"Statement"})
(n77 {childNum:"5",code:"(",functionId:14,isCFGNode:"True",location:"21:7:446:446",type:"Statement"})
(n78 {childNum:"4",code:"except",functionId:14,isCFGNode:"True",location:"21:1:440:445",type:"Statement"})
(n28 {childNum:"12",code:"return ntStatus ;",functionId:14,isCFGNode:"True",location:"40:1:804:819",type:"ReturnStatement"})
(n30 {childNum:"11",code:"Cleanup :",functionId:14,isCFGNode:"True",location:"39:0:794:801",type:"Label"})
(n75 {childNum:"7",code:")",functionId:14,isCFGNode:"True",location:"21:33:472:472",type:"Statement"})
(n273 {code:"EXIT",functionId:131,isCFGNode:"True",type:"CFGExitNode"})
(n190 {childNum:"8",code:")",functionId:131,isCFGNode:"True",location:"60:33:1323:1323",type:"Statement"})
(n191 {childNum:"7",code:"EXCEPTION_EXECUTE_HANDLER",functionId:131,isCFGNode:"True",location:"60:8:1298:1322",type:"Statement"})
(n145 {childNum:"13",code:"return ntStatus ;",functionId:131,isCFGNode:"True",location:"79:1:1637:1652",type:"ReturnStatement"})
(n147 {childNum:"12",code:"Cleanup :",functionId:131,isCFGNode:"True",location:"78:0:1627:1634",type:"Label"})
(n193 {childNum:"5",code:"except",functionId:131,isCFGNode:"True",location:"60:1:1291:1296",type:"Statement"})
(n183 {childNum:"0",code:"ntStatus = GetExceptionCode ( )",functionId:131,isCFGNode:"True",location:"63:2:1331:1360",type:"ExpressionStatement"})
(n192 {childNum:"6",code:"(",functionId:131,isCFGNode:"True",location:"60:7:1297:1297",type:"Statement"})
(n181 {childNum:"1",code:"goto Cleanup ;",functionId:131,isCFGNode:"True",location:"64:2:1364:1376",type:"GotoStatement"})
(n273 {code:"EXIT",functionId:131,isCFGNode:"True",type:"CFGExitNode"})
(n190 {childNum:"8",code:")",functionId:131,isCFGNode:"True",location:"60:33:1323:1323",type:"Statement"})
(n191 {childNum:"7",code:"EXCEPTION_EXECUTE_HANDLER",functionId:131,isCFGNode:"True",location:"60:8:1298:1322",type:"Statement"})
(n145 {childNum:"13",code:"return ntStatus ;",functionId:131,isCFGNode:"True",location:"79:1:1637:1652",type:"ReturnStatement"})
(n147 {childNum:"12",code:"Cleanup :",functionId:131,isCFGNode:"True",location:"78:0:1627:1634",type:"Label"})
(n193 {childNum:"5",code:"except",functionId:131,isCFGNode:"True",location:"60:1:1291:1296",type:"Statement"})
(n183 {childNum:"0",code:"ntStatus = GetExceptionCode ( )",functionId:131,isCFGNode:"True",location:"63:2:1331:1360",type:"ExpressionStatement"})
(n192 {childNum:"6",code:"(",functionId:131,isCFGNode:"True",location:"60:7:1297:1297",type:"Statement"})
(n181 {childNum:"1",code:"goto Cleanup ;",functionId:131,isCFGNode:"True",location:"64:2:1364:1376",type:"GotoStatement"})
Demo code:
typedef struct _DATACOPY
{
DWORD SourceLength;
PVOID Source;
DWORD DestLength;
PVOID Dest;
} DATACOPY, *PDATACOPY;
NTSTATUS WriteWhatWhere(PDEVICE_OBJECT DeviceObject, PIRP Irp, PDATACOPY dataCopy)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
try
{
//Verify that the structure being read is in usermode
ProbeForRead(dataCopy, sizeof(DATACOPY), sizeof(UCHAR));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
ntStatus = GetExceptionCode();
goto Cleanup;
}
if (dataCopy->DestLength < dataCopy->SourceLength)
{
ntStatus = STATUS_INVALID_BUFFER_SIZE;
goto Cleanup;
}
//Vuln: Don't verify where the pointers in the structure are located
RtlCopyMemory(dataCopy->Dest, dataCopy->Source, dataCopy->SourceLength);
Cleanup:
return ntStatus;
}
NTSTATUS Safe(PDEVICE_OBJECT DeviceObject, PIRP Irp, PDATACOPY dataCopy)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
size_t size;
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
try
{
//Verify that the structure being read is in usermode
ProbeForRead(dataCopy, sizeof(DATACOPY), sizeof(UCHAR));
size = dataCopy->SourceLength;
ProbeForWrite(dataCopy->Dest, size, sizeof(UCHAR));
ProbeForRead(dataCopy->Source, size, sizeof(UCHAR));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
ntStatus = GetExceptionCode();
goto Cleanup;
}
if (dataCopy->DestLength < dataCopy->SourceLength)
{
ntStatus = STATUS_INVALID_BUFFER_SIZE;
goto Cleanup;
}
//Vuln: Don't verify where the pointers in the structure are located
RtlCopyMemory(dataCopy->Dest, dataCopy->Source, size);
Cleanup:
return ntStatus;
}