[BUUCTF]REVERSE——[GXYCTF2019]simple CPP

[GXYCTF2019]simple CPP

annex

step

  1. Routine inspection, 64-bit program, no shell
    Insert picture description here
  2. Try running the program to see the general situation
    Insert picture description here
  3. 64-bit ida is loaded, first retrieve the string and view the information about the flag.
    Insert picture description here
    According to the string about the flag, the key function
    main() is too long, so I don’t post it directly. Look at it section by section.
  4. In reverse, we must look at the program from the bottom up.
    The first is about the judgment of flag. If the judgment of 168 is satisfied, it is the correct flag. The flag is wrapped with GXY{} in the
    Insert picture description here
    sub_7FF603EF19C0() function. The function is too long. It should not be a calculation. It should be a function function written by yourself. When called in conjunction with sub_7FF603EF19C0 It is guessed that the function of this function is to output the parameter string. According to 171~175, it can be guessed that the string of flag is stored in Block
  5. Look up and see where the various parameters in the if judgment come from
    Insert picture description here

The algorithm is a bit messy,
please sort it out v38 = v18[2];
v19 = v18[1];
v20 = v18[0];

v22 = v19 & v20
v21[0] = v19 & v20
getv22=v21[0]= v19 & v20=v18[1]&v18[0]

v23 = v38 & ~v20
v21[1] = v23;
getv23 =v21[1]= v38 & ~v20=v18[2]&~v18[0]

v24 = ~v19;
getv24 = ~v19=~v18[1]

v25 = v38 & v24;
v21[2] = v38 & v24;
getv21[2] = v38 & v24=v25=v18[2]& ~v18[1]

v26 = v20 & v24;
v21[3] = v26;
getv26 = v20 & v24=v21[3]=v18[0]&~v18[1]

v23=v21[1]=1176889593874
getv18[2]&~v18[0]=1176889593874

v27 = v23 | v22 | v25 | v26
getv27 =(v18[1]&v18[0]) | (v18[1]&v18[0]) |(v18[2]& ~v18[1]) | (v18[0]&~v18[1])=4483974544037412639

V18 = V28 [. 1];
V29 = V18 [2];
V30 & V25 = V18 * | & V29 (V22 | V28 & V18 * ~ | ~ (V28 | V18 *)) = 577031497978884115i64
givev30 =(v18[2]& ~v18[1]) & v18[0] | v18[2] & ((v18[1]&v18[0]) | v18[1] & ~v18[0] | ~(v18[1] | v18[0]))=577031497978884115

v31 = v27 == 4483974544037412639i64;
v27 ^ v18[3] == 4483974543195470111i64) to
obtainv183^(v18[1]&v18[0]) | (v18[1]&v18[0]) |(v18[2]& ~v18[1]) | (v18[0]&~v18[1])=4483974544037412639

Finally, all the expressions are replaced with v18[0], v18[1], v18[2], v18[3]. Use the z3 library to solve this equation
x, y, z, w represent v18[0]~v18[3]

 from z3 import *

x,y,z,w=BitVecs('x y z w',64)

s=Solver()

s.add((~x)&z==1176889593874)
s.add(((z&~x)|(x&y)|(z&(~y))|(x&(~y)))^w==4483974543195470111)
s.add(((z&~y)&x|z&((x&y)|y&~x|~(y|x)))==577031497978884115)
s.add(((z&~x)|(x&y)|(z&~y)|(x&~y))==4483974544037412639)
s.add(((z&(~x)) | (x&y) | y & z) == (((~x)& z)|864693332579200012))

s.check()
m = s.model()
for i in m:
    print("%s = 0x%x"%(i,m[i].as_long()))

Insert picture description here

  1. Our purpose is to find the value in the block, and continue to look up to see where the data in
    Insert picture description here
    v18 comes from. The data in v18 comes from v11, v12, v13, v14, and the value of the data in v11 is related to v40 and v6. , Continue to look up.
    Insert picture description here
    At the beginning of the program, sub_7FF603EF19C0() is called to output the two sentences we saw at the beginning of operation. According to the guess at runtime, the function of sub_7FF603EF1DE0() is to let us input data and store it in the block. According to the guess on lines 51 and 53, v40-5 should be greater than 25, and the 5 should be GXY{}, so the length of the flag is 25, and the length of the flag stored in v40.
    Then, starting from line 76, from 76 to 85, the data we input should be qword_7FF603EF6048XORed and stored in v6.
    Click directly on qword_7FF603EF6048 to see that the value is 0, but any number of 0 XOR is itself, and it feels wrong, but I still tried it. When it is equal to 0, then the values ​​of v11 are the values ​​in v6. It is the string we input, that is, the number we solve with z3 is our flag, and it is
    obviously wrong to convert it into a string .
    Insert picture description here
    Therefore, there must be a function in the program that assigns qword_7FF603EF6048.
    Right-click the parameter, select jump to xref, and check where the parameter
    Insert picture description here
    is referenced. You will find that there is a sub_7FF603EF1720 function, which is assigned to the
    Insert picture description here
    two functions of memcpy and memove, which is more conspicuous. , They are often used to copy bytes, so here should be i_will_check_is_debug_or_not copied to qword_7FF603EF6048, when qword_7FF603EF6048=i_will_check_is_debug_or_not, try it
Dst = 'i_will_check_is_debug_or_noi_wil'
flag=[0x3E,0x3A,0x46,0x05,0x33,0x28,0x6F,0x0D,0x8C,0x00,0x8A,0x09,0x78,0x49,0x2C,0xAC,0x08,0x02,0x07,0x17,0x15,0x3E,0x30,0x13,0x32,0x31,0x06]
s=''
for i in range(len(flag)):
    s+=chr(ord(Dst[i]) ^ flag[i])
    #s+=chr(flag[i])
print(s)

Insert picture description here
Seeing the garbled code in the middle, weird, no trick. Baidu learned after watching other master wp that the reason is that the equation is more than one solution, and the result of the second part is e!P0or_a during the competition.

from z3 import *

x,y,z,w=BitVecs('x y z w',64)

s=Solver()

s.add((~x)&z==1176889593874)
s.add(((z&~x)|(x&y)|(z&(~y))|(x&(~y)))^w==4483974543195470111)
s.add(((z&~y)&x|z&((x&y)|y&~x|~(y|x)))==577031497978884115)
s.add(((z&~x)|(x&y)|(z&~y)|(x&~y))==4483974544037412639)
s.add(((z&(~x)) | (x&y) | y & z) == (((~x)& z)|864693332579200012))

s.check()
m = s.model()
for i in m:
    print("%s = 0x%x"%(i,m[i].as_long()))

w = [0x32,0x31,0x06]
z = [0x08,0x02,0x07,0x17,0x15,0x3E,0x30,0x13]
y = "e!P0or_a"
x = [0x3e,0x3a,0x46,0x05,0x33,0x28,0x6f,0x0d]
Dst = 'i_will_check_is_debug_or_noi_wil'

flag=[0x3E,0x3A,0x46,0x05,0x33,0x28,0x6F,0x0D,0x8C,0x00,0x8A,0x09,0x78,0x49,0x2C,0xAC,0x08,0x02,0x07,0x17,0x15,0x3E,0x30,0x13,0x32,0x31,0x06]
s=''
for i in range(len(flag)):
    s+=chr(ord(Dst[i]) ^ flag[i])
    #s+=chr(flag[i])
print(s)

b=""
for i in range(len(x)):
    b+=chr(ord(Dst[i]) ^ x[i])
print(b)

Insert picture description here
From We1l_D0n, change äeéb' _ó to e! P0or_a is the final flag

flag{We1l_D0ne!P0or_algebra_am_i}

参考 wp :https://www.cnblogs.com/LLeaves/p/13522069.html

This master did this problem dynamically, and it was found that it was easier to figure out the logic of the program. Well, actually I don’t know how to use ida
Insert picture description here

Guess you like

Origin blog.csdn.net/mcmuyanga/article/details/113628506