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}