re入门小题

re入门小题

re入门小题

IDA pro 7.7 全插件版,Lazy IDA为无名侠的版本。

IDA配置看IDA篇。

题目源自b站无名侠

默认有C语言,汇编和python基础

文章目录

1. base64变表

base64编码原理

类似于进制转换,256->64进制

数据取每6bit->v(0-64)->编码表取出下标v对应的字符

下载T5.exe,ida打开,左栏ctrl+F搜索main相关函数。

www.zeeklog.com  - re入门小题

快捷键N改一波名称

www.zeeklog.com  - re入门小题

逻辑:异或->base64->比较字符串

跟踪sub_455A94,找到sub_45A3F0函数

www.zeeklog.com  - re入门小题

跟踪off_529000,其存放一个字符串地址的偏移量,继续跟踪

www.zeeklog.com  - re入门小题
标准编码表
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

魔改之后的编码表
ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/

只需将魔改之后的编码对应到标准编码表的相同位置,之后再正常解码就行。(比如Z对应到A)

import base64
import time

t1="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
t2="ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
c='Wj1gWE9xPSGUQ0KCPCGET09WR1qSzZ'
flag=''
for i in c:
    flag+=t1[t2.index(i)]
flag=bytearray(base64.b64decode(flag+"=="))
for i in range(len(flag)):
    flag[i]^=i
print(bytes(flag))
#b'flag{YOU_FIND_IT_HAHA}'

2. IDA动态调试

ida打开T6.exe

www.zeeklog.com  - re入门小题
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  size_t i; // [esp+190h] [ebp-340h]
  char Str2[264]; // [esp+3A4h] [ebp-12Ch] BYREF
  char Str1[32]; // [esp+4ACh] [ebp-24h] BYREF

  qmemcpy(Str1, &unk_50DE50, 28u);//内存复制28位
  printf("[6] Hi CTFer,Input your flag:");
  scanf("%s", Str2);
  for ( i = 0; i < j__strlen(Str1); ++i )
    Str1[i] = ((i + 1) ^ Str1[i]) - i;
  if ( !j__strcmp(Str1, Str2) )
    printf("you are right\n");
  else
    printf("you are wrong\n");
  return 0;
}

F2打断点,debugger选择local windows debugger,F9开启调试

www.zeeklog.com  - re入门小题

输入12345678,在出现的汇编页面F5出伪代码。

www.zeeklog.com  - re入门小题

跟踪Str1

www.zeeklog.com  - re入门小题

点击字符串开头F,按快捷键A,将其解析成字符串。

www.zeeklog.com  - re入门小题

或者选中一片内存,右键->convert->convert to python list(Byte)alt+0查看结果

www.zeeklog.com  - re入门小题
a2=[0x46, 0x6C, 0x61, 0x67, 0x7B, 0x54, 0x68, 0x69, 0x73, 0x5F, 0x49, 0x53, 0x5F, 0x54, 0x37, 0x5F, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5F, 0x45, 0x41, 0x53, 0x59, 0x7D]
print(bytes(a2))

Flag{This_IS_T7_DEBUG_EASY}

3. 动态调试解RC4

流密码RC4加密解密是同一个算法

ida打开rc4.exe,搜main函数,改一波名。

观察到sub_FEF057是一个反调试函数且只执行一次,接收用户输入44个字符。

v7要与input最后的值相同。

www.zeeklog.com  - re入门小题

直接运行rc4.exe,此时反调试函数已执行,在下图位置打断点。

www.zeeklog.com  - re入门小题

debugger->attach to process,选择rc4的进程,以附加形式调试正在运行的程序

www.zeeklog.com  - re入门小题


www.zeeklog.com  - re入门小题

复制上去,F9运行,跟踪一波input的值(可以shift+F12),记录地址,再F9到第二个断点,此时RC4已完成,查看input的值

867DB6A7C7741F7EF97D8DF3295498D5E9B4B8895B620FC958902BD01E431A94C78A253280FD61950893EBA6

可以在运行到第一个断点时,将input对应的内存右键->paste data成上面的值来验证RC4加密解密算法为同一个。

跟踪v7的值

E415C4EDA62F5610BB13EBAD7556C7BBBBE9B9CC023A509F369069BE7C4244CAC6D4245CD2B924C11893B3EA

同理,在第一个断点通过paste data,再F9运行到第二个断点,可以看到RC4之后的值

www.zeeklog.com  - re入门小题

SYC{Pjx_s_Wom3n_cl0thing_1s_S0oo0o0_cute!1i}

4. IDA代码修复与数组识别

打开T7.exe

锁定main函数,它启动了一个定时器来反调试。

www.zeeklog.com  - re入门小题

if ( sub_401000(Str, "flag{") != Str || Source[32] != '}' )可以看出Str与Source其实是一个数组,快捷键Y修改Str的长度为52。

跟踪sub_401270,它的返回值未被接收,故快捷键Y改函数返回值类型为void。

*(_BYTE *)(a3 + *(_DWORD *)(a1 + 4 * v4)) = a2[v4];之中的a3应该修改为char *类型来指向一个数组,其中的a1应当为指向4字节(DWORD)的指针int *

www.zeeklog.com  - re入门小题

改完后,代码变清晰,a3作为输出,与输入a2存在映射关系。

www.zeeklog.com  - re入门小题

同理,修改sub_4011F0,sub_401360的返回值类型为void

跟踪sub_4011F0的dword_404040,右键->array将其转换为数组合,

www.zeeklog.com  - re入门小题

此时可得到整个代码的主要逻辑:取flag{}中间的值->异或->映射->比较字符串

import base64
import time
a23=bytearray(b"23gjf13au98hk3a1090zp8qjs41h39jp")
a1=[0x00000004, 0x0000000F, 0x0000000B, 0x0000001E, 0x0000000E, 0x00000014, 0x0000001F, 0x00000009, 0x00000017, 0x00000002, 0x00000019, 0x0000001C, 0x00000012, 0x00000010, 0x00000000, 0x00000008, 0x00000011, 0x00000001, 0x00000015, 0x00000003, 0x0000000A, 0x0000001D, 0x0000000C, 0x00000016, 0x00000018, 0x0000000D, 0x0000001B, 0x00000005, 0x00000007, 0x00000006, 0x00000013, 0x0000001A]
a2=[0]*32
bt_404040=[0x00000053, 0x00000045, 0x0000005C, 0x0000001E, 0x00000050, 0x00000013, 0x0000002F, 0x00000078, 0x00000004, 0x00000053, 0x00000058, 0x0000004A, 0x00000043, 0x00000001, 0x00000041, 0x0000002A, 0x00000008, 0x00000040, 0x00000067, 0x0000002F, 0x0000000C, 0x0000004A, 0x00000012, 0x0000002E, 0x00000041, 0x0000006C, 0x00000005, 0x00000054, 0x00000040, 0x00000012, 0x0000005B, 0x0000004F]
v4=0
while (v4<32):
    a2[v4]=a23[a1[v4]]
    v4+=1
for i in range(32):
    a2[i]^=bt_404040[i]
print(b"flag{"+bytes(a2)+b"}")
#b'flag{5t4t1c_An4lys1s_1s_E4sy_2_me!!!~}'

5. UPX脱壳

upx是一种开源的压缩壳软件

加壳:upx a1.exe

脱壳:upx -d a1.exe (很多时候不管用)

www.zeeklog.com  - re入门小题

手动脱壳目标

  1. 找到程序入口点(OEP)
  2. 在原始程序入口地址处设置硬件断点(硬件断点不会修改程序)

ida64打开helloupx11文件,发现其为elf文件,不能在windows运行,故拖入kali虚拟机

ls -al
chmod 777 ./helloupx11 添加可执行权限
www.zeeklog.com  - re入门小题

ida查看一下字符串,可以看到是upx加壳

www.zeeklog.com  - re入门小题

我们需要用到ida运程调试服务器。在IDA Pro 7.7.220118 SP1\dbgsrv目录下有个linux_server64,将其拖入kali中。

./linux_ser* 启动监听
ifconfig 查看虚拟机ip地址

ida选择remote linux debugger,并输入虚拟机ip,如果端口占用则ps查看进程id再kill -9 PID杀进程

www.zeeklog.com  - re入门小题

F2在开头打个软件断点,然后开始调试,F4执行到retn按F7,一直跟踪直到看到如下内存(要转成code才看得到)。

www.zeeklog.com  - re入门小题

跟踪unk_401D55,按c解析成代码,再按p创建函数,再按F5查看伪代码

www.zeeklog.com  - re入门小题
辨识一波
qword_4190E8[355] -> printf
sub_401190 -> strlen
sub_401130 -> strcmp

跟踪aFlagBffab77df5,看到flag为flag{bffab77df5cea353e2325bb4437c3d0b}

硬件断点

在401D55的endbr64处F2,再右键->edit breakpoint,点上hardware,使其成为硬件断点。

重新开启调试,跟踪到硬件断点处,按U取消定义,选中一片内存按C,按P,按F5看逻辑。

www.zeeklog.com  - re入门小题

参考

www.zeeklog.com  - re入门小题

Read more

深入理解 Proxy 和 Object.defineProperty

在JavaScript中,对象是一种核心的数据结构,而对对象的操作也是开发中经常遇到的任务。在这个过程中,我们经常会使用到两个重要的特性:Proxy和Object.defineProperty。这两者都允许我们在对象上进行拦截和自定义操作,但它们在实现方式、应用场景和灵活性等方面存在一些显著的区别。本文将深入比较Proxy和Object.defineProperty,包括它们的基本概念、使用示例以及适用场景,以帮助读者更好地理解和运用这两个特性。 1. Object.defineProperty 1.1 基本概念 Object.defineProperty 是 ECMAScript 5 引入的一个方法,用于直接在对象上定义新属性或修改已有属性。它的基本语法如下: javascript 代码解读复制代码Object.defineProperty(obj, prop, descriptor); 其中,obj是目标对象,prop是要定义或修改的属性名,descriptor是一个描述符对象,用于定义属性的特性。 1.2 使用示例 javascript 代码解读复制代码//

By Ne0inhk

Proxy 和 Object.defineProperty 的区别

Proxy 和 Object.defineProperty 是 JavaScript 中两个不同的特性,它们的作用也不完全相同。 Object.defineProperty 允许你在一个对象上定义一个新属性或者修改一个已有属性。通过这个方法你可以精确地定义属性的特征,比如它是否可写、可枚举、可配置等。该方法的使用场景通常是需要在一个对象上创建一个属性,然后控制这个属性的行为。 Proxy 也可以用来代理一个对象,但是相比于 Object.defineProperty,它提供了更加强大的功能。使用 Proxy 可以截获并重定义对象的基本操作,比如访问属性、赋值、函数调用等等。在这些操作被执行之前,可以通过拦截器函数对这些操作进行拦截和修改。因此,通过 Proxy,你可以完全重写一个对象的默认行为。该方法的使用场景通常是需要对一个对象的行为进行定制化,或者需要在对象上添加额外的功能。 对比 以下是 Proxy 和 Object.defineProperty 的一些区别对比: 方面ProxyObject.defineProperty语法使用 new Proxy(target,

By Ne0inhk