From 2ca8624185dbcbd165e689bda3aa8ec69bcb6ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Thu, 7 Mar 2024 15:16:25 +0100 Subject: [PATCH] linux: Fix unreliable injection when libc is absent Such as early in the process lifetime, and in targets without an RTLD. The range chosen by our ProcessCodeSwapScope could happen to overlap with the program's ELF header, which we would subsequently parse and then carry on to fail in spectacular ways. So for the case when libc is absent, instead of attempting the full bootstrap right away, only perform mmap() and then return. Since we now allocate enough for both the bootstrapper and the loader, we can eliminate the second mmap() in the case when libc is already there. --- src/linux/frida-helper-backend.vala | 138 ++++++++++++-------- src/linux/helpers/bootstrapper-arm.bin | Bin 8320 -> 8344 bytes src/linux/helpers/bootstrapper-arm64.bin | Bin 7354 -> 7354 bytes src/linux/helpers/bootstrapper-mips.bin | Bin 10624 -> 10624 bytes src/linux/helpers/bootstrapper-mips64.bin | Bin 9792 -> 9856 bytes src/linux/helpers/bootstrapper-mips64el.bin | Bin 9792 -> 9792 bytes src/linux/helpers/bootstrapper-mipsel.bin | Bin 10624 -> 10624 bytes src/linux/helpers/bootstrapper-x86.bin | Bin 6598 -> 6612 bytes src/linux/helpers/bootstrapper-x86_64.bin | Bin 6657 -> 6669 bytes src/linux/helpers/bootstrapper.c | 33 +++-- src/linux/helpers/inject-context.h | 9 +- 11 files changed, 110 insertions(+), 70 deletions(-) diff --git a/src/linux/frida-helper-backend.vala b/src/linux/frida-helper-backend.vala index b83a4a906..d6b6dae4c 100644 --- a/src/linux/frida-helper-backend.vala +++ b/src/linux/frida-helper-backend.vala @@ -900,7 +900,7 @@ namespace Frida { LoaderLayout loader_layout = compute_loader_layout (spec, fallback_address); BootstrapResult bootstrap_result = yield bootstrap (loader_layout.size, cancellable); - var loader_base = (uint64) bootstrap_result.context.loader_base; + var loader_base = (uint64) bootstrap_result.context.allocation_base; try { unowned uint8[] loader_code = Frida.Data.HelperBackend.get_loader_bin_blob ().data; @@ -915,9 +915,9 @@ namespace Frida { loader_ctx.libc = (HelperLibcApi *) (loader_base + loader_layout.libc_api_offset); write_memory (loader_base + loader_layout.ctx_offset, (uint8[]) &loader_ctx); write_memory (loader_base + loader_layout.libc_api_offset, (uint8[]) &bootstrap_result.libc); - write_memory (loader_base + loader_layout.agent_entrypoint_offset, spec.entrypoint.data); - write_memory (loader_base + loader_layout.agent_data_offset, spec.data.data); - write_memory (loader_base + loader_layout.fallback_address_offset, fallback_address.data); + write_memory_string (loader_base + loader_layout.agent_entrypoint_offset, spec.entrypoint); + write_memory_string (loader_base + loader_layout.agent_data_offset, spec.data); + write_memory_string (loader_base + loader_layout.fallback_address_offset, fallback_address); return yield launch_loader (FROM_SCRATCH, spec, bootstrap_result, null, fallback_address, loader_layout, cancellable); @@ -940,7 +940,7 @@ namespace Frida { string fallback_address = make_fallback_address (); LoaderLayout loader_layout = compute_loader_layout (spec, fallback_address); - uint64 loader_base = (uint64) bootstrap_result.context.loader_base; + uint64 loader_base = (uint64) bootstrap_result.context.allocation_base; uint64 loader_ctrlfds_location = loader_base + loader_layout.ctx_offset; if (bootstrap_result.context.enable_ctrlfds) { @@ -1014,7 +1014,7 @@ namespace Frida { Future future_agent = establish_connection (launch, spec, bres, agent_ctrl, fallback_address, cancellable); - var loader_base = (uint64) bres.context.loader_base; + var loader_base = (uint64) bres.context.allocation_base; var call_builder = new RemoteCallBuilder (loader_base, saved_regs); call_builder.add_argument (loader_base + loader_layout.ctx_offset); @@ -1072,9 +1072,11 @@ namespace Frida { var result = new BootstrapResult (); unowned uint8[] bootstrapper_code = Frida.Data.HelperBackend.get_bootstrapper_bin_blob ().data; - uint64 bootstrapper_base = 0; size_t bootstrapper_size = round_size_to_page_size (bootstrapper_code.length); + uint64 allocation_base = 0; + size_t allocation_size = size_t.max (bootstrapper_size, loader_size); + uint64 remote_mmap = 0; uint64 remote_munmap = 0; ProcMapsEntry? remote_libc = ProcMapsEntry.find_by_path (pid, local_libc.path); @@ -1085,28 +1087,48 @@ namespace Frida { } if (remote_mmap != 0) { - bootstrapper_base = yield allocate_memory (remote_mmap, bootstrapper_size, + allocation_base = yield allocate_memory (remote_mmap, allocation_size, Posix.PROT_READ | Posix.PROT_WRITE | Posix.PROT_EXEC, cancellable); + } else { + var code_swap = yield new ProcessCodeSwapScope (this, bootstrapper_code, cancellable); + uint64 code_start = code_swap.code_start; + uint64 code_end = code_start + bootstrapper_size; + maybe_fixup_helper_code (code_start, bootstrapper_code); + + var call_builder = new RemoteCallBuilder (code_start, saved_regs); + + uint64 bootstrap_ctx_location; + call_builder.reserve_stack_space (sizeof (HelperBootstrapContext), out bootstrap_ctx_location); + + var bootstrap_ctx = HelperBootstrapContext (); + bootstrap_ctx.allocation_size = allocation_size; + write_memory (bootstrap_ctx_location, (uint8[]) &bootstrap_ctx); + + call_builder.add_argument (bootstrap_ctx_location); + + RemoteCall bootstrap_call = call_builder.build (this); + RemoteCallResult bootstrap_result = yield bootstrap_call.execute (cancellable); + var status = (HelperBootstrapStatus) bootstrap_result.return_value; + if (bootstrap_result.status != COMPLETED || status != ALLOCATION_SUCCESS) + throw_bootstrap_error (bootstrap_result, status, code_start, code_end); + + uint8[] output_context = read_memory (bootstrap_ctx_location, sizeof (HelperBootstrapContext)); + Memory.copy (&bootstrap_ctx, output_context, output_context.length); + + allocation_base = (uint64) bootstrap_ctx.allocation_base; + + code_swap.revert (); } try { - if (bootstrapper_base != 0) - write_memory (bootstrapper_base, bootstrapper_code); + write_memory (allocation_base, bootstrapper_code); + maybe_fixup_helper_code (allocation_base, bootstrapper_code); HelperBootstrapStatus status = SUCCESS; do { - uint64 code_start; - ProcessCodeSwapScope? code_swap = null; - if (bootstrapper_base != 0) { - code_start = bootstrapper_base; - } else { - code_swap = yield new ProcessCodeSwapScope (this, bootstrapper_code, cancellable); - code_start = code_swap.code_start; - } + uint64 code_start = allocation_base; uint64 code_end = code_start + bootstrapper_size; - maybe_fixup_helper_code (code_start, bootstrapper_code); - var call_builder = new RemoteCallBuilder (code_start, saved_regs); unowned uint8[] fallback_ld_data = fallback_ld.data; @@ -1120,10 +1142,11 @@ namespace Frida { .reserve_stack_space (fallback_libc_data.length + 1, out fallback_libc_location); var bootstrap_ctx = HelperBootstrapContext (); + bootstrap_ctx.allocation_base = (void *) allocation_base; + bootstrap_ctx.allocation_size = allocation_size; bootstrap_ctx.page_size = Gum.query_page_size (); bootstrap_ctx.fallback_ld = (string *) fallback_ld_location; bootstrap_ctx.fallback_libc = (string *) fallback_libc_location; - bootstrap_ctx.loader_size = loader_size; bootstrap_ctx.enable_ctrlfds = PidFileDescriptor.getfd_is_supported (); bootstrap_ctx.libc = (HelperLibcApi *) libc_api_location; write_memory (bootstrap_ctx_location, (uint8[]) &bootstrap_ctx); @@ -1144,26 +1167,8 @@ namespace Frida { status = (HelperBootstrapStatus) bootstrap_result.return_value; } - if (!(bootstrap_result.status == COMPLETED && (status == SUCCESS || status == TOO_EARLY))) { - if (bootstrap_result.status == COMPLETED) { - throw new Error.NOT_SUPPORTED ("Bootstrapper failed due to '%s'; " + - "please file a bug", - Marshal.enum_to_nick (status)); - } else { - uint64 pc = bootstrap_result.regs.program_counter; - if (pc >= code_start && pc < code_end) { - throw new Error.NOT_SUPPORTED ( - "Bootstrapper crashed with signal %d at offset 0x%x; please file a bug\n%s", - bootstrap_result.stop_signal, - (uint) (pc - code_start), - bootstrap_result.regs.to_string ()); - } else { - throw new Error.NOT_SUPPORTED ("Bootstrapper crashed with signal %d; please file a bug\n%s", - bootstrap_result.stop_signal, - bootstrap_result.regs.to_string ()); - } - } - } + if (!(bootstrap_result.status == COMPLETED && (status == SUCCESS || status == TOO_EARLY))) + throw_bootstrap_error (bootstrap_result, status, code_start, code_end); uint8[] output_context = read_memory (bootstrap_ctx_location, sizeof (HelperBootstrapContext)); Memory.copy (&result.context, output_context, output_context.length); @@ -1184,19 +1189,13 @@ namespace Frida { result.libc.dlerror = rebase_pointer ((uintptr) dlerror, local_android_ld, remote_ld); } - if (code_swap != null) - code_swap.revert (); - if (status == TOO_EARLY) yield resume_until_execution_reaches ((uint64) result.context.r_brk, cancellable); } while (status == TOO_EARLY); - - if (bootstrapper_base != 0) - yield deallocate_memory (remote_munmap, bootstrapper_base, bootstrapper_size, cancellable); } catch (GLib.Error e) { - if (bootstrapper_base != 0) { + if (remote_munmap != 0) { try { - yield deallocate_memory (remote_munmap, bootstrapper_base, bootstrapper_size, null); + yield deallocate_memory (remote_munmap, allocation_base, allocation_size, null); } catch (GLib.Error e) { } } @@ -1207,6 +1206,29 @@ namespace Frida { return result; } + [NoReturn] + private static void throw_bootstrap_error (RemoteCallResult bootstrap_result, HelperBootstrapStatus status, + uint64 code_start, uint64 code_end) throws Error { + if (bootstrap_result.status == COMPLETED) { + throw new Error.NOT_SUPPORTED ("Bootstrapper failed due to '%s'; " + + "please file a bug", + Marshal.enum_to_nick (status)); + } else { + uint64 pc = bootstrap_result.regs.program_counter; + if (pc >= code_start && pc < code_end) { + throw new Error.NOT_SUPPORTED ( + "Bootstrapper crashed with signal %d at offset 0x%x; please file a bug\n%s", + bootstrap_result.stop_signal, + (uint) (pc - code_start), + bootstrap_result.regs.to_string ()); + } else { + throw new Error.NOT_SUPPORTED ("Bootstrapper crashed with signal %d; please file a bug\n%s", + bootstrap_result.stop_signal, + bootstrap_result.regs.to_string ()); + } + } + } + private static void * rebase_pointer (uintptr local_ptr, ProcMapsEntry local_module, ProcMapsEntry remote_module) { var offset = local_ptr - local_module.base_address; return (void *) (remote_module.base_address + offset); @@ -1371,8 +1393,8 @@ namespace Frida { } public async void deallocate (BootstrapResult bres, Cancellable? cancellable) throws Error, IOError { - yield deallocate_memory ((uint64) bres.libc.munmap, (uint64) bres.context.loader_base, bres.context.loader_size, - cancellable); + yield deallocate_memory ((uint64) bres.libc.munmap, (uint64) bres.context.allocation_base, + bres.context.allocation_size, cancellable); } } @@ -1672,23 +1694,26 @@ namespace Frida { } protected enum HelperBootstrapStatus { + ALLOCATION_SUCCESS, + ALLOCATION_ERROR, + SUCCESS, AUXV_NOT_FOUND, TOO_EARLY, LIBC_LOAD_ERROR, LIBC_UNSUPPORTED, - MMAP_ERROR, } protected struct HelperBootstrapContext { + void * allocation_base; + size_t allocation_size; + size_t page_size; string * fallback_ld; string * fallback_libc; HelperRtldFlavor rtld_flavor; void * rtld_base; void * r_brk; - size_t loader_size; - void * loader_base; bool enable_ctrlfds; int ctrlfds[2]; HelperLibcApi * libc; @@ -2181,6 +2206,11 @@ namespace Frida { } } + public void write_memory_string (uint64 address, string str) throws Error { + unowned uint8[] data = str.data; + write_memory (address, data[:data.length + 1]); + } + private static ssize_t process_vm_readv_impl (uint pid, [CCode (array_length_type = "unsigned long")] Posix.iovector[] local_iov, diff --git a/src/linux/helpers/bootstrapper-arm.bin b/src/linux/helpers/bootstrapper-arm.bin index 363492f0334f28d3716810926efda658184b7bfe..1bbe33bf4d3fdb56d6217b60aa2a4508789909cb 100644 GIT binary patch delta 1095 zcmYLJONdif82-=Ay~)j((KBP3#A#-7=dlnCOkAiV-DIe*LZLyXKEOq^P!t5SXhn;4 z#%ds&qjxwJvT(=|s@NiJwL-fXA%b1CE(Di8?!zO4TJ54z7fSr@WW>eK|9*YvzjtP` zIq9bRiCj%o2`7kph*Vf~XNNZIu~idRdO=m?GpdD*cCOq;G+^2-opwY(xfc9qJ;u*^ z7YusJ=*VKsR>Y)fZn5GfRLqwnc`Dov*(BxPn*DK<RLh z=Lth`hlC!1pXfVp2Jw-eUm7isahjR#D$xojaYkASwXt0ueU}UDr zQz7pY+Q{P#nE;9^OhJ!3Dzw4NZQvdGxeBc+;6aRy7=n!<=XFVFv!ue9QXz9s2UEV# z70|@6(5v?eJq9_?gw8>4J3=>b1+S3vpDXmgu2`X;aiJGLk3gQ1Ct?{kFVDrst!R?- z@@A|sY*SNTS3(nd{NV|G1@aGVp$}XTI#t7SNoKCJ?4_&7$#rIS%kNmaT&@RgE`q9q z9kBd0*it~3rRqV_QU1@+IrMmMJ+OiPPtXnc`iDd?ft*WHnAz0jSWA~MTnq@vD`qkC z6%2b}=mIWu5`%8%^0}EAaUf0+5CN}%N0V;`FOdj#SB3txEZ0~A%#~ZL@ub(^y_+-g zTkGS#Z}6n;r90aJIWF&5qrJ;JodIfpk6wGjWs=2Dv5#auF4>=QRicnA_H`=^%E?4F z$(OV_xi9g-pcfidTsU3EFbz-+H7cRo>GUv8@~^}y){y@s3hcP-wLkm(0PInBM&;m3 z9BFchh~vYa$I1WQ3qD9Rv5aU8^cwae^gMjq28fO?haI#zOSBcA)-2w{%C!@&N(zm+LKiL+EdCH&)Q42;qMPm-5S;fe7ea$n#6lO9@w+oq=;FNZo_o&u z?sv~ScYF52Y^Ru?>U0c|(xkSYd3lM5?omS}j9Qw}^7stV#KVzYQw&7N)7MO0J z`WVq&)=;`8w^)^3m)G$9Mc!uPHGzzPgsBYAsDSs@v4JM5t z_xp!`ZUVkz)-rTx#r*@J1=>vS_j-5FW(NdwD0_6NP+oLOO9kFGoZ6-swv7W82cn1; z^uAqFC%Fa|j_T#ANNr`4ItNX=gc}OrC(yg zpHRI0g)q=0K;S^c40{r3>(*SZN=~x=On?&VixQ&mzZ14%rxLG7Y6!=fiaI zD`D!enVK*sfI)($F=5K^<3Qw08-MX(R~Y$S=E-tHm_N|fJE1VQVqtE=ZovMPNoHD> z-O6dAZL_C@`Jo}qH^8fiUg-++7N`p?VO|)v_1%7}1=|H=PT{ z2lMl#yzRX@_A%}h59e*c-cLTAJw7_t>rGJn8Aw+35xJDzU~kC%tYkOkJ0sQE=GcJY zq(_Ig*2Tzq7#2IXXn$HC#=m95IPc>9@Z<~23Ylf}uCfwiGvCs9gqXVShJAdi TF3AVg4)6TgTW4Sj{u|)`oRPG@ diff --git a/src/linux/helpers/bootstrapper-arm64.bin b/src/linux/helpers/bootstrapper-arm64.bin index cab66e195a5c027851a9a21907770f5939bce4f8..e276d5a699afc35772c297d24a52c9451db8e37f 100644 GIT binary patch delta 605 zcmX9*O=uHQ5T4n$*`I(7&99`i8;FE9(Aq<>R4Q%|Me$&oi{L@*MPfZEw%{!o(3Tu@ zed$qbP^8(5LN|x>AgKpY(Ssg5c-o}2q!tuHwLTQr*?M?^`(|c+YJKX#kqHe< z@kR&7Q$bvTQo)Nr^H$arUI@fOkT4C+HZyF`ljm7kKe4?(SA(<=SRpCF+!Kc z>}9KcF;isVobw;*6`e4JTE#=Cb{S*`0irIk%qo0A&4k^=<780+Q9+3M;!DUcV-}zB zB{c9VuVWf7@DG>>PY#fPVv2U!Y(AHu>L&S59GWc??T%rJuT<`mkKF-N%w?fj9AouG z0OuM&qeQ$j#IK=luSTGu0le7Xl&$$sxw^J7Z2e|v0k%%~{#V$e>Gwn*m%(yb)PBq7 zr91}tYpD}2Q$3}Dv(LcxN7(Ym2=bR~>{5V1^*GVAiPmLFTZ)wmK(!Q;tv1niSls^O ze`gBiQOXb7zYcQEs+FaWQeUaCN4ZYchRN>8jdAN8;q@RtBhU4(P`GxmxTuZcQel&C z$dmYx3we4p2u}Bu+0^=AqD5`@sm)&q^HDOz4qa++}+}L0(bE=*Ohy?%Pl1` zwEfphEYq=pgcpwyJ{`9@WEk+|=hhy7rJO(1^ZpA2VCHO(C)EsUJf|9=9?(Te*|f|nK%G$=wTXf6`#NkPHef>0|x z=<*|;l(u+C_N15yDTvXV-t-_SB1vi?Q4mX!vK9KBt%u?LH}KzkGqYA$D?Av@N)0?2 zfu@nQJQ)Hn283y7UIx1;C98F~=}Hqk$2Od@g}VHC(cY(0YqwXW8e=$=< zsNbWS!Qj#iVG8vnWKijG$cF%o6bbHtc!GI+Dc+%pw?rS)cu5Sh_;CCnDXEs%Nn6d= z^r<}}CRnm05GsAs@_taeM}|K~EN?ym&GHzlEdtc90yHereM|Z}2Hk1|8alwU?RCYu z`O&KBZ?eu`jt*e!gdcR7Kc4zZ@-YRRHaFbQqQTB06Dse<1ocxo)VDdfZ5n!ms>H-D zADfMGs7#Vfhh*D4;j*Y*3{x+~6{kb8T^@4>_P9#iAb!Br_qgt?++iQse!Hj;4^p%& z#m!wGcit0TV`4#>AM#f{N)z~raM&(x2@D*^RZ$2`4eWz@@08WlLvYL%ue5a1Uq_8b zKP+Xu&n&M`x5;hDMwQ;Z?_xEufM-Nby^HJOxf)4++m-Q$dCLQ`UYsC&I_`8SGT_Ni ztu4`2PY-U&{}ur_H@zt)wG4(uNi$!YtDivxG0&+85&=Y$Mtk diff --git a/src/linux/helpers/bootstrapper-mips.bin b/src/linux/helpers/bootstrapper-mips.bin index 1ee956e2119ee309cea78babf591c666fb2293fa..ad152cea4e76aaeb0df696b36aca840ba8e17fa1 100644 GIT binary patch delta 3120 zcmZ`*ZEO_B8GdJO?YrOu_TY@q`0LI$>pSBk9Ki~9b1jQ)T0^XG0wR!Ni7SxSYAnTV zswz^cd?iM@sAsQXP~<4Cdct<_59&3aq16#w0uoaFgQ_%&Dyq5>RZ+_ie$W;b>`EibCkBPQNR5W_1Tx{ zh<%AN_C@NoFVF$|Jnge*sV8XCddlVu!5zmgP|!Y2y7hi@cm6nO!t3LroV>C2(3ln| z_Y;MUnMNYfK`gO{m<8F~)a7nZvu>RP&nP9D_INY-Q{+3*6Jv!FKa8>WPK-Bf&+$Ui z5K}AWc;=P?Q9&^jdtgDuHFH$P7vcst)jAsz8fj|XI!$51r<=}Av4%V+7Hi7JL2z8w zvQ2?U?pB5zcg)gL*~@Bn{7cQ0?rMy+uPSH(&jxo*37n+3`q#5;BWz44eHE=zEY|M5 z2iXHnJ5~tK~dzVMY0vZ`v4yiLEnH3c;hb_;1rQbX)Pl*AT@vcu?~Vk$6n!7N+NUjK;-p*7mvErReN%tfeE z&yY?xm8~AaK`CWaa37VcJ>>#L8*5(=qstDuG!vA9tS8i|3mEZTC0D1Vt5B+3zU_%J zF2_AFBUg&0_7B8zemQ2QPEMIJV)za69{eR7?WoL_f15dW$N))h`xeTxmr?y4wD$o{G= zfw%vcK+aaRVDE0#epZmJp+Z7ATwfqhqVpjmu1D2~jOIdf95Ta(bq+~6i#TU>L*5Vl z;#raZo{P0tcgeBpgLOSkr;N0y@;aj4arnbzl;4g=N-5*yWpMqQk#l@bC4}=QMTPP2 zyfNnnSS1nUgyiJTG6z`r8t zz{(zAV;gXDpZziL^D=bjLEH0$c1WJ8C3=s>ELln%;OU)EW52z$cS4@O%s+JX}- z7;eEq7My3n0T!HsAhsfiNzVfLpwj_4UE44i79Eb0=s?g-TB{_JrxcQiof9w zLw*n`7gcwG{*Urj-Shk}i}G>Z%de}2U#m^!V;5cT;>K#ETZmPwB}*4g(_5jQ*i8zT zl5}Z6`B-?c587ZS%`1)7A=XVwm2zR}BoUAo`VD zct=`bQDbJVX_w$Gkmy$amzkJ*_05j$mHVtM-_%h?y$ zkbRzI?MZgPo@H-?zfTMN=WA}QOuGMD1s*%%)j@Qe%8y+Q z4)iy`cLxWzVf+m3uF4U}yqEuG9Q7Oz!>hjhj*@5LnRrSg&mgo;lPXGU%yOdql^+%KTa0$ksUFr@4=%tRZ2l3i$NC@_XLj{hUE z57FA|@se7~^KjgNynf{!)a&3Y>M?48Q5`sP6T;8H&3Lq`hbpoNkJP6^;h$oNO|h`6 z7-}`vZlu*Eqy=afncarbLMF?Ejo1_cz-b5MW(so3lu z+5{9J5VwKxKIuQ@*mx16Dw8sG=!}Qr)&%QUmgBz_>(60qv)%y!z{TS5iX7%CtXI!y z6qNI#X0sQwh8X}OTF*>9(F}nbus>5p`pjBLt)SYOAcgUt09R7_jE2qQ782P)B3mc~ f3(0IDnJpx delta 3085 zcmZWrZ)_CD6@Rn0=Rf$sd*=KXo7>}NedqcTE&`RaxQNZ!Bu--~R_qF^vBcH53JNqq zN)|Z{7o|AXLv&mZX;~VP^QXIPDyV+X ztFBC*ey(^L^sd{J6q6`OT^R*Ve1H?J=Di!U@G>sF#r|F*@lz%A>N29+?XJmvW+^WB z^k?Z0?%pFUog*hnHU8+Eu%;>IPtyjLziEsNlB)WZPk%Tc`yCQ_<#qN8v8J?pWrPWl z@U*fXG3ePI^5NW_b79ivwow4%1Y&+m+6GK|3uq~)hT>w_8)k>ZtT$quE`sj;H9)_$ z4z8(@^NutbIYd5;Pl|`$R`#jjC2z9NM7HGh=kBjtJ^zChw8o_coO@q>n?2O2kY)r1 z=mW9j*mGZou&%uX=|( zJVgwX6M55dq$1ZGXVjoNJ5K@lt?|+_g_lriq^)j7^{a0a=|-%5jRn%A%0uSj)ChYY z4)Ox}My=Z^m*dfGq+^YvMK#lb?wBFsrQz~Nk*h@-i@s9f_sNST&&A~`NaD_aSNfiZ z4T~ccLDnV4DvtZ_{YYgc(pJ$WxNkRG6=`29J1la(2x}Azz9}{&`ZfkxRt#-y$Liw7 zL+GQMGS%I#{YSv_+J{Q4;&@KT#jbW-m%( z7fNQ5mI?;+xssLTuqgp2vZ~+7xp(X$aY_HGZhDz$AnNiTbW}jcH7M;@Ox=(Q>Px6* z<`sk27HRC#_oAdPN%}HbPm2_GOi5ufhmBZjjk$Mgy%KW2jL7k5SN9xEW~OdHVZgdz{o<}fIJDv6P^_+LmJXzu`!s5@|5Gm zQl#L*Zk9Wfr(T(wqLxt7CC?N53$_zymD6)zOAqQN(!zLMO{EqfE;TX+1f^b1?W31 zQGAe^->d77+#tPJJ)e9a(c~ViLpRV)-$>sis@4rk78CpA6CxBltg9ydSuAedQJq$@ zNPkf>Dbrk&qP$Rp;h(?2s~tz_(ZcpucxX*%9V?#8Q*|>g5ib3&j(Lj7cSGC<{eDRr zmk8Jyd2pYbs(;fNaU{5f9TmCYuKGdOzpp4^eN8h6JTyBXF{OiIIk>O-OMU>6ebgBm z*+zt@7$SN}bn3m)5l)(t>gF`4%S9FDY5Ewi?a#C@mBx?J@opZ!M~b+qn}Jvd$S8ft zQb3-^Rgh5&?Rs(ih4&pNZ@O7LBdhf~Qhh)Q-2DEAvH}LcQfA>`C|fXc?NpZQC_W7K1$HEtBH!pY;MY7G8vPrUfev-{HI}odS+70C`eo6z zFSB8LfgQCkvftR}Sf71~W$gkxY)`VZ>VIU)oGNJ@)OqwGe}fqJuqD{4+>@aS49WnF z#(Rlj?8CnmFZYrs>3P=yxz~0ca2|678&1;<_cD@K4e|%j)u6i}=_wAszrWCVp_dx~;sV`vk&NqPG`ox^ttO4ng< z3+*=8vWoikot>$dAgT-nN*1; zkc%b}Akc{^d{Vp}ZpZ+&otSq@?!wXZ=yf9dJmb*qvOi}!0!RX76X$lIb>qC#XlF4V zjGRYnYeLC;^0A^L&j1K)?Uk>y%=swpx6Aa)02!~fWVtMNkpgW8M_S38$rz-4h#J}X zY~9m7Bwk*unG7k6v>DxzX{M`w>XcX5_z9WJgnXKYA!~;$ZE!}48AqyVk8}p}tSsJ` z?^e=st`PJRnD2t!ePpD>TFg-094IjQHMosGs~88c;K5hQV;Gm>8^^aC--LC%rE?B- zkRRA^+C?3If+0_0y?#!`e+#4;6wo76te2-E%aC!%Iw12xCkR^=t!s{`49z!Jv4I+) r6rHQ4o#RHZC1-)r7H)(ECR<>(1@>EDw}l&Ff!W1c&Bo@tjkx+>Q*4BR diff --git a/src/linux/helpers/bootstrapper-mips64.bin b/src/linux/helpers/bootstrapper-mips64.bin index 82719e32b64d2747d909cffe5463b61be4af62df..2314e142eabde5425eb306ea73fb138af5a627c0 100644 GIT binary patch delta 3956 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 N$gA8j<2=yZ{$JYtXRURt>3Z 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 F{{_)-h=%|G diff --git a/src/linux/helpers/bootstrapper-x86.bin b/src/linux/helpers/bootstrapper-x86.bin index d440d5ad03bdaa88f8f1e7194de5450a82ca489b..80b908f941d3edb17e533ff6f9f259d5e1da32d1 100644 GIT binary patch delta 1371 zcmYjRZ%kWN6u+;1v=1n@<8O6{{COy0W=UaYEHYC!o?Q%0fYG6GWHTm?4~tt!>o&7W z*=uEYH+KOpwlm?w{9v+ZG$@3%(~vhossjEYm>>{CvJv0bjmeg19NC`dw$u3K-1C0t zp5O1>bI*O#^$YbqKD^d(V843np#E72LRsBUAcU0>qDaL3ELO(AQ5#TTFWD!$G_1_3 zKN@ijA>>-VVufX*5{wa;^^v2pI2YeYxcLi@i1Wg4<@qPjdTIE9r(qAWx-+Bs_vR|5|rV<#X$X zf$!?ObGgt8@>|s4DhlLL?<~Fx3Hs%9`btEzhwp$iIVs{z;#-6goMf-43nDusoE7%7 zT+_kU<&FPTuK^zcNjSQv5O}c1Nqnogqm=lrM>PMIIJ5yp=I!Ail;YA-PL~#$59C8< z^wSQ6;#m;B@j8o}8mnA44TC7x^>c7iqG(Xb`SZLI?-*%qh|HhLQBScFbGh8w(ZQTCd7tJISD7-sL9%X_SG3y`JWR)dRK{yNZ4x@90R zlI|M5s3*&jza3zDT#k1^tzYsBNC-$muKBr8YFARx_)+i%7r5}^ZRq9_?_0mb8>)!` z8{WtuTc9O>DcUBm`eUiHaTBCb_J-)SJjjQ6yUNDJYQf7^#44eAFiRHNSvA;K*~?%L zvtwY7upzMBECKc%_8ZtU%xsZ`K2`%Z$-H1G>jpc_VwQU08k?~^C49nC7FY2%4|o?> z^)^_cBSp|r+CRbStj`oLJPH;4KQzaVSu2GCHfY^$xowB~K4;U`T49N8SSy5^tU#&| zHraDhg(>GDdqpZ0wz2>~^(+R~!xCT*v1Mtyb>uOGdXrtukzMLI@et-wfd)VU`83we z8nbIELmbS@fHIBs!zaJ(&HMjudw=x3>?eh?d>F*u=^vmJJV~RMc-E)T%CHtVL8D)= zt2rf)uLB70BK9{dUq6~Ke>07K#Wo=NeI|M&6XgRInfI5{=+CSockKC9xSihVVW<{{ z=6+US7mY4)jgQkBerx*SrMxuydxmB(qpj2EpUh#~CajM(+H%aoPUf*cUE2hg-#aM+ zCHyF`?_2DJ_qUQ%Rw2ot-WAGb?t!CPjM13=mU(9#j8O0NI!q$=%TC-Rm(tU+OvkHW zdxDSGy^rt=0hqXL5G~BOj?pUxHd93!mPor?sINiOATILPdI1JCy>A~|E86pBJABeZ zZaO3*@DhiC6k7EHNBcNJnq^0tV_O;uWgt##)14e@m%Csm3~izTa&-}~WLUlkK6qTo YNkheq7T1~%NGx7_RQO=Dy5vLCKb1&DfdBvi delta 1408 zcmY*Ze@q)y9Dhfz?G?%nVHA`qzYd(J(}rbpaVSh~7+p;OJ2ZjlA0*BMb(>cmi%pAd zGhZ%`44)};adBI=EHO+;y13$&c@Av%JBl;Xq?Lg*|HM)eMPGM-x=V?31L;2aL5kr?^P0ykX~(aXv%JgLu8k!ubP zIuM$#!d;q2!}1vMYN|X;4xIms(cfML`n~z!B#&WvQk5s78tF=lks9E{Q)*zCoC*GE z7!pQ%qdwwfQ76@afLolvgIfwz-wf_ptNN})HRZlU4v?7@xKp{u{L z{%HaWqw#(xUN8|^Z-QR`Eo;l*tVHJCfkpKSxXGPrk{DsCX&qa_y%k7tk=;^aC$#7+ zQ^5#_1mww#hddg6i+{tpry2d7Py|f=?kOsi^(_^-J?q~Xot(-edZ`nMqGk010XY@8$VRFSV z3UXkWHrO9_CGTAo|M%)!y3bz4S?OW>dfQbI57rs+dMC3l@R3YFz6 z%-gQtzruLMNC*lvwdXb?@~hm0MRwY+4O2G91#2OJM_ zK@mjXmz;v^@hFKMVqT|UBoWR3K8YQNBYb|J0e~-BM*1wY z5UzPP$rxzWd`1_Gw>GrHiM-ZGK9LaYMqUR>=w1Uu_cKJ@E)}Riq}Q2HC<_SyIrS2{ l+g0SU0F;VIN5B(yjJlMB1bWC-$GK?I)x-72>r0O2`~$3gYMTH6 diff --git a/src/linux/helpers/bootstrapper-x86_64.bin b/src/linux/helpers/bootstrapper-x86_64.bin index d9bbd352032457e4f85a219fe41e43c6ad20c5ad..63625083f8a37e006e038b8dfd6658b29495258f 100644 GIT binary patch delta 759 zcmX9+O-vI(6rOD@+n{yZ7!kZcaMWrf=_HU~l+cE*KEfVIN;Sr-KNt^aD0l!B()KV} zHqcBp#OTR`9#se_9AJ&c;?X81BBLYv1$+;t{|x&Gfov}Ub7XL=1I!0OoqbMZ*Ini=w-Z8ERD7IIL9F6_aBZzmNyLJYnQR!>t4 za$hXWpE@CnwOkFGftjJvl7c?u>ss!aH2AKwp%uPgWAg~Db^%|cZ?HmgTSd zCPe+v2r-j12Idfr^S&sc69t~?mH`0X7lXW=Ia)g44O!80vjKUHt$(-$vmsy6@-;LK z^KP?Yj<$)o|4isLmKb~&tYO7@zA)~eQG63&;SW6QeS+Qkc^N5@2!{r9G%N-1&W~a+ zcVC0!NC{Sk4z9$pZ$EzzyzJ~m#A@K!&94!RSj$Ah`L@A#oDchvDU29=Q?C9NBVaAk zIYh7AlN1O*^__W4$V-OKNtLa@>=DUQq_)Rar0d>LsjxWT@Vf!mAX}!OYD`%dY4xm< z7E|g#OAR>;UUSpK{rsc6&L#9vluq$WZCBca8a$a+OAQFFKFUtgSRivcI}s;P?n}D( zWp0$ZFt>)Ch+(CYtg@<*AkhNV0Wc?N)cajJmhb}QoTs;UdR%iz%miDS>y3o$?kDyn Q+gx?3gqx9t&0uTfKP`d$wg3PC delta 741 zcmX9+Pe@cj7@t{P_hH$tils>@GS(JEJESDW#xA?BX6XeRY7t&Mcv$FQ7V#?;y8xZVD_k{z$OW^+)gn2%!BVb{*bK0H}SF@z>RgChoD77 zGxZ21`6S5$(3z6Yanr$n2RvGX?>MIXh?{(&8o7yE@p)P8o5FYGwC`T;3-~plKOY8E zWe6cFNg~YZCNZ9BA0cY5{{>mpR+-#ya1HC0 zW>|wEIb3$C>I<|Oe3yv~c2;Lzl|9Dzf{gm_KX@NRD8-Aw7|aTonOW!J<16l53y|w{ zmAZuhcuooknJ`JZ5Q8wq-!Wcvj@2M^Ra}b|rXk0~EYX0#;9s3`D5S(3Qha>F;9Jgi zwU>G5HGEgA_y!p!I%mlf02gj6RzQFzrwA2VVxp>7ZC&^mY8A~Su|2v;vZ79_Rt{DC zs8Bb#{zmo%BKVJ-2%N?_IUl&v&;kP(eB15Gr1%H5txFIw(cUkcwHBO~39YrSGGDI1 zFTsqDl8E0t%dEi&Xjb|?)pUOi&i;Kb!R9;iut&t)rJ?lZ5VJ-}*n2N$)?kiemb`|^ z6e$D6!}6`x5N(9J-`y|lxvpzITE7d&_(%+~Vj>ByYaYqB17s1P$PisgT3WzJLqR{a JXSTGa>i;e?_v`=w diff --git a/src/linux/helpers/bootstrapper.c b/src/linux/helpers/bootstrapper.c index a19b00be6..5f579ae1e 100644 --- a/src/linux/helpers/bootstrapper.c +++ b/src/linux/helpers/bootstrapper.c @@ -155,6 +155,14 @@ frida_bootstrap (FridaBootstrapContext * ctx) FridaLibcApi * libc = ctx->libc; FridaProcessLayout process; + if (ctx->allocation_base == NULL) + { + ctx->allocation_base = mmap (NULL, ctx->allocation_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + return (ctx->allocation_base == MAP_FAILED) + ? FRIDA_BOOTSTRAP_ALLOCATION_ERROR + : FRIDA_BOOTSTRAP_ALLOCATION_SUCCESS; + } + if (!frida_probe_process (ctx->page_size, &process)) return FRIDA_BOOTSTRAP_AUXV_NOT_FOUND; @@ -174,10 +182,6 @@ frida_bootstrap (FridaBootstrapContext * ctx) if (!frida_resolve_libc_apis (&process, libc)) return FRIDA_BOOTSTRAP_LIBC_UNSUPPORTED; - ctx->loader_base = mmap (NULL, ctx->loader_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (ctx->loader_base == MAP_FAILED) - return FRIDA_BOOTSTRAP_MMAP_ERROR; - ctx->ctrlfds[0] = -1; ctx->ctrlfds[1] = -1; if (ctx->enable_ctrlfds) @@ -1109,28 +1113,31 @@ frida_prctl (int option, unsigned long arg2, unsigned long arg3, unsigned long a #ifdef BUILDING_TEST_PROGRAM +#include #include #include int main (void) { - FridaLibcApi libc; FridaBootstrapContext ctx; - size_t result; - - bzero (&libc, sizeof (libc)); + FridaBootstrapStatus status; + FridaLibcApi libc; bzero (&ctx, sizeof (ctx)); + ctx.allocation_size = 4096; + status = frida_bootstrap (&ctx); + assert (status == FRIDA_BOOTSTRAP_ALLOCATION_SUCCESS); + printf ("allocation_base: %p\n", ctx.allocation_base); + assert (ctx.allocation_base != NULL); + + bzero (&libc, sizeof (libc)); ctx.page_size = getpagesize (); - ctx.loader_size = 4096; ctx.enable_ctrlfds = true; ctx.libc = &libc; - result = frida_bootstrap (&ctx); - - printf ("result: %zu\n", result); - printf ("loader_base: %p\n", ctx.loader_base); + status = frida_bootstrap (&ctx); + printf ("status: %zu\n", status); return 0; } diff --git a/src/linux/helpers/inject-context.h b/src/linux/helpers/inject-context.h index 91b7f4899..8fa65c069 100644 --- a/src/linux/helpers/inject-context.h +++ b/src/linux/helpers/inject-context.h @@ -26,24 +26,27 @@ typedef int FridaRtldFlavor; enum _FridaBootstrapStatus { + FRIDA_BOOTSTRAP_ALLOCATION_SUCCESS, + FRIDA_BOOTSTRAP_ALLOCATION_ERROR, + FRIDA_BOOTSTRAP_SUCCESS, FRIDA_BOOTSTRAP_AUXV_NOT_FOUND, FRIDA_BOOTSTRAP_TOO_EARLY, FRIDA_BOOTSTRAP_LIBC_LOAD_ERROR, FRIDA_BOOTSTRAP_LIBC_UNSUPPORTED, - FRIDA_BOOTSTRAP_MMAP_ERROR, }; struct _FridaBootstrapContext { + void * allocation_base; + size_t allocation_size; + size_t page_size; const char * fallback_ld; const char * fallback_libc; FridaRtldFlavor rtld_flavor; void * rtld_base; void * r_brk; - size_t loader_size; - void * loader_base; int enable_ctrlfds; int ctrlfds[2]; FridaLibcApi * libc;