本帖最后由 StarrySky 于 2025-8-26 15:01 编辑
参加了一下国际比赛以下是我的解题思路
打开NP管理器反编译APK
[Java] 纯文本查看 复制代码 @POST("flag")
Call<String> getFlag(@Body FlagRequest flagRequest)
找到获取Flag的方法com.sekai.bank.network.ApiService.getFlag
转到FlagRequest[Java] 纯文本查看 复制代码 public class FlagRequest {
private boolean unmask_flag;
public FlagRequest(boolean z) {
this.unmask_flag = z;
}
public boolean getUnmaskFlag() {
return this.unmask_flag;
}
public void setUnmaskFlag(boolean z) {
this.unmask_flag = z;
}
}
从这里分析的值,我们可以伪造一个POST请求来得到Flag
抓包先登录,通过ProxyPin抓包看看请求体 发现有一个X-Signature 继续打开NP管理器搜索X-Signature字符串 [Java] 纯文本查看 复制代码 public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
try {
chain = chain.proceed(request.newBuilder().header("X-Signature", generateSignature(request)).build());
return chain;
} catch (Exception e) {
Log.e("SekaiBank-API", "Failed to generate signature: " + e.getMessage());
return chain.proceed(request);
}
}
可以看到一个generateSignature方法,定位进去看看 [Java] 纯文本查看 复制代码 private String generateSignature(Request request) throws IOException, GeneralSecurityException {
Throwable e;
String str = request.method() + "/api".concat(getEndpointPath(request)) + getRequestBodyAsString(request);
SekaiApplication instance = SekaiApplication.getInstance();
PackageManager packageManager = instance.getPackageManager();
String packageName = instance.getPackageName();
try {
Signature[] apkContentsSigners;
if (VERSION.SDK_INT >= 28) {
PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 134217728);
SigningInfo signingInfo = packageInfo.signingInfo;
apkContentsSigners = signingInfo != null ? signingInfo.hasMultipleSigners() ? signingInfo.getApkContentsSigners() : signingInfo.getSigningCertificateHistory() : packageInfo.signatures;
} else {
apkContentsSigners = packageManager.getPackageInfo(packageName, 64).signatures;
}
if (apkContentsSigners == null || apkContentsSigners.length <= 0) {
throw new GeneralSecurityException("No app signature found");
}
MessageDigest instance2 = MessageDigest.getInstance("SHA-256");
for (Signature toByteArray : apkContentsSigners) {
instance2.update(toByteArray.toByteArray());
}
return calculateHMAC(str, instance2.digest());
} catch (NameNotFoundException e2) {
e = e2;
throw new GeneralSecurityException("Unable to extract app signature", e);
} catch (NoSuchAlgorithmException e3) {
e = e3;
throw new GeneralSecurityException("Unable to extract app signature", e);
}
}
可以看到str字符串,是由getEndpointPath和getRequestBodyAsString拼接得到的 [Java] 纯文本查看 复制代码 String str = request.method() + "/api".concat(getEndpointPath(request)) + getRequestBodyAsString(request); SekaiApplication instance = SekaiApplication.getInstance(); 分析完开始HOOK 这里的HOOK我采用的朋友开发的Luahook calculateHMAC方法看看第一个参数str
参数是POST/api/auth/login{"password":"114514","username":"114514"} 那就简单了,直接HookgetEndpointPath和getRequestBodyAsString方法 [mw_shl_code=java,true]hook("com.sekai.bank.network.ApiClient$SignatureInterceptor",
lpparam.classLoader,
"getEndpointPath",
"okhttp3.Request",
function(it)
end,
function(it)
it.result="/flag"
end)
hook("com.sekai.bank.network.ApiClient$SignatureInterceptor",
lpparam.classLoader,
"getRequestBodyAsString",
"okhttp3.Request",
function(it)
end,
function(it)
it.result=[[{"unmask_flag":true}]]
end)
de] 接着我们直接登录,然后他就会自动计算X-Signature,然后拿ProxyPin 重写请求就行了
拿到flag
|