Pickfordmatt / SharpLocker

610 stars 144 forks source link

Enhancements #2

Open keldnorman opened 4 years ago

keldnorman commented 4 years ago

sharplocker2

To get the current background image:

Image myimage = new Bitmap(@Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft\\Windows\\Themes\\TranscodedWallpaper"));

and to get the account picture:

RegistryKey AccountPictureReg = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\AccountPicture", true);
string AccountPictureFilename = AccountPictureReg.GetValue("SourceId").ToString();
AccountPictureReg.Close();

string AccountPicture = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft\\Windows\\AccountPictures\\" + AccountPictureFilename);

Console.WriteLine(" Value: " + AccountPicture);
3top1a commented 4 years ago

I made these changes & added username detection in my fork. Waiting for it to get merged. *I used a different account picture detection, yours doesn't account for the default picture.

Mezuse commented 4 years ago

hey just wondering where you would put this code? ^^^

amydevs commented 4 years ago

Would also be really cool if there were sign in options and support for multiple accounts to make it seem more believable, in the mean time I might try looking into ways to make this work.

cftad commented 4 years ago

Would also be really cool if there were sign in options and support for multiple accounts to make it seem more believable, in the mean time I might try looking into ways to make this work.

@jy1263 I agree, I'm looking to do just that in a WPF fork (to give more control over the styling). https://github.com/cftad/SharpLocker

CL0Pinette commented 4 years ago

There is one problem. the background image is not always the lockscreen image. I'm gonna try to replace the background image with the lockscreen image.

amydevs commented 4 years ago

@CL0Pinette been tryna figure that out but idk if thats possible without administrator privileges, because u can't access C:\ProgramData\Microsoft\Windows\SystemData\\ReadOnly\ without it.

msvamp commented 4 years ago

@CL0Pinette There is another idea. A fairly large number of users have the Windows Spotlight feature turned on, which displays Bing-provided images on the lock screen. You can randomly grab one from %LOCALAPPDATA%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets as it doesn't require admin rights. Try to pick one with size > 250 or 300KB (or better, check its resolution or aspect ratio) so as to avoid picking a Start Menu tile image. Also, I've noticed that Windows uses %WINDIR%\Web\Screen\img103.png as a fallback lock screen image when Spotlight is enabled but no Spotlight images have been downloaded yet, or if Spotlight is unavailable due to some reason.

I've also read that the registry keys OriginalFile_A or Creative\LandscapeAssetPath present in the location HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lock Screen\ contain the filesystem path to the current lock screen image in use, when Windows Spotlight is enabled. I've just enabled Spotlight on my PC and am yet to find out if it's true.

KrypticCoconut commented 4 years ago

Hello, keldnorman, where can i write that code for profile pin?

phanirithvij commented 4 years ago

@msvamp I think the originalfile_A that you mentioned is not related to the Windows spotlight. I believe it corresponds to the lock screen with Picture. image I changed it a few times and the binary data does contain some of the parts of the files I've selected.

Also HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SystemProtectedUserData\<Your SID>\AnyoneRead\LockScreen has (Default) as ZACEDB or some permutation which changes when you select a different picture where each letter represents an image and the permutation represents the order in which stuff is shown in the settings page. Also, it's read-only.

I'd like to know where you read about Originalfile_A and how I can decode the binary data to the original file path tho...

msvamp commented 4 years ago

@phanirithvij I frankly don't remember where I found it. I did look through my history and only found some help articles and support pages that mention clearing certain entries in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lock Screen can help reset lock screen settings (and the wallpaper) to default to help people resolve issues with their lockscreen. (Maybe I didn't look deep enough in the history)

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SystemProtectedUserData\<Your SID>\AnyoneRead\LockScreen has (Default)

This looks something interesting, though I have hardly found the (Default) value containing any important data.

where you read about Originalfile_A and how I can decode the binary data to the original file path tho...

I don't think Microsoft has disclosed anywhere about how the value is stored in the registry key, but I found a useful LockScreen class in the Windows Runtime API after I read this answer on SuperUser. This could be of some use to you -

[Windows.System.UserProfile.LockScreen,Windows.System.UserProfile,ContentType=WindowsRuntime]::OriginalImageFile.AbsolutePath

PowerShell Command Output

The problem with this path is: it is the path of the original file while applying a lockscreen image. So this value remains unchanged although the original image is deleted in the future.

phanirithvij commented 4 years ago

@msvamp Thanks for your quick reply. I did put together some go code which can get the spotlight lock screen wallpaper path exactly following this blog from winhelponline.

Not a C# dev (not a go dev either :) )

Expand code ```go package main import ( "encoding/hex" "errors" "io" "log" "os/user" "strings" "golang.org/x/sys/windows/registry" ) func main() { log.SetFlags(0) // log.SetFlags(log.LstdFlags | log.Lshortfile) d, err := getLockScreenPath() if err != nil { log.Fatal(err) } log.Println(d) // fmt.Println(d) } func getSysLockScreenConfig() { // sid, err := getUserSID() // if err != nil { // log.Fatal(err) // } data, err := hex.DecodeString("9a19a1622d473e54073d5bd08883f92a1852") if err != nil { log.Fatal(err) } log.Println(data) // S-1-5-21-1131672954-3644571216-278812857-1001\SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen ret := `SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen` // ret := sid + `\SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen` key, err := registry.OpenKey(registry.CURRENT_USER, ret, registry.READ) // key, err := registry.OpenKey(registry.USERS, ret, registry.READ) defer key.Close() if err != nil { log.Fatal(err) } subValues, err := key.ReadValueNames(100) for _, v := range subValues { _, b, err := key.GetValue(v, nil) if err != nil { log.Fatal(err) } if b == registry.SZ || b == registry.EXPAND_SZ { // data, _, _ := key.GetStringValue(v) // log.Println("string", data) } else if b == registry.BINARY { bin, _, _ := key.GetBinaryValue(v) log.Println(v, "binary", len(bin)) data := []byte{} for i := 0; i < len(bin); i++ { if bin[i] != 0 { data = append(data, bin[i]) } } log.Println(data, len(data)) // log.Println(string(data), len(data)) } else if b == registry.DWORD || b == registry.DWORD_BIG_ENDIAN { // data, _, _ := key.GetIntegerValue(v) // log.Println("integer", data) } else { // var buf []byte // buf = make([]byte, n) // n, b, err = key.GetValue(v, buf) // if err != nil { // log.Fatal(err) // } // log.Println("unknown type", buf) } // log.Println(key.GetStringValue()) } if (err != nil && err != io.EOF) || len(subValues) == 0 { log.Fatal(err) } } func getUserSID() (string, error) { uinstance, err := user.Current() if err != nil { return "", err } // https://pkg.go.dev/os/user#User // Uid is the Sid on windows return uinstance.Uid, err } // ErrNotSpotLight means currently windows spotlight is turned off var ErrNotSpotLight = errors.New("Not Windows spotlight") func getLockScreenRegKeySpotLight() (string, error) { // win.GetCurrentProcessId() sid, err := getUserSID() if err != nil { return "", err } ret := `SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Creative\` + sid key, err := registry.OpenKey(registry.LOCAL_MACHINE, ret, registry.READ) defer key.Close() if err != nil { log.Fatal(err) return "", err } windowsSpotlight, _, err := key.GetIntegerValue("RotatingLockScreenEnabled") if err != nil { return "", err } if windowsSpotlight == 1 { subKeys, err := key.ReadSubKeyNames(100) if (err != nil && err != io.EOF) || len(subKeys) == 0 { log.Println(err) log.Fatal(err, " Subkeys doesn't exist, possibly wrong place to look for lockscreen ", len(subKeys)) return "", err } return ret + `\` + subKeys[len(subKeys)-1], nil } return "", ErrNotSpotLight } func getLockScreenPath() (string, error) { sid, err := getUserSID() if err != nil { log.Fatal(err) } lockScreenRegKey, err := getLockScreenRegKeySpotLight() if err != nil { if err == ErrNotSpotLight { // not windows spotlight could be one of picture/slideshow log.Println("Not windows spotlight") ret := `SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen` key, err := registry.OpenKey(registry.CURRENT_USER, ret, registry.READ) slideshowEnabled, _, err := key.GetIntegerValue("SlideshowEnabled") if err != nil { log.Println(err) return "", nil } if slideshowEnabled == 1 { // check what registry changes // This is close to impossible as I have non lead log.Println("Slide show") ret = `SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen` key, err := registry.OpenKey(registry.CURRENT_USER, ret, registry.READ) spath, _, err := key.GetStringValue("SlideshowDirectoryPath1") if err != nil { if err == registry.ErrNotExist { log.Println("No slideshow directories selected by user") } else { log.Println(err) } } else { // TODO decode SlideshowDirectoryPath1 etc. log.Println("Slideshow path encoded", spath) } } else { // Picture // TODO decode OriginalFile_A // printing as a string shows some kind of pattern can try ret = `SOFTWARE\Microsoft\Windows\CurrentVersion\SystemProtectedUserData\` + sid + `\AnyoneRead\LockScreen` log.Println("Picture") key, err := registry.OpenKey(registry.LOCAL_MACHINE, ret, registry.READ) s, _, err := key.GetStringValue("") if err != nil { log.Println(err) } // In the order there can be Letters L in A-Z // And they keys OriginalFile_{L} may or may not exist // For eg. OriginalFile_Z does not exist log.Println("Order", strings.Split(s, "")) getSysLockScreenConfig() } return "", nil } log.Fatal(err) return "", err } // Spotlight log.Println("Spotlight") key, err := registry.OpenKey(registry.LOCAL_MACHINE, lockScreenRegKey, registry.READ) defer key.Close() if err != nil { log.Fatal(err) return "", err } p, _, err := key.GetStringValue("landscapeImage") if err != nil { return "", err } return p, nil } ```

Look at getLockScreenRegKeySpotLight and getLockScreenPath functions and ignore other stuff.

Also @jy1263 I was able to access C:\ProgramData\Microsoft\Windows\SystemData\<SID>\ReadOnly without admin privileges.

phanirithvij commented 4 years ago

@jy1263 a python snippet to list contents of the C:\ProgramData\Microsoft\Windows\SystemData\<SID>\ReadOnly dir, which runs for on my machine without needing of admin rights

from pathlib import Path
# pip install pywin32
import win32security
import os

def get_user_sid():
    desc = win32security.GetFileSecurity(
        ".", win32security.OWNER_SECURITY_INFORMATION
    )
    sid = desc.GetSecurityDescriptorOwner()

    # https://www.programcreek.com/python/example/71691/win32security.ConvertSidToStringSid
    sid = win32security.ConvertSidToStringSid(sid)
    return sid

sid = get_user_sid()
dirname = Path(
    f'C:\ProgramData\Microsoft\Windows\SystemData\{sid}\ReadOnly')
for root, dirs, files in os.walk(dirname, topdown=False):
    for name in files:
        print(os.path.join(root, name))
    for name in dirs:
        print(os.path.join(root, name))
phanirithvij commented 4 years ago

For anyone interested

Go code to read lockscreen state ```go package main import ( "encoding/hex" "errors" "io" "log" "os" "os/user" "strconv" "strings" "github.com/spf13/afero" "golang.org/x/sys/windows/registry" ) func main() { log.SetFlags(0) // log.SetFlags(log.LstdFlags | log.Lshortfile) d, err := getLockScreenPath() if err != nil { log.Fatal(err) } log.Println(d) // fmt.Println(d) } func getSysLockScreenConfig() { // sid, err := getUserSID() // if err != nil { // log.Fatal(err) // } data, err := hex.DecodeString("9a19a1622d473e54073d5bd08883f92a1852") if err != nil { log.Fatal(err) } log.Println(data) // S-1-5-21-1131672954-3644571216-278812857-1001\SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen ret := `SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen` // ret := sid + `\SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen` key, err := registry.OpenKey(registry.CURRENT_USER, ret, registry.READ) // key, err := registry.OpenKey(registry.USERS, ret, registry.READ) defer key.Close() if err != nil { log.Fatal(err) } subValues, err := key.ReadValueNames(100) for _, v := range subValues { _, b, err := key.GetValue(v, nil) if err != nil { log.Fatal(err) } if b == registry.SZ || b == registry.EXPAND_SZ { // data, _, _ := key.GetStringValue(v) // log.Println("string", data) } else if b == registry.BINARY { bin, _, _ := key.GetBinaryValue(v) log.Println(v, "binary", len(bin)) data := []byte{} for i := 0; i < len(bin); i++ { if bin[i] != 0 { data = append(data, bin[i]) } } // log.Println(data, len(data)) log.Println(string(data), len(data)) } else if b == registry.DWORD || b == registry.DWORD_BIG_ENDIAN { // data, _, _ := key.GetIntegerValue(v) // log.Println("integer", data) } else { // var buf []byte // buf = make([]byte, n) // n, b, err = key.GetValue(v, buf) // if err != nil { // log.Fatal(err) // } // log.Println("unknown type", buf) } // log.Println(key.GetStringValue()) } if (err != nil && err != io.EOF) || len(subValues) == 0 { log.Fatal(err) } } func getUserSID() (string, error) { uinstance, err := user.Current() if err != nil { return "", err } // https://pkg.go.dev/os/user#User // Uid is the Sid on windows return uinstance.Uid, err } // ErrNotSpotLight means currently windows spotlight is turned off var ErrNotSpotLight = errors.New("Not Windows spotlight") func getLockScreenRegKeySpotLight() (string, error) { // win.GetCurrentProcessId() sid, err := getUserSID() if err != nil { return "", err } ret := `SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Creative\` + sid key, err := registry.OpenKey(registry.LOCAL_MACHINE, ret, registry.READ) defer key.Close() if err != nil { log.Fatal(err) return "", err } windowsSpotlight, _, err := key.GetIntegerValue("RotatingLockScreenEnabled") if err != nil { return "", err } if windowsSpotlight == 1 { subKeys, err := key.ReadSubKeyNames(100) if (err != nil && err != io.EOF) || len(subKeys) == 0 { log.Println(err) log.Fatal(err, " Subkeys doesn't exist, possibly wrong place to look for lockscreen ", len(subKeys)) return "", err } return ret + `\` + subKeys[len(subKeys)-1], nil } return "", ErrNotSpotLight } func getLockScreenPath() (string, error) { sid, err := getUserSID() if err != nil { log.Fatal(err) } lockScreenRegKey, err := getLockScreenRegKeySpotLight() if err != nil { if err == ErrNotSpotLight { // not windows spotlight could be one of picture/slideshow log.Println("Not windows spotlight") ret := `SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen` key, err := registry.OpenKey(registry.CURRENT_USER, ret, registry.READ) slideshowEnabled, _, err := key.GetIntegerValue("SlideshowEnabled") if err != nil { log.Println(err) return "", nil } if slideshowEnabled == 1 { // check what registry changes // This is close to impossible as I have non lead log.Println("Slide show") ret = `SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen` key, err := registry.OpenKey(registry.CURRENT_USER, ret, registry.READ) spath, _, err := key.GetStringValue("SlideshowDirectoryPath1") if err != nil { if err == registry.ErrNotExist { log.Println("No slideshow directories selected by user") } else { log.Println(err) } } else { // TODO decode SlideshowDirectoryPath1 etc. log.Println("Slideshow path encoded", spath) log.Fatal("Slideshow not IMPLEMENTED") } } else { // Picture // TODO decode OriginalFile_A // printing as a string shows some kind of pattern can try ret = `SOFTWARE\Microsoft\Windows\CurrentVersion\SystemProtectedUserData\` + sid + `\AnyoneRead\LockScreen` log.Println("Picture") key, err := registry.OpenKey(registry.LOCAL_MACHINE, ret, registry.READ) s, _, err := key.GetStringValue("") if err != nil { log.Println(err) } // In the order there can be Letters L in A-Z // And they keys OriginalFile_{L} may or may not exist // For eg. OriginalFile_Z does not exist if len(s) == 0 { log.Fatal("No pictures selected by user") } log.Println("Order", s) var labelx byte = s[0] filename, err := getFakeLockScreenFilePath(labelx) if err != nil { if _, ok := err.(*os.PathError); ok { // labled file doesn't exist // might be one from C:\Windows\Web\Screen webScreenDir := `C:\Windows\Web\Screen` // eg. Z is C:\Windows\Web\Screen\img100.jpg // TODO Assuming Z -> 100, Y -> 101, X -> 102 etc. inum := 190 - labelx if inum >= 100 && inum <= 105 { str := strconv.FormatInt((int64)(inum), 10) filename = webScreenDir + `\img` + str + ".jpg" _, err := os.Stat(filename) if err != nil { // dirty trick? No. Windows is dirty // if jpg not found png filename = webScreenDir + `\img` + str + ".png" _, err := os.Stat(filename) if err != nil { return "", err } } return filename, nil } return "", errors.New("Couldn't get the image") } log.Fatal(err) } // getSysLockScreenConfig() // sysDataRecover() return filename, nil } return "", nil } log.Fatal(err) return "", err } // Spotlight log.Println("Spotlight") key, err := registry.OpenKey(registry.LOCAL_MACHINE, lockScreenRegKey, registry.READ) defer key.Close() if err != nil { log.Fatal(err) return "", err } p, _, err := key.GetStringValue("landscapeImage") if err != nil { return "", err } return p, nil } func sysDataRecover() { sid, err := getUserSID() if err != nil { log.Fatal(err) } systemData := `C:\ProgramData\Microsoft\Windows\SystemData\` + sid + `\ReadOnly` base := afero.NewOsFs() folder, err := base.Open(systemData) defer folder.Close() if err != nil { log.Fatal(err) } afero.Walk(base, folder.Name(), func(path string, info os.FileInfo, err error) error { if err != nil { log.Fatal(err) } // TODO file can be PNG with .jpg extension // Need to check file magic info or something if !info.IsDir() && strings.HasSuffix(info.Name(), "LockScreen.jpg") { log.Println(path, info.Size()) } return nil }) } func getFakeLockScreenFilePath(label byte) (string, error) { sid, err := getUserSID() if err != nil { return "", err } systemData := `C:\ProgramData\Microsoft\Windows\SystemData\` + sid + `\ReadOnly\LockScreen_` + string(label) + `\LockScreen.jpg` lockscrfile, err := os.Open(systemData) defer lockscrfile.Close() if err != nil { return "", err } return lockscrfile.Name(), nil } ```

go get -u -v github.com/spf13/afero golang.org/x/sys/windows/registry Then go run file.go or go build file.go && ./file