Skip to content

Instantly share code, notes, and snippets.

@stevefan1999-personal
Created June 24, 2018 07:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stevefan1999-personal/31623529fd5a1941ff1fd310e5c84a64 to your computer and use it in GitHub Desktop.
Save stevefan1999-personal/31623529fd5a1941ff1fd310e5c84a64 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
public class SigScanSharp
{
public byte[] Target { get; set; }
private bool PatternCheck(int nOffset, byte[] arrPattern)
{
for (int i = 0; i < arrPattern.Length; i++) {
if (arrPattern[i] == 0x0)
continue;
if (arrPattern[i] != this.Target[nOffset + i])
return false;
}
return true;
}
public ulong FindPattern(string szPattern, out long lTime)
{
Stopwatch stopwatch = Stopwatch.StartNew();
byte[] arrPattern = ParsePatternString(szPattern);
for (int nModuleIndex = 0; nModuleIndex < Target.Length; nModuleIndex++) {
if (this.Target[nModuleIndex] != arrPattern[0])
continue;
if (PatternCheck(nModuleIndex, arrPattern)) {
lTime = stopwatch.ElapsedMilliseconds;
return (ulong)nModuleIndex;
}
}
lTime = stopwatch.ElapsedMilliseconds;
return 0;
}
private byte[] ParsePatternString(string szPattern)
{
List<byte> patternbytes = new List<byte>();
foreach (var szByte in szPattern.Split(' '))
patternbytes.Add(szByte == "?" ? (byte)0x0 : Convert.ToByte(szByte, 16));
return patternbytes.ToArray();
}
}
class Program {
static bool IsElevated => WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
static void Main(string[] args) {
if (!IsElevated) {
Console.WriteLine("Error: this program requires administrator permission");
goto exit;
}
var streamServer = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
"NVIDIA Corporation",
"NvStreamSrv"
);
var streamBackup = Path.Combine(streamServer, "nvstreamer.bak.exe");
if (File.Exists(streamBackup)) {
Console.WriteLine("Error: nvstreamer is already patched");
goto exit;
}
var streamer = Path.Combine(streamServer, "nvstreamer.exe");
Console.WriteLine("Backing up nvstreamer.exe to nvstreamer.bak.exe");
try {
File.Copy(streamer, streamBackup);
Console.WriteLine("Backing up nvstreamer.exe success");
} catch {
Console.WriteLine("Unable to back up nvstreamer.exe");
goto exit;
}
Console.WriteLine("Patching nvstreamer.exe");
try {
Console.WriteLine("Loading nvstreamer.exe");
var streamerBytes = File.ReadAllBytes(streamer);
Console.WriteLine($"File size: {streamerBytes.Length}");
var scanner = new SigScanSharp() {
Target = streamerBytes
};
var pat = scanner.FindPattern("FF 15 ? ? ? ? EB 22 4C 8B 45 F0", out var time);
if (pat != 0) {
Console.WriteLine($"ScreenMonitor::Impl::IsFrameSkipped->ClipCursor found at {pat:X}, time taken {time} ms");
Console.WriteLine("Writing nops");
Parallel.For(0, 6, i => streamerBytes[pat + (uint)i] = 0x90);
var check = streamerBytes.Skip((int)pat).Take(10).ToArray();
Console.WriteLine($"Final bytes: {BitConverter.ToString(check).Replace("-", " ")}");
Console.WriteLine("Writing back to file");
try {
File.WriteAllBytes(streamer, streamerBytes);
Console.WriteLine("Success!");
} catch {
Console.WriteLine("File failed to write");
}
} else {
Console.WriteLine("ScreenMonitor::Impl::IsFrameSkipped->ClipCursor not found");
}
} catch {
Console.WriteLine("Unable to load nvstreamer.exe");
goto exit;
}
exit:
Console.WriteLine("Press enter to exit...");
Console.ReadLine();
}
}
@stevefan1999-personal
Copy link
Author

new signature: FF 15 ? ? ? ? 48 8D 4F 10

.text:00000001400C6906 48 8D 8D B0 01 00 00                                            lea     rcx, [rbp+410h+var_260]
.text:00000001400C690D FF 15 2D 69 3C 00                                               call    cs:ClipCursor
.text:00000001400C6913
.text:00000001400C6913                                                 loc_1400C6913:                          ; CODE XREF: sub_1400C6410+6C↑j
.text:00000001400C6913                                                                                         ; sub_1400C6410+4CE↑j
.text:00000001400C6913 48 8D 4F 10                                                     lea     rcx, [rdi+10h]

Try using this golang code I wrote:

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"path"
	"time"

	"rsc.io/binaryregexp"
)

type PatchUnitExecutableInfo struct {
	dirPath string
	name    string
}

type PatchUnit struct {
	regex      *binaryregexp.Regexp
	executable PatchUnitExecutableInfo
}

var nvStream = PatchUnit{
	binaryregexp.MustCompile("(\u00FF\u0015.{4})\u0048\u008D\u004F\u0010"),
	PatchUnitExecutableInfo{path.Join(os.Getenv("ProgramW6432"), "NVIDIA Corporation", "NvStreamSrv"), "nvstreamer.exe"},
}

func patchNvStream(nvStream PatchUnit) error {
	joinDirPath := func(name string) string {
		return path.Join(nvStream.executable.dirPath, name)
	}

	if fp, err := os.OpenFile(joinDirPath(nvStream.executable.name), os.O_RDWR, 0666); err != nil {
		return err
	} else {
		defer fp.Close()
		createBackup := func() error {
			t := time.Now()
			formatted := fmt.Sprintf("%d-%02d-%02dT%02d-%02d-%02d",
				t.Year(), t.Month(), t.Day(),
				t.Hour(), t.Minute(), t.Second())
			fp.Seek(0, io.SeekStart)
			if fpBackup, err := os.Create(joinDirPath(fmt.Sprintf("%s-%s.bak", nvStream.executable.name, formatted))); err != nil {
				return err
			} else {
				defer fpBackup.Close()
				_, err := io.Copy(fpBackup, fp)
				return err
			}
		}

		reader := bufio.NewReader(fp)
		i, err := fp.Seek(0, io.SeekCurrent)
		if err != nil {
			return err
		}
		strMatch := nvStream.regex.FindReaderSubmatchIndex(reader)
		if len(strMatch) <= 0 {
			return errors.New("can't find the signature")
		}
		fmt.Printf("[+] Found the signature from Nvidia Stream Server at 0x%X!\n", strMatch[2])
		if err := createBackup(); err != nil {
			return err
		}
		fmt.Println("[+] Backup of Nvidia Stream Server created!\n")
		if _, err = fp.Seek(i, io.SeekStart); err != nil {
			return err
		}
		if _, err = fp.WriteAt([]byte{0x90, 0x90, 0x90, 0x90, 0x90, 0x90}, int64(strMatch[2])); err != nil {
			return err
		}
		fmt.Printf("[+] Written NOPs to 0x%X!\n", strMatch[2])
	}
	return nil
}

func main() {
	if err := patchNvStream(nvStream); err != nil {
		panic(err)
	} else {
		fmt.Println("[+] Nvidia Stream Server is now patched to unlock screen!")
	}
}

@stevefan1999-personal
Copy link
Author

I have confirmed the clipping is unbounded after my patch by using moonlight to drag the touch control outside my main monitor and so it goes to the second

@RL-shuyi
Copy link

I have confirmed the clipping is unbounded after my patch by using moonlight to drag the touch control outside my main monitor and so it goes to the second
特別感謝您的辛勤付出,我受困于這個問題很長時間了,直到發現您的帖子,很難描述我的激動心情!請原諒我的無知,對於程序代碼一竅不通,斗膽請求您給與我一個能夠運行的程序,再次表達對您的敬意!!郵箱:liuxiaoke10@icloud.com 再次表達歉意,給您添麻煩

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment