BUUCTF_reverse_findit

一、查壳
1、使用工具

2、检查结果

这表明程序​​未加壳​​,并且是安卓逆向,我们可以直接进行下一步的代码分析。 

二、分析代码
1、静态分析

我用的是jadx-gui

具体的代码是这样的

package com.example.findit;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

/* loaded from: classes.dex */
public class MainActivity extends ActionBarActivity {
    /* JADX INFO: Access modifiers changed from: protected */
    @Override // android.support.v7.app.ActionBarActivity, android.support.v4.app.FragmentActivity, android.app.Activity
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn = (Button) findViewById(R.id.widget3);
        final EditText edit = (EditText) findViewById(R.id.widget2);
        final TextView text = (TextView) findViewById(R.id.widget1);
        final char[] a = {'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'};
        final char[] b = {'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'};
        btn.setOnClickListener(new View.OnClickListener() { // from class: com.example.findit.MainActivity.1
            @Override // android.view.View.OnClickListener
            public void onClick(View v) {
                char[] x = new char[17];
                char[] y = new char[38];
                for (int i = 0; i < 17; i++) {
                    if ((a[i] < 'I' && a[i] >= 'A') || (a[i] < 'i' && a[i] >= 'a')) {
                        x[i] = (char) (a[i] + 18);
                    } else if ((a[i] >= 'A' && a[i] <= 'Z') || (a[i] >= 'a' && a[i] <= 'z')) {
                        x[i] = (char) (a[i] - '\b');
                    } else {
                        x[i] = a[i];
                    }
                }
                String m = String.valueOf(x);
                if (m.equals(edit.getText().toString())) {
                    for (int i2 = 0; i2 < 38; i2++) {
                        if ((b[i2] >= 'A' && b[i2] <= 'Z') || (b[i2] >= 'a' && b[i2] <= 'z')) {
                            y[i2] = (char) (b[i2] + 16);
                            if ((y[i2] > 'Z' && y[i2] < 'a') || y[i2] >= 'z') {
                                y[i2] = (char) (y[i2] - 26);
                            }
                        } else {
                            y[i2] = b[i2];
                        }
                    }
                    String n = String.valueOf(y);
                    text.setText(n);
                    return;
                }
                text.setText("答案错了肿么办。。。不给你又不好意思。。。哎呀好纠结啊~~~");
            }
        });
    }

    @Override // android.app.Activity
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

三、破解方法

博主java学的不咋地,大概还是可以的,大概就是说给a和b进行加密给x和y
那就直接验证呗,我直接给它改成c语言,这应该也是大多数人的第一思路

#include <stdio.h>
int main() {
      char b[] = {'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'};
      char a[] = {'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'};

                unsigned char x[17]={0};
                unsigned char y[38]={0};
                for (int i = 0; i < 17; i++) {
                    if ((a[i] < 'I' && a[i] >= 'A') || (a[i] < 'i' && a[i] >= 'a')) {
                        x[i] = (a[i] + 18);
                    } else if ((a[i] >= 'A' && a[i] <= 'Z') || (a[i] >= 'a' && a[i] <= 'z')) {
                        x[i] =  (a[i] - 8);
                    } else {
                        x[i] = a[i];
                    }
                }
                for (int i1 = 0; i1 < 17; i1++) {
                  printf("%c", x[i1]);
                }
                
                    for (int i2 = 0; i2 < 38; i2++) {
                        if ((b[i2] >= 'A' && b[i2] <= 'Z') || (b[i2] >= 'a' && b[i2] <= 'z')) {
                            y[i2] =  (b[i2] + 16);
                            if ((y[i2] > 'Z' && y[i2] < 'a') || y[i2] >= 'z') {
                                y[i2] =  (y[i2] - 26);
                            }
                        } else {
                            y[i2] = b[i2];
                        }
                    }
                    for (int i3 = 0; i3 < 38; i3++) {
                      printf("%c", y[i3]);
                    }
return 0;
}

结果是这样的LzakAkLzwXdsyZgewflag{c164675262033b4c49bdf7f9cda28a75}

反面实例

#include <stdio.h>
int main() {
      char b[] = {'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'};
      char a[] = {'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'};

                char x[17]={0};
                char y[38]={0};
                for (int i = 0; i < 17; i++) {
                    if ((a[i] < 'I' && a[i] >= 'A') || (a[i] < 'i' && a[i] >= 'a')) {
                        x[i] = (char) (a[i] + 18);
                    } else if ((a[i] >= 'A' && a[i] <= 'Z') || (a[i] >= 'a' && a[i] <= 'z')) {
                        x[i] = (char) (a[i] - 8);
                    } else {
                        x[i] = a[i];
                    }
                }
                for (int i1 = 0; i1 < 17; i1++) {
                  printf("%c", x[i1]);
                }
                
                    for (int i2 = 0; i2 < 38; i2++) {
                        if ((b[i2] >= 'A' && b[i2] <= 'Z') || (b[i2] >= 'a' && b[i2] <= 'z')) {
                            y[i2] = (char) (b[i2] + 16);
                            if ((y[i2] > 'Z' && y[i2] < 'a') || y[i2] >= 'z') {
                                y[i2] = (char) (y[i2] - 26);
                            }
                        } else {
                            y[i2] = b[i2];
                        }
                    }
                    for (int i3 = 0; i3 < 38; i3++) {
                      printf("%c", y[i3]);
                    }
return 0;
}

结果是LzakAkLzwXdsyZgew��a�{c164675262033b4c49bd�7�9cda28a75}

这个版本是我最初的版本,应该有很多人跟我一样犯了这个错,哎,这个我愁死了,我到处问,我还换了个编译器,没想到啊这个是数据类型的问题

在C语言中,char类型默认为signed char(有符号字符),取值范围是-128到127。而unsigned char的取值范围是0到255。


假设b[i2]是字符'z'(ASCII 122),执行y[i2] = b[i2] + 16后:
如果使用unsigned char,值为138(大于122),条件y[i2] >= 'z'为真,会执行y[i2] = y[i2] - 26得到112(字符'p'),正确。
如果使用signed char,值为-118(负数),条件y[i2] >= 'z'为假(因为-118 < 122),不会减去26,结果错误地保持为-118(输出不可读字符)。

就是这样的,可能会有人问了为什么这个超过127会变成负数了呢
这个又涉及其他的知识了
计算机里面的数据是按照补吗存储的不懂建议搜一下,这里简单叙述一下
 01111111 (127)

10000000(-1)
同时它也是128
表示负数是因为char类型认为第一位二进制位代表符号其余位取反加1就是后面的数值了即1
而unsigned类型就把这个规矩忽略了
也算有收获的,吃一堑长一智,没白费时间

四、最终flag

flag{c164675262033b4c49bdf7f9cda28a75}

### 关于 UF_CURVE_reverse_direction 的定义与使用 `UF_CURVE_reverse_direction` 是 NX/Open API 中的一个功能函数,用于反转曲线的方向。该操作通常在处理几何对象时非常有用,尤其是在需要调整曲线方向以满足特定设计需求的情况下。 #### 功能描述 `UF_CURVE_reverse_direction` 主要作用是对指定的曲线进行方向上的翻转。这种翻转不会改变曲线的实际形状或位置,而是仅更改其参数化方向。这意味着如果原始曲线上的一点对应于某个参数 \( t \),那么经过 `UF_CURVE_reverse_direction` 处理后,这一点对应的参数将是反向后的值[^4]。 #### 参数说明 以下是 `UF_CURVE_reverse_direction` 的典型调用形式及其参数解释: ```c int UF_CURVE_reverse_direction (tag_t curve_tag); ``` - **curve_tag**: 表示目标曲线的对象标签(Tag)。这是 NX 系统内部用来唯一标识几何实体的一种机制。 返回值是一个整数类型的结果码,指示操作的成功与否。成功执行会返回零;非零值则表示错误发生,并可通过其他诊断工具进一步查询具体原因。 #### 示例代码 下面提供了一个简单的 C++ 实现例子来展示如何应用此函数: ```cpp #include "uf_cur.h" #include <iostream> void ReverseCurveDirection(tag_t curveId){ int status; // 反转给定ID代表的曲线之方向 status = UF_CURVE_reverse_direction(curveId); if(status != 0){ std::cerr << "Failed to reverse the direction of curve." << std::endl; } } ``` 上述片段展示了基本流程:接收一个曲线 ID 输入至自定义方法中,在其中尝试对其实施方向逆转并检查状态反馈以便及时响应潜在异常情况。 #### 结合场景分析 当涉及到复杂模型构建或者特征创建过程中需要用到多个连续排列好的路径段组合而成的新结构时候(比如桥梁过渡面生成)[^2], 正确设置每一段之间的衔接关系就显得尤为重要了。此时利用此类API可以有效简化前期准备工作量同时提高自动化程度. 另外值得注意的是,在某些情况下可能还需要配合其他辅助类如引用所提到过的`ask_curve_ends`, 获取端点信息之后再决定是否有必要施行这一变换动作 [^1].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值