daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

strings-file-triage.md (26439B)


      1 ---
      2 title: "strings & File Triage"
      3 description: "Triage an unknown file or a blob of unallocated space: strings in depth (-n, -t x, -e l for UTF-16, piping into IOC regexes), file/magic bytes, xxd and hexdump, exiftool metadata, binwalk, carving with foremost/scalpel/photorec, bulk_extractor, hashing and ssdeep, PDF and Office maldoc checks, YARA — with the Windows equivalents (Sysinternals strings, Get-FileHash, certutil, Format-Hex) alongside."
      4 category: dfir
      5 subcategory: "Analysis"
      6 tags: [dfir, forensics, strings, file-analysis, carving, hexdump, magic-bytes, metadata, yara, malware-triage, windows, linux]
      7 tools: ["strings / bstrings / Sysinternals strings.exe", "file / libmagic", "xxd / hexdump / Format-Hex", "exiftool", "binwalk", "foremost / scalpel / photorec", "bulk_extractor", "ssdeep / hashdeep", "pdfid / pdf-parser / peepdf", "oletools (olevba, oleid, oledump)", "YARA", "Detect It Easy (DiE)", "pestudio / pev / readpe", "HxD / ImHex"]
      8 difficulty: intermediate
      9 updated: "2026-09-26"
     10 ---
     11 
     12 # strings & File Triage
     13 
     14 Before a disassembler, before a sandbox, there is the ten-minute pass every unknown file gets: **what is it really** (`file`, magic bytes), **what is written inside it** (`strings`, in the right encoding), **what does it carry** (`exiftool`, `binwalk`, embedded objects), **what does it match** (hashes, `ssdeep`, YARA). The same tools, pointed at a memory image, a swap file or the unallocated blocks of a disk, become **carving** — pulling files and indicators out of space no filesystem points to. This card is those tools, Linux/macOS first with the **Windows equivalent** next to each, and the patterns that make `strings` output readable instead of a 40,000-line wall.
     15 
     16 > [!warning] Handle malware like malware
     17 > Work on a copy, in a VM with no shared clipboard or network, with the file renamed to `sample.bin` so nothing double-clicks it. `strings`, `file` and `exiftool` do not execute anything — but `binwalk -e`, `7z x` and PDF tools that render *can* trigger parser bugs. Snapshot first.
     18 
     19 ## Identify: what is it really?
     20 
     21 ```bash
     22 file sample.bin                          # libmagic: type, arch, linker, packer hints
     23 file -b --mime-type sample.bin           # bare MIME
     24 file -z archive.gz                       # look inside compressed
     25 file -k sample.bin                       # keep going, report all matches (polyglots)
     26 file *                                   # a whole directory, quickly
     27 xxd sample.bin | head -4                 # eyeball the magic yourself
     28 ```
     29 
     30 ```powershell
     31 # Windows: no `file`, so read the magic
     32 Format-Hex .\sample.bin -Count 32
     33 certutil -dump .\sample.bin | Select -First 5          # for certs/PKCS
     34 # or install: winget install GnuWin32.File / use TrID (trid.exe sample.bin)
     35 ```
     36 
     37 | Magic (hex) | ASCII | Type |
     38 |---|---|---|
     39 | `4D 5A` | `MZ` | Windows PE (exe/dll/sys) — `PE\0\0` follows at offset in `0x3C` |
     40 | `7F 45 4C 46` | `.ELF` | Linux/Unix executable |
     41 | `CF FA ED FE` / `CA FE BA BE` | | Mach-O 64-bit / universal (fat) |
     42 | `50 4B 03 04` | `PK..` | ZIP — also **docx/xlsx/pptx, jar, apk, ipa, odt** |
     43 | `D0 CF 11 E0 A1 B1 1A E1` | | OLE2 / CFB — legacy **doc/xls/ppt, msi, msg** |
     44 | `25 50 44 46` | `%PDF` | PDF |
     45 | `7B 5C 72 74 66` | `{\rtf` | RTF (CVE-2017-11882 territory) |
     46 | `1F 8B` | | gzip |
     47 | `42 5A 68` | `BZh` | bzip2 |
     48 | `FD 37 7A 58 5A 00` | `.7zXZ.` | xz |
     49 | `37 7A BC AF 27 1C` | `7z..'.` | 7-Zip |
     50 | `52 61 72 21 1A 07` | `Rar!..` | RAR |
     51 | `75 73 74 61 72` @257 | `ustar` | tar |
     52 | `FF D8 FF` | | JPEG |
     53 | `89 50 4E 47 0D 0A 1A 0A` | `.PNG` | PNG |
     54 | `47 49 46 38` | `GIF8` | GIF |
     55 | `52 49 46 46` | `RIFF` | WAV/AVI/WebP |
     56 | `53 51 4C 69 74 65` | `SQLite` | SQLite DB (browser history, Windows Timeline, mobile apps) |
     57 | `72 65 67 66` | `regf` | Windows registry hive |
     58 | `45 6C 66 46 69 6C 65` | `ElfFile` | Windows EVTX |
     59 | `4C 00 00 00 01 14 02 00` | `L...` | Windows LNK |
     60 | `4D 41 4D 04` / `53 43 43 41` @4 | `MAM.` / `SCCA` | Prefetch (compressed Win10 / raw) |
     61 | `EF BB BF` / `FF FE` / `FE FF` | | UTF-8 BOM / UTF-16 LE / BE text |
     62 | `23 21` | `#!` | script with shebang |
     63 | `4D 53 43 46` | `MSCF` | CAB |
     64 | `43 57 53` / `46 57 53` | `CWS`/`FWS` | Flash |
     65 | `00 00 00 xx 66 74 79 70` | `ftyp` @4 | MP4/MOV/HEIC |
     66 | `4B 44 4D` | `KDM` | VMware VMDK |
     67 | `63 6F 6E 65 63 74 69 78` | `conectix` | VHD |
     68 | `45 56 46 09 0D 0A FF 00` | `EVF` | EnCase E01 |
     69 | `4C 69 4D 45` | `LiME` | LiME memory dump |
     70 
     71 > [!tip] Extension lies, magic mostly doesn't
     72 > `invoice.pdf.exe`, `report.docm` renamed to `.doc`, a JPEG with a PHP webshell appended (`file` says JPEG, `strings` says `<?php`), a ZIP that is also a valid PDF. `file -k` and looking at **both ends** of the file (`xxd | head`, `xxd | tail`) catch most polyglots and appended payloads. Trailing data after the PNG `IEND` chunk or after the ZIP central directory is never innocent.
     73 
     74 ## `strings` in depth
     75 
     76 GNU `strings` (binutils) prints runs of printable characters ≥ 4 bytes. The defaults hide half of what a Windows binary contains.
     77 
     78 ```bash
     79 strings sample.bin                        # ASCII (and single-byte) runs ≥ 4 chars
     80 strings -n 8 sample.bin                   # minimum length 8 — cuts the noise dramatically
     81 strings -a sample.bin                     # -a: scan the WHOLE file, not just loaded sections (default on modern binutils, be explicit)
     82 strings -e l sample.bin                   # 16-bit little-endian = UTF-16LE: Windows API strings, paths, registry keys, PowerShell in .NET binaries
     83 strings -e b sample.bin                   # UTF-16 big-endian (rare: Java, some Mac formats)
     84 strings -e S sample.bin                   # single 8-bit incl. high-ASCII (Latin-1 lures, some packers)
     85 strings -t x sample.bin                   # prefix each string with its hex offset (-t d decimal, -t o octal) → jump there in a hex editor
     86 strings -t x -e l sample.bin | grep -i 'cmd\|powershell\|http'
     87 strings -a -n 6 sample.bin; strings -a -n 6 -e l sample.bin    # ALWAYS run both — ASCII and UTF-16 — on Windows samples
     88 strings -f *.bin                          # -f: print filename before each string (many files)
     89 strings sample.bin | sort | uniq -c | sort -rn | head    # repeated strings = table entries, decoy padding
     90 strings sample.bin | awk 'length > 60'    # long strings: base64 blobs, embedded scripts, URLs with parameters
     91 ```
     92 
     93 | Platform | Equivalent |
     94 |---|---|
     95 | macOS | `strings` is from LLVM/cctools: `strings -a sample.bin`; **no `-e l`** — use `iconv`/`python` below, or `brew install binutils` → `gstrings -e l` |
     96 | Windows | **Sysinternals** `strings.exe -a -n 6 sample.bin` scans ASCII **and** Unicode by default (`-u` Unicode only, `-a` ASCII only, `-o` offsets, `-s` recurse); **bstrings** (EZ Tools) adds regex and built-in IOC patterns — see [EZ Tools](/sheets/dfir/ez-tools-kape#bstrings--better-strings) |
     97 | PowerShell | `Select-String -Path sample.bin -Pattern 'http' -Encoding Unicode` for a quick UTF-16 grep, or `[IO.File]::ReadAllBytes` + regex |
     98 | Any | FLOSS (Mandiant `floss sample.exe`) — recovers **obfuscated** and **stack** strings from PE files that plain `strings` never sees; run it after `strings` disappoints |
     99 
    100 ```bash
    101 # UTF-16 strings on macOS/Windows-less environments without -e l
    102 python3 -c "import re,sys;d=open(sys.argv[1],'rb').read();print('\n'.join(m.group().decode('utf-16le') for m in re.finditer(rb'(?:[\x20-\x7e]\x00){6,}',d)))" sample.bin
    103 ```
    104 
    105 ### Making `strings` output useful: the IOC pass
    106 
    107 Save the full output once (`strings -a -n 6 sample.bin > s.txt; strings -a -n 6 -e l sample.bin >> s.txt`) and grep the file instead of re-running.
    108 
    109 ```bash
    110 S=s.txt
    111 grep -Eio 'https?://[a-z0-9./?=_%:-]+' $S | sort -u                          # URLs
    112 grep -Eo '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' $S | sort -u | grep -Ev '^(0|127|255)\.'   # IPv4 (drops version-number noise imperfectly — eyeball it)
    113 grep -Eio '\b[a-z0-9.-]+\.(com|net|org|io|ru|cn|top|xyz|info|biz|onion|pw|cc|su)\b' $S | sort -u   # domains
    114 grep -Eio '[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}' $S | sort -u                # emails
    115 grep -Ei '\\\\[^\\ ]+\\[^\\ ]+' $S | sort -u                                   # UNC paths
    116 grep -Ei 'HKEY_|HKLM|HKCU|CurrentVersion\\Run|Software\\Microsoft' $S | sort -u   # registry
    117 grep -Ei '\.(exe|dll|bat|ps1|vbs|js|hta|scr|lnk|tmp|dat|log)\b' $S | sort -u   # filenames
    118 grep -Ei 'C:\\|%APPDATA%|%TEMP%|\\Temp\\|\\Users\\|/tmp/|/dev/shm|/var/tmp' $S | sort -u   # paths
    119 grep -Ei 'powershell|cmd\.exe|/c |-enc|-nop|-w hidden|IEX|Invoke-|DownloadString|FromBase64|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|schtasks|sc \|net user|whoami' $S   # LOLBins & PS
    120 grep -Ei 'CreateRemoteThread|VirtualAlloc|WriteProcessMemory|NtUnmapViewOfSection|SetWindowsHookEx|IsDebuggerPresent|GetTickCount|CryptEncrypt|InternetOpen|WinHttp|URLDownloadToFile|ShellExecute|WinExec|RegSetValue|AdjustTokenPrivileges|OpenProcess|LoadLibrary|GetProcAddress' $S | sort -u   # suspicious imports
    121 grep -Ei 'user-agent|mozilla/|accept:|content-type' $S                        # hardcoded HTTP client
    122 grep -Ei 'password|passwd|pwd=|token|secret|api[_-]?key|BEGIN (RSA|OPENSSH|EC) PRIVATE|AKIA[0-9A-Z]{16}' $S   # credentials
    123 grep -Ei 'mutex|Global\\|Local\\' $S                                           # mutex names → hunt on other hosts
    124 grep -Ei 'pdb$|\.pdb\b|[A-Z]:\\Users\\[^\\]+\\(source|Desktop|Documents)' $S   # PDB path = developer username & project name
    125 grep -Ei 'upx|aspack|themida|vmprotect|mpress|petite|\.packed|this program cannot be run' $S   # packer strings
    126 grep -Eo '[A-Za-z0-9+/]{40,}={0,2}' $S | head                                  # base64 blobs → decode below
    127 grep -Eo '[0-9a-f]{32}\b|[0-9a-f]{40}\b|[0-9a-f]{64}\b' $S | sort -u | head   # hashes / hex keys
    128 grep -Eio '(bitcoin|btc|monero|xmr|wallet|\.onion|ransom|decrypt|your files)' $S   # ransomware notes
    129 ```
    130 
    131 ```bash
    132 # Decode what you found
    133 echo 'SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQA' | base64 -d | iconv -f utf-16le -t utf-8   # PowerShell -enc is UTF-16LE base64
    134 echo 'aHR0cDov...' | base64 -d | file -                                                    # what is inside the blob?
    135 printf '\x68\x74\x74\x70' | xxd; echo 68747470 | xxd -r -p                                 # hex ↔ bytes
    136 python3 -c "import sys;print(''.join(chr(ord(c)^0x41) for c in open('blob','rb').read().decode('latin1')))"   # single-byte XOR guess
    137 # Brute-force single-byte XOR / ROT / base64 layers: CyberChef "Magic" op, or `xortool -c 20 blob`, or `unxor`
    138 ```
    139 
    140 > [!tip] Strings are cheap for the attacker to fake
    141 > Decoy strings (legitimate-looking URLs, fake PDB paths, whole English dictionaries) are common in packed samples. A binary with **almost no** strings, or only library boilerplate, is *more* suspicious than one full of them: it is packed or the strings are built at runtime — run FLOSS, or dump it from memory after it unpacks (see [Volatility](/sheets/dfir/volatility) `windows.dumpfiles` / `malfind`).
    142 
    143 ## Hex: `xxd`, `hexdump`, `od`, editors
    144 
    145 ```bash
    146 xxd sample.bin | less                     # canonical: offset, hex, ASCII
    147 xxd -s 0x3C -l 4 sample.bin               # -s seek, -l length: read the PE header offset
    148 xxd -s -64 sample.bin                     # last 64 bytes (appended data?)
    149 xxd -c 32 -g 1 sample.bin | head          # 32 bytes per line, grouped by 1
    150 xxd -p sample.bin | head -c 200           # plain hex, no formatting (for grep / diff)
    151 xxd -r -p hex.txt > out.bin               # hex → binary
    152 hexdump -C sample.bin | head              # BSD-style canonical (macOS default)
    153 od -A x -t x1z -v sample.bin | head       # od: hex offsets, 1-byte hex, ASCII, no * for repeats
    154 cmp -l a.bin b.bin | head                 # byte-level diff; `vbindiff a b`, `radiff2 -x a b` for visual
    155 dd if=sample.bin bs=1 skip=$((0x1000)) count=512 2>/dev/null | xxd | head   # cut a region
    156 ```
    157 
    158 ```powershell
    159 Format-Hex .\sample.bin -Offset 0x3C -Count 4
    160 Format-Hex .\sample.bin | Select -Last 4
    161 [BitConverter]::ToString((Get-Content .\sample.bin -Encoding Byte -TotalCount 16)) -replace '-',' '
    162 ```
    163 
    164 GUI hex editors: **HxD** (Windows, free, huge files, disk/RAM editing, data inspector), **ImHex** (cross-platform, pattern language decodes structures for you, hex + entropy + strings + yara in one), **010 Editor** (paid, binary templates for every format), `hexyl` (terminal, coloured). Registry hive, PE and NTFS record templates exist for all three — worth it when you need to read a structure by hand.
    165 
    166 ## Metadata: `exiftool`
    167 
    168 ```bash
    169 exiftool sample.jpg                            # everything: camera, GPS, timestamps, software, author
    170 exiftool -G1 -a -s sample.docx                 # group names, all duplicates, tag names as they are in the file
    171 exiftool -a -u -g1 -ee sample.pdf              # unknown tags, embedded streams
    172 exiftool -gps:all -n photo.jpg                 # coordinates in decimal
    173 exiftool -Author -Creator -Producer -CreateDate -ModifyDate *.pdf *.doc*       # who made the docs, with what
    174 exiftool -r -csv -common -CreateDate -Author /mnt/img/home/*/Documents > docs.csv   # recurse, CSV for Timeline Explorer
    175 exiftool -time:all -a -G0:1 -s sample.docx     # every timestamp incl. Office internal ones vs filesystem
    176 exiftool -if '$gpslatitude' -r -p '$filename,$gpslatitude,$gpslongitude' .   # only geotagged files
    177 exiftool -X sample.jpg > meta.xml; exiftool -j sample.jpg > meta.json
    178 exiftool -all= copy.jpg                         # strip (never on evidence — for your own redaction)
    179 ```
    180 
    181 What to read: **Office** `Creator`/`LastModifiedBy`/`Company`/`RevisionNumber`/`TotalEditTime`/`Template` (`normal.dotm` vs something odd), `Application` and `AppVersion` (a "2019 Word" doc from a 2010 build); **PDF** `Producer`/`Creator` (`LibreOffice`, `Microsoft: Print To PDF`, `mPDF` from a webapp, `Ghostscript`), `CreateDate` vs `ModifyDate`, XMP history; **images** `Make`/`Model`/`Software`/`GPSPosition`/`DateTimeOriginal`, thumbnail that does not match the image (edited photo); **LNK/EXE** `exiftool` reads PE version info (`CompanyName`, `OriginalFileName` — a `svchost.exe` whose original name is `stealer.exe`).
    182 
    183 ## Archives, containers, embedded objects
    184 
    185 ```bash
    186 # Office docs are ZIPs — look inside without Office
    187 unzip -l sample.docx; unzip -p sample.docx word/vbaProject.bin | file -      # macro container present?
    188 unzip -p sample.docx word/_rels/document.xml.rels | grep -io 'target="http[^"]*"'   # remote template injection
    189 unzip -p sample.docx docProps/core.xml docProps/app.xml                      # metadata XML
    190 7z l sample.bin; 7z x -osample_extracted sample.bin                          # 7z opens almost anything: zip, cab, msi, iso, vhd, wim, chm, pe resources
    191 binwalk sample.bin                          # signature scan for embedded files (firmware, but also polyglots and stego)
    192 binwalk -e sample.bin                       # extract them (into _sample.bin.extracted/)
    193 binwalk -E sample.bin                       # entropy graph — flat high entropy = encrypted/compressed/packed
    194 binwalk -R '\x50\x4b\x03\x04' sample.bin    # raw byte search with offsets
    195 foremost -t all -i sample.bin -o carved/    # carve known types out of ANY blob (same tool as disk carving below)
    196 ```
    197 
    198 ```bash
    199 # PE quick look (Linux) — imports, sections, entropy, timestamps
    200 readpe -h sample.exe; readpe -i sample.exe | head -60      # pev
    201 pescan sample.exe                                          # pev heuristics
    202 python3 -c "import pefile;p=pefile.PE('sample.exe');print(p.FILE_HEADER.dump());[print(e.dll,[i.name for i in e.imports][:8]) for e in p.DIRECTORY_ENTRY_IMPORT]"
    203 diec sample.exe                                            # Detect It Easy: compiler, packer, protector
    204 # Windows GUI: pestudio (indicators, imports scored, strings, VT lookup), DiE, CFF Explorer, PE-bear
    205 ```
    206 
    207 ## Documents: PDF and Office maldoc triage
    208 
    209 ```bash
    210 # PDF
    211 pdfid.py sample.pdf                          # counts of /JS /JavaScript /OpenAction /AA /Launch /EmbeddedFile /URI /ObjStm — any of the first five = open it further
    212 pdf-parser.py -a sample.pdf                  # stats: objects by type
    213 pdf-parser.py --search JavaScript sample.pdf # find the object
    214 pdf-parser.py -o 12 -f -w sample.pdf         # dump object 12, filters applied, raw
    215 pdf-parser.py --search /Launch sample.pdf; pdf-parser.py --search /URI sample.pdf
    216 peepdf -i sample.pdf                         # interactive; `js_analyse` / `extract js`
    217 qpdf --qdf --object-streams=disable sample.pdf out.pdf   # decompress everything so grep/strings work on it
    218 strings out.pdf | grep -Ei 'javascript|/JS|/Launch|/URI|/EmbeddedFile|/OpenAction|cmd|powershell'
    219 
    220 # Office (OLE and OOXML) — oletools
    221 oleid sample.doc                             # summary: encrypted? VBA? XLM? external relationships? flash?
    222 olevba sample.docm                           # dump macros + auto-exec triggers + suspicious keywords + IOCs table
    223 olevba --decode --deobf sample.docm          # decode hex/base64/StrReverse, attempt deobfuscation
    224 olevba --reveal sample.docm                  # macro source with obfuscated strings replaced
    225 oledump.py sample.doc                        # streams; 'M' = macro stream; -s 7 -v = decompress stream 7
    226 oledump.py -p plugin_http_heuristics sample.doc
    227 mraptor sample.doc                           # AutoExec + Write/Execute = suspicious, one line
    228 rtfobj sample.rtf                            # embedded OLE objects in RTF (Equation Editor exploits)
    229 msodde sample.docx                           # DDE field attacks
    230 xlmdeobfuscator -f sample.xls                # Excel 4.0 (XLM) macros
    231 ```
    232 
    233 ## Hashing, fuzzy hashing, known-good/bad
    234 
    235 ```bash
    236 sha256sum sample.bin; md5sum sample.bin; sha1sum sample.bin
    237 hashdeep -c md5,sha1,sha256 -r ./samples/ > hashes.txt                    # recursive multi-hash
    238 hashdeep -c sha256 -r -a -k known-good.txt ./bin/                          # audit dir against a known set (-a audit, -k known)
    239 hashdeep -c sha256 -r -m -k nsrl.txt /mnt/img/usr/bin                      # -m: show only files that MATCH known (whitelist noise)
    240 hashdeep -c sha256 -r -x -k nsrl.txt /mnt/img/usr/bin                      # -x: show only UNKNOWN files — the review list
    241 ssdeep -b sample.bin                                                       # context-triggered piecewise hash
    242 ssdeep -bl -r ./samples/ > fuzzy.txt; ssdeep -bm fuzzy.txt new.bin         # match a new sample against a set (score 0–100)
    243 ssdeep -d -r ./samples/                                                    # cluster near-duplicates within a directory
    244 tlsh -f sample.bin                                                         # TLSH — better on small/heavily-modified files
    245 # Look up, don't upload (an upload tells the attacker you found it):
    246 #   VirusTotal hash search, MalwareBazaar, Hybrid Analysis, `vt file <sha256>` CLI, ANY.RUN search
    247 ```
    248 
    249 ```powershell
    250 Get-FileHash .\sample.bin -Algorithm SHA256                # MD5, SHA1, SHA256, SHA384, SHA512
    251 Get-ChildItem -Recurse | Get-FileHash -Algorithm SHA256 | Export-Csv hashes.csv
    252 certutil -hashfile .\sample.bin SHA256                     # no PowerShell
    253 certutil -hashfile .\sample.bin MD5
    254 sigcheck64.exe -a -h -vt .\sample.exe                     # Sysinternals: signature, version, hashes, VirusTotal (-vt requires accepting ToS)
    255 sigcheck64.exe -e -u -vr -s C:\Windows\System32 > unsigned.txt   # unsigned exes in a tree
    256 ```
    257 
    258 ## Carving: files from unallocated space, swap, memory
    259 
    260 ```bash
    261 # Get the blob: unallocated blocks of a partition (Sleuth Kit), or the whole image, or pagefile/hiberfil/mem
    262 blkls -o 2048 disk.dd > unalloc.raw
    263 
    264 # foremost — header/footer carving, config-driven, fast
    265 foremost -t jpg,png,pdf,doc,zip,exe -i unalloc.raw -o carved-foremost/     # -t types (or all), writes audit.txt with offsets
    266 foremost -c /etc/foremost.conf -i disk.dd -o carved/                      # custom signatures in the conf
    267 # scalpel — same idea, faster, edit /etc/scalpel/scalpel.conf to UNCOMMENT the types you want first
    268 scalpel -c /etc/scalpel/scalpel.conf -o carved-scalpel/ unalloc.raw
    269 # photorec — best for media (400+ formats), interactive TUI, works on damaged fs; /cmd for scripting
    270 photorec /log /d carved-photorec/ /cmd disk.dd fileopt,everything,enable,search
    271 # bulk_extractor — does NOT carve files; it scans EVERY byte for FEATURES: emails, URLs, IPs, phone numbers, credit cards,
    272 #   JSON, base64, EXIF, zip/gzip/rar contents (recursively decompressed!), Windows PE headers, hex keys, domains
    273 bulk_extractor -o be-out/ disk.dd                          # 10–30 min per 100 GB; multi-threaded
    274 bulk_extractor -o be-out/ -E email -E url -E domain -E exif unalloc.raw    # -E enable only listed scanners
    275 ls be-out/            # email.txt url.txt domain.txt ip.txt telephone.txt ccn.txt exif.txt zip.txt json.txt *_histogram.txt
    276 head be-out/url_histogram.txt be-out/email_histogram.txt   # ranked — top hits first
    277 bulk_extractor -o be-out/ -F iocs.txt disk.dd              # -F: search for your own list of strings (offsets to features.txt)
    278 bulk_extractor -o be-out/ -f 'Invoke-|-enc ' disk.dd       # -f: regex
    279 # Every hit carries a byte offset (or "offset-ZIP-offset" for compressed) → dd/xxd there, or `fiwalk`/`identify_filenames.py` to map offset → filename via the fs
    280 identify_filenames.py --all be-out/ be-out-annotated/ --image disk.dd
    281 ```
    282 
    283 ```bash
    284 # Manual carving when you know the header: find offsets, cut
    285 grep -obUaP '\xFF\xD8\xFF\xE0' unalloc.raw | head            # -o offsets, -b byte offset, -U binary, -a text, -P perl regex
    286 python3 - <<'PY'
    287 import re
    288 d=open('unalloc.raw','rb').read()
    289 for i,m in enumerate(re.finditer(rb'%PDF-1\.\d.*?\x25\x25EOF', d, re.S)):
    290     open(f'carved_{i}.pdf','wb').write(m.group()); print(i, m.start(), len(m.group()))
    291 PY
    292 # Strings over the whole blob, with offsets, into the IOC pass above
    293 strings -a -t x -n 8 unalloc.raw > unalloc-strings.txt; strings -a -t x -n 8 -e l unalloc.raw >> unalloc-strings.txt
    294 # Windows pagefile/hiberfil: strings + bstrings work directly; decompress hiberfil first for real analysis
    295 #   hibr2bin.exe hiberfil.sys hiber.raw   (Comae/Magnet)   then Volatility / strings on hiber.raw
    296 ```
    297 
    298 > [!info] What carving cannot do
    299 > Fragmented files come out corrupt (only the first fragment, or garbage joined on). SSDs with TRIM zero deleted blocks quickly — carving an SSD imaged days after deletion mostly yields nothing. Encrypted/compressed containers carve as one opaque blob. Carved files have **no name, no path, no timestamps**: to get those back, match the carved file's hash/offset to `$MFT`/`fls -d` deleted entries or the USN journal.
    300 
    301 ## YARA: match what you already know
    302 
    303 ```bash
    304 yara -r rules/ sample.bin                                  # recurse a rules dir
    305 yara -s rule.yar sample.bin                                # -s print matching strings + offsets
    306 yara -m -s rules.yar sample.bin                            # -m print rule metadata
    307 yara -r -w -f rules/ /mnt/img/home/                        # -w no warnings, -f fast mode
    308 yara -C compiled.yarc sample.bin; yarac rules/*.yar compiled.yarc   # precompile big rule sets
    309 yara rules.yar 1234                                        # scan a live PID (Linux, root)
    310 yara -D sample.bin                                         # dump module data (pe, elf, hash, math)
    311 yara -d filename=sample.bin -d filesize=$(stat -c%s sample.bin) rules.yar sample.bin   # external variables
    312 yara-x scan rules/ sample.bin                              # yara-x: the Rust rewrite, same syntax, faster, better errors
    313 ```
    314 
    315 ```yara
    316 rule triage_suspicious_pe_strings
    317 {
    318     meta:
    319         author = "DAEMON"
    320         description = "Quick triage: PE with injection APIs + a URL + a PowerShell flag"
    321     strings:
    322         $api1 = "VirtualAllocEx" ascii
    323         $api2 = "WriteProcessMemory" ascii
    324         $api3 = "CreateRemoteThread" ascii
    325         $url  = /https?:\/\/[a-z0-9.\-]+\/[a-z0-9\/._-]*/ ascii wide nocase
    326         $ps   = "-enc" ascii wide nocase
    327         $ps2  = "FromBase64String" ascii wide
    328     condition:
    329         uint16(0) == 0x5A4D and filesize < 5MB and
    330         2 of ($api*) and ($url or any of ($ps*))
    331 }
    332 ```
    333 
    334 Rule sources: **Neo23x0/signature-base** (Loki/Thor), **Yara-Rules/rules**, **ReversingLabs**, **Elastic protections-artifacts**, **InQuest awesome-yara** index, ESET, Malpedia (login), plus the packer/crypto/capability rules in **mandiant/capa** (`capa sample.exe` gives you ATT&CK capabilities without writing rules). Keep an `iocs.yar` per case with the hashes, mutexes, PDB paths and URLs you pulled out of `strings` — then scan every other host's triage collection with it.
    335 
    336 ## Ten-minute triage checklist
    337 
    338 ```bash
    339 f=sample.bin
    340 file -k $f; sha256sum $f; ssdeep -b $f; exiftool -G1 -s $f | head -40
    341 xxd $f | head -4; xxd $f | tail -4
    342 strings -a -n 6 $f > s.txt; strings -a -n 6 -e l $f >> s.txt; wc -l s.txt
    343 grep -Eio 'https?://[^ "]+|\b([0-9]{1,3}\.){3}[0-9]{1,3}\b|[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}' s.txt | sort -u
    344 grep -Ei 'powershell|cmd\.exe|-enc|VirtualAlloc|WriteProcessMemory|CreateRemoteThread|HKCU|HKLM|\\Temp\\|\.pdb' s.txt | sort -u | head -40
    345 binwalk $f | head; binwalk -E $f >/dev/null && echo "see entropy png"
    346 diec $f 2>/dev/null || pescan $f 2>/dev/null
    347 yara -r ~/rules/ $f; capa $f 2>/dev/null | head -40
    348 # then decide: benign / known-bad (hash hit) / needs sandbox (ANY.RUN, CAPE, Joe) / needs a reverser
    349 ```
    350 
    351 1. **Identity**: `file -k`, magic head/tail, size, entropy. Packed? Polyglot? Appended data?
    352 2. **Hashes**: SHA-256 to VT/MalwareBazaar *search* (do not upload yet); `ssdeep` against your case corpus.
    353 3. **Metadata**: `exiftool` — author, tool, timestamps, PDB path, version info vs filename.
    354 4. **Strings**, both encodings, then the IOC greps. Save everything to the case notes with offsets.
    355 5. **Structure**: imports/sections (PE), objects (PDF), macros (Office), embedded files (`binwalk`, `7z l`).
    356 6. **Match**: YARA rule sets, capa. Write the case rule from what you found.
    357 7. **Decide** the next stop: sandbox, [Volatility](/sheets/dfir/volatility) for a memory-resident stage, or a reverser.
    358 
    359 ## Related
    360 
    361 - [EZ Tools & KAPE](/sheets/dfir/ez-tools-kape) — `bstrings`, `Hasher`, `EZViewer` on Windows
    362 - [Linux forensics](/sheets/dfir/linux-forensics) — where unallocated space comes from (`blkls`), Sleuth Kit
    363 - [Acquisition](/sheets/dfir/disk-imaging) — getting the disk/memory image to carve
    364 - [Volatility 3](/sheets/dfir/volatility) — dumping unpacked binaries from memory for a second `strings` pass
    365 - [Hashing](/sheets/cryptography/hashing) — algorithm reference