728x90
반응형
윈도우에서 pagefile.sys 는 가상 메모리 파일로 RAM 에서 용량이 모자를 경우 하드디스크의 일부 영역을 메모리 공간으로 활용하는 것이다.
pagefile.sys 파일은 PC를 포맷하지 않고 오래 쓸수록 그 용량이 늘어나며 필자의 pagefile.sys 는 1.5GB 정도로 확인된다.
일반적으로 대용량이기 때문에 텍스트 형태로 보기 어려우며 문자열을 따로 추출해서 봐야한다.
다음 page_brute.py 소스코드를 통해 텍스트 추출을 한다.
#!/usr/bin/python
#
# page_brute.py
#
import sys
import argparse
import datetime
import glob
import os
import os.path
import binascii
try:
import yara
except:
print("[!] - ERROR: Could not import YARA...")
print("...did you install yara and yara-python? Exiting.")
sys.exit()
def is_block_null(block):
#Here we test to see if the block is null..if so, skip.
RAW_BLOCK=binascii.hexlify(block)
NULL_REF=binascii.hexlify(NULL_REFERENCE)
if RAW_BLOCK == NULL_REF:
return True
else:
return False
def build_ruleset():
if RULETYPE == "FILE":
try:
rules=yara.compile(str(RULES))
print("..... Ruleset Compilation Successful.")
return rules
except:
print("[!] - Could not compile YARA rule: %s") % RULES
print("Exiting.")
sys.exit()
elif RULETYPE == "FOLDER":
RULEDATA=""
#::Get list of files ending in .yara
RULE_COUNT = len(glob.glob1(RULES,"*.yar"))
if RULE_COUNT != 0:
for yara_file in glob.glob(os.path.join(RULES, "*.yar")):
try:
yara.compile(str(yara_file))
print("..... Syntax appears to be OK: %s ") % yara_file
try:
with open(yara_file, "r") as sig_file:
file_contents=sig_file.read()
RULEDATA=RULEDATA + "\n" + file_contents
except:
print("..... SKIPPING: Could not open file for reading: %s ") % yara_file
except:
print("..... SKIPPING: Could not compile rule: %s ") % yara_file
try:
rules=yara.compile(source=RULEDATA)
print("..... SUCCESS! Compiled noted yara rulesets.\n")
return rules
except:
print("[!] - Some catastropic error occurred in the compilation of signatureswithin the directory. Exiting.")
sys.exit()
else:
print("No files ending in .yar within: %s ") % RULES
print("Exiting.")
sys.exit()
elif RULETYPE == "DEFAULT":
rules=yara.compile(str(RULES))
print("[+] - Ruleset Compilation Successful.")
return rules
else:
print("[!] - ERROR: Possible catastrophic error on build_ruleset. Exiting.")
sys.exit()
def print_procedures():
print("[+] - PAGE_BRUTE running with the following options:")
print("\t[-] - FILE: %s") % FILE
print("\t[-] - PAGE_SIZE: %s") % PAGE_SIZE
print("\t[-] - RULES TYPE: %s") % RULETYPE
print("\t[-] - RULE LOCATION: %s") % RULES
print("\t[-] - INVERSION SCAN: %s") % INVERT
print("\t[-] - WORKING DIR: %s") % WORKING_DIR
print("\t=================\n")
def main():
global FILE
global PAGE_SIZE
global RULES
global SCANNAME
global INVERT
global RULETYPE
global NULL_REFERENCE
argument_parser = argparse.ArgumentParser(description="Checks pages in pagefiles for YARA-based rule matches. Useful to identify forensic artifacts within Windows-based page files and characterize blocks based on regular expressions.")
group_arg = argument_parser.add_argument_group()
group_arg.add_argument("-f", "--file", metavar="FILE", help="Pagefile or any chunk/block-based binary file")
group_arg.add_argument("-p", "--size", metavar="SIZE", help="Size of chunk/block in bytes (Default 4096)")
group_arg.add_argument("-o", "--scanname", metavar="SCANNAME", help="Descriptor of the scan session - used for output directory")
group_arg.add_argument("-i", "--invert", help="Given scan options, match all blocks that DO NOT match a ruleset",action='store_true')
group_arg = argument_parser.add_mutually_exclusive_group()
group_arg.add_argument("-r", "--rules", metavar="RULEFILE", help="File/directory containing YARA signatures (must end with .yar)")
args = argument_parser.parse_args()
if len(sys.argv) < 2:
# print argument_parser.print_help()
sys.exit()
#::Check to see if file was provided::#
if args.file:
try:
with open(args.file):
FILE=args.file
print("[+] - PAGE_BRUTE processing file: %s") % FILE
except:
print("[!] - Could not open %s. Exiting.") % FILE
sys.exit()
else:
print("[!] - No file provided. Use -f, --file to provide a file. Exiting.")
sys.exit()
#::Check to see if page size provided::#
if args.size:
PAGE_SIZE=int(args.size)
NULL_REFERENCE= '\x00' * PAGE_SIZE
else:
PAGE_SIZE=4096
NULL_REFERENCE= '\x00' * PAGE_SIZE
#::Check if --scan-name provided::#
if args.scanname:
SCANNAME=args.scanname
else:
SCANNAME="PAGE_BRUTE-" + datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") + "-RESULTS"
#::Check if --invert-match provided::#
if args.invert:
INVERT=True
else:
INVERT=False
#::Check if --rule-file provdided - if not, use default ruleset::#
if args.rules:
RULES=args.rules
try:
#::Is File?::#
if os.path.isfile(RULES):
RULETYPE="FILE"
print("[+] - YARA rule of File type provided for compilation: %s") % RULES
elif os.path.isdir(RULES):
print("[+] - YARA rule of Folder type provided for compilation: %s") % RULES
RULETYPE="FOLDER"
except:
print("[!] - Possible catastrophic error with the provided rule file...exiting.")
sys.exit()
else:
try:
with open("default_signatures.yar"):
RULES="default_signatures.yar"
RULETYPE="DEFAULT"
except:
print("[!] - Could not locate \"default_signature.yar\". Find it or provide custom signatures via --rules. Exiting.")
sys.exit()
#::Compile rules::#
authoritative_rules=build_ruleset()
#::Build directory structure
global WORKING_DIR
WORKING_DIR=SCANNAME
if not os.path.exists(WORKING_DIR):
os.makedirs(WORKING_DIR)
#::Let People Know what we're doing::#
print_procedures()
#::Find Evil::#
page_id=0
with open(FILE, "rb") as page_file:
while True:
matched=False
raw_page=page_file.read(PAGE_SIZE)
if raw_page == "":
print("Done!")
print("Ending page_id is: %s") % page_id
break
if not is_block_null(raw_page):
#::Determine if block is null...:
for matches in authoritative_rules.match(data=raw_page):
if INVERT == True:
matched=True
else:
CHUNK_OUTPUT_DIR=os.path.join(WORKING_DIR,matches.rule)
print(" [!] FLAGGED BLOCK ") + str(page_id) + ": " + matches.rule
if not os.path.exists(CHUNK_OUTPUT_DIR):
os.makedirs(CHUNK_OUTPUT_DIR)
#::Save chunk to file::#
CHUNK_OUTPUT_FWD=os.path.join(CHUNK_OUTPUT_DIR,str(page_id) + ".block")
page_export=open(CHUNK_OUTPUT_FWD,'w+')
page_export.write(raw_page)
page_export.close()
if INVERT == True:
if matched == False:
CHUNK_OUTPUT_DIR=os.path.join(WORKING_DIR,"INVERTED-MATCH")
print(" [!] BLOCK DOES NOT MATCH ANY KNOWN SIGNATURE ") + str(page_id)
if not os.path.exists(CHUNK_OUTPUT_DIR):
os.makedirs(CHUNK_OUTPUT_DIR)
CHUNK_OUTPUT_FWD=os.path.join(CHUNK_OUTPUT_DIR,str(page_id) + ".block")
page_export=open(CHUNK_OUTPUT_FWD,'w+')
page_export.write(raw_page)
page_export.close()
#::Increment Counter for offset increment::#
page_id=page_id+1
if __name__ == "__main__":
main()
위 파이썬 소스코드를 실행하려면 YARA 를 추가로 인스톨 해야한다.
CMD 창에서 다음 명령어를 입력하자.
pip install yara
위 파이썬 코드에 -h 옵션을 줘서 실행하면 아래와 같다.
반응형
'윈도우 포렌식' 카테고리의 다른 글
크롬에 저장된 계정정보 복호화(Chrome password decrypt) (0) | 2022.11.07 |
---|---|
bstrings 를 이용한 대용량 파일 문자열 추출 (0) | 2022.11.03 |
윈도우 침해사고 MFT 및 이벤트로그 분석 (0) | 2022.10.31 |
크롬 브라우저 계정정보 추출(비밀번호 복호화) (0) | 2022.10.28 |
윈도우 MFT 분석 analyzeMFT 도구 사용 (0) | 2022.10.26 |
댓글