ddctf再来一杯java,2019DDCTF的一道简单逆向

昨晚躺尸的时候看到群里大佬发了一张DDCTF战况的图就起床做了一下,也就有了这个题解,RE2跟RE1其实核心思想是差不多的,只是多了一些移位操作罢了,算是弥补上个月0CTF、“西湖论剑”逆向零的突破吧

终究还是太菜了,另外一道CPP逆向也是看得头疼

——2019.4.13

0x00 查壳

fd205dcff090

一看是UPX壳,修复一下然后直接脱!

fd205dcff090

0x01 分析

1.载入IDA X86

main函数伪代码

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

{

int result; // eax@2

char v4; // [sp+4h] [bp-804h]@1

char v5; // [sp+5h] [bp-803h]@1

char v6; // [sp+404h] [bp-404h]@1

char Dst; // [sp+405h] [bp-403h]@1

v6 = 0;

memset(&Dst, 0, 0x3FFu);

v4 = 0;

memset(&v5, 0, 0x3FFu);

printf("please input code:");

scanf("%s", &v6);

sub_401000(&v6);

if ( !strcmp(&v4, "DDCTF{reverseME}") )

{

printf("You've got it!!%s\n", &v4);

result = 0;

}

else

{

printf("Try again later.\n");

result = 0;

}

return result;

}

sub_401000函数伪代码

unsigned int __cdecl sub_401000(const char *a1)

{

_BYTE *v1; // ecx@0

unsigned int v2; // edi@1

unsigned int result; // eax@1

int v4; // ebx@2

v2 = 0;

result = strlen(a1);

if ( result )

{

v4 = a1 - v1;

do

{

*v1 = byte_402FF8[v1[v4]];

++v2;

++v1;

result = strlen(a1);

}

while ( v2 < result );

}

return result;

}

程序大致就是将输入字符串在函数sub_401000中进行简单变换后与"DDCTF{reverseME}"比较

2.载入OD

直接在变换函数前断点

fd205dcff090

然后动态调试

伪代码中的变换就是401020~40103E的内容

fd205dcff090

核心代码无非就三条

……

movsx eax,byte ptr ds:[ebx+eax]//ds:[ebx+eax]寻址获得的数据即为将要处理的数据,并将其字扩展存入eax中

mov dl,byte ptr ds:[eax+0x402FF8]//通过eax和0x402FF8相对寄存器存址获得的字节数据存入dl中

……

mov byte ptr ds:[ecx],dl//dl数据写入数据段

……

//循环执行

所以该函数就是将输入的字符串逐个字符的hex作为偏移量在数据段中寻址获得的字符逐个拼接并写入数据段

即伪代码是

flag=""

for i in input

flag+=ds:[hex(i)+0x402FF8]

查看地址为0x402FF8起的数据段内容

.rdata:00402FF8 ; char byte_402FF8[]

.rdata:00402FF8 byte_402FF8 db ? ; DATA XREF: sub_401000+24�r

.rdata:00402FF9 align 10h

.rdata:00402FF9 _rdata ends

.rdata:00402FF9

.data:00403000 ; Section 3. (virtual address 00003000)

.data:00403000 ; Virtual size : 000003E4 ( 996.)

.data:00403000 ; Section size in file : 00000200 ( 512.)

.data:00403000 ; Offset to raw data for section: 00001600

.data:00403000 ; Flags C0000040: Data Readable Writable

.data:00403000 ; Alignment : default

.data:00403000 ; ===========================================================================

.data:00403000

.data:00403000 ; Segment type: Pure data

.data:00403000 ; Segment permissions: Read/Write

.data:00403000 _data segment para public 'DATA' use32

.data:00403000 assume cs:_data

.data:00403000 ;org 403000h

.data:00403000 ___security_cookie dd 0BB40E64Eh ; DATA XREF: _main+6�r

.data:00403000 ; __security_check_cookie(x)�r ...

.data:00403004 dword_403004 dd 44BF19B1h ; DATA XREF: ___report_gsfailure+B0�r

.data:00403004 ; ___security_init_cookie+2B�w ...

.data:00403008 db 0FFh

.data:00403009 db 0FFh

.data:0040300A db 0FFh

.data:0040300B db 0FFh

.data:0040300C db 0FFh

.data:0040300D db 0FFh

.data:0040300E db 0FFh

.data:0040300F db 0FFh

.data:00403010 dword_403010 dd 0FFFFFFFEh ; DATA XREF: .text:004013E2�r

.data:00403014 dword_403014 dd 1 ; DATA XREF: .text:004013C8�r

.data:00403018 aZyxwvutsrqponm db '~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>'

.data:00403018 db '=

.data:00403078 ; int argc

注意到0x403018起定义了这么一段字符

~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>'=

到此就可以解题了,直接逆算法遍历目标字符串获得输入

dst="DDCTF{reverseME}"

str="~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>'=

flag=""

for i in dst:

index=str.find(i)

flag+=chr(index+(0x403018-0x402FF8))

print("flag:"+flag)

获得flag是ZZ[JX#,9(9,+9QY!

fd205dcff090

最后包裹上DDCTF{}提交即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值