4

I'm currently working with FASM to compile Windows executables. However, I have noticed that there is a high rate of AV false positives, which I'm trying to understand and resolve.

My approach is to create a minimal executable and try to "fix" the format, until AV's do not flag it. The goal is to understand what triggers the AV's suspicion.

VirusTotal result for the below code

format PE GUI 4.0
entry start
include 'win32ax.inc'

section '.text' code readable executable
start:
    invoke  MessageBoxA, 0, Message, Title, 0
    invoke  ExitProcess, 0

section '.data' data readable writeable
    maybe_there_should_be_a_rw_section_too dd ?

section '.rdata' data readable
    Title           db 'Test', 0
    Message         db 'Hello, World!', 0

section '.idata' import data readable writeable
    library \
        ntdll, 'ntdll.dll', \
        kernel32, 'kernel32.dll', \
        user32, 'user32.dll'
    import kernel32, \
        ExitProcess, 'ExitProcess'
    import user32, \
        MessageBoxA, 'MessageBoxA'

This code is the minimal executable. I've tried following approaches to make it seem more "normal" to AV:

  • Add a .rsrc section with VersionInfo and a manifest
  • Add some additional imports (maybe too few imports seem suspicious?)

So far, this has not lowered the false positive rate.

This is what triggered even more false positives on VirusTotal:

  • Adding 1 KB of repeating mov eax, 0 opcodes to the code section
  • Adding RT_RCDATA with 1 KB of data
  • Adding 1 KB of data to the .data or .rdata sections

Question: Are there any recommendations or good practives to avoid false positives without using digital signatures? Especially, when adding more code or data to the assembly, many AV flag the executable, which definitely would lead to complains.

bytecode77
  • 14,163
  • 30
  • 110
  • 141
  • 1
    I noticed this myself, with some AV, but I always thought it was because I was using some encryption/decryption algorithm. I never thought that it could already be triggered by just a messagebox. :) Since many AVs use heuristics, I don't think that there is a general rule, because there is no single AV. – Devolus May 06 '21 at 10:09
  • 1
    On Linux, when you let FASM make an executable directly (instead of a `.o` to be linked by `ld`), it omits any section headers, using *only* program headers for loadable segments. So usual tools like `objdump -d` and `gdb` don't find a `.text` section, which makes it less convenient to debug, for example. I could certainly imagine that similar things in PE executables would be something you'd see more in hand-crafted malware than in "normal" programs, so some antivirus programs might take them as possible warning signs. – Peter Cordes May 06 '21 at 10:11
  • 1
    "Handcrafted malware" is a perfect description. I think decryption loops are detected heuristically, but this file above is detected scan-time, because it does not perform any suspicious activity in runtime. So I'm wondering: What scantime characteristics does this executable exhibit? Anything missing that a typical compiler would add (maybe)? – bytecode77 May 06 '21 at 10:39
  • Nothing wrong with your question, but FWIW I think the burden should be on the AV authors to not do "racial profiling", not on us, the programmers, to try and circumvent it. – 500 - Internal Server Error May 06 '21 at 11:09
  • From what I've observed what triggers the AVs is the absence or presence of patterns in the code. For example, linking your code with the CRT won't trigger any AV. The AVs are probably looking for the fingerprints of the most common runtimes. Also, patterns like moving the address of an API in a register without calling it or call an API with wrong/fake parameters usually trigger the AVs. They also use machine learning (trained on real malware packers' code) so it's hard to say what is actually matching. Small files with low imports are considered suspicious too. – Margaret Bloom May 06 '21 at 13:45

0 Answers0