---
# System prepended metadata

title: Flare-on 11

---

# Flare-on 11

# Challenge 1
Given an exe and src python code of that exe. Read the src, we see the flag is generated by function GenerateFlagText, which decrypt encrypted flag with simple xor
![image](https://hackmd.io/_uploads/Byl4Hgv-1l.png)
They key decrypt is x + y * 20 where x and y are the params passed into this function
Follow where this function called, we conclude that x, y will be the 10 for both
![image](https://hackmd.io/_uploads/rJAsBgPWJe.png)
![image](https://hackmd.io/_uploads/rJhTSxPWyl.png)

Flag: welcom_to_11@flare-on.com

# Challenge2
We're given an executed coded in Go, and lucky that it's not stripped at all. For first part, it requires user to do some math for a random number times (atmost will be 8)
![image](https://hackmd.io/_uploads/S1YQdlvW1e.png)
![image](https://hackmd.io/_uploads/rJKY_evW1l.png)
![image](https://hackmd.io/_uploads/ryg6AgPZ1x.png)

After finish this first part, a checksum is required. This checksum then decoded hex. If input checksum is not a valid checksum (not in hex string format), it prints out "Not a valid checksum...".
![image](https://hackmd.io/_uploads/SyWhEZPWJl.png)
Then the decode input will be checked length, if its length is 32, then it passed as key for chacha20poly1305 decrypt, else, it prints out "Maybe it's time to analyze the binary! ;)"
![image](https://hackmd.io/_uploads/BJ7OvrwZ1e.png)
![image](https://hackmd.io/_uploads/SytrPHw-Je.png)
If key is wrong, it also prints out same message as above.

Take a deeper look into binary, the flow of code is kinda weird, cause it pass input checksum as decrypt key but not yet check it, and the check appear after that call the chacha_open(), maybe it's intense of author.

In first, it convert the hexbyte input back to hex string
![image](https://hackmd.io/_uploads/SkcGKHvW1x.png)
Then it's passed into main_a, in this function, it xor input with key "FlareOn2024" then encode base64 the output, latter compare with a hardcode base64 string 
![image](https://hackmd.io/_uploads/H16UcBP-Je.png)
[Decrypt](https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true,false)XOR(%7B'option':'UTF8','string':'FlareOn2024'%7D,'Standard',false)&input=Y1FvRlJRRXJYMVlBVncxelZRZEZVU3hmQVFOUkJYVU5BeEJTZTE1UUNWUlZKMXBRRXdkL1dGQlVBbEVsQ0ZCRlVubGFCMVVMQnlSZEJFRmRmVnRXVkE9PQ) it, we get the checksum: 7fd7dd1d0e959f74c133c13abb740b9faa61ab06bd0ecd177645e93b1e3825dd

Decrypt flag then stored in UserCacheDir in form of JPG image.
![image](https://hackmd.io/_uploads/rJVm3BPZyx.png)
![image](https://hackmd.io/_uploads/HkuvhrvWJx.png)

Flag: Th3_M4tH_Do_b3_mAthng@flare-on.com

# Challenge 3:

Given a yara file, we have to find a file that match that yara rule.
Take a look into the yara rule, there are bunch of rules, but just some of them are required to get the flag.

![image](https://hackmd.io/_uploads/HywW48w-kx.png)

After for a while, i found that only conditions where equal condition appears and the operation can be convert back like (add, sub, mul, xor) that actual help us find the flag. Wickly remove all reduntdant condition, all the left is just kind easy to find.
```python=
uint8(58) + 25 == 122 
uint32(52) ^ 425706662 == 1495724241 
uint32(17) - 323157430 == 1412131772 
hash.crc32(8, 2) == 0x61089c5c 
hash.crc32(34, 2) == 0x5888fc1b 
uint8(36) + 4 == 72 
uint8(27) ^ 21 == 40 
uint32(59) ^ 512952669 == 1908304943 
uint8(65) - 29 == 70 
uint8(45) ^ 9 == 104 
uint32(28) - 419186860 == 959764852 
uint8(74) + 11 == 116 
hash.crc32(63, 2) == 0x66715919 
hash.sha256(14, 2) == "403d5f23d149670348b147a15eeb7010914701a7e99aad2e43f90cfa0325c76f" 
hash.sha256(56, 2) == "593f2d04aab251f60c9e4b8bbc1e05a34e920980ec08351a18459b2bc7dbf2f6" 
uint8(75) - 30 == 86 
uint32(66) ^ 310886682 == 849718389 
uint32(10) + 383041523 == 2448764514 
uint32(37) + 367943707 == 1228527996 
uint32(22) ^ 372102464 == 1879700858 
uint8(2) + 11 == 119 
hash.md5(0, 2) == "89484b14b36a8d5329426a3d944d2983" 
uint32(46) - 412326611 == 1503714457 
hash.crc32(78, 2) == 0x7cab8d64 
uint8(7) - 15 == 82 
uint32(70) + 349203301 == 2034162376 
hash.md5(76, 2) == "f98ed07a4d5f50f7de1410d905f1477f" 
uint32(80) - 473886976 == 69677856 
uint32(3) ^ 298697263 == 2108416586 
uint8(21) - 21 == 94 
uint8(16) ^ 7 == 115 
uint32(41) + 404880684 == 1699114335 
hash.md5(50, 2) == "657dae0913ee12be6fb2a6f687aae1c7" 
uint8(26) - 7 == 25 
hash.md5(32, 2) == "738a656e8e8ec272ca17cd51e12f558b" 
uint8(84) + 3 == 128 
```
For hash check, because it's just two character for each check, so it can be easy crack by bruteforce
The left it just recover back to from add/sub/xor

Flag: 1RuleADayK33p$Malw4r3Aw4y@flare-on.com

# Challenge 4
Given a html file, open it in browser, it's exactly "mememaker"
![image](https://hackmd.io/_uploads/Bk_Gc8wZJx.png)

Take a look into logic javascript code, it's so long and fully obfuscated.
![image](https://hackmd.io/_uploads/rJPPqLPZ1x.png)

Deobfuscate this code can be done by many tool, for me, i use [this](https://deobfuscate.relative.im/)

The deobfuscated code is pretty simple, in that, a0k function is likely have the flag.
```cpp=
function a0k() {
  const a = a0g.alt.split('/').pop()
  if (a !== Object.keys(a0e)[5]) {
    return
  }
  const b = a0l.textContent,
    c = a0m.textContent,
    d = a0n.textContent
  if (
    a0c.indexOf(b) == 14 &&
    a0c.indexOf(c) == a0c.length - 1 &&
    a0c.indexOf(d) == 22
  ) {
    var e = new Date().getTime()
    while (new Date().getTime() < e + 3000) {}
    var f =
      d[3] +
      'h' +
      a[10] +
      b[2] +
      a[3] +
      c[5] +
      c[c.length - 1] +
      '5' +
      a[3] +
      '4' +
      a[3] +
      c[2] +
      c[4] +
      c[3] +
      '3' +
      d[2] +
      a[3] +
      'j4' +
      a0c[1][2] +
      d[4] +
      '5' +
      c[2] +
      d[5] +
      '1' +
      c[11] +
      '7' +
      a0c[21][1] +
      b.replace(' ', '-') +
      a[11] +
      a0c[4].substring(12, 15)
    f = f.toLowerCase()
    alert(atob('Q29uZ3JhdHVsYXRpb25zISBIZXJlIHlvdSBnbzog') + f)
  }
}
```
The decode base64 in alert ("Congratulations! Here you go: ") suggest that f is the flag we have to find.
f is construct from a, b, c, d, a0c variable where:
 + a0c: hardcode array of string
 + a: a0e[5] ==> 'boy_friend0.jpg'
 + b: a0c[14] ==> 'FLARE On'
 + c: a0c[len(a0c) - 1] ==> 'Security Expert'
 + d: a0c[22] ==> 'Malware'
==> f: wh0A_it5_4_cru3l_j4va5cr1p7@FLARE-On.com
flag is in lower form: wh0a_it5_4_cru3l_j4va5cr1p7@flare-on.com
Flag: wh0a_it5_4_cru3l_j4va5cr1p7@flare-on.com
We can also change the js code that always match the condition, so that the brower show the flag for us
![image](https://hackmd.io/_uploads/rJ8j7Bdbyx.png)

# Challenge 5
![image](https://hackmd.io/_uploads/rkyr4Su-Jl.png)

Given us a copy of a system, with a hint is that server crashed, and it may be related to sshd. As it hints that server is crashed, searching for the coredump file, we found that it's exactly sshd coredump.
![image](https://hackmd.io/_uploads/B1QruBdW1x.png)

Using gdb, we can find where the system has crashed. To make gdb regcognize all shared lib that crashed program load, we need to let gdb know the right libraty folder, not on your own system but the /usr/lib and /usr/lib64 of the given one.
```
set solib-search-path /path/usr/lib:/path/usr/lib64
```
using two commands "info shared libarary" and "info proc mappings" we can find where librarys loaded on mem. Typically, a lib appears as deleted, but combines result of two commands, we can conlude that it's liblzma.so
![image](https://hackmd.io/_uploads/ByYYy8jWke.png)
![image](https://hackmd.io/_uploads/rk59kUobyx.png)

Using bt command, we can find return address, from that, we can identify where it crashed

![image](https://hackmd.io/_uploads/SyrWJ8ob1e.png)

The return address is 0x0007f4a18c8f88f which is in range of liblzma.so.5

sshd and liblzma, which lead us into the famous [CVE-2024-3094](https://securelist.com/xz-backdoor-part-3-hooking-ssh/113007/) 

According to the blog, it hooks the RSA_public_decrypt function. Take a look into binary liblzma.so.5, we can easy find where the backdoor located
![image](https://hackmd.io/_uploads/Sk8WjuuZ1l.png)

To find key and nonce, the code reveal that it start with '\x48\x7A\x40\xC5', search the sequence bytes in coredump, we can quicky find key and nonce of that 
![image](https://hackmd.io/_uploads/HJwih_O-Jl.png)
key: 94 3d f6 38 a8 18 13 e2 de 63 18 a5 7 f9 a0 ba 2d bb 8a 7b a6 36 66 d0 8d 11 a6 5e c9 14 d6 6f
nonce: f2 36 83 9f 4d cd 71 1a 52 86 29 55
Decrypt shellcode, we get beautiful code that can F5 easy :))
![image](https://hackmd.io/_uploads/HyJrRcOZ1g.png)

The logic kinda straight forward, connect socket, receive key, nonce for "salcha20", filename to read, read file, then encrypt "salcha20", send back to server.
All the info may be still on stack, so to find the info, we have to find the stackframe of this backdoor function.
Start of shellcode
![image](https://hackmd.io/_uploads/SyZD2ouZkl.png)
The frame contain info is inside the main_backdoor
![image](https://hackmd.io/_uploads/ByfTnjdWJl.png)
RBP of main_backdoor = RBP sub_0 - (5(push) + 1(call)) * 8
RBP of sub_0 = (RSP before call backdoor) - (1(push) + 1(call)) * 8
For now, to find key, nonce, and encrypted data is not easy as before, cause no hint or signature to find. We need to lean on the current debug status, find exactly where server crashed and trace back.
![image](https://hackmd.io/_uploads/BJgz9s_Zye.png)

RIP = 0, which lead to crash, it maybe due to a call/jmp to 0, from return address find before, we can find RVA of this address, which is 0x988F (0x0007f4a18c8f88f  - 0x7f4a18c86000). Follow the return RVA, the call above is call RAX, and RAX in context is exactly 0.
![image](https://hackmd.io/_uploads/rJ_zii_b1e.png)
Read the assembly code, we can see that, RSP value we want to find will be plus 8 compare to the current RSP, due to call instruction.
from all above info, RBP of main_backdoor = current_rsp + 8 - 8 * 8  = 0x7ffcc6601e98 - 0x38 = 0x7ffcc6601e60
==> key
![image](https://hackmd.io/_uploads/ryV072OZ1l.png)
==> nonce:
![image](https://hackmd.io/_uploads/Sy8MN2_-1l.png)
==> file_name:
![image](https://hackmd.io/_uploads/Hy9uVndZye.png)
==> encrypted data
![image](https://hackmd.io/_uploads/HJZ6E3O-Jx.png)
For encrypted data, i take until it meets the null byte (actual only 0x40 bytes from start).
Try decrypt using cyberchef, but it doesn't work :) After for a while, i found that salcha20 is customized a little bit, not "expand 32-byte k" as normal, but "expand 32-byte K" :) 
To decrypt, me myself chose to write a program that run that shellcode, with key, nonce, and enc as above.

Flag: supp1y_cha1n_sund4y@flare-on.com

# Challenge 9
Given a x64 executable. Run it, it's absolute Flag checker
![image](https://hackmd.io/_uploads/SJGRj5FZJl.png)

At main function
![image](https://hackmd.io/_uploads/H1VV25F-Jg.png)
First, it registers an ExceptionFilter but the handler is nothing but an simple error message and exit
![image](https://hackmd.io/_uploads/BJwxactZ1l.png)

Key is copied into an hardcode address, then pass into a shellcode at lpAddress is called. Find reference to lpAddress, it is used in a TLS_Callback
![image](https://hackmd.io/_uploads/HyHFT5KbJg.png)
VirtualAlloc a memory range 0x800000 bytes with RXW permission, then copy the same byte from 0x140097AF0 into that address.

Jump to where the shellcode locate, it's kinda weird. First instruction is "hlt", which is an previlege instruction, can only run in kernel mode. If run in userspace, it will generate an EXCEPTION_PRIV_INSTRUCTION
![image](https://hackmd.io/_uploads/SyBRkotW1l.png)
As analyze before, the handler at main function just print out error message and exit, so it have to another mechanism to handle exception and it may enabled even before main function is called.
IDA support to find EntryPoint, after the TLS_Callback, the main entrypoint will be called
![image](https://hackmd.io/_uploads/r1mUbitbJg.png)
At start, it jump to scrt_common_main_seh, and inside this function, we find what we want.
Before main is called, an array of function from First to Last is called
![image](https://hackmd.io/_uploads/S1yfzsFbkx.png)
![image](https://hackmd.io/_uploads/BJCzfjK-yl.png)
+ sub_140001090: Get ntdll handle
+ sub_140002000: Find RtlInstallFunctionTableCallback address
+ sub_140001030: Call RtlInstallFunctionTableCallback

As [MSDN ](https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlinstallfunctiontablecallback), the API is used to add a dynamic function table to the dynamic function table list.
Why is it important here ? The [x64 exception handle](https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170) mechanism in MSDN and excellent [article](https://codemachine.com/articles/x64_deep_dive.html#exception_handling) on x64 say it all
![image](https://hackmd.io/_uploads/S1Pt5jYZ1l.png)
So when exception occurs, the PGET_RUNTIME_FUNCTION_CALLBACK Callback will be called, it generates a runtime function, which used for handle exception.
The struct of RUNTIME FUNCTION is defined as below:
![image](https://hackmd.io/_uploads/rJ3ypitZke.png)
Let's jump into the callback, we find the logic to generate RUNTIME FUNCTION
![image](https://hackmd.io/_uploads/SkZOTiK-Jg.png)
```python=
FunctionStart = exception_ocurr offset
FunctionEnd = FunctionStart + 1
UnwindInfo = FunctionEnd + idc.get_wide_byte(base + FunctionEnd) + 1
UnwindInfo += (UnwindInfo & 1)
```
The UnwindInfo hold the infomations that need to handle the exception
![image](https://hackmd.io/_uploads/SJPwm3Y-Jx.png)
At first, with naive thinking, i write a simple script that find the handler and jump immediately from where exception occurs into handler. That give me the flow of that code but still a lot of stubs doesn't make sense, ie: before exception, R8 hold the address of input key, but in the handle, the value of R8 in context no longer hold that value, ..

After for while, reading the the MSDN again, i found that the unwind codes array is the reason i lost the track. It's kinda similar as VM obfuscate, each unwind code is contain info with normal intense to clean the stack, but in this case, it does some "magic" work.
Base on the [ReactOS src](https://doxygen.reactos.org/d8/d2f/unwind_8c_source.html), i write some script that simulate that flow of unwind code (still some bug in this code, but it help me figure out the lost track). 
```python=
def handle(base, exception_offset):
    start_offset = exception_offset
    end_offset = start_offset + 1
    unwind_offset = end_offset  + get_wide_byte(base + end_offset) + 1
    unwind_offset += unwind_offset & 1
    unwind_info =  base + unwind_offset
    #print('UnwindInfo: ' + hex(unwind_info))
    flags = (get_wide_byte(unwind_info) & 0xf8) >> 3 
    #print('FLAG: ' + hex(flags)) 
    sizeofprolog = get_wide_byte(unwind_info + 1) 
    #print('Size of prolog: ' + hex(sizeofprolog))
    countofcode = get_wide_byte(unwind_info + 2)
    #print('COUNT OF CODE: ' + hex(countofcode))
    frame = get_wide_byte(unwind_info + 3)
    fram_reg = frame & 0xf 
    #print('FRAME REG: ' + hex(fram_reg))
    framoffset = (frame & 0xf0) >> 4
    #print('FRAME_OFFSET: ' + hex(framoffset))
    unwindcode = unwind_info + 4
    i = 0
    while i < countofcode:
        k = 0
        #print('Uwincode address: ' + (hex(unwindcode)))
        code_offset = get_wide_byte(unwindcode)
        code = get_wide_byte(unwindcode + 1)
        opcode = (code & 0xf) 
        #print('OPCODE: ' + hex(opcode) + ': ', end='')
        opinfo = (code & 0xf0) >> 4
        if opcode == UWOP_PUSH_NONVOL:
            insn = 'pop ' + regs[opinfo]
            #print(insn)
            exception_offset += patch_asm(base + exception_offset, insn)
            k = 1
        elif opcode == UWOP_ALLOC_LARGE:
            if opinfo != 0:
                insn = 'add rsp, ' + hex(get_wide_dword(unwindcode + 2))
                #print(insn)
                exception_offset += patch_asm(base + exception_offset, insn)
                k = 3
            else:
                insn = 'add rsp, ' + hex(get_wide_word(unwindcode + 2) * 8)
                #print(insn)
                exception_offset += patch_asm(base + exception_offset, insn)
                k = 2
        elif opcode == UWOP_ALLOC_SMALL:
            insn = 'add rsp, ' + hex(8 * (opinfo + 1))
            #print(insn)
            exception_offset += patch_asm(base + exception_offset, insn)
            k = 1
        elif opcode == UWOP_SET_FPREG:
            reg = regs[fram_reg]
            delta = framoffset * 16
            if delta:
                insn = 'mov rsp, ' + reg + ' - ' + hex(delta) +']'
            else:
                insn = 'mov rsp, ' + reg 
            #print(insn)
            exception_offset += patch_asm(base + exception_offset, insn)
            k = 1
        elif opcode == UWOP_SAVE_NONVOL:
            reg = regs[opinfo]
            offset = get_wide_word(unwindcode + 2)
            insn = 'mov ' + reg + ', [rsp + ' + hex(offset) +']'
            #print(insn)
            exception_offset += patch_asm(base + exception_offset, insn)
            k = 2
        elif opcode == UWOP_SAVE_NONVOL_FAR:
            reg = regs[opinfo]
            offset = get_wide_dword(unwindcode + 2)
            insn = 'mov ' + reg + ', [rsp + ' + hex(offset) +']' 
            #print(insn)
            exception_offset += patch_asm(base + exception_offset, insn)
            k = 3
        elif opcode == UWOP_EPILOG:
            k = 1
        elif opcode == UWOP_SPARE_CODE:
            k = 2
        elif opcode == UWOP_PUSH_MACHFRAME:
            insn = 'add rsp, ' + hex(opinfo * 8)
            #print(insn)
            exception_offset += patch_asm(base + exception_offset, insn)
            insn = 'mov rip, [rsp]'
            #print(insn)
            insn = 'mov rsp, [rsp + 0x18]'
            exception_offset += patch_asm(base + exception_offset, insn)
            #print(insn)
            k = 1
        i += k
        unwindcode += k * 2
    countofcode *= 2
    countofcode += countofcode % 4
    handler = base +  get_wide_dword(unwind_info + 4 + countofcode)
    # delta = handler - base - exception_offset - 5
    # patch_byte(base + exception_offset, 0xe9)
    # patch_dword(base + exception_offset + 1, delta)
    # create_insn(base + exception_offset)
    set_cmt(base + start_offset, hex(unwind_info) + ', ' + hex(handler), 0)
    return handler
```
Beside that obfuscation x64 exception mechanism, the code at Exception Handler is also obfuscated
![image](https://hackmd.io/_uploads/ryW4lTYb1l.png)
The inside the call always has the same logic as below
![image](https://hackmd.io/_uploads/rk8LZ6tZ1e.png)
First, it pop the return address into hardcode address, then it decrypt the real instruction by moving the opcode of real instruction and the then return address is calculated. So each instruction is actual just do one instruction at a time, which is the decrypted code. For deobfuscate the call obfuscate, i use this silly code
```python=
def patch_call(call, start_call, ret):
    ea = start_call
    create_insn(ea) # pop instruction
    poped_addr = get_operand_value(ea, 0)
    patch_qword(poped_addr, ret)
    ea += 0xe # point to mov
    insn_len = create_insn(ea)
    ah = get_wide_byte(get_operand_value(ea, 1)) << 8 
    ea += insn_len # point to lea
    insn_len = create_insn(ea)
    eax = ah + get_operand_value(ea, 1)
    ea += insn_len # point to mov
    addr_patch = get_operand_value(ea, 0)
    patch_dword(addr_patch, eax)
    ea = addr_patch
    real_insn = create_insn(ea)
    if print_insn_mnem(ea) == 'jmp':
        jmp = get_operand_value(ea, 0)
        delta = jmp - call - 5
        patch_byte(call, 0xe9)
        patch_dword(call + 1, delta)
        return jmp
    #in case it not a jmp to htl
    for i in range(real_insn):
        patch_byte(call + i, get_wide_byte(ea + i))
    create_insn(call)
    ea = poped_addr + 8
    create_insn(ea)
    delta = get_operand_value(ea, 1) # get the real return value
    return ret + delta    
```
Dump the deobfuscated shellcode to a file, investigate on that code, we can found some key concept below:
 + There' re 32 checks, everytime check fail, it jump into function sub_1400011F0 which print out "Wrong key" message and terminate program.
 ![image](https://hackmd.io/_uploads/SJc0qk5-yx.png)
 + For each check, it is a equation of operation include plus, xor, mul where input key is manage to join in mul operation, each equation take random 8 characters from input key, each character mul with a hardcode number, then xor/add with another hardcode number
 + The hardcode value is not show up clearly in the code but hided by some simple maths (push a number on stack, add/sub a number, the result is the actual value, ...) which can be quickly remove by find the pattern replace with coressponse value of that value.
 ![image](https://hackmd.io/_uploads/ByXw-g9WJe.png)

 + Almost value is manual construct byte by byte (except the value used to mul with input key character), each byte of the value appear in form of array, corresponse to two type of operations xor and add. the final value can be managed to collect with help of idapython script. But compare to actual value we find when debug, some of them are slicely different.

At this point, we decided to debug and log the results of every operation, then convert each result back to the 'actual value' used in the operations. After debugging the first check, we can reimplement it in Python for the first case like this

```python=
def c1():
    result = data[0x4] * 0xef7a8c
    result = result + 0x9d865d8d
    result = result - (data[0x18] * 0x45b53c)
    result = result + 0x18baee57
    result = result - (data[0x0] * 0xe4cf8b)
    result = result + 0x6ec04422
    result = result - (data[0x8] * 0xf5c990)
    result = result + 0x6bfaa656
    result = result ^ (data[0x14] * 0x733178)
    result = result ^ 0x61e3db3b
    result = result ^ (data[0x10] * 0x9a17b8)
    result = result + 0x35d7fb4f
    result = result ^ (data[0xc] * 0x773850)
    result = result ^ 0x5a6f68be
    result = result ^ (data[0x1c] * 0xe21d3d)
    result = result ^ 0x5c911c23
    result = result + 0x7e9b8687
    result &= 0xffffffffffffffff
    return result
```

We still have 31 functions like this left, and while debugging each one is possible, it would be extremely time-consuming. I decided to automate the process using IDAPython. My plan is to dump the values of each operation and then back-calculate them to find the hardcoded numbers. I patched the input to `\x00 * 32` to make the calculation easier. With my deobfuscated shellcode dump file, it's easy to locate the offset of any instruction. First, I found that there are only 32 test instructions, each one checking the final value in each function

![image](https://hackmd.io/_uploads/ByRqoxhW1e.png)

I’ll set breakpoints at each of these 32 `test` instructions.

![image](https://hackmd.io/_uploads/Sk9Apx2ZJe.png)

Each of the 32 checks will trigger a conditional jump to a Print "Wrong" function if the check fails. To automate the debugging process, you’ll need to ensure that the instruction pointer (RIP) is automatically adjusted after each failed check. To handle this, I’ll also set 32 additional breakpoints on each `cmovnz` instruction. Every time a breakpoint on a `cmovnz` instruction is hit, it will automatically adjust RIP to point to the correct jmp instruction to continue debugging smoothly. Below is my script to dump the values:

```python=
test_array =[0x179fd,0x2f386,0x4751a,0x5d2cd,0x7230b,0x8917b,0xa0de8,0xb7d00,0xd0742,0xe7b7b,0xff3a3,0x1164ea,0x12ce52,0x14492b,0x15ec1e,0x176fbd,0x190732,0x1a5a58,0x1bc75d,0x1d572b,0x1ecdf1,0x205671,0x21b636,0x22f442,0x243e47,0x25a19e,0x26ec62,0x285d0b,0x29e558,0x2b5f19,0x2cd429,0x2e4b8f]


cmove_array = [0x17a07, 0x2f390, 0x47524, 0x5d2d7, 0x72315, 0x89185, 0xa0df2, 0xb7d0a, 0xd074c, 0xe7b85, 0xff3ad, 0x1164f4, 0x12ce5c, 0x144935, 0x15ec28, 0x176fc7, 0x19073c, 0x1a5a62, 0x1bc767, 0x1d5735, 0x1ecdfb, 0x20567b, 0x21b640, 0x22f44c, 0x243e51, 0x25a1a8, 0x26ec6c, 0x285d15, 0x29e562, 0x2b5f23, 0x2cd433, 0x2e4b99]


base = get_qword(0x14089B8E0)
for i in range(len(test_array)):
    idaapi.create_insn(base+test_array[i])
    add_bpt(base+test_array[i],0,BPT_DEFAULT);
for i in range(len(cmove_array)):
    idaapi.create_insn(base + cmove_array[i])
    add_bpt(base + cmove_array[i], 0, BPT_DEFAULT)
    
for i in range(len(test_array)+len(cmove_array)):  
    ida_dbg.continue_process()
    idaapi.wait_for_next_event(WFNE_SUSP, -1)
    if(idc.print_insn_mnem(get_reg_value("rip"))=="cmovnz"):
        set_reg_value(get_reg_value("rip")+idaapi.create_insn(get_reg_value("rip"))+idaapi.create_insn(get_reg_value("rip")+idaapi.create_insn(get_reg_value("rip"))),"rip")
    else:
        offset = get_reg_value("rip")-base
        value_final = get_reg_value(print_operand(get_reg_value("rip"),0))
        print(hex(value_final),end=",")  
        
f.close()
```

We will got 32 final value in mỗi hàm với input is `\x00 * 32` :
```
0x5be3e290,0x62a2a0fb,0x3ade6641,0x18d62e9b4,0xffffffffd01904a1,0xffffffffbbe5233e,0x8478c40,0xffffffffb1b9939b,0xfffffffff31da2f5,0x8c8bc76,0xffffffffd45091a6,0x1a35812a,0xffffffffd8bc839e,0xffffffffe724ad90,0x1a1d901a,0xffffffff81514d31,0xffffffff530d9146,0x5db36e01,0x6c511b62,0xffffffff4f1727a1,0x213022fe,0xfffffffff4d5f043,0xffffffff92a2ef25,0xfffffffedf1a2ab0,0xffffffff750e3b65,0x448addb5,0xfffffffffe691b35,0xffffffffed2a9d03,0x224e42c5,0xfffffffda375005b,0xfffffffe71ef098c,0xffffffffbcc44d66
```
Similarly, I set a breakpoint on the `mul` instruction to dump the factor values in `rsp`

![image](https://hackmd.io/_uploads/BkyTMb2Zyx.png)

After the first `mul`, the value is pushed to the stack. Starting from the second `mul`, it will use the result of the previous calculation to perform an `xor`, `add`, or `sub` with the newly multiplied result. It's easy to calculate the offsets of these instructions from the mul instruction's address (as they appear just a few instructions after mul) using my deobfuscated shellcode dump file. The output for the first three check functions will look like this.

![image](https://hackmd.io/_uploads/BJ9n4bnWye.png)

Now, we have dumped the sign and factors of each multiplication operation. Next, I set a breakpoint on the `ldmxcsr` instruction to dump the hardcoded value used for calculations between the multiplication operations (`mul`).

![image](https://hackmd.io/_uploads/HkCvUbhZkx.png)

My dump: 

![image](https://hackmd.io/_uploads/SkpqFZhbJg.png)


The final piece of data we need is the sign of the operations between the multiplication steps. Through debugging, I found a pattern: if the operation is an `xor`, there is an array containing the xor values, indexed accordingly: 

![image](https://hackmd.io/_uploads/rJ8d3-h-1g.png)

For example, if you want to XOR `0x5` with `0x32`, there is an array pre-calculated with the XOR results. By taking the address of the value `0x32` and adding 5, you get the result of `0x32 ^ 0x5 = 0x37`. The array looks like this:

```asm=
addr:   value
0x00:   0x32    //0x32= 0x32 ^ 0x0
0x01:   0x33    //0x33= 0x33 ^ 0x1
0x02:   0x30    //0x30= 0x32 ^ 0x2
0x03:   0x31
0x04:   0x36
0x05:   0x37
0x06:   0x34
0x07:   0x35
0x08:   0x3a
0x09:   0x3b
0x0a:   0x38
0x0b:   0x39
0x0c:   0x3e
0x0d:   0x3f
0x0e:   0x3c
0x0f:   0x3d
...
...
...
```

From all of the above, I was able to reimplement all 32 check functions and use Z3 to find the flag


```python=
from z3 import *
def c1():
    result = data[0x4] * 0xef7a8c
    result = result + 0x9d865d8d
    result = result - (data[0x18] * 0x45b53c)
    result = result + 0x18baee57
    result = result - (data[0x0] * 0xe4cf8b)
    result = result + 0x6ec04422
    result = result - (data[0x8] * 0xf5c990)
    result = result + 0x6bfaa656
    result = result ^ (data[0x14] * 0x733178)
    result = result ^ 0x61e3db3b
    result = result ^ (data[0x10] * 0x9a17b8)
    result = result + 0x35d7fb4f
    result = result ^ (data[0xc] * 0x773850)
    result = result ^ 0x5a6f68be
    result = result ^ (data[0x1c] * 0xe21d3d)
    result = result ^ 0x5c911c23
    result = result + 0x7e9b8687
    result &= 0xffffffffffffffff
    return result

def c2():
    result = data[0x11] * 0x99aa81
    result = result + 0x8b1215af
    result = result ^ (data[0x5] * 0x4aba22)
    result = result + 0x598015bf
    result = result ^ (data[0x15] * 0x91a68a)
    result = result ^ 0x6df18e52
    result = result ^ (data[0x1] * 0x942fde)
    result = result + 0x15c825ee
    result = result - (data[0xd] * 0xfe2fbe)
    result = result + 0xd5682b64
    result = result - (data[0x1d] * 0xd7e52f)
    result = result + 0x798bd018
    result = result ^ (data[0x19] * 0xe44f6a)
    result = result + 0x1992adc2
    result = result + (data[0x9] * 0xaf71d6)
    result = result + 0x921121d3
    result = result + 0x1eeb7552
    result &= 0xffffffffffffffff
    return result

def c3():
    result = data[0xa] * 0x48c500
    result = result + 0x70255e44
    result = result - (data[0x1e] * 0x152887)
    result = result + 0x65f04e48
    result = result - (data[0xe] * 0xaa4247)
    result = result ^ 0x3d63ec69
    result = result ^ (data[0x16] * 0x38d82d)
    result = result ^ 0x872eca8f
    result = result ^ (data[0x1a] * 0xf120ac)
    result = result + 0x803dbdcf
    result = result + (data[0x2] * 0x254def)
    result = result ^ 0xee380db3
    result = result ^ (data[0x12] * 0x9ef3e7)
    result = result + 0x921556f5
    result = result + (data[0x6] * 0x69c573)
    result = result + 0x3653a3a3
    result = result + 0xc45c0f3
    result &= 0xffffffffffffffff
    return result

def c4():
    result = data[0xb] * 0x67dda4
    result = result + 0xf4753afc
    result = result + (data[0x1f] * 0x5bb860)
    result = result ^ 0xc1d47fc9
    result = result ^ (data[0x17] * 0xab0ce5)
    result = result + 0x544ff977
    result = result + (data[0x7] * 0x148e94)
    result = result + 0x634c1be7
    result = result - (data[0xf] * 0x9e06ae)
    result = result + 0x5239df9c
    result = result ^ (data[0x3] * 0xfb9de1)
    result = result ^ 0x4e3633f7
    result = result - (data[0x1b] * 0xa8a511)
    result = result ^ 0xa61f9208
    result = result + (data[0x13] * 0xd3468d)
    result = result + 0x4a5d7a48
    result = result + 0x109bee5e
    result &= 0xffffffffffffffff
    return result

def c5():
    result = data[0xc] * 0x640ba9
    result = result + 0x516c7a5c
    result = result - (data[0x0] * 0xf1d9e5)
    result = result + 0x8b424d6b
    result = result + (data[0x1c] * 0xd3e2f8)
    result = result + 0x3802be78
    result = result + (data[0x18] * 0xb558ce)
    result = result + 0xccbe7372
    result = result - (data[0x8] * 0x2f03a7)
    result = result ^ 0xe050b170
    result = result + (data[0x10] * 0xb8fa61)
    result = result ^ 0x1fc22df6
    result = result - (data[0x14] * 0xe0c507)
    result = result ^ 0xd8376e57
    result = result + (data[0x4] * 0x8e354e)
    result = result + 0x2d34cdf8
    result = result + 0xff187080
    result &= 0xffffffffffffffff
    return result

def c6():
    result = data[0x11] * 0xa9b448
    result = result ^ 0x9f938499
    result = result + (data[0x5] * 0x906550)
    result = result + 0x407021af
    result = result ^ (data[0xd] * 0xaa5ad2)
    result = result ^ 0x77cf83a7
    result = result ^ (data[0x1d] * 0xc49349)
    result = result ^ 0x3067f4e7
    result = result + (data[0x9] * 0x314f8e)
    result = result + 0xcd975f3b
    result = result ^ (data[0x15] * 0x81968b)
    result = result + 0x893d2e0b
    result = result - (data[0x19] * 0x5ffbac)
    result = result ^ 0xf3378e3a
    result = result - (data[0x1] * 0xf63c8e)
    result = result + 0xe3e276d5
    result = result + 0x71a14c73
    result &= 0xffffffffffffffff
    return result

def c7():
    result = data[0x16] * 0xa6edf9
    result = result ^ 0x77c58017
    result = result - (data[0x12] * 0xe87bf4)
    result = result + 0x666428c0
    result = result - (data[0x2] * 0x19864d)
    result = result + 0xbe77b413
    result = result + (data[0x6] * 0x901524)
    result = result ^ 0x247bf095
    result = result ^ (data[0xa] * 0xc897cc)
    result = result ^ 0xeff7eea8
    result = result ^ (data[0xe] * 0x731197)
    result = result + 0x67a0d262
    result = result + (data[0x1e] * 0x5f591c)
    result = result + 0x316661f9
    result = result + (data[0x1a] * 0x579d0e)
    result = result + 0xcbd804e4
    result = result + 0x6ff28cb5
    result &= 0xffffffffffffffff
    return result

def c8():
    result = data[0x17] * 0x9afaf6
    result = result ^ 0xdb895413
    result = result + (data[0x13] * 0x7d1a12)
    result = result + 0x398603bc
    result = result + (data[0xb] * 0x4d84b1)
    result = result + 0xa30387dc
    result = result - (data[0xf] * 0x552b78)
    result = result ^ 0xf54a725e
    result = result ^ (data[0x7] * 0xf372a1)
    result = result + 0xb3aefc53
    result = result + (data[0x1f] * 0xb40eb5)
    result = result ^ 0x16fa70d2
    result = result ^ (data[0x3] * 0x9e5c18)
    result = result + 0x38784353
    result = result ^ (data[0x1b] * 0xf2513b)
    result = result + 0xa1fc09f0
    result = result + 0xfe291bf8
    result &= 0xffffffffffffffff
    return result

def c9():
    result = data[0x1c] * 0xac70b9
    result = result + 0xdae0a932
    result = result ^ (data[0x4] * 0xc42b6f)
    result = result ^ 0xbc03104c
    result = result - (data[0x0] * 0x867193)
    result = result + 0xdc48c63a
    result = result - (data[0xc] * 0x6d31fe)
    result = result ^ 0x4baeb6d0
    result = result - (data[0x10] * 0xaaae58)
    result = result + 0x328ede08
    result = result + (data[0x14] * 0x9faa7a)
    result = result + 0xbe0a2c9c
    result = result + (data[0x18] * 0x354ac6)
    result = result ^ 0xd8ad17f1
    result = result - (data[0x8] * 0x3f2acb)
    result = result + 0x74948177
    result = result + 0x9c3ec96d
    result &= 0xffffffffffffffff
    return result

def c10():
    result = data[0x1d] * 0xe9d18a
    result = result ^ 0xcb5557ea
    result = result ^ (data[0x19] * 0x8aa5b9)
    result = result ^ 0x9125a906
    result = result - (data[0x11] * 0x241997)
    result = result + 0x6e46fcb8
    result = result + (data[0x5] * 0xe3da0f)
    result = result + 0x442800ec
    result = result + (data[0xd] * 0xa5f9eb)
    result = result + 0xbde8f9af
    result = result + (data[0x15] * 0xd6e0fb)
    result = result + 0x36268dbd
    result = result + (data[0x1] * 0x8dc36e)
    result = result + 0xc54b7d21
    result = result ^ (data[0x9] * 0xb072ee)
    result = result + 0xd5e54e3f
    result = result + 0x40dfbc25
    result &= 0xffffffffffffffff
    return result

def c11():
    result = data[0x1e] * 0xd14f3e
    result = result ^ 0xa06c215b
    result = result - (data[0x1a] * 0xc5ecbf)
    result = result + 0xb197c5c0
    result = result ^ (data[0x6] * 0x19ff9c)
    result = result ^ 0x66e7d06c
    result = result + (data[0x2] * 0xe3288b)
    result = result ^ 0x80af4325
    result = result ^ (data[0xa] * 0xcfb18c)
    result = result + 0x1ec37c6d
    result = result ^ (data[0x12] * 0xd208e5)
    result = result + 0xf96d2b51
    result = result + (data[0xe] * 0x42240f)
    result = result + 0x78cdd8c3
    result = result - (data[0x16] * 0x1c6098)
    result = result + 0x2c2ba3a6
    result = result + 0xf4c281a5
    result &= 0xffffffffffffffff
    return result

def c12():
    result = data[0xb] * 0x3768cc
    result = result ^ 0x19f61419
    result = result - (data[0x3] * 0x43be16)
    result = result + 0x566cc6a8
    result = result ^ (data[0xf] * 0xb7cca5)
    result = result + 0x6db0599e
    result = result + (data[0x1b] * 0xf6419f)
    result = result ^ 0xbd613538
    result = result ^ (data[0x13] * 0xae52fc)
    result = result + 0x717a44dd
    result = result - (data[0x17] * 0x5eeb81)
    result = result + 0xdd02182d
    result = result ^ (data[0x7] * 0xec1845)
    result = result ^ 0xef8e5416
    result = result + (data[0x1f] * 0x61a3be)
    result = result ^ 0x9288d4fa
    result = result + 0x7e4241fb
    result &= 0xffffffffffffffff
    return result

def c13():
    result = data[0x10] * 0x336e91
    result = result + 0xa1eb20e3
    result = result - (data[0x4] * 0xd45de9)
    result = result + 0xc7e538e6
    result = result + (data[0x8] * 0x76c8f8)
    result = result ^ 0xd8caa2cd
    result = result - (data[0x14] * 0x945339)
    result = result + 0x524d7efa
    result = result + (data[0xc] * 0x4474ec)
    result = result + 0x1b817d33
    result = result ^ (data[0x0] * 0x51054f)
    result = result ^ 0x3321c9b1
    result = result - (data[0x18] * 0xd7eb3b)
    result = result + 0x36f6829d
    result = result - (data[0x1c] * 0xad52e1)
    result = result ^ 0x6ce2191a
    result = result + 0xc64bcbd
    result &= 0xffffffffffffffff
    return result

def c14():
    result = data[0x1d] * 0x725059
    result = result ^ 0xa8b69f6b
    result = result + (data[0x11] * 0x6dcfe7)
    result = result ^ 0x653c249a
    result = result + (data[0x1] * 0x8f4c44)
    result = result ^ 0x68e87685
    result = result - (data[0x9] * 0xd2f4ce)
    result = result + 0x78dc723b
    result = result ^ (data[0xd] * 0xe99d3f)
    result = result + 0xed16797a
    result = result + (data[0x5] * 0xada536)
    result = result + 0x6a5fa557
    result = result - (data[0x19] * 0xe0b352)
    result = result ^ 0x43c00020
    result = result + (data[0x15] * 0x8675b6)
    result = result + 0x34a29213
    result = result + 0xdfe69582
    result &= 0xffffffffffffffff
    return result

def c15():
    result = data[0x2] * 0x4a5e95
    result = result + 0x5ed7a1f1
    result = result + (data[0x16] * 0x3a7b49)
    result = result ^ 0x87a91310
    result = result - (data[0x6] * 0xf27038)
    result = result ^ 0xf64a0f19
    result = result + (data[0x1e] * 0xa187d0)
    result = result + 0x44338ca3
    result = result - (data[0x12] * 0xfc991a)
    result = result ^ 0xf9ddd08f
    result = result - (data[0x1a] * 0x4e947a)
    result = result + 0xa656e8d2
    result = result ^ (data[0xe] * 0x324ead)
    result = result + 0x6965859c
    result = result - (data[0xa] * 0x656b1b)
    result = result + 0x8c112443
    result = result + 0x3e24bb39
    result &= 0xffffffffffffffff
    return result

def c16():
    result = data[0xb] * 0x251b86
    result = result + 0xa751192c
    result = result - (data[0x7] * 0x743927)
    result = result ^ 0xf851da43
    result = result ^ (data[0x1f] * 0x9a3479)
    result = result ^ 0x335087a5
    result = result ^ (data[0x3] * 0x778a0d)
    result = result ^ 0x4bfd30d3
    result = result - (data[0x1b] * 0x7e04b5)
    result = result + 0xa2abfb6b
    result = result ^ (data[0x13] * 0xf1c3ee)
    result = result + 0x460c48a6
    result = result + (data[0xf] * 0x883b8a)
    result = result + 0x7b2ffbdc
    result = result + (data[0x17] * 0x993db1)
    result = result + 0xa98b27fa
    result = result + 0xddf7842c
    result &= 0xffffffffffffffff
    return result

def c17():
    result = data[0x10] * 0xbae081
    result = result + 0x2359766f
    result = result ^ (data[0x18] * 0xc2483b)
    result = result + 0xea986a57
    result = result - (data[0x1c] * 0x520ee2)
    result = result ^ 0xa6ff8114
    result = result + (data[0x8] * 0x9864ba)
    result = result + 0x42833507
    result = result - (data[0x0] * 0x7cd278)
    result = result ^ 0x360be811
    result = result ^ (data[0x4] * 0xbe6605)
    result = result + 0xb36d8573
    result = result + (data[0x14] * 0x3bd2e8)
    result = result + 0xb790cfd3
    result = result - (data[0xc] * 0x548c2b)
    result = result + 0x2a0e04cc
    result = result + 0xdecd786e
    result &= 0xffffffffffffffff
    return result

def c18():
    result = data[0x11] * 0xfb213b
    result = result + 0x988c29bd
    result = result ^ (data[0x9] * 0xde6876)
    result = result ^ 0x8649fde3
    result = result ^ (data[0x1d] * 0x629ff7)
    result = result ^ 0xa0eeb203
    result = result - (data[0x19] * 0xdbb107)
    result = result ^ 0x94aa6b62
    result = result - (data[0x1] * 0x262675)
    result = result + 0x2030ab78
    result = result + (data[0x5] * 0xd691c5)
    result = result + 0xa4c118ba
    result = result - (data[0xd] * 0xcafc93)
    result = result + 0xeee421de
    result = result - (data[0x15] * 0x81f945)
    result = result + 0x6ffcc3f8
    result = result + 0x9cb62931
    result &= 0xffffffffffffffff
    return result

def c19():
    result = data[0xa] * 0x52f44d
    result = result ^ 0x33b3d0e4
    result = result ^ (data[0x1e] * 0xe6e66e)
    result = result + 0xd8a28650
    result = result - (data[0x6] * 0xf98017)
    result = result ^ 0x456e6c1d
    result = result - (data[0xe] * 0x34fcb0)
    result = result ^ 0x28709cd8
    result = result ^ (data[0x2] * 0x4d8ba9)
    result = result + 0xb5482f53
    result = result ^ (data[0x12] * 0x6c7e92)
    result = result + 0x2af1d741
    result = result + (data[0x16] * 0xa4711e)
    result = result ^ 0x22e79af6
    result = result + (data[0x1a] * 0x33d374)
    result = result + 0xee8102f2
    result = result + 0x6c86bd72
    result &= 0xffffffffffffffff
    return result

def c20():
    result = data[0x1b] * 0x65ac37
    result = result + 0x15e586b0
    result = result ^ (data[0x1f] * 0xc6dde0)
    result = result ^ 0x2354cad4
    result = result ^ (data[0xf] * 0x154abd)
    result = result ^ 0xfee57fd5
    result = result ^ (data[0x13] * 0xa5e467)
    result = result + 0x315624ef
    result = result ^ (data[0x17] * 0xb6bed6)
    result = result + 0xad7a4f5b
    result = result - (data[0x7] * 0x832ae7)
    result = result + 0xe961bedd
    result = result + (data[0xb] * 0xc46330)
    result = result + 0xb561e29b
    result = result ^ (data[0x3] * 0x3f8467)
    result = result ^ 0x95a6a1c4
    result = result + 0xeef1cae7
    result &= 0xffffffffffffffff
    return result

def c21():
    result = data[0x18] * 0xb74a52
    result = result ^ 0x8354d4e8
    result = result ^ (data[0x4] * 0xf22ecd)
    result = result + 0xcb340dc5
    result = result + (data[0x14] * 0xbef4be)
    result = result ^ 0x60a6c39a
    result = result ^ (data[0x8] * 0x7fe215)
    result = result + 0xb14a7317
    result = result - (data[0x10] * 0xdb9f48)
    result = result + 0x4356fa0e
    result = result - (data[0x1c] * 0xbb4276)
    result = result + 0x6df1ddb8
    result = result ^ (data[0x0] * 0xa3fbef)
    result = result + 0x4c22d2d3
    result = result ^ (data[0xc] * 0xc5e883)
    result = result ^ 0x50a6e4c9
    result = result + 0x271a433a
    result &= 0xffffffffffffffff
    return result

def c22():
    result = data[0xd] * 0x4b2d02
    result = result ^ 0x4b59b93a
    result = result - (data[0x9] * 0x84bb2c)
    result = result ^ 0x42d5652c
    result = result ^ (data[0x19] * 0x6f2d21)
    result = result + 0x1020133a
    result = result + (data[0x1d] * 0x5fe38f)
    result = result + 0x9d7f84e0
    result = result + (data[0x15] * 0xea20a5)
    result = result ^ 0x60779ceb
    result = result ^ (data[0x11] * 0x5c17aa)
    result = result ^ 0x1aaf8a2d
    result = result - (data[0x5] * 0xb9feb0)
    result = result + 0x5241fd05
    result = result - (data[0x1] * 0x782f79)
    result = result + 0x303ed7ca
    result = result + 0xb77294fa
    result &= 0xffffffffffffffff
    return result

def c23():
    result = data[0x6] * 0x608d19
    result = result + 0xd1119d14
    result = result - (data[0xe] * 0xbe18f4)
    result = result ^ 0xb86f9b72
    result = result ^ (data[0x1e] * 0x88dec9)
    result = result + 0xaf5cd797
    result = result ^ (data[0x12] * 0xb68150)
    result = result + 0xc2f8c45b
    result = result + (data[0x16] * 0x4d166c)
    result = result + 0xbb1e1039
    result = result - (data[0x2] * 0x495e3f)
    result = result + 0xe727b98e
    result = result - (data[0xa] * 0x5caba1)
    result = result + 0xe5c3093f
    result = result + (data[0x1a] * 0x183a4d)
    result = result + 0x35fc681f
    result = result + 0x997b5ce3
    result &= 0xffffffffffffffff
    return result

def c24():
    result = data[0xb] * 0xffd0ca
    result = result + 0x70d93118
    result = result ^ (data[0x7] * 0xbf2b59)
    result = result + 0xc76bad6e
    result = result + (data[0x17] * 0x29df01)
    result = result + 0xeef034a2
    result = result ^ (data[0x1b] * 0xbbda1d)
    result = result + 0x5923194e
    result = result - (data[0x1f] * 0x5d24a5)
    result = result + 0x7eeff867
    result = result + (data[0xf] * 0x3dc505)
    result = result + 0x9645116f
    result = result ^ (data[0x13] * 0x4e25a6)
    result = result + 0x2468b30a
    result = result - (data[0x3] * 0xae1920)
    result = result ^ 0xd3db6142
    result = result + 0x44850ff1
    result &= 0xffffffffffffffff
    return result

def c25():
    result = data[0x4] * 0xf56c62
    result = result ^ 0x6c7d1f41
    result = result + (data[0x10] * 0x615605)
    result = result + 0x5b52f6ee
    result = result + (data[0x14] * 0x828456)
    result = result ^ 0x6f059759
    result = result - (data[0x1c] * 0x50484b)
    result = result + 0x84e222af
    result = result ^ (data[0x8] * 0x89d640)
    result = result + 0xfd21345b
    result = result - (data[0x18] * 0xe4b191)
    result = result + 0xfe15a789
    result = result ^ (data[0x0] * 0x8c58c1)
    result = result ^ 0x4c49099f
    result = result + (data[0xc] * 0xa13c4c)
    result = result ^ 0x27c5288e
    result = result + 0xff6724f5
    result &= 0xffffffffffffffff
    return result

def c26():
    result = data[0x1] * 0x73aaf0
    result = result ^ 0xa04e34f1
    result = result + (data[0x1d] * 0xf61e43)
    result = result + 0xd09b66f3
    result = result + (data[0x19] * 0x8cb5f0)
    result = result + 0xc11c9b4b
    result = result ^ (data[0x11] * 0x4f53a8)
    result = result + 0x9b9a98d2
    result = result + (data[0x9] * 0xb2e1fa)
    result = result ^ 0x77c07fd8
    result = result - (data[0x15] * 0xb8b7b3)
    result = result + 0x77d3eadf
    result = result + (data[0xd] * 0x13b807)
    result = result ^ 0x758dd142
    result = result ^ (data[0x5] * 0xdd40c4)
    result = result + 0xbb68781a
    result = result + 0x4fa227c4
    result &= 0xffffffffffffffff
    return result

def c27():
    result = data[0xe] * 0xca894b
    result = result + 0xa34fe406
    result = result + (data[0x12] * 0x11552b)
    result = result + 0x3764ecd4
    result = result ^ (data[0x16] * 0x7dc36b)
    result = result + 0xb45e777b
    result = result ^ (data[0x1a] * 0xcec5a6)
    result = result ^ 0x2d59bc15
    result = result + (data[0x1e] * 0xb6e30d)
    result = result ^ 0xfab9788c
    result = result ^ (data[0xa] * 0x859c14)
    result = result + 0x41868e54
    result = result + (data[0x6] * 0xd178d3)
    result = result + 0x958b0be3
    result = result ^ (data[0x2] * 0x61645c)
    result = result + 0x9dc814cf
    result = result + 0x847feabe
    result &= 0xffffffffffffffff
    return result

def c28():
    result = data[0x1b] * 0x7239e9
    result = result + 0x89f1a526
    result = result - (data[0x3] * 0xf1c3d1)
    result = result + 0x10d75f98
    result = result ^ (data[0xb] * 0x1b1367)
    result = result ^ 0x31e00d5a
    result = result ^ (data[0x13] * 0x8038b3)
    result = result + 0xb5163447
    result = result + (data[0x1f] * 0x65fac9)
    result = result + 0xe04a889a
    result = result - (data[0x17] * 0xd845ca)
    result = result + 0x5482e3a8
    result = result + (data[0xf] * 0xb2bbbc)
    result = result ^ 0x3a017b92
    result = result ^ (data[0x7] * 0x33c8bd)
    result = result + 0x540376e3
    result = result + 0x4f17f36d
    result &= 0xffffffffffffffff
    return result

def c29():
    result = data[0x0] * 0x53a4e0
    result = result + 0x9f9e7fc2
    result = result - (data[0x10] * 0x9bbfda)
    result = result + 0x69b383f1
    result = result - (data[0x18] * 0x6b38aa)
    result = result + 0x68ece860
    result = result + (data[0x14] * 0x5d266f)
    result = result + 0x5a4b0e60
    result = result - (data[0x8] * 0xedc3d3)
    result = result ^ 0x93e59af6
    result = result - (data[0x4] * 0xb1f16c)
    result = result ^ 0xe8d2b9a9
    result = result + (data[0xc] * 0x1c8e5b)
    result = result + 0x977c6d7d
    result = result + (data[0x1c] * 0x78f67b)
    result = result + 0xac22677
    result = result + 0xb154dea3
    result &= 0xffffffffffffffff
    return result

def c30():
    result = data[0x11] * 0x87184c
    result = result + 0x8d5ea528
    result = result ^ (data[0x19] * 0xf6372e)
    result = result + 0x16ad4f89
    result = result - (data[0x15] * 0xd7355c)
    result = result + 0x44df01cb
    result = result ^ (data[0x5] * 0x471dc1)
    result = result ^ 0x572c95f4
    result = result - (data[0x1] * 0x8c4d98)
    result = result + 0x6b9af38c
    result = result - (data[0xd] * 0x5ceea1)
    result = result ^ 0xf703dcc1
    result = result - (data[0x1d] * 0xeb0863)
    result = result + 0xad3bc09d
    result = result ^ (data[0x9] * 0xb6227f)
    result = result + 0xb95195e9
    result = result + 0xcea17ee8
    result &= 0xffffffffffffffff
    return result

def c31():
    result = data[0x1e] * 0x8c6412
    result = result ^ 0xc08c361c
    result = result ^ (data[0xe] * 0xb253c4)
    result = result + 0x21bb1147
    result = result + (data[0x2] * 0x8f0579)
    result = result + 0x596ee7a
    result = result - (data[0x16] * 0x7ac48a)
    result = result + 0xbb787dd5
    result = result + (data[0xa] * 0x2737e6)
    result = result ^ 0xa2bb7683
    result = result - (data[0x12] * 0x4363b9)
    result = result ^ 0x88c45378
    result = result ^ (data[0x6] * 0xb38449)
    result = result + 0xdf623f88
    result = result + (data[0x1a] * 0x6e1316)
    result = result + 0x1343dee9
    result = result + 0x1c966ad9
    result &= 0xffffffffffffffff
    return result

def c32():
    result = data[0x13] * 0x390b78
    result = result + 0x7d5deea4
    result = result - (data[0xf] * 0x70e6c8)
    result = result + 0x915cc61e
    result = result ^ (data[0x1b] * 0xd8a292)
    result = result + 0xd772913b
    result = result - (data[0x17] * 0x978c71)
    result = result + 0x1a27a128
    result = result + (data[0x1f] * 0x9a14d4)
    result = result + 0x49698f34
    result = result ^ (data[0x7] * 0x995144)
    result = result + 0x2d188cbe
    result = result ^ (data[0xb] * 0x811c39)
    result = result + 0xd22fca9b
    result = result ^ (data[0x3] * 0x9953d7)
    result = result ^ 0x80877669
    result = result + 0x6bddb88
    result &= 0xffffffffffffffff
    return result


data = [BitVec(f'data{i}', 8) for i in range(32)]

s = Solver()


s.add(c1() == 0)
s.add(c2() == 0)
s.add(c4() == 0)
s.add(c3() == 0)
s.add(c5() == 0)
s.add(c6() == 0)
s.add(c7() == 0)
s.add(c8() == 0)
s.add(c9() == 0)
s.add(c10() == 0)
s.add(c11() == 0)
s.add(c12() == 0)
s.add(c13() == 0)
s.add(c14() == 0)
s.add(c15() == 0)
s.add(c16() == 0)
s.add(c17() == 0)
s.add(c18() == 0)
s.add(c19() == 0)
s.add(c20() == 0)
s.add(c21() == 0)
s.add(c22() == 0)
s.add(c23() == 0)
s.add(c24() == 0)
s.add(c25() == 0)
s.add(c26() == 0)
s.add(c27() == 0)
s.add(c28() == 0)
s.add(c29() == 0)
s.add(c30() == 0)
s.add(c31() == 0)
s.add(c32() == 0)

def print_all_sat(solver):
    solutions = []
    while solver.check() == sat:
        model = solver.model()
        result = ''.join(chr(model[byte].as_long()) for byte in data)
        print("SAT Solution:")
        print(result)
        exclusion = Or([byte != model[byte] for byte in data])
        solver.add(exclusion)

print_all_sat(s)

```


Flag: `$$_4lway5_k3ep_mov1ng_and_m0ving@flare-on.com`






















