# Masochistic Sudoku (80 solves)
> Clam's tired of the ease and boredom of traditional sudoku. Having just one solution that can be determined via a simple online sudoku solver isn't good enough for him. So, he made masochistic sudoku! Since there are no hints, there are around 6*10^21 possible solutions but only one is actually accepted!>> Find it on the shell server at /problems/2020/masochistic_sudoku/.>> Author: aplet123
In this challenge we have to solve sudoku. But we don't know what numbers are present and the initial field looks like this:
```bash+---+---+---+---+---+---+---+---+---+|   |   |   |   |   |   |   |   |   |+---+---+---+---+---+---+---+---+---+|   |   |   |   |   |   |   |   |   |+---+---+---+---+---+---+---+---+---+|   |   |   |   |   |   |   |   |   |+---+---+---+---+---+---+---+---+---+|   |   |   |   |   |   |   |   |   |+---+---+---+---+---+---+---+---+---+|   |   |   |   |   |   |   |   |   |+---+---+---+---+---+---+---+---+---+|   |   |   |   |   |   |   |   |   |+---+---+---+---+---+---+---+---+---+|   |   |   |   |   |   |   |   |   |+---+---+---+---+---+---+---+---+---+|   |   |   |   |   |   |   |   |   |+---+---+---+---+---+---+---+---+---+|   |   |   |   |   |   |   |   |   |+---+---+---+---+---+---+---+---+---+```
If we fill the board with random numbers and hit **q**, the **check_flag** function will be called. The function checks few board positions for known values by calling **get_value** function with row_number, col_number and our entered number:
```c++int get_value(int row, int col, int number){  srand(13 * ((100 * row + 10 * col + number) ^ 0x2A) % 10067);  return rand();}```
The returned value is compared with hardcoded number like this:
```asm.text:000000000040124E                 push    rbp.text:000000000040124F                 mov     rbp, rsp.text:0000000000401252                 sub     rsp, 20h.text:0000000000401256                 mov     eax, cs:board.text:000000000040125C                 mov     edx, eax		; our value.text:000000000040125E                 mov     esi, 0		; col.text:0000000000401263                 mov     edi, 0		; row.text:0000000000401268                 call    get_value.text:000000000040126D                 cmp     eax, 68989C40h.text:0000000000401272                 setz    al.text:0000000000401275                 movzx   eax, al.text:0000000000401278                 mov     edi, eax.text:000000000040127A                 call    assert.text:000000000040127F ; ---------------------------------------------------------------------------.text:000000000040127F                 mov     eax, cs:dword_603170.text:0000000000401285                 mov     edx, eax		; our value.text:0000000000401287                 mov     esi, 4		; col.text:000000000040128C                 mov     edi, 0		; row.text:0000000000401291                 call    get_value.text:0000000000401296                 cmp     eax, 4ED659A2h.text:000000000040129B                 setz    al.text:000000000040129E                 movzx   eax, al.text:00000000004012A1                 mov     edi, eax.text:00000000004012A3                 call    assert.text:00000000004012A8 ; ---------------------------------------------------------------------------.text:00000000004012A8                 mov     eax, cs:dword_603178.text:00000000004012AE                 mov     edx, eax.text:00000000004012B0                 mov     esi, 6.text:00000000004012B5                 mov     edi, 0.text:00000000004012BA                 call    get_value.text:00000000004012BF                 cmp     eax, 7BB524E0h.text:00000000004012C4                 setz    al.text:00000000004012C7                 movzx   eax, al.text:00000000004012CA                 mov     edi, eax.text:00000000004012CC                 call    assert.text:00000000004012D1 ; ---------------------------------------------------------------------------.text:00000000004012D1                 mov     eax, cs:dword_60317C.text:00000000004012D7                 mov     edx, eax.text:00000000004012D9                 mov     esi, 7.text:00000000004012DE                 mov     edi, 0.text:00000000004012E3                 call    get_value.text:00000000004012E8                 cmp     eax, 72B33E08h.text:00000000004012ED                 setz    al.text:00000000004012F0                 movzx   eax, al.text:00000000004012F3                 mov     edi, eax.text:00000000004012F5                 call    assert.text:00000000004012FA ; ---------------------------------------------------------------------------.text:00000000004012FA                 mov     eax, cs:dword_60318C.text:0000000000401300                 mov     edx, eax.text:0000000000401302                 mov     esi, 2.text:0000000000401307                 mov     edi, 1.text:000000000040130C                 call    get_value.text:0000000000401311                 cmp     eax, 678DACB0h```
Solution:
First of all, our task is to find this hardcoded numbers. I wrote simple program that does that:
```c++#include <stdlib.h>#include <time.h>#include <stdio.h>#include <map>#include <list>#include <set>#include <iostream>#include <algorithm>
std::list<std::list<int>> mapping = {    {0, 0, 0x68989C40},    {0, 4, 0x4ED659A2},    {0, 6, 0x7BB524E0},      {0, 7, 0x72B33E08},    {1, 2, 0x678DACB0},    {1, 4, 0x16C64CB9},    {1, 5, 0x776ABFDB},    {1, 6, 0x49025844},    {2, 4, 0x2496CFE6},    {2, 5, 0x7F0845AE},    {2, 7, 0x6E9739BA},    {3, 0, 0x0C24786E},    {3, 2, 0x7F1F38C9},    {4, 0,  0x33AF080},    {4, 1, 0x20AFEC13},    {4, 7, 0x79A4CFE3},    {4, 8, 0x14CAF991},    {5, 6, 0x2A7CEA7F},    {5, 8, 0x0BDB3DFA},    {6, 1, 0x7732CF61},    {6, 3,  0x2D070EB},    {6, 4,  0x702A9DF},    {7, 2, 0x741DEDC1},    {7, 3, 0x1491F67C},    {7, 4, 0x7DF52E16},    {7, 6, 0x1A72C9C4},    {8, 1, 0x7F53CB83},    {8, 2, 0x551B572E},    {8, 4, 0x134A8092},    {8, 8, 0x56063756},};
int brute(int row, int col, int find_val) {    int c;    for (int i = 0; i < 0xffffffff; i++) {        srand(13 * ((100 * row + 10 * col + i) ^ 0x2A) % 10067);        c = rand();        if (c == find_val) {            printf("FOUND KEY at [%d, %d] == %d\n", row + 1, col + 1, i);            break;                        }    }}
int main() {    for (auto &elem : mapping) {        std::list<int>::iterator it = elem.begin();        auto v1 = *it;        std::advance(it, 1);        auto v2 = *it;        std::advance(it, 1);        auto v3 = *it;        brute(v1, v2, v3);    }
    return 0;}```
```bashFOUND KEY at [1, 1] == 1FOUND KEY at [1, 5] == 6FOUND KEY at [1, 7] == 8FOUND KEY at [1, 8] == 5FOUND KEY at [2, 3] == 5FOUND KEY at [2, 5] == 8FOUND KEY at [2, 6] == 3FOUND KEY at [2, 7] == 1FOUND KEY at [3, 5] == 1FOUND KEY at [3, 6] == 2FOUND KEY at [3, 8] == 9FOUND KEY at [4, 1] == 9FOUND KEY at [4, 3] == 7FOUND KEY at [5, 1] == 5FOUND KEY at [5, 2] == 3FOUND KEY at [5, 8] == 8FOUND KEY at [5, 9] == 9FOUND KEY at [6, 7] == 3FOUND KEY at [6, 9] == 5FOUND KEY at [7, 2] == 4FOUND KEY at [7, 4] == 6FOUND KEY at [7, 5] == 2FOUND KEY at [8, 3] == 6FOUND KEY at [8, 4] == 1FOUND KEY at [8, 5] == 9FOUND KEY at [8, 7] == 7FOUND KEY at [9, 2] == 2FOUND KEY at [9, 3] == 1FOUND KEY at [9, 5] == 3FOUND KEY at [9, 9] == 4```
After that we go to online sudoku solver, enter this values and hit solve.
We fill the board with right values and get the flag :)
Here is my board:
 ![board](images/board.png)
```actf{sud0ku_but_f0r_pe0ple_wh0_h4te_th3mselves}```
