diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2458a48 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +build/ +docker-compose.yml +prod.env.example +README.md +.env +.gitignore +.git +LICENSE \ No newline at end of file diff --git a/StringFinder.py b/StringFinder.py new file mode 100644 index 0000000..b6a04b9 --- /dev/null +++ b/StringFinder.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +from os import listdir +from os.path import isfile, join +import argparse +import re + +#Add argument options +parser = argparse.ArgumentParser(description="program that prints matching strings for files in a given directory") +parser.add_argument('-d', '--dir', help="directory to run (default is CWD)") +args = parser.parse_args() + +if args.dir: + directory = args.dir +else: + directory = './' + +onlyfiles = [f for f in listdir(directory) if isfile(join(directory, f))] + +#find strings using python and return the results specified +def findstrings(encoding, file, min=4): + results = {} + with open(f'{directory}{file}', 'rb') as f: + f.data = f.read() + results['ascii'] = [s.decode('utf-8', 'ignore') for s in re.findall(b'[\x1f-\x7e]{%d,}' % min, f.data)] + results['wide'] = [s.decode('utf-16le', 'ignore') for s in re.findall(b'(?:[\x1f-\x7e][\x00]){%d,}' % min, f.data)] + return results[encoding] + +def print_formatted(string_result, encoding): + for i,x in enumerate(string_result): + print(f'$string{encoding[0]}{i} = \"{x}\" {encoding}') + +def print_banner(header): + print("-" * 25, header, "-" * 25) + +#do a bitwise AND for any amount of strings in the files we're working with and print it in a yara friendly format +def find_matches(encoding): + string_result = set(findstrings(encoding, onlyfiles[0])) + for f in onlyfiles[1:]: + string_result &= set(findstrings(encoding, f)) + print_formatted(string_result, encoding) + +if __name__ == "__main__": + print_banner("ASCII") + find_matches("ascii") + print_banner("WIDE LE") + find_matches("wide") \ No newline at end of file diff --git a/YaraShare/paul.yara b/YaraShare/paul.yara new file mode 100644 index 0000000..8be1e66 --- /dev/null +++ b/YaraShare/paul.yara @@ -0,0 +1,20 @@ +rule Sample_Exercise5 { + meta: + author = "asdfjklas;vnklas;vsav" + description = "Matches all words in test file" + date = "06/22/2021" + version = "1.0" + license = "N/A" + family="N/A" + sha256_hashes= "N/A" + weight= 0 + scope ="['testing', 'asdfmkoasdfjknosadfn']" + intel ="['N/A']" + strings: + $string1 = "hello" + $string2 = "exercise" + $string3 = "five" + + condition: + all of them +} diff --git a/build/Dockerfile b/build/Dockerfile index 58f8b32..65ade2a 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -24,7 +24,8 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ make \ openssh-server \ pkg-config \ - unzip + unzip \ + python3 # install yara RUN cd /tmp \ @@ -49,15 +50,21 @@ RUN unzip -P $ZIP_PASS malware.zip && rm -rf malware.zip #setup user RUN useradd -rm -s /bin/bash -u 1000 $SSH_USERNAME RUN echo "$SSH_USERNAME:$SSH_PASSWORD" | chpasswd +RUN mv /opt/StringFinder.py /bin/ && chmod +x /bin/StringFinder.py RUN echo "uuid=\$(cat /proc/sys/kernel/random/uuid |cut -d '-' -f 1) \ && mkdir \$uuid && cd \$uuid \ && mkdir strelka \ && mkdir output \ +&& mkdir exercise-1 \ +&& mkdir exercise-2 \ +&& mkdir exercise-3 \ && mkdir exercise-4 \ && mkdir exercise-5 \ && ln -s /opt/malware malware \ +&& ln -s /opt/example.yar exercise-1/example.yar \ && cp -R /opt/exercise-4/* exercise-4/ \ && cp -R /opt/exercise-5/* exercise-5/ \ +&& cp malware/*_*.vbs exercise-2/ \ && cp malware/intriguing_France.vbs exercise-5/samples/ \ && ln -s /YaraShare exercise-5/YaraShare \ && cp /opt/fileshot-config.yml fileshot-config.yml \ diff --git a/example.yar b/example.yar new file mode 100644 index 0000000..6c4b06d --- /dev/null +++ b/example.yar @@ -0,0 +1,123 @@ +// All examples taken from: https://yara.readthedocs.io/en/stable/writingrules.html + +rule dummy +{ + condition: + false +} + +rule ExampleRule +{ + strings: + $my_text_string = "text here" + $my_hex_string = { E2 34 A1 C8 23 FB } + + condition: + $my_text_string or $my_hex_string +} + +rule CommentExample // ... and this is single-line comment +{ + condition: + false // just a dummy rule, don't do this +} + +rule WildcardExample +{ + strings: + $hex_string = { E2 34 ?? C8 A? FB } + + condition: + $hex_string +} + +rule XorExample1 +{ + strings: + $xor_string = "This program cannot" xor + + condition: + $xor_string +} + +rule Base64Example1 +{ + strings: + $a = "This program cannot" base64 + + condition: + $a +} + +rule RegExpExample1 +{ + strings: + $re1 = /md5: [0-9a-fA-F]{32}/ + $re2 = /state: (on|off)/ + + condition: + $re1 and $re2 +} + +rule CountExample +{ + strings: + $a = "dummy1" + $b = "dummy2" + + condition: + #a == 6 and #b > 10 +} + +rule InExample +{ + strings: + $a = "dummy1" + $b = "dummy2" + + condition: + $a in (0..100) and $b in (100..filesize) +} + +rule FileSizeExample +{ + condition: + filesize > 200KB +} + +rule OfExample4 +{ + strings: + $a = "dummy1" + $b = "dummy2" + $c = "dummy3" + + condition: + 1 of them // equivalent to 1 of ($*) +} + +rule MetadataExample +{ + meta: + my_identifier_1 = "Some string data" + my_identifier_2 = 24 + my_identifier_3 = true + + strings: + $my_text_string = "text here" + $my_hex_string = { E2 34 A1 C8 23 FB } + + condition: + $my_text_string or $my_hex_string +} + +import "pe" + +rule Test +{ + strings: + $a = "some string" + + condition: + $a and pe.entry_point == 0x1000 +} \ No newline at end of file