""" Hook AnyDesk backend process — monitors file I/O, bitmaps, clipboard. Usage: python hook_backend.py Must run as Administrator (backend runs as SYSTEM). """ import frida import sys import time import json from datetime import datetime AGENT = r""" var hc = 0; function gx(mod, name) { try { var m = Process.findModuleByName(mod); return m ? m.findExportByName(name) : null; } catch(e) { return null; } } // --- CreateFileW --- var a1 = gx('KERNEL32.DLL', 'CreateFileW'); if (a1) { Interceptor.attach(a1, { onEnter: function(args) { try { var path = args[0].readUtf16String(); if (!path) return; var pl = path.toLowerCase(); if (pl.indexOf('\\device\\')!==-1||pl.indexOf('\\pipe\\')!==-1||pl.indexOf('condrv')!==-1) return; var access = args[1].toInt32()>>>0, disp = args[4].toInt32(); var isW = (access&0x40000000)!==0||(access&0x2)!==0; var isC = disp===1||disp===2||disp===4; var fl=[]; if(path.indexOf('..\\')!==-1) fl.push('TRAV_BS'); if(path.indexOf('../')!==-1) fl.push('TRAV_FS'); if(pl.indexOf('startup')!==-1) fl.push('STARTUP'); send({t:'F', path:path, w:isW, c:isC, fl:fl}); } catch(e){} }}); hc++; } // --- WriteFile --- var a2 = gx('KERNEL32.DLL', 'WriteFile'); if (a2) { Interceptor.attach(a2, { onEnter: function(args) { try { var sz = args[2].toInt32(); if (sz > 32) { var preview = args[1].readByteArray(Math.min(sz, 128)); var arr = new Uint8Array(preview); var str = ''; for (var i = 0; i < Math.min(arr.length, 128); i++) { var b = arr[i]; str += (b >= 0x20 && b < 0x7f) ? String.fromCharCode(b) : '.'; } send({t:'W', sz:sz, preview:str}); } } catch(e){} }}); hc++; } // --- MoveFileExW --- var a3 = gx('KERNEL32.DLL', 'MoveFileExW'); if (a3) { Interceptor.attach(a3, { onEnter: function(args) { try { send({t:'M', src:args[0].readUtf16String(), dst:args[1].readUtf16String()}); } catch(e){} }}); hc++; } // --- CreateDIBSection (DeskRT output) --- var a4 = gx('GDI32.dll', 'CreateDIBSection'); if (a4) { Interceptor.attach(a4, { onEnter: function(args) { try { var p = args[1]; if (p.isNull()) return; var w=p.add(4).readS32(), h=p.add(8).readS32(), bpp=p.add(14).readU16(); send({t:'B', w:w, h:h, bpp:bpp, alloc:Math.abs(w)*Math.abs(h)*(bpp/8)}); } catch(e){} }}); hc++; } // --- Clipboard --- var a5 = gx('USER32.dll', 'SetClipboardData'); if (a5) { Interceptor.attach(a5, { onEnter: function(args) { send({t:'C', op:'SET', fmt:args[0].toInt32()}); }}); hc++; } var a6 = gx('USER32.dll', 'GetClipboardData'); if (a6) { Interceptor.attach(a6, { onEnter: function(args) { this.f=args[0].toInt32(); }, onLeave: function(r) { if(!r.isNull()) send({t:'C', op:'GET', fmt:this.f}); } }); hc++; } // --- send/recv on backend too --- var sc=0, rc=0; var a7 = gx('WS2_32.dll', 'send'); if (a7) { Interceptor.attach(a7, { onLeave: function(r) { var n=r.toInt32(); if(n>0){sc++;if(sc<=10||sc%50===0)send({t:'N',d:'S',sz:n,n:sc});}}}); hc++; } var a8 = gx('WS2_32.dll', 'recv'); if (a8) { Interceptor.attach(a8, { onLeave: function(r) { var n=r.toInt32(); if(n>0){rc++;if(rc<=10||rc%50===0)send({t:'N',d:'R',sz:n,n:rc});}}}); hc++; } send({t:'log', m:hc+' hooks on backend'}); """ def main(): if len(sys.argv) < 2: print("Usage: python hook_backend.py ") print("Run as Administrator!") sys.exit(1) pid = int(sys.argv[1]) print(f"[+] Attaching to backend PID {pid}...") cfn = {1:'TEXT',2:'BITMAP',8:'DIB',13:'UNICODE',15:'HDROP',17:'DIBV5'} t0 = time.time() events = [] def on_msg(msg, data): if msg['type'] != 'send': print(f" [!] {msg.get('description','error')}") return p = msg['payload'] t = p.get('t','') ts = time.time() - t0 if t == 'log': print(f" [*] {p['m']}") elif t == 'F': fl = ' '.join(f'[{f}]' for f in p.get('fl',[])) mode = ('W' if p['w'] else 'R') + ('+C' if p['c'] else '') print(f" [{ts:7.2f}s] [FILE {mode:4s}] {p['path']} {fl}") events.append(p) elif t == 'W': # Only show interesting writes (not log lines) if 'info 2026' not in p['preview'] and 'warning 2026' not in p['preview']: print(f" [{ts:7.2f}s] [WRITE {p['sz']:6d}b] {p['preview'][:80]}") events.append(p) elif t == 'M': print(f" [{ts:7.2f}s] [MOVE] {p['src']} -> {p['dst']}") events.append(p) elif t == 'B': print(f" [{ts:7.2f}s] [BITMAP] {p['w']}x{p['h']} @{p['bpp']}bpp ({p['alloc']:,.0f}b)") events.append(p) elif t == 'C': fn = cfn.get(p['fmt'], f"FMT{p['fmt']}") print(f" [{ts:7.2f}s] [CLIP] {p['op']} {fn}") events.append(p) elif t == 'N': print(f" [{ts:7.2f}s] [NET] {p['d']} {p['sz']}b #{p['n']}") try: session = frida.attach(pid) except Exception as e: print(f"[!] Failed: {e}") print("[!] Run as Administrator — backend runs as SYSTEM") sys.exit(1) script = session.create_script(AGENT, runtime='v8') script.on('message', on_msg) script.load() time.sleep(1) print(f"\n{'='*60}") print(" Backend hooked. Now:") print(" 1. Use AnyDesk file transfer to send a file") print(" 2. Copy/paste between machines") print(" 3. Move mouse (DeskRT frames)") print(" Ctrl+C to stop") print(f"{'='*60}\n") try: while True: time.sleep(0.1) except KeyboardInterrupt: print("\n[+] Stopping...") out = f"backend_{pid}_{datetime.now().strftime('%H%M%S')}.json" with open(out, 'w') as f: json.dump(events, f, indent=2) print(f"[+] {len(events)} events -> {out}") session.detach() if __name__ == '__main__': main()