Reverse入门[不断记录]

Posted Aiwin-Hacker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Reverse入门[不断记录]相关的知识,希望对你有一定的参考价值。

文章目录


前言

心血来潮,想接触点Reverse,感受下Reverse,于是从CTF的简单题目中慢慢入门


提示:以下是本篇文章正文内容,下面案例可供参考

一、[SWPUCTF 2021 新生赛]re1

1、工具:IDA
直接使用IDA将exe反编译,得到一堆代码。

使用Ctrl+X,查看编译流程,然后使用F5,查看代码。

int __cdecl main(int argc, const char **argv, const char **envp)

  char Str2[1008]; // [rsp+20h] [rbp-60h] BYREF
  char Str1[1000]; // [rsp+410h] [rbp+390h] BYREF
  int i; // [rsp+7FCh] [rbp+77Ch]

  _main();
  strcpy(Str2, "34sy_r3v3rs3");
  printf("please put your flag:");
  scanf("%s", Str1);
  for ( i = 0; i <= 665; ++i )
  
    if ( Str1[i] == 101 )
      Str1[i] = 51;
  
  for ( i = 0; i <= 665; ++i )
  
    if ( Str1[i] == 97 )
      Str1[i] = 52;
  
  if ( strcmp(Str1, Str2) )
    printf("you are wrong,see again!");
  else
    printf("you are right!");
  system("pause");
  return 0;

将输入的字符,ascii为101的变成51,97的变成52,然后与str2对比,一致则成功。

s = '34sy_r3v3rs3'
r = ''
for i in s:
    if ord(i) ==51:
        r += chr(101)
    elif ord(i) == 52:
        r += chr(97)
    else:
        r += i
print(r)

得到flag

二、[SWPUCTF 2021 新生赛]re2

int __cdecl main(int argc, const char **argv, const char **envp)

  char Str2[64]; // [rsp+20h] [rbp-90h] BYREF
  char Str[68]; // [rsp+60h] [rbp-50h] BYREF
  int v7; // [rsp+A8h] [rbp-8h]
  int i; // [rsp+ACh] [rbp-4h]

  _main();
  strcpy(Str2, "ylqq]aycqyp");
  printf(Format);
  gets(Str);
  v7 = strlen(Str);
  for ( i = 0; i < v7; ++i )
  
    if ( (Str[i] <= 96 || Str[i] > 98) && (Str[i] <= 64 || Str[i] > 66) )
      Str[i] -= 2;
    else
      Str[i] += 24;
  
  if ( strcmp(Str, Str2) )
    printf(asc_404024);
  else
    printf(aBingo);
  system("pause");
  return 0;

s = 'ylqq]aycqyp'
l = []
for i in s:
    l.append(ord(i))
# print(l)
l = [121, 108, 113, 113, 93, 97, 121, 99, 113, 121, 112, 123]
r = ''
for i in l:
    if (i <= 94 or i > 96) and (i <= 62 or i > 64):
        r += chr(i + 2)
    else:
        r += chr(i - 24)
print(r)

得到的结果进行caser,并且猜一下,得到nss_caesar

三、[GFCTF 2021]wordy[花指令]

  1. 花指令实质就是一串垃圾指令,它与程序本身的功能无关,并不影响程序本身的逻辑。在软件保护中,花指令被作为一种手段来增加静态分析的难度,花指令也可以被用在病毒或木马上,通过加入花指令改变程序的特征码,躲避杀软的扫描,从而达到免杀的目的。
  2. 花指令是让反编译器无法反编译起到混淆租用的指令,一般最常见的就是在机器码中加入 E8,E8 加入后会将汇编代码改变为 CALL,而后续的机器码代表的东西是没有意义的,不是一个函数,所以 CALL 之后反编译器无法识别。


存在大量jmp跳转,导致程序无法正常编译,尝试将跳转nop掉,即将其转换成空指令。

startaddr = 0x1135
endaddr = 0x3100

for i in range(startaddr,endaddr):
    if get_wide_byte(i) == 0xEB:
        if get_wide_byte(i+1) == 0xFF:
            patch_byte(i,0x90)
            print("[+] Addr  is patched".format(hex(i)))

起始地址是main函数的0x1135到结束,通过遍历byte,判断是否和EB FF,即jmp的机械码,是则改成90,即nop。

看到flag为GFCTFu_are2wordy

四、[NSSRound#3 Team]jump_by_jump[花指令]

  1. 先找主函数入口,即main

可以看到0041188C处有call,并且爆红,可以判断为花指令,因此要消除即变成nop,选中41188C,按快捷键D,将其转换为数据。

然后将0E8h改成0x90即nop机器码

快捷键C,将数据再次转换成指令,并将下面黄色的部分依次使用C转换成指令。

最后往上选中main入口,快捷键P生成函数,然后F5,获得函数代码。

int __cdecl main_0(int argc, const char **argv, const char **envp)

  int i; // [esp+D0h] [ebp-2Ch]
  char v5[28]; // [esp+DCh] [ebp-20h] BYREF

  strcpy(v5, "NSSCTFJump_b9_jump!");
  for ( i = 0; i < 21; ++i )
    v5[i] = (v5[i] + v5[(i * i + 123) % 21]) % 128;
  sub_4110CD("%s", (char)v5);
  return 0;

发现flag根本没被加密,直接开始Shift+F12就可以看到字符串。

五、[NSSRound#3 Team]jump_by_jump_revenge[花指令]

跟上面一样,将爆红那里改成空指令,P+F5得到伪代码。

int __cdecl main_0(int argc, const char **argv, const char **envp)

  int i; // [esp+D0h] [ebp-40h]
  char Str1[36]; // [esp+E8h] [ebp-28h] BYREF

  sub_411037("%s", (char)Str1);
  for ( i = 0; i < 29; ++i )
    Str1[i] = (Str1[i] + Str1[(i * i + 123) % 21]) % 96 + 32;
  if ( !j_strcmp(Str1, "~4G~M:=WV7iX,zlViGmu4?hJ0H-Q*") )
    puts("right!");
  else
    puts("nope!");
  return 0;

将flag打乱了,并且进行了变换,逆向解密。

a = ['~', '4', 'G', '~', 'M', ':', '=', 'W', 'V', '7', 'i', 'X', ',', 'z', 'l', 'V', 'i', 'G', 'm', 'u', '4', '?', 'h',
     'J', '0', 'H', '-', 'Q', '*']

for i in range(28, -1, -1):
    k = (i * i + 123) % 21
    for j in range(5):
        x = (ord(a[i]) - 32 + j * 96 - ord(a[k]))
        if 33 <= x <= 126:
            a[i] = chr(x)
            break
print("".join(a))

六、[WUSTCTF 2020]level2[UPX脱壳]

  1. 脱壳,就是说把程序的外壳给脱掉,从而能够看到真正的程序,在程序运行时,首先是壳取得控制权并对程序进行压缩,从而隐藏程序真正的OEP(原始的程序入口点),一般丢进IDX后,函数特别少,是加壳了。
  2. 程序的脱壳一般总体是三个步骤:
  1. 找到OEP,程序运行壳代码执行完后会跳转到真正的OEP
  2. 抓到内存文件,将新得到的源文件保存,可从头到后复制
  3. 对PE文件进行修复

萌新,手动脱壳不是很现实,一些脱壳工具链接:
UPX脱壳工具



六、[HUBUCTF 2022 新生赛]simple_RE

int __cdecl main(int argc, const char **argv, const char **envp)

  int v4; // [rsp+24h] [rbp-44h] BYREF
  void *Buf1; // [rsp+28h] [rbp-40h] BYREF
  char v6[56]; // [rsp+30h] [rbp-38h] BYREF

  sub_401770(argc, argv, envp);
  printf("please input the flag:");
  scanf("%s", v6);
  Buf1 = 0i64;
  sub_401570(v6, &Buf1, &v4);
  if ( !memcmp(Buf1, a5mc58bphliax7j, v4) )
    printf("\\nsuccess!");
  else
    printf("\\nfailed!");
  if ( Buf1 )
    free(Buf1);
  return 0;

输入的v6经过sub_401570()函数加密与a5mc58bphliax7j比较,一致则成功,a5mc58bphliax7j的值为5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8==,有点像是base64。

但是下面好像还有一串字符串,不知道干什么的,看了下加密函数。

好像加密跟下面的字符串有关,正常的base64也解密不出来,可能是base64换表。

七、[SWPUCTF 2021 新生赛]easyapp

发现PK头,直接改成zip后缀,解压得到一个apk安卓,反编译,得:

Encode类:

package com.example.ilililililil;

public class Encoder

  private int key = 123456789;

  public String encode(String paramString)
  
    StringBuilder localStringBuilder = new StringBuilder();
    paramString = paramString.toCharArray();
    int i = paramString.length;
    for (int j = 0; j < i; j++)
      localStringBuilder.append((char)(paramString[j] ^ this.key));
    return localStringBuilder.toString();
  

public /* synthetic */ void lambda$onCreate$0$MainActivity(final EditText editText, View v) 
    System.out.println(encoder.encode(editText.getText().toString()));
    if (encoder.encode(editText.getText().toString()).equals("棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌")) 
        Toast.makeText(this, "YES", 0).show();
     else 
        Toast.makeText(this, "NO", 0).show();
    

MainActivity类:

package com.example.ilililililil;

import java.lang.reflect.Field;

public class MainActlvity

  public MainActlvity()
  
    try
    
      Field localField = Encoder.class.getDeclaredField("key");
      localField.setAccessible(true);
      localField.set(MainActivity.encoder, Integer.valueOf(987654321));
    
    catch (NoSuchFieldException localNoSuchFieldException)
    
    
    catch (IllegalAccessException localIllegalAccessException)
    
    
    localIllegalAccessException.printStackTrace();
  

可以知道key变成了987654321

所以exp为:

code = '棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌'
key = 987654321
flag = ""
for i in code:
    flag += chr((ord(i) ^ key) % 128)
print(flag)

得到flag NSSCTFapkYYDS

八、[鹏城杯 2022]baby_re[apk反编译+JNI]


反编译得到关键代码:


  private static final void onCreate$lambda-0(MainActivity paramMainActivity, int[] paramArrayOfInt, View paramView)
  
    Intrinsics.checkNotNullParameter(paramMainActivity, "this$0");
    Intrinsics.checkNotNullParameter(paramArrayOfInt, "$c");
    paramView = ((EditText)paramMainActivity._$_findCachedViewById(R.id.input)).getText().toString().chars().toArray();
    Intrinsics.checkNotNullExpressionValue(paramView, "flag.toArray()");
    if (Arrays.equals(paramMainActivity.baby_xor(paramView), paramArrayOfInt))
      Toast.makeText((Context)paramMainActivity, (CharSequence)"Success", 1).show();
    else
      Toast.makeText((Context)paramMainActivity, (CharSequence)"Failed", 0).show();
  
  
  protected void onCreate(Bundle paramBundle)
  
    super.onCreate(paramBundle);
    ActivityMainBinding localActivityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
    Intrinsics.checkNotNullExpressionValue(localActivityMainBinding, "inflate(layoutInflater)");
    this.binding = localActivityMainBinding;
    paramBundle = localActivityMainBinding;
    if (localActivityMainBinding == null)
    
      Intrinsics.throwUninitializedPropertyAccessException("binding");
      paramBundle = null;
    
    setContentView((View)paramBundle.getRoot());
    ((Button)_$_findCachedViewById(R.id.btn)).setOnClickListener(new MainActivity..ExternalSyntheticLambda0(this, new int[]  119, 9, 40, 44, 106, 83, 126, 123, 33, 87, 113, 123, 112, 

 技术图片

技术图片

技术图片

技术图片

技术图片技术图片

技术图片技术图片

 

 

 技术图片

技术图片

技术图片

 技术图片

 

以上是关于Reverse入门[不断记录]的主要内容,如果未能解决你的问题,请参考以下文章

CTF入门

CTF入门指南

ctf入门指南

CTF入门指南

CTF入门指南

JavaEE Tutorials (19) - Web应用安全入门