Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Injecting Clink from shim #437

Closed
ImportTaste opened this issue Feb 28, 2023 · 6 comments
Closed

Injecting Clink from shim #437

ImportTaste opened this issue Feb 28, 2023 · 6 comments
Labels
question Question about something working as intended The usage is working as intended

Comments

@ImportTaste
Copy link

I'm using this repo's shim implementation: https://github.com/kiennq/scoop-better-shimexe

My clink.shim file reads as thus:

path = C:\Clink\bin\clink_x64.exe
args = --profile "C:\Clink\usr"

When I try the command clink.exe inject (clink.exe being the shim), it spits out the following error:

514c inject                    612 ---- 2023/02/28 14:17:30.083 -------------------------------------------------
514c inject                    613 Injecting Clink...
514c inject_dll                269 Version: 1.4.20.236aba
514c inject_dll                270 Arch: x64
514c inject_dll                271 DLL: C:\Users\#\AppData\Local\Temp\clink\dll_cache\1.4.20.236aba_66976246\clink_dll_x64.dll
514c inject_dll                273 Parent pid: 21580
514c check_dll_version         168 DLL version: 00010004 00140000
514c inject_dll                315 Unknown host 'clink.exe'.
  • Note: I removed my username and changed it to a # symbol

Calling C:\Clink\bin\clink_x64.exe --profile "C:\Clink\usr" directly works correctly, however, so there's something about the way Clink is coded that makes it not work correctly when called from a shim.

I tried changing the path to C:\Clink\bin\clink.bat, but ran into two problems.

  1. Since the shim exe file is x86, the bat file tries to call clink_x86.exe instead of clink_x64.exe.
  2. Even if I compile an x64 version of the shim exe file, for some reason it strips the last directory from the path and gives me the error: '"C:\Clink\\clink_x64.exe"' is not recognized as an internal or external command, operable program or batch file.
    • This happens with the x86 shim as well, except the error includes clink_x86.exe instead.

Here are the shim files (clink.exe & clink.shim): clink_shim.zip

@chrisant996
Copy link
Owner

Clink has to know what process to inject into. If you don't specify one via --session then it uses the parent process. When cmd.exe runs clink inject, cmd.exe is the parent process, so Clink is able to automatically find the right cmd.exe process.

Since you're using an .exe shim, the shim is the parent process. But no process id was specified, and the Clink cannot inject into the shim process, so it fails. "Unknown host 'clink.exe'" means "clink.exe is not cmd.exe, so can't inject into clink.exe".

The reason it selects the clink_x86.exe is because the alternative exe shim is x86, and so the OS has automatically been dropped into x86 mode, and so the clink.bat file sees that the current OS mode is x86 and so it naturally accommodates that, since that's what the mode the user has selected externally.

Let's back up a few steps:

What was the motivation for trying to use scoop-better-shimexe?
What problem was encountered that is trying to be solved by making an exe shim?

Any attempt to use an exe shim for Clink will force the OS mode to use the same CPU emulation mode as the exe itself. E.g. on an ARM device, if the exe shim is x64, then the exe shim will force x64 mode even though the CPU is natively ARM64 and even if the original cmd.exe that invoked the shim was ARM64.

That's the whole reason Clink has its own clink.bat shim -- it is functionally necessary to have a batch script shim.

If you can share what problem was encountered, maybe there's a better way to solve the problem than creating an exe shim (which will inherently cause other problems).

@chrisant996 chrisant996 added question Question about something working as intended The usage is working as intended labels Feb 28, 2023
@ImportTaste
Copy link
Author

ImportTaste commented Feb 28, 2023

What was the motivation for trying to use scoop-better-shimexe?

Having my profile path automatically included in the arguments without having to edit the batch file.

@chrisant996
Copy link
Owner

If you want to always use a particular profile, have you considered setting %CLINK_PROFILE%? See docs for more info.

@ImportTaste
Copy link
Author

If you want to always use a particular profile, have you considered setting %CLINK_PROFILE%? See docs for more info.

I knew about it, but using a shim was more appealing to me. Oh well.

@chrisant996
Copy link
Owner

chrisant996 commented Mar 1, 2023

@ImportTaste You can still use a shim. Just not an exe shim. Or if you want to use an exe shim, then you need to make the shim find its parent process and pass that via --session parent_process_id.

Or you can simply make your own separate clink.bat file in a separate directory, and put that directory earlier in the %PATH% so that it gets used instead of Clink's own clink.bat file. Your separate script can be as simple as:

@c:\clink\bin\clink.bat --profile c:\clink\usr %*

I think there are several easy ways to get exactly the behavior you want, without using %CLINK_PROFILE%. But an exe shim isn't one of them. And also wouldn't be simple to write, because it takes extra coding to avoid interfering with the ability to actually inject. And also an exe shim can inherently interfere with the context and CPU type or emulation, which can in turn mess with registry access and file system access, because of how 64/32 virtualization works in Windows.

@ImportTaste
Copy link
Author

ImportTaste commented Aug 18, 2023

I forgot I never replied to this, but here is the launch script I ended up with. I think it's very neat and tidy, so hopefully it will be of help to someone else.

@ECHO OFF & SETLOCAL

::Config
SET "_clinkBin=CLINK EXE DIR WITHOUT QUOTES GOES HERE"
SET "_clinkUsr=PROFILE DIR WITHOUT QUOTES GOES HERE"

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

IF ["%*"]==[""]           SET "_clinkArg=inject"
IF ["%*"]==["--quiet"]    SET "_clinkArg=inject --quiet"
IF NOT DEFINED _clinkArg  SET "_clinkArg=%*"

SET "_clinkExe=%_clinkBin%\clink_x%PROCESSOR_ARCHITECTURE:~-2%.exe"

CALL:WIN+R_Test "%~f0"
IF %ERRORLEVEL% EQU 0 (
    ENDLOCAL ^
    & WMIC.exe PROCESS CALL CREATE ^
    "cmd.exe /K SET \"CLINK_PROFILE=%_clinkUsr%\" & \"%_clinkExe%\" %_clinkArg%" >NUL ^
    || PAUSE
) ELSE (
    ENDLOCAL ^
    & SET "CLINK_PROFILE=%_clinkUsr%" ^
    & "%_clinkExe%" %_clinkArg%"
)

EXIT /B 0


:WIN+R_Test
SETLOCAL
SET "_test=%CMDCMDLINE%"
<NUL SET /P="%_test:"=:%" ^
    | findstr.exe /B /C:"%COMSPEC% /c ::%~1%: " >NUL
ENDLOCAL & EXIT /B %ERRORLEVEL%

The Win+R part refers to the Run window that comes up from that Windows shortcut. If the batch file is on the PATH environment variable, or you insert the full path of the batch file, it'll create a new window that won't immediately close after launch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Question about something working as intended The usage is working as intended
Projects
None yet
Development

No branches or pull requests

2 participants