Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add check for reproducible build in PE module #1219

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/modules/pe.rst
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,13 @@ Reference
Path of the PDB file for this PE if present.

* Example: pe.pdb_path == "D:\\workspace\\2018_R9_RelBld\\target\\checkout\\custprof\\Release\\custprof.pdb"

.. c:type:: is_reproducible_build

.. versionadded:: 3.13.0

Value that indicates if the PE is build using compiler settings to achieve reproducibility.


.. c:function:: exports(function_name)

Expand Down
6 changes: 6 additions & 0 deletions libyara/include/yara/pe.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,13 @@ typedef struct _IMAGE_RESOURCE_DIRECTORY {
#define IMAGE_DEBUG_TYPE_MISC 4
#define IMAGE_DEBUG_TYPE_EXCEPTION 5
#define IMAGE_DEBUG_TYPE_FIXUP 6
#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7
#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8
#define IMAGE_DEBUG_TYPE_BORLAND 9
#define IMAGE_DEBUG_TYPE_RESERVED10 10
#define IMAGE_DEBUG_TYPE_CLSID 11
#define IMAGE_DEBUG_TYPE_REPRO 16
#define IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20

typedef struct _IMAGE_DEBUG_DIRECTORY {
DWORD Characteristics;
Expand Down
12 changes: 10 additions & 2 deletions libyara/modules/pe/pe.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ static void pe_parse_debug_directory(
size_t pdb_path_len;
char* pdb_path = NULL;

set_integer(0, pe->object, "is_reproducible_build");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to set this to zero here? What happens if the debug directory entry (or something else we check later on) is corrupt. In this case a user can get an incorrect value (pe.is_reproducible_build would be zero) when it should be UNDEFINED at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your suggestion. Now the value is set to 0 only when debug directory is empty or when code successfully iterated through all entries


data_dir = pe_get_directory_entry(
pe, IMAGE_DIRECTORY_ENTRY_DEBUG);

Expand Down Expand Up @@ -322,6 +324,12 @@ static void pe_parse_debug_directory(

if (!struct_fits_in_pe(pe, debug_dir, IMAGE_DEBUG_DIRECTORY))
break;

if (yr_le32toh(debug_dir->Type) == IMAGE_DEBUG_TYPE_REPRO)
{
set_integer(1, pe->object, "is_reproducible_build");
continue;
}

if (yr_le32toh(debug_dir->Type) != IMAGE_DEBUG_TYPE_CODEVIEW)
continue;
Expand Down Expand Up @@ -363,7 +371,6 @@ static void pe_parse_debug_directory(
if (pdb_path_len > 0 && pdb_path_len < MAX_PATH)
{
set_sized_string(pdb_path, pdb_path_len, pe->object, "pdb_path");
break;
}
}
}
Expand Down Expand Up @@ -2806,7 +2813,8 @@ begin_declarations;
declare_integer("number_of_symbols");
declare_integer("size_of_optional_header");
declare_integer("characteristics");

declare_integer("is_reproducible_build");

declare_integer("entry_point");
declare_integer("image_base");
declare_integer("number_of_rva_and_sizes");
Expand Down
8 changes: 8 additions & 0 deletions tests/test-pe.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,14 @@ int main(int argc, char** argv)
}",
"tests/data/mtxex.dll");

assert_true_rule_file(
"import \"pe\" \
rule test { \
condition: \
pe.is_reproducible_build == 1 \
}",
"tests/data/mtxex.dll");

assert_true_rule_file(
"import \"pe\" \
rule test { \
Expand Down