123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467openCoreopenCtypesopenPosixTypesopenForeignopenPrintf(* Yara types *)(* MAX_THREADS is 32 - see include/yara/limits.h *)(* --------------------------------------------------------------------------- *)(* YR_COMPILER *)typeyrcompilerletyrcompiler:yrcompilerstructuretyp=structure"YR_COMPILER"(* YR_RULE *)typeyrruleletyrrule:yrrulestructuretyp=structure"YR_RULE"(* YR_META *)typeyrmetaletyrmeta:yrmetastructuretyp=structure"YR_META"(* YR_NAMESPACE *)typeyrnamespaceletyrnamespace:yrnamespacestructuretyp=structure"YR_NAMESPACE"(* YR_STRING *)typeyrstringletyrstring:yrstringstructuretyp=structure"YR_STRING"(* YR_RULES *)typeyrrulesletyrrules:yrrulesstructuretyp=structure"YR_RULES"(* Types shortcuts *)typeyrcptr=yrcompilerptr(* let yrcptr : yrcptr typ = ptr yrcompiler *)typeyrcptrptr=yrcompilerptrptr(* let yrcptrptr : yrcptrptr typ = ptr ptr yrcompiler *)(* --------------------------------------------------------------------------- *)(* YR_META *)letyrmeta_identifier=fieldyrmeta"identifier"string;;letyrmeta_type=fieldyrmeta"type"int32_t;;let()=sealyrmeta;;typeyara_meta={identifier:string;typ:int;}(* --------------------------------------------------------------------------- *)(* YR_NAMESPACE *)letyrnamespace_name=fieldyrnamespace"name"string;;let()=sealyrnamespace;;typeyara_namespace={name:string;}(* --------------------------------------------------------------------------- *)(* YR_STRING *)letyrstring_gflags=fieldyrstring"g_flags"int32_t;;letyrstring_gflags=fieldyrstring"length"int32_t;;letyrstring_identifier=fieldyrstring"identifier"string;;letyrstring_string=fieldyrstring"string"string;;letyrstring_chained=fieldyrstring"chained_to"(ptryrstring);;letyrstring_rule=fieldyrstring"rule"(ptryrrule);;let()=sealyrstring;;typeyara_string={identifier:string;str:string;}(* --------------------------------------------------------------------------- *)(* YR_RULE *)(* struct YR_RULE {
* int32 g_flags;
* int32 t_flags[32]; // MAX_THREADS
* union {const char *identifier; uint64_t identifier_; };
* union {const char *tags; uint64_t tags_;};
* union {YR_META *metas; uint64_t metas_;};
* union {YR_STRING *strings; uint64_t strings_;};
* union {YR_NAMESPACE *ns, uin64_t ns_;};
* uint64 time_cost;
* };
* *)letyrrule_gflags=fieldyrrule"g_flags"int32_t;;letyrrule_tflags=fieldyrrule"t_flags"(array32int32_t);;letyrrule_identifier=fieldyrrule"identifier"string;;letyrrule_tags=fieldyrrule"tags"string;;letyrrule_metas=fieldyrrule"metas"(ptryrmeta);;letyrrule_strings=fieldyrrule"strings"(ptryrstring);;letyrrule_ns=fieldyrrule"ns"(ptryrnamespace);;letyrrule_timecost=fieldyrrule"time_cost"uint64_t;;let()=sealyrrule;;(*
type yrrulesptr
let yrrulesptr : yrrulesptr typ = ptr yrrules
*)typeyara_rule={identifier:string;tags:string;(*
metas : yara_meta list;
strings : yara_string list;
ns : yara_namespace list;
*)}(* --------------------------------------------------------------------------- *)(* YR_CALLBACK_FUNC *)(* typedef int YR_CALLBACK_FUNC(
int message,
void *message_data,
void *user_data);
*)letyrcallback_t=int@->ptrvoid@->ptrvoid@->returningint(* --------------------------------------------------------------------------- *)(* YR_COMPILER_CALLBACK_FUNC *)(* typedef int YR_COMPILER_CALLBACK_FUNC(
int error_level,
const char* file_name,
int line_number,
const char* message,
void *user_data);
*)letyrcompilercallback_t=int@->string@->int@->string@->ptrvoid@->returningvoid(* --------------------------------------------------------------------------- *)(* Yara API *)(*
* int yr_initialize(void)
*
*)letyr_initialize=foreign"yr_initialize"(void@->(returningint))(*
* int yr_finalize(void)
*
*)letyr_finalize=foreign"yr_finalize"(void@->(returningint))(*
* void yr_finalize_thread(void)
*
*)letyr_finalize_thread=foreign"yr_finalize_thread"(void@->(returningvoid))(*
* int yr_compiler_create(YR_COMPILER **compiler)
*
*)letyr_compiler_create=foreign"yr_compiler_create"(ptr(ptryrcompiler)@->(returningint))(*
* void yr_compiler_destroy(YR_COMPILER *compiler)
*
*)letyr_compiler_destroy=foreign"yr_compiler_destroy"(ptryrcompiler@->(returningvoid))(*
* int yr_compiler_set_callback(YR_COMPILER *compiler,
* YR_COMPILER_CALLBACK_FUNC callback, void *user_data)
*)letyr_compiler_set_callback=foreign"yr_compiler_set_callback"(ptryrcompiler@->funptryrcompilercallback_t@->ptrvoid@->(returningint))(*
* int yr_compiler_add_file(YR_COMPILER *compiler, FILE *file, const char* namespace, const char *filename)
*
*)letyr_compiler_add_file=foreign"yr_compiler_add_file"(ptryrcompiler@->ptrint@->string@->string@->(returningint))(*
* int yr_compiler_add_fd(YR_COMPILER *compiler, YR_FILE_DESCRIPTOR rules_fd, const char* namespace, const char* file_name)
*
*)letyr_compiler_add_fd=foreign"yr_compiler_add_fd"(ptryrcompiler@->int@->string@->string@->(returningint))(*
* int yr_compiler_add_string(YR_COMPILER *compiler, const char *string, const char *namespace)
*
*)letyr_compiler_add_string=foreign"yr_compiler_add_string"(ptryrcompiler@->string@->string@->(returningint))(*
* int yr_compiler_get_rules(YR_COMPILER *compiler, const char *string, const char *namespace)
*
*)letyr_compiler_get_rules=foreign"yr_compiler_get_rules"(ptryrcompiler@->ptr(ptryrrules)@->(returningint))(*
* void yr_rules_destroy(YR_RULES *rules)
*
*)letyr_rules_destroy=foreign"yr_rules_destroy"(ptryrrules@->(returningvoid))(*
* int yr_rules_load(const char* filename, YR_RULES *rules)
*
*)letyr_rules_load=foreign"yr_rules_load"(string@->ptryrrules@->(returningint))(*
* int yr_rules_save(YR_RULES *rules, const char *filename)
*
*)letyr_rules_save=foreign"yr_rules_save"(ptryrrules@->string@->(returningint))(*
* int yr_compiler_define_integer_variable(YR_COMPILER *compiler, const char *identifier, int64_t value)
*
*)letyr_compiler_define_integer_variable=foreign"yr_compiler_define_integer_variable"(ptryrcompiler@->string@->int64_t@->(returningint))(*
* int yr_compiler_define_float_variable(YR_COMPILER *compiler, const char *identifier, double value)
*
*)letyr_compiler_define_float_variable=foreign"yr_compiler_define_float_variable"(ptryrcompiler@->string@->float@->(returningint))(*
* int yr_compiler_define_boolean_variable(YR_COMPILER *compiler, const char *identifier, int value)
*
*)letyr_compiler_define_boolean_variable=foreign"yr_compiler_define_boolean_variable"(ptryrcompiler@->string@->int@->(returningint))(*
* int yr_compiler_define_string_variable(YR_COMPILER *compiler, const char *identifier, const char* value)
*
*)letyr_compiler_define_string_variable=foreign"yr_compiler_define_string_variable"(ptryrcompiler@->string@->string@->(returningint))(*
* int yr_rules_scan_mem(YR_RULES *rules, const uint8_t *buf, size_t bufsize,
* int flags, YR_CALLBACK_FUNC callback, void *user_data, int timeout)
*)letyr_rules_scan_mem=foreign"yr_rules_scan_mem"(ptryrrules@->ptruint8_t@->size_t@->int@->funptryrcallback_t@->ptrvoid@->int@->(returningint))(*
* int yr_rules_scan_file(YR_RULES *rules, const char *filename,
* int flags, YR_CALLBACK_FUNC callback, void *user_data, int timeout)
*)letyr_rules_scan_file=foreign"yr_rules_scan_file"(ptryrrules@->string@->int@->funptryrcallback_t@->ptrvoid@->int@->(returningint))(*
* int yr_rules_scan_fd(YR_RULES *rules, YR_FILE_DESCRIPTOR fd,
* int flags, YR_CALLBACK_FUNC callback, void *user_data, int timeout)
*)letyr_rules_scan_fd=foreign"yr_rules_scan_fd"(ptryrrules@->int@->int@->funptryrcallback_t@->ptrvoid@->int@->(returningint))(* --------------------------------------------------------------------------- *)typeerrors=|Error_success|Error_insufficient_memory|Error_could_not_open_file|Error_could_not_map_file|Error_zero_length_file|Error_invalid_file|Error_corrupt_file|Error_unsupported_file_version|Error_too_many_scan_threads|Error_scan_timeout|Error_callback_error|Error_too_many_matches[@@derivingenum](* TODO: Add function for textual representation of errors *)(* TODO: Propagate all errors up *)(* --------------------------------------------------------------------------- *)typemessages=|Callback_msg_nothing|Callback_msg_rule_matching|Callback_msg_rule_not_matching|Callback_msg_scan_finished|Callback_msg_import_module|Callback_msg_module_imported[@@derivingenum](* --------------------------------------------------------------------------- *)letyara_init()=letres=errors_of_enum(yr_initialize())inmatchreswith|SomeError_success->Ok()|_->Or_error.error_string"Cannot initialize Yara"letyara_deinit()=letres=errors_of_enum(yr_finalize())inmatchreswith|SomeError_success->Ok()|_->Or_error.error_string"Cannot deinitialize Yara"letyara_create()=letcompiler=allocate(ptryrcompiler)(from_voidpyrcompilernull)inletres=errors_of_enum(yr_compiler_createcompiler)inmatchreswith|SomeError_success->letcomp=!@compilerinOkcomp|_->Or_error.error_string"Cannot create Yara compiler"letyara_add_filecompilerfilenamens=letfd=Unix.openfilefilename~mode:[Unix.O_RDONLY;]~perm:0o400inletrealfd=Unix.File_descr.to_intfdinletres=yr_compiler_add_fdcompilerrealfdnsfilenameinmatcherrors_of_enumreswith|SomeError_success->Ok()|_->Or_error.error_string"Cannot add the rules file to Yara compiler"letyara_add_stringcompilerstrns=letres=errors_of_enum(yr_compiler_add_stringcompilerstrns)inmatchreswith|SomeError_success->Ok()|_->Or_error.error_string"Cannot add the rules to Yara compiler"(* Rules load and save *)letyara_get_rulescompiler=letrules=allocate(ptryrrules)(from_voidpyrrulesnull)inletres=errors_of_enum(yr_compiler_get_rulescompilerrules)in(* TODO: Print some rules information for debug purpose *)matchreswith|SomeError_success->Ok(!@rules)|_->Or_error.error_string"Cannot get any rules!"(* Scan *)(* TODO: In what form we should accept Yara rules? *)letyara_scan_memrulesbuffn=letcallbackmsgmsgdatauserdata=(* CALLBACK_MSG_RULE_MATCHING *)letrcvd=messages_of_enummsginlet_=matchrcvdwith|SomeCallback_msg_rule_matching->(* msgdata is YR_RULE in this case *)letrawrule=!@(from_voidpyrrulemsgdata)in(* TODO: Handle the result of the coercion *)letrule={identifier=getfrawruleyrrule_identifier;(* TODO: How to check if NULL before? *)tags=getfrawruleyrrule_tags;(* Convert pointer to a list here *)(*
metas = getf rawrule yrrule_metas;
strings = getf rawrule yrrule_strings;
ns = getf rawrule yrrule_ns;
*)(* tags = ""; *)}inPrintf.printf"MATCHED: %s\n"rule.identifier;fnrule|SomeCallback_msg_rule_not_matching->(* msgdata is YR_RULE in this case *)letrawrule=!@(from_voidpyrrulemsgdata)in(* TODO: Handle the result of the coercion *)letrule={identifier=getfrawruleyrrule_identifier;(* TODO: How to check if NULL before? *)(*tags = getf rawrule yrrule_tags;*)tags="";}inPrintf.printf"UNMATCHED: %s\n"rule.identifier;|_->()in(* TODO: At some point in the future return something more
* meaningful than simply 0... maybe 42? *)0in(* We run "fn" as a callback *)letbuflen=Unsigned.Size_t.of_int(String.lengthbuf)in(* TODO: Remove unnecessary copy *)letbufp=CArray.of_listchar(String.to_listbuf)inletbuffer=coerce(ptrchar)(ptruint8_t)(CArray.startbufp)inletresult=yr_rules_scan_memrulesbufferbuflen0callbacknull0inletres=errors_of_enumresultinmatchreswith|SomeError_success->Ok()|_->Or_error.error_string"Cannot perform the Yara scan"(* Scan *)(* TODO: In what form we should accept Yara rules? *)letyara_scan_filerulesfilenamefn=letcallbackmsgmsgdatauserdata=(* CALLBACK_MSG_RULE_MATCHING *)letrcvd=messages_of_enummsginlet_=matchrcvdwith|SomeCallback_msg_rule_matching->(* msgdata is YR_RULE in this case *)letrawrule=!@(from_voidpyrrulemsgdata)in(* TODO: Handle the result of the coercion *)letrule={identifier=getfrawruleyrrule_identifier;(* TODO: How to check if NULL before? *)tags=getfrawruleyrrule_tags;(*
metas = getf rawrule yrrule_metas;
strings = getf rawrule yrrule_strings;
ns = getf rawrule yrrule_ns;
*)(* tags = ""; *)}inPrintf.printf"MATCHED: %s\n"rule.identifier;fnrule(* Is this one really needed? *)|SomeCallback_msg_rule_not_matching->(* msgdata is YR_RULE in this case *)letrawrule=!@(from_voidpyrrulemsgdata)in(* TODO: Handle the result of the coercion *)letrule={identifier=getfrawruleyrrule_identifier;(* TODO: How to check if NULL before? *)(* tags = getf rawrule yrrule_tags; *)tags="";}inPrintf.printf"UNMATCHED: %s\n"rule.identifier;|_->()in(* TODO: At some point in the future return something more
* meaningful than simply 0... maybe 42? *)0inletresult=yr_rules_scan_filerulesfilename0callbacknull0inletres=errors_of_enumresultinmatchreswith|SomeError_success->Ok()|_->Or_error.error_string"Cannot perform the Yara scan"(* TODO: Provide macro-like stuff, e.g. yr_rules_foreach, yr_rule_enable, ... *)