In the Kitchen Wrist Twistin like it's Stir Fry

Table of Contents

Awwww another cute strfry challenge

Description

I love a little strfry

nc ctf.umbccd.io 5100

Problem

Given a number and string, strfry it to right string expected.

-----------------------------------------------------------------
                            Welcome!
  You will be presented with 30 flags of the form DogeCTF{flag}  
   You'll have to twist your wrist a little and scramble them
                   like Migos to get the flag!
          Before you go take this: 31234, you'll need it
-----------------------------------------------------------------



Unscrambled String: DogeCTF{D@nc3_w1th_mY_d0gs_1n_tH3_n1ghTt1m3}

Solution

Read strfry source:

/* Copyright (C) 1992-2019 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.
   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
char *
strfry (char *string)
{
  static int init;
  static struct random_data rdata;
  if (!init)
    {
      static char state[32];
      rdata.state = NULL;
      __initstate_r (time ((time_t *) NULL) ^ getpid (),
                     state, sizeof (state), &rdata);
      init = 1;
    }
  size_t len = strlen (string);
  if (len > 0)
    for (size_t i = 0; i < len - 1; ++i)
      {
        int32_t j;
        __random_r (&rdata, &j);
        j = j % (len - i) + i;
        char c = string[i];
        string[i] = string[j];
        string[j] = c;
      }
  return string;
}

Seems the random seed generation process uses PID and TIME.

Script:

strfry.c: Do strfry and interaction

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <time.h>
#include <errno.h>

// compiled under real Linux

#define PORT 5100

int msleep(long msec)
{
    struct timespec ts;
    int res;

    if (msec < 0)
    {
        errno = EINVAL;
        return -1;
    }

    ts.tv_sec = msec / 1000;
    ts.tv_nsec = (msec % 1000) * 1000000;

    do
    {
        res = nanosleep(&ts, &ts);
    } while (res && errno == EINTR);

    return res;
}

char *strfry(char *string, int key)
{
    static int init;
    static struct random_data rdata;

    if (!init)
    {
        static char state[32];
        initstate_r(time((time_t *)NULL) ^ key,
                    state, sizeof(state), &rdata);
        init = 1;
    }

    size_t len = strlen(string);
    if (len > 0)
        for (size_t i = 0; i < len - 1; ++i)
        {
            int j;
            random_r(&rdata, &j);
            j = j % (len - i) + i;

            char c = string[i];
            string[i] = string[j];
            string[j] = c;
        }

    return string;
}

void cut_string_from_index(char *origin, char *dest, int index)
{
    for (int i = 0;; i++)
    {
        char temp_char = origin[index + i];
        if (temp_char == '\n')
        {
            dest[i] = '\0';
            return;
        }
        dest[i] = temp_char;
    }
}

int main(int argc, char const *argv[])
{
    struct sockaddr_in address;
    int sock = 0, valread;
    struct sockaddr_in serv_addr;
    // char *hello = "Hello from client";
    char first_buffer[1024] = {0};
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("[-] Socket creation error");
        return -1;
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // Convert IPv4 and IPv6 addresses from text to binary form
    if (inet_pton(AF_INET, "35.245.160.192", &serv_addr.sin_addr) <= 0)
    {
        printf("[-] Invalid address/ Address not supported");
        return -1;
    }

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("[-] Connection Failed");
        return -1;
    }
    msleep(200);
    valread = read(sock, first_buffer, 1024);
    printf("%s", first_buffer);
    // 66 * 5 + 35
    printf("[*][PARSE KEY CHARS] %c%c%c%c%c\n", first_buffer[365], first_buffer[366], first_buffer[367], first_buffer[368], first_buffer[369]);
    int key = (first_buffer[365] - '0') * 10000 + (first_buffer[366] - '0') * 1000 + (first_buffer[367] - '0') * 100 + (first_buffer[368] - '0') * 10 + (first_buffer[369] - '0');
    printf("[*][PARSE KEY INT] %d\n", key);
    char query_buffer[200];
    // 66 * 7 + 4 + 20
    cut_string_from_index(first_buffer, query_buffer, 486);
    printf("[*][PARSE FIRST QUERY] %s\n", query_buffer);
    int length = strlen(query_buffer);
    char result[length + 1];
    strfry(query_buffer, key);
    strcpy(result, query_buffer);
    printf("%s\n", query_buffer);
    result[length] = '\n';
    if (send(sock, result, length + 1, 0) == -1)
    {
        printf("[-] Send failed.");
        return -1;
    }
    while (true)
    {
        char buffer[1024] = "";
        valread = read(sock, buffer, 1024);
        printf("%s", buffer);
        if (buffer[0] != 'U')
        {
            return 0;
        }
        cut_string_from_index(buffer, query_buffer, 20);
        printf("[*][PARSE QUERY] %s\n", query_buffer);
        int length = strlen(query_buffer);
        char result[length + 1];
        strfry(query_buffer, key);
        strcpy(result, query_buffer);
        printf("%s\n", query_buffer);
        result[length] = '\n';
        if (send(sock, result, length + 1, 0) == -1)
        {
            printf("[-] Send failed.");
            return -1;
        }
    }
    return 0;
}
gcc ./strfry.c -o netcat
./netcat

Result

➜  ~ ./netcat
-----------------------------------------------------------------
                            Welcome!
  You will be presented with 30 flags of the form DogeCTF{flag}  
   You'll have to twist your wrist a little and scramble them
                   like Migos to get the flag!
          Before you go take this: 31234, you'll need it
-----------------------------------------------------------------



Unscrambled String: DogeCTF{D@nc3_w1th_mY_d0gs_1n_tH3_n1ghTt1m3}
[*][PARSE KEY CHARS] 31234
[*][PARSE KEY INT] 31234
[*][PARSE FIRST QUERY] DogeCTF{D@nc3_w1th_mY_d0gs_1n_tH3_n1ghTt1m3}
gn0h3gnm{D_1_m3@}gsH1C1hn_T1ctdw_YetDF_tT_o3
Unscrambled String: DogeCTF{T@k3_1t_wH1p_1t_1nT3rm1$$10n}
[*][PARSE QUERY] DogeCTF{T@k3_1t_wH1p_1t_1nT3rm1$$10n}
0e3T{kC_1g1FD1n1T3_nwH_o1prm1$_t@}tT$
Unscrambled String: DogeCTF{l3t_th3_b1rd$_fLy}
[*][PARSE QUERY] DogeCTF{l3t_th3_b1rd$_fLy}
glLf_Frbey3tD3{}_htoC1T_d$
Unscrambled String: DogeCTF{th3y_tH1nK_w3_UsEd_@_ch34t_C0d3}
[*][PARSE QUERY] DogeCTF{th3y_tH1nK_w3_UsEd_@_ch34t_C0d3}
s}D30yhtc_3K_C@1Hweg_F{UhdE_T_t_433dotCn
Unscrambled String: DogeCTF{WhY_y0u_k33p_l00k1n_@t_m3}
[*][PARSE QUERY] DogeCTF{WhY_y0u_k33p_l00k1n_@t_m3}
e31y{_Wgl@3hkk_C3Dmu_poTY}00_n_Ft0
Unscrambled String: DogeCTF{R41nDr0p$_Dr0p_top$}
[*][PARSE QUERY] DogeCTF{R41nDr0p$_Dr0p_top$}
pTFCger}nt$opDpr1$0_oD4R{D0_
Unscrambled String: DogeCTF{b@D_anD_b0uj33}
[*][PARSE QUERY] DogeCTF{b@D_anD_b0uj33}
o0D3{bg3FC_Tbn_@jeD}uaD
Unscrambled String: DogeCTF{Im_r1D1n_4r0und_in_@_c0up3}
[*][PARSE QUERY] DogeCTF{Im_r1D1n_4r0und_in_@_c0up3}
_CT_c_rF_{}3n4r1mDgunpo1@nid0D_0eIu
Unscrambled String: DogeCTF{B1tch_1m_4_D0g_woof}
[*][PARSE QUERY] DogeCTF{B1tch_1m_4_D0g_woof}
wD_1oC}e1gfgD0_tcmhB{oT__oF4
Unscrambled String: DogeCTF{W3_D1D_th3_m0$t_Y3@h}
[*][PARSE QUERY] DogeCTF{W3_D1D_th3_m0$t_Y3@h}
h3__FgD{$_03_WteDhDoYtTCm1@3}
Unscrambled String: DogeCTF{D4bb1n_0n_3m_lik3_the_usu@l}
[*][PARSE QUERY] DogeCTF{D4bb1n_0n_3m_lik3_the_usu@l}
_e3{bb}u_glDnsmF0o3u__T4enCh_ki1ltD@
Unscrambled String: DogeCTF{1m_Y0ung_4nD_rich}
[*][PARSE QUERY] DogeCTF{1m_Y0ung_4nD_rich}
egrciYgDonFn_T_{14mhC0u}_D
Unscrambled String: DogeCTF{1n_th3_cr0ckpot}
[*][PARSE QUERY] DogeCTF{1n_th3_cr0ckpot}
eD{n3otr_Fgtc1}phC0oTc_k
Unscrambled String: DogeCTF{0ut3r_$pace_KiD_CuD1}
[*][PARSE QUERY] DogeCTF{0ut3r_$pace_KiD_CuD1}
r3uoe{_pKD}_gtiaC_D1F0ceDTCu$
Unscrambled String: DogeCTF{$4v@g3_ruthl3$s}
[*][PARSE QUERY] DogeCTF{$4v@g3_ruthl3$s}
$}orhv4F3$CDe{lt3T_sgug@
Unscrambled String: DogeCTF{4nD_Y0u_kn0w_w3_winn1n}
[*][PARSE QUERY] DogeCTF{4nD_Y0u_kn0w_w3_winn1n}
Cnei__g{Dw3Dn_Twkwu0Fnn0n14}_oY
Unscrambled String: DogeCTF{W3_c4m3_fr0m_n0th1n_to_$0methin}
[*][PARSE QUERY] DogeCTF{W3_c4m3_fr0m_n0th1n_to_$0methin}
og}0tmtW_m0_nt0c__enm_ohDC143Tfnri$3eFh{
Unscrambled String: DogeCTF{$3v3nt33n_f1v3_s@me_c0l0r_T-$hirt}
[*][PARSE QUERY] DogeCTF{$3v3nt33n_f1v3_s@me_c0l0r_T-$hirt}
Ts33T0$_3nivD_{3l-gFoc1feem@_vt3}$nhCr_tr0
Unscrambled String: DogeCTF{M@m4_t0lD_m3}
[*][PARSE QUERY] DogeCTF{M@m4_t0lD_m3}
0@4Fmo_T{3tmC_DeDlM}g
Unscrambled String: DogeCTF{real_fr0g_3ye$}
[*][PARSE QUERY] DogeCTF{real_fr0g_3ye$}
e{eeDrFrgy$_a3To_lCg}f0
Unscrambled String: DogeCTF{D1vin_0ff_th3_$t4g3}
[*][PARSE QUERY] DogeCTF{D1vin_0ff_th3_$t4g3}
3{e_n_t0}iD1fgCfo$3_htD4gFvT
Unscrambled String: DogeCTF{T@k3_mY_sh0e$_4nd_w@lk_4_m1l3}
[*][PARSE QUERY] DogeCTF{T@k3_mY_sh0e$_4nd_w@lk_4_m1l3}
e3mD4mh{_e_4ll_sd3@}kT@1Cwg_0noTF$k__Y
Unscrambled String: DogeCTF{W@lk_1t_lik3_1_t4lk_it}
[*][PARSE QUERY] DogeCTF{W@lk_1t_lik3_1_t4lk_it}
k_Ct_Dt_Flli@3oiTkteW4}kgl_{_11
Unscrambled String: DogeCTF{$@y_th4t_w3_b33n_be3f1ng_D0g}
[*][PARSE QUERY] DogeCTF{$@y_th4t_w3_b33n_be3f1ng_D0g}
ot0fCgb314h_tg_n@wF}Dn_3$3_eD3_yeb{gT
Unscrambled String: DogeCTF{Y0_Y3@h_d@t_w@y}
[*][PARSE QUERY] DogeCTF{Y0_Y3@h_d@t_w@y}
}e0hg_@_FdtYyCY@3{oT_D@w
Unscrambled String: DogeCTF{put_th4t_th1nG_in_sp0rt}
[*][PARSE QUERY] DogeCTF{put_th4t_th1nG_in_sp0rt}
0t_4Tp_hFtgr_utnpoteG}i_s1{hDtCn
Unscrambled String: DogeCTF{T4k3_th3_@1r_0ut_th3_b4ll}
[*][PARSE QUERY] DogeCTF{T4k3_th3_@1r_0ut_th3_b4ll}
b_1eut0C_3Tltl4}@trk_{__gho33hTD4F
Unscrambled String: DogeCTF{Th3_c0upe_c@m3_1mp0rteD}
[*][PARSE QUERY] DogeCTF{Th3_c0upe_c@m3_1mp0rteD}
tF_Tc{D_rpg3uoT0mc1h_mp03ee}C@eD
Unscrambled String: DogeCTF{It_g0t_fl4me$_oUt_th3_r34r$}
[*][PARSE QUERY] DogeCTF{It_g0t_fl4me$_oUt_th3_r34r$}
l}et3re3gto$_0I{oUDtm_F__4T4h$_tfrgC
Unscrambled String: DogeCTF{Wh3n_1_coulD_ju$t_h0p_1n_@_P0r$ch3}
[*][PARSE QUERY] DogeCTF{Wh3n_1_coulD_ju$t_h0p_1n_@_P0r$ch3}
}Dn_oh0un$@ucC_er3WhP_h3j_1T_{D1pc_$olgtF_0
Nice job! Here's your flag: DawgCTF{3th0s_p@th0s_l0g0s_m1g0s}
Nemo Xiong avatar
Nemo Xiong
ex-Cybersecurity Executor, now a student in Unimelb
comments powered by Disqus