
public static String getAppSignature(Context context) { try { return hex(context.getPackageManager().getPackageInfo(context.getPackageName(), 64).signatures[0].toByteArray()); } catch (Exception unused) { return ; } }跳到hex函数private static String hex(byte[] bArr) throws NoSuchAlgorithmException { try { MessageDigest messageDigest MessageDigest.getInstance(SHA1); //声明sha1算法 messageDigest.update(bArr); //传入参数bArr byte[] bArrDigest messageDigest.digest(); //计算出结果 StringBuilder sb new StringBuilder(); for (byte b : bArrDigest) { String hexString Integer.toHexString(b UByte.MAX_VALUE); //UByte.MAX_VALUE即无符号字节的最大值也就是255按位与255转换为无符号整数 while (hexString.length() 2) { hexString 0 hexString; } sb.append(hexString); } return sb.toString().toLowerCase(); } catch (Exception unused) { return ; } }问题是如何找到hex函数的参数context.getPackageManager() .getPackageInfo(context.getPackageName(), 64) .signatures[0] .toByteArray()64 是PackageManager.GET_SIGNATURES这个常量的值就是请求签名的指令码然后signatures[0]取到签名再.toByteArray()转换成字节在jadx中拿到签名sha10F BF 65 80 2A 94 64 9F 01 92 0C 2A 09 66 C2 93 4E 81 7F 73写个脚本跑出来secret [ 86, 10, 3, 1, 77, 124, 123, 97, 109, 37, 64, 90, 2, 89, 8, 5, 111, 115, 64, 66, 4, 16, 65, 62, 123, 8, 88, 81, 30 ] key 0fbf65802a94649f01920c2a0966c2934e817f73 flag .join( chr(b ^ ord(key[i % len(key)])) for i, b in enumerate(secret) ) print(flag)drive公司的驱动程序好像出bug了连接的程序也连接不上重新连接驱动还需要重新输入密钥请尽快修复程序连接驱动缺失的符号md5f2c6151d6c0d99f3666129b97e2100f5。核心文件只有两个link.exe和Driver.sys一个程序一个驱动先看exe的string\\.\Device????? flag可能是在device这里破坏了sys文件本质是PE文件同样具有MZ开头但是我们查看发现原本的4D 5A变成了09 5A改回去之后发现下面还有异常内容J...D......L.!Th -s p6ogr%m c%nno 0 bedrundin .OSThis转16进制是54 68 69 73而这里是54 68 2D 73经gpt观察后发现每 4 字节的第 1 个字节都像是被异或了0x44。按这个规律恢复后Driver.sys重新变成正常 PE 驱动并能看到关键字符串\??\DeviceDrive \Device\MYDEVICE flag is you input wrong真正缺失的符号是Drive并且Drive的md5刚好是f2c6151d6c0d99f3666129b97e2100f5再把exe修改好下面是gpt独秀修复驱动后继续分析驱动逻辑。DriverEntry中创建了内核设备和符号链接DeviceName: \Device\MYDEVICE SymbolicLink: \??\DeviceDrive同时注册了几个派发函数其中IRP_MJ_DEVICE_CONTROL指向主要处理函数。用户态link.exe发送的控制码是0x222000进入驱动的DeviceControl分支后可以看到它会读取用户输入的 32 字节缓冲区然后做第一层原地变换for (i 1; i 32; i) { buf[i - 1] ^ ((buf[i - 1] % 0x12) buf[i] 5) ^ 0x34; }这里有一个关键观察每一轮修改的是buf[i - 1]但会用到还没被修改的buf[i]。这说明如果要逆推原输入应当从末尾往前推而不是从开头往后推。第一层变换后驱动把结果传入另一个校验函数。这个函数分两轮处理输入。第一轮使用初始值0x34做链式异或prev 0x34; for (i 0; i len; i) { tmp[i] input[i] ^ prev; prev input[i]; }