DF-0871 / craft_benign.py
#!/usr/bin/env python3 """Build a BENIGN NTFS image: well-formed $AttrDef with short NUL-terminated names so the do/while at ntfs_vfsops.c:458-460 stops at j<64 (no overflow). Used as the negative control for DF-0871 causation. Reuses craft_img.py's builder; only swaps in a benign attrdef data stream.""" import sys, struct sys.path.insert(0, sys.path[0]) import craft_img as C A_STD = 0x10 def benign_attrdef_records(): """Two well-formed 160-byte attrdef records (short names) + terminator.""" out = bytearray() for name, atype in [("$STANDARD_INFORMATION", A_STD), ("$FILE_NAME", 0x30)]: e = bytearray(C.ATTRDEF_RECSZ) for i, ch in enumerate(name): struct.pack_into("<H", e, i * 2, ord(ch)) struct.pack_into("<I", e, 128, atype) # ad_type # trailing fields left zero -> do/while stops at name NUL, j < 64 out += e out += bytearray(C.ATTRDEF_RECSZ) # all-zero terminator return bytes(out) def build(out_path): img = bytearray(C.NCLUSTERS * C.CLU) img[0:C.BPS] = C.boot_sector() rec0 = C.mft_record(1,1,0, C.resident_attr(C.A_DATA,8,b"\x00"*8)+C.term_attr()) img[C.MFTCN*C.CLU+0*C.RECSZ:C.MFTCN*C.CLU+1*C.RECSZ] = rec0 ad = benign_attrdef_records() rec4 = C.mft_record(1,1,0, C.resident_attr(C.A_DATA,len(ad),ad)+C.term_attr()) img[C.MFTCN*C.CLU+4*C.RECSZ:C.MFTCN*C.CLU+5*C.RECSZ] = rec4 iroot = C.well_formed_index_root() rec5 = C.mft_record(1,1,0x0002, C.resident_attr(C.A_INDXROOT,len(iroot),iroot,name="$I30")+C.term_attr()) img[C.MFTCN*C.CLU+5*C.RECSZ:C.MFTCN*C.CLU+6*C.RECSZ] = rec5 bmp = b"\xFF"*16 rec6 = C.mft_record(1,1,0, C.resident_attr(C.A_DATA,len(bmp),bmp)+C.term_attr()) img[C.MFTCN*C.CLU+6*C.RECSZ:C.MFTCN*C.CLU+7*C.RECSZ] = rec6 runs = C.runs_encode(C.UPCASE_CN, C.UPCASE_NCLU) nr = C.nonresident_data_attr(runs, C.UPCASE_NCLU*C.CLU, C.UPCASE_NCLU*C.CLU) rec10 = C.mft_record(1,1,0, nr+C.term_attr()) img[C.MFTCN*C.CLU+10*C.RECSZ:C.MFTCN*C.CLU+11*C.RECSZ] = rec10 uo = C.UPCASE_CN*C.CLU img[uo:uo+C.UPCASE_NCLU*C.CLU] = C.upcase_table() with open(out_path,"wb") as f: f.write(img) print(f"[+] wrote benign {out_path} ({len(img)} bytes)") if __name__ == "__main__": build(sys.argv[1] if len(sys.argv)>1 else "ntfs_benign.img") |