Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the two converses of DDCTF2019?

2025-01-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)05/31 Report--

The content of this article mainly focuses on what are the two opposites of DDCTF2019. The content of the article is clear and clear. It is very suitable for beginners to learn and is worth reading. Interested friends can follow the editor to read together. I hope you can get something through this article!

01Confused

First refer to the link https://www.52pojie.cn/forum.php?mod=viewthread&tid=860237&page=1

First of all, it is no problem to analyze that the sub_1000011D0 is a key function. Directly shift+f12 locates the string of DDCTF to this part of the logic.

If ((unsigned int) sub_1000011D0 (* ((_ int64 *) & v14 + 1)) = = 1) objc_msgSend (v17, "onSuccess"); else objc_msgSend (v17, "onFailed")

After following in, I found out

_ int64 _ fastcall sub_1000011D0 (_ int64 A1) {char v2; / / [rsp+20h] [rbp-C0h] _ int64 v3; / / [rsp+D8h] [rbp-8h] v3 = A1; memset (& v2, 0, 0xB8uLL); sub_100001F60 (& v2, A1); return (unsigned int) sub_100001F00 (& v2);}

This function first allocates a space the size of 0xb8, then fills it with 0x00, and then passes in a sub_100001F60 function to follow the space.

_ int64 _ fastcall sub_100001F60 (_ int64 A1, _ int64 a2) {* (_ DWORD *) A1 = 0; * (_ DWORD *) (A1 + 4) = 0; * (_ DWORD *) (A1 + 8) = 0; * (_ DWORD *) (A1 + 12) = 0; * (_ DWORD *) (A1 + 16) = 0; * (_ DWORD *) (A1 + 176) = 0; * (_ BYTE *) (A1 + 32) = 0xF0u * (_ QWORD *) (A1 + 40) = sub_100001D70; * (_ BYTE *) (A1 + 48) = 0xF1u; * (_ QWORD *) (A1 + 56) = sub_100001A60; * (_ BYTE *) (A1 + 64) = 0xF2u; * (_ QWORD *) (A1 + 72) = sub_100001AA0; * (_ BYTE *) (A1 + 80) = 0xF4u; * (_ QWORD *) (A1 + 88) = sub_100001CB0; * (_ BYTE *) (A1 + 96) = 0xF5u * (_ QWORD *) (A1 + 124) = sub_100001CF0; * (_ BYTE *) (A1 + 1122) = 0xF3u; * (_ QWORD *) (A1 + 120) = sub_100001B70; * (_ BYTE *) (A1 + 128) = 0xF6u; * (_ QWORD *) (A1 + 136) = sub_100001B10; * (_ BYTE *) (A1 + 144) = 0xF7u; * (_ QWORD *) (A1 + 152) = sub_100001D30; * (_ BYTE *) (A1 + 160) = 0xF8u * (_ QWORD *) (A1 + 168) = sub_100001C60; qword_100003F58 = malloc (0x400uLL); return _ memcpy_chk ((char *) qword_100003F58 + 48, a2, 18LL,-1LL);}

First of all, press H to change these to unsigned_int8 type, which is convenient to see. Compared with the previous article, we can see that the vm_cpu structure is initialized. The first six four bytes are obviously registers, and the last few are binding functions corresponding to virtual machine bytecode and bytecode. Here, you can switch to the structures window and press insert to create a structure. In this way, we can see more clearly that the code should first briefly analyze the function corresponding to the first 0xF0 virtual machine instruction for the following initialized structure and each function corresponding to opcode

_ int64 _ _ fastcall sub_100001D70 (_ _ int64 A1) {_ _ int64 result; / / raxsigned int * v2; / / [rsp+Ch] [rbp-18h] v2 = (signed int *) (* (_ QWORD *) (A1 + 24) + 2LL); switch (* (unsigned _ int8 *) (* (_ QWORD *) (A1 + 24) + 1LL)) {case 0x10u: * (_ DWORD *) A1 = * v2scapebreak Case 0x11u: * (_ DWORD *) (A1 + 4) = * v2 qword_100003F58 case 0x12u: * (_ DWORD *) (A1 + 8) = * v2 char case 0x13u: * (_ DWORD *) (A1 + 12) = * v2 char case 0x14u: * (_ DWORD *) A1 = * (char *) qword_100003F58 + * v2); break;default:break;} result = A1; * (_ QWORD *) (A1 + 24) + = 6LLX return result;}

First of all, you can see that (_ QWORD*) (A1 _ pointer 24) is referenced at the beginning of each function, so guess that this is the instruction pointer register. Create a structure in the structure window to name the offset qword* myeip.

You can see that v2 is the content of the second byte after where the virtual machine instruction pointer register points, and then there is a switch structure, which determines which virtual machine register is specified in the first byte after the virtual machine instruction, and then assigns v2 to the register. If it is 0x14, assign * ((char*) qword_100003F58+*v2) to the first register. Obviously, this qword100003F58 is equivalent to the stack of the virtual machine. Then the function is responsible for moving the instruction pointer register. The virtual machine instruction corresponding to this function takes up six bytes, so at the end there is * (_ QWORD*) (a1q24) + = 6LL. So the function of this function is to pass an immediate number into a register of the virtual machine and name it movreg_imm for later viewing

Then the function corresponding to the second 0xF1

_ _ int64 _ _ fastcall sub_100001A60 (_ _ int64 A1) {_ int64 result; / / rax result = (unsigned int) (* (_ DWORD *) (A1 + 4) ^ * (_ DWORD *) A1); * (_ DWORD *) A1 = result; + + * (_ QWORD *) (A1 + 24); return result;}

You can see that he XOR the values in the first two registers and then put the results in the first register. The same virtual machine instruction takes up one byte. This function is responsible for adding 1 byte to the instruction pointer register.

The functions corresponding to 0xF2 and 0xF6 should be combined.

_ int64 _ _ fastcall sub_100001AA0 (_ _ int64 A1) {_ _ int64 result; / / rax * (_ DWORD *) (A1 + 16) = * (_ DWORD *) A1 = = * ((char *) qword_100003F58 + * (unsigned _ int8 *) (* (_ QWORD *) (A1 + 24) + 1LL)); result = A1; * (_ QWORD *) (A1 + 24) + = 2LLLX return result;} _ int64 _ fastcall sub_100001B10 (_ int64 A1) {_ int64 result / / raxif (* (_ DWORD *) (A1 + 16)) * (_ DWORD *) (A1 + 16) = 0 QWORD * (_ QWORD *) (A1 + 24) + = * (unsigned _ int8 *) (* (_ QWORD *) (A1 + 24) + 1LL); result = A1; * (_ QWORD *) (A1 + 24) + = 2LLX return result;}

You can see that in 0xF2, he put

* (_ DWORD*) A1 benchmark * ((char*) qword_100003F58+* (unsigned__int8*) (* (_ QWORD*) (A1 / 24) + 1LL) The result of this expression is put in * (_ DWORD*) (a1q16). In 0xF6, he moves the eip instruction pointer register according to * (_ DWORD*) (a1q16). It is obvious that the function of this register is the flag register, which stores the result of comparison, and then the latter function is the conditional jump instruction.

And then 0xF4

_ int64 _ fastcall sub_100001CB0 (_ int64 A1) {_ int64 result; / / rax result = (unsigned int) (* (_ DWORD *) (A1 + 4) + * (_ DWORD *) A1); * (_ DWORD *) A1 = result; + + * (QWORD *) (A1 + 24); return result;}

It is obvious that this actually does the addition operation, adding up the values of the first two registers into the first register, and naming it addregimm

And then 0xF5

_ int64 _ _ fastcall sub_100001CF0 (_ _ int64 A1) {_ int64 result; / / rax result = (unsigned int) (* (_ DWORD *) A1-* (_ DWORD *) (A1 + 4)); * (_ DWORD *) A1 = result; + + * (_ QWORD *) (A1 + 24); return result;}

Similar to the function above, this is subtraction, which is called subregimm

The function corresponding to the follow-up 0xF3 found that there was only one curly bracket, so it was named nop

And then 0xF7

_ _ int64 _ _ fastcall sub_100001D30 (_ _ int64 A1) {_ _ int64 result; / / rax result = * (unsigned int *) (* (_ QWORD *) (A1 + 24) + 1LL); * (_ DWORD *) (A1 + 24) = result; * (_ QWORD *) (A1 + 24) + = 5LLscape return result;}

You can see that he put the operands in (_ DWORD*) (a1q176). No matter what he is doing, take a look at 0xF8 first.

_ _ int64 _ _ fastcall sub_100001C60 (_ _ int64 A1) {_ int64 result; / / rax result = sub_100001B80 ((unsigned int) (char) * (_ DWORD *) A1, 2LL); * (_ DWORD *) A1 = (char) result; + + * (_ QWORD *) (A1 + 24); return result;} _ int64 _ fastcall sub_100001B80 (char A1, int a2) {bool v3; / / [rsp+7h] [rbp-11h] bool v4 / / [rsp+Fh] [rbp-9h] char v5; / / [rsp+17h] [rbp-1h] v4 = 0 flag if (A1 > = 65) v4 = A1 = 97) v3 = A1 vm_r1 = 0; A1-> vm_r2 = 0; A1-> vm_r3 = 0; A1-> vm_r4 = 0; A1-> flag = 0; A1-> myeip = 0; LOBYTE (A1-> opcode_f0) = 0xF0u; A1-> mov_reg_imm = (_ _ int64) mov_reg_imm LOBYTE (A1-> opcode_f1) = 0xF1u; A1-> xor_r1_r2 = (_ _ int64) xor_r1_r2; LOBYTE (A1-> opcode_f2) = 0xF2u; A1-> cmp_r1_imm = (_ _ int64) cmp_r1_imm; LOBYTE (A1-> opcode_f4) = 0xF4u; A1-> add_r1_r2 = (_ int64) add_r1_r2; LOBYTE (A1-> opcode_f5) = 0xF5u; A1-> dec_r1_r2 = (_ _ int64) sub_r1_r2; LOBYTE (A1-> opcode_f3) = 0xF3u A1-> nop = (_ _ int64) nop; LOBYTE (A1-> opcode_f6) = 0xF6u; A1-> jz_imm = (_ int64) jz_imm; LOBYTE (A1-> opcode_f7) = 0xF7u; A1-> mov_buff_imm = (_ int64) mov_buff_imm; LOBYTE (A1-> opcode_f8) = 0xF8u; A1-> shift_r1_2 = (_ _ int64) shift_r1_2; qword_100003F58 = malloc (0x400uLL); return _ memcpy_chk ((char *) qword_100003F58 + 48, a2, 18LL,-1LL) }

Now go back and look at the second function called in the sub_100001F00 function

_ _ int64 _ _ fastcall sub_100001F00 (vm_cpu * A1) {A1-> myeip = (_ _ int64) & loc_100001980 + 4 int8 while (* (unsigned _ int8 *) A1-> myeip! = 0xF3) sub_100001E50 (A1); free (qword_100003F58); return A1-> vm_r6;}

You can see that this function initializes the myeip instruction pointer register to point it to (_ _ int64) & loc_100001980+4. Now that the vm_cpu structure is clear, we can translate (_ _ int64) & the virtual machine opcode at loc_100001980+4 according to the structure. Now that we know the functions of these opcode. In fact, it doesn't take much effort to extract the code for execution or write a script sentence by sentence translation. He just puts an immediate number into R1, then determines the case, and then transforms it by Caesar, and we write a script directly in idapython and come out.

".join ([chr (0x41 + (int (I [- 2:], 16) + 2-0x41)% 26) if int (I [- 2:], 16)

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report