extensions = "decompiler"
scopes = scope:calls {
to = "strcpy",
where = caller:named "read_argument",
using = { parameters = { var:named "input" } },
with = check,
}
function check(project, context)
local decomp = project:decompile(context.caller.address)
local matches = decomp:query {
query = [[
$var = strlen($param);
if ($var < _) {
strcpy(_, $param);
}
]],
}
local addr_check = matches:address_of_match(2)
local addr_strcpy = matches:address_of_match(3)
if addr_check and addr_strcpy then
return result:patch {
name = "Buffer overflow in program",
description = "The buffer overflow in read_argument has been patched",
evidence = {
functions = {
[context.caller.address] = {
annotate:at {
location = addr_check,
message = "The length of the input is checked against the buffer size...",
},
annotate:at {
location = addr_strcpy,
message = "...which prevents the buffer overflow in this call to strcpy.",
},
},
},
},
}
end
-- Patch not found: report the vulnerability
local var = context.inputs[2]
if var and var.annotation == "input" then
return result:high {
name = "Buffer overflow in program",
description = "A stack-based buffer overflow in read_argument",
evidence = {
functions = {
[context.caller.address] = {
annotate:at {
location = context.caller.call_address,
message = "The first argument of read_argument is passed to strcpy without a bounds check.",
},
},
},
},
}
end
end