攻防世界easyJava(re Moble)

easyJava

题目考察:jeb反编译工具的使用,逆向能力,本题是基于enigma密码机的一个加密,可以参考博客https://blog.csdn.net/kyoma/article/details/51857944,大致题目使用的加密就是这个原理。

题目分析


    private static char a(String arg1, b arg2, a arg3) {
        return arg3.a(arg2.a(arg1));
    }

    static Boolean a(String arg1) {
        return MainActivity.b(arg1);
    }

    private static Boolean b(String arg8) {
        Boolean v0_1;
        int v0 = 0;
        if(!arg8.startsWith("flag{")) {
            v0_1 = Boolean.valueOf(false);
        }
        else if(!arg8.endsWith("}")) {
            v0_1 = Boolean.valueOf(false);
        }
        else {
            String v2 = arg8.substring(5, arg8.length() - 1);
            b v4 = new b(Integer.valueOf(2));
            a v5 = new a(Integer.valueOf(3));
            StringBuilder v3 = new StringBuilder();
            int v1 = 0;
            while(v0 < v2.length()) {
                v3.append(MainActivity.a(v2.charAt(v0) + "", v4, v5));
                Integer v6 = Integer.valueOf(v4.b().intValue() / 25);
                if(v6.intValue() > v1 && v6.intValue() >= 1) {
                    ++v1;
                }

                ++v0;
            }

            v0_1 = Boolean.valueOf(v3.toString().equals("wigwrkaugala"));
        }

        return v0_1;
    }

    protected void onCreate(Bundle arg3) {
        super.onCreate(arg3);
        this.setContentView(2130968603);
        this.findViewById(2131427446).setOnClickListener(new View$OnClickListener(((Context)this)) {
            public void onClick(View arg5) {
                if(MainActivity.a(this.a.findViewById(2131427445).getText().toString()).booleanValue()) {
                    Toast.makeText(this.a, "You are right!", 1).show();
                }
                else {
                    Toast.makeText(this.a, "You are wrong! Bye~", 1).show();
                    new Timer().schedule(new TimerTask() {
                        public void run() {
                            System.exit(1);
                        }
                    }, 2000);
                }
            }
        });
    }

首先,拿到题目一个apk文件,拖入jeb反编译,得到的MainActivity的大致代码如下。第一步肯定是要看到最下面的onCreate()方法,观察题目大概是要我们干什么。

可以发现,他是将我们输入的东西,传入到a()方法中,然后若返回结果是true,那么,就会输出“you are right!”。很显然我们需要令他成立。

可以看到a()方法其实并没有什么,就是调用了一下b()方法,将我们输入的传了过去。

b()方法是这个MainActivity中主要的一段代码。他有三个判断,第一个判断开头是否为“flag{”,第二个判断是否以"}"结尾。第三个比较关键,他初始化了a类和b类型为v4 v5,同时分别传入构造函数2和3.然后把我们输入的字符串的每个字符和v4,v5传入带有三个形参的a()方法中。就是去执行a.a(b.a(“字符”)),返回结果是一个字符类型的值,将每个我们输入的值执行后返回,拼接起来和”wigwrkaugala“比较,若相等就是正确的了。


public class a {
    public static ArrayList a;
    static String b;
    Integer[] c;
    static Integer d;

    static {
        a.a = new ArrayList();
        a.b = "abcdefghijklmnopqrstuvwxyz";
        a.d = Integer.valueOf(0);
    }

    public a(Integer arg8) {
        super();
        this.c = new Integer[]{Integer.valueOf(7), Integer.valueOf(14), Integer.valueOf(16), Integer.valueOf(21), Integer.valueOf(4), Integer.valueOf(24), Integer.valueOf(25), Integer.valueOf(20), Integer.valueOf(5), Integer.valueOf(15), Integer.valueOf(9), Integer.valueOf(17), Integer.valueOf(6), Integer.valueOf(13), Integer.valueOf(3), Integer.valueOf(18), Integer.valueOf(12), Integer.valueOf(10), Integer.valueOf(19), Integer.valueOf(0), Integer.valueOf(22), Integer.valueOf(2), Integer.valueOf(11), Integer.valueOf(23), Integer.valueOf(1), Integer.valueOf(8)};
        int v0;
        for(v0 = arg8.intValue(); v0 < this.c.length; ++v0) {
            a.a.add(this.c[v0]);
        }

        for(v0 = 0; v0 < arg8.intValue(); ++v0) {
            a.a.add(this.c[v0]);
        }
    }

    public char a(Integer arg5) {
        char v0_1;
        int v0 = 0;
        Integer v1 = Integer.valueOf(0);
        if(arg5.intValue() == -10) {
            a.a();
            v0_1 = " ".charAt(0);
        }
        else {
            while(v0 < a.a.size() - 1) {
                if(a.a.get(v0) == arg5) {
                    v1 = Integer.valueOf(v0);
                }

                ++v0;
            }

            a.a();
            v0_1 = a.b.charAt(v1.intValue());
        }

        return v0_1;
    }

    public static void a() {
        a.d = Integer.valueOf(a.d.intValue() + 1);
        if(a.d.intValue() == 25) {
            int v0 = a.a.get(0).intValue();
            a.a.remove(0);
            a.a.add(Integer.valueOf(v0));
            a.d = Integer.valueOf(0);
        }
    }
}

首先对于这个a类,我们在初始化的时候传入了3,可以看到在a的构造函数中,他实现的就是相当于enigma密码机转动了三格,然后在调用a方法的时候,最终返回的值v0_1就是"abcdefghijklmnopqrstuvwxyz"的第v0个,v0就是传入的Integer类型的值在ArrayList[7, 14, 16, 21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8]中的索引值
同时可以发现在他给v0_1赋值前,调用了void a()方法,可以发现这个方法本身是实现对ArrayList的转动,但是由于可以发现他有一个判断条件,要令成员变量d为25的时候才执行,因为d初始赋值是0,而我们也不会调用25次,所以是不会触发到这里面的。

public class b {
    public static ArrayList a;
    static String b;
    Integer[] c;
    static Integer d;

    static {
        b.a = new ArrayList();
        b.b = "abcdefghijklmnopqrstuvwxyz";
        b.d = Integer.valueOf(0);
    }

    public b(Integer arg9) {
        super();
        this.c = new Integer[]{Integer.valueOf(8), Integer.valueOf(25), Integer.valueOf(17), Integer.valueOf(23), Integer.valueOf(7), Integer.valueOf(22), Integer.valueOf(1), Integer.valueOf(16), Integer.valueOf(6), Integer.valueOf(9), Integer.valueOf(21), Integer.valueOf(0), Integer.valueOf(15), Integer.valueOf(5), Integer.valueOf(10), Integer.valueOf(18), Integer.valueOf(2), Integer.valueOf(24), Integer.valueOf(4), Integer.valueOf(11), Integer.valueOf(3), Integer.valueOf(14), Integer.valueOf(19), Integer.valueOf(12), Integer.valueOf(20), Integer.valueOf(13)};
        int v0;
        for(v0 = arg9.intValue(); v0 < this.c.length; ++v0) {
            b.a.add(this.c[v0]);
        }

        for(v0 = 0; v0 < arg9.intValue(); ++v0) {
            b.a.add(this.c[v0]);
        }
    }

    public Integer a(String arg5) {
        int v0 = 0;
        Integer v1 = Integer.valueOf(0);
        if(b.b.contains(arg5.toLowerCase())) {
            Integer v2 = Integer.valueOf(b.b.indexOf(arg5));
            while(v0 < b.a.size() - 1) {
                if(b.a.get(v0) == v2) {
                    v1 = Integer.valueOf(v0);
                }

                ++v0;
            }
        }
        else {
            if(arg5.contains(" ")) {
                v1 = Integer.valueOf(-10);
                goto label_24;
            }

            v1 = Integer.valueOf(-1);
        }

    label_24:
        b.a();
        return v1;
    }

    public static void a() {
        int v0 = b.a.get(0).intValue();
        b.a.remove(0);
        b.a.add(Integer.valueOf(v0));
        b.b = b.b + "" + b.b.charAt(0);
        b.b = b.b.substring(1, 27);
        b.d = Integer.valueOf(b.d.intValue() + 1);
    }

    public Integer b() {
        return b.d;
    }
}

b类的话其实和a类是很相似的,在构造函数的初始化适合a类的初始化是一样的,不过我们一开始传的值是2,所以就是相当于转动了二格。

然后看到b类中关键的a方法的代码,可以知道传入的是我们输入的字符串的单个字符,返回的是一个Integer类型的值,在MainActivity中作为a类的a方法的传入值。

可以知道我们的返回v1是等于v0,v0是v2在ArrayList[8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13]中的索引
而v2就是我们输入字符在"abcdefghijklmnopqrstuvwxyz"中的索引

然后在给v1赋值后我们可以发现,他调用了b类的void a()方法,void a()方法是实现了对ArrayList的一次转动,以及对字符串"abcdefghijklmnopqrstuvwxyz"的一次转动

到这边就分析完了,只需要写出逆向的脚本就可以得到正确的输入了。

python脚本

from collections import deque#双端队列
alpha = deque("abcdefghijklmnopqrstuvwxyz") 
t1 = deque([8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13]) 
t2 = deque([7, 14, 16, 21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8])

ss = 'wigwrkaugala'
for _ in range(2): 
    t1.append(t1.popleft()) #实现转动
for _ in range(3): 
    t2.append(t2.popleft()) 
print(t1) 
print(t2)

def dec(s): 
    i = t2[(ord(s) - ord('a'))] #ord(s) - ord('a')就可以得到在那个a到z的字符中的索引值
    i = t1[(i)] 
    print(alpha[i], end='')
    t1.append(t1.popleft()) 
    alpha.append(alpha.popleft())
for s in ss: dec(s)

    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
原装进口,最新版本Jquery Moblile jQuery Mobile Overview jQuery’s mobile strategy can be summarized simply: A unified user interface system that works seamlessly across all popular mobile device platforms, built on the rock-solid jQuery and jQuery UI foundation. Focused on a feature-rich but lightweight codebase built on progressive enhancement with a flexible, theming system and ThemeRoller tool. The framework includes an Ajax navigation system that brings animated page transitions and a core set of UI widgets: pages, dialogs, toolbars, listviews, buttons with icons, form elements, accordions, collapsibles, and more. The critical difference with our approach is the wide variety of mobile platforms we’re targeting with jQuery Mobile so no browser or device is left behind. We've also focused on making jQuery Mobile easy to learn with a simple, markup-based system to applying behavior and theming. For more advanced developers, there is a rich API of global configuration options, events, and methods to apply scripting, generate dynamic pages, and even build native apps with tools like PhoneGap. To make this broad support possible, all pages in jQuery Mobile are built on a foundation of clean, semantic HTML to ensure compatibility with pretty much any web-enabled device. In devices that interpret CSS and JavaScript, jQuery Mobile applies progressive enhancement techniques to unobtrusively transform the semantic page into a rich, interactive experience that leverages the power of jQuery and CSS. Accessibility features such as WAI-ARIA are tightly integrated throughout the framework to provide support for screen readers and other assistive technologies.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值