AAA: immortal
题目给的apk里面是一个RPC调用, 发现找了ByteService这个服务
public void callCTFService(int i, int i2) {
try {
Class<?> cls = Class.forName("android.os.ServiceManager");
Parcel obtain = Parcel.obtain();
Parcel obtain2 = Parcel.obtain();
obtain.writeInterfaceToken("android.os.IByteCTFService");
obtain.writeInt(i2);
((IBinder) cls.getMethod("getService", String.class).invoke(cls.newInstance(), "ByteCTFService")).transact(i, obtain, obtain2, 0);
obtain2.readException();
} catch (RemoteException | ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
然后用题目给的一个xml链接, 通过
- AndroidStudio → Tools → SDK Manager → SDK Update Sites 添加题目给的xml,然后启动一个题目给的模拟器. 之后root模拟器,然后在已有服务里扒拉可以的jar包, 找到了framework.jar & services.jar
- 浏览器打开xml, 通过xml里的一个link下载system-image. 然后用7z解压system.img, Winhex打开super.img, 在里面也能扒拉出上面两个jar包
用jadx分析可知调用链:apk → IByteCTFService in framework.jar → ByteCTFService in service.jar → com.bytedance.bytectf.A in framework.jar
打开一看是lambada calculus, 可以查一些资料Lambda calculus引论 ,
丘奇编码, 认知科学家写给小白的Lambda演算 以及 wiki百科.
所以首先要搞明白A类里每个method的含义,根据查找的资料, 半猜半试得到下面的结果.
function | description |
---|---|
A.a | 返回0 |
A.b | 自增1 |
A.c | 乘法 |
A.d | 加法 |
A.e | 加上n(利用A.b实现) |
check里检查一个16元一次方程组. 因此利用sympy求方程组, 直接抄check部分的java代码把它转成python的.
这里摸来了站队内4老师的脚本:
import re
import sympy
code = open('check.java', 'r').read()
# a list of tuple
# func[0]:编号 func[1]:函数的code段
func = re.findall(r"private boolean check(\d+)\(\) {([^}]*)}", code, re.DOTALL)
class AA:
def __init__(self):
self.a = 0
self.b = lambda x: x+1
self.c = lambda x, y: x + y
self.d = lambda x, y: x * y
def e(n):
return lambda x : x+n
self.e = e
a = AA()
m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14,m15,m16 = sympy.symbols('m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14,m15,m16')
ll = []
for f in func:
fid, code = f
# code = re.sub('a(\d+)\.b\(', '1+(', code)
code = code.split('}')[0].replace('A<Integer> ', '').replace('Function ', '').replace('this.', '').replace(' ', '')
# print(code)
code, ret = code.split('return')
exec(code)
ret = ret.strip().replace('((Integer) ((Function) ', '((').replace('.apply(f)).apply(0)).intValue();', '))')
num, val = ret.split(' == ')
ll.append(eval(val + ' - ' + num))
print('\n'.join(str(x) for x in ll))
result = sympy.solve(ll,[m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14,m15,m16])
s = ''
for v in [m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14,m15,m16]:
s += (chr(result[v]))
print(s)