I have a list of hexadecimal strings of REG_EXPAND_SZ type. Sample: reg,[HKEY_LOCAL_MACHINE\SOFTWAR\WOW6432Node], "Pathethic"=hex(2):43,00,3a,00,5c,00,57,00,49,00,4e,00,44,00,4f,00,57,00,53,00,\00,00 //Ignore the parsing and formatting part.
I need to convert it to the original string.
Expected output: %systemroot%
Actual output: C:\Windows
The problem is that when user initially run the command terminal expands it: reg add HKEY_LOCAL_MACHINE\SOFTWAR\WOW6432Node /v Pathetic /t REG_EXPAND_SZ /d "%systemroot%". Later the actual expanded string is used. For example: initial %systemroot% = actual C:\Windows. When I convert hex string to the regular one I get C:\Windows.
That is why I wonder if there any library or tool to get the key by providing value, meaning reverse. C:\Window :=os.Getenv(???).
package main
import (
"encoding/hex"
"fmt"
"log"
"os"
)
func CToGoString(b []byte) string {
var buf []byte
for _, c := range b {
if c != 0 {
buf = append(buf, c)
}
}
return string(buf)
}
func main() {
str := "43003a005c00570049004e0044004f00570053000000" //%systemroot%
bs, err := hex.DecodeString(str)
if err != nil {
panic(err)
}
//s := CToGoString(bs)
result := CToGoString(bs)
fmt.Println(result)
f, err := os.OpenFile("rollback.bat", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
log.Fatal(err)
}
f.WriteString(result + "\n")
}
I have tried doing it manually but there are more expanded strings than I expected. Therefore, my program is limited. Please advise any solutions for this problem. `
func reverseEnvVar(value string) string {
// Use os.ExpandEnv() to expand environment variables in the input string
expanded := os.ExpandEnv(value)
// Check if the expanded string matches a known environment variable value
switch expanded {
case os.Getenv("SystemRoot"):
return "%systemroot%"
case os.Getenv("ProgramFiles"):
return "%programfiles%"
case os.Getenv("ProgramFiles(x86)"):
return "%programfiles(x86)%"
case os.Getenv("AppData"):
return "%appdata%"
case os.Getenv("LocalAppData"):
return "%localappdata%"
case os.Getenv("UserProfile"):
return "%userprofile%"
case os.Getenv("TEMP"):
return "%temp%"
case os.Getenv("TMP"):
return "%tmp%"
default:
// If the expanded string doesn't match a known environment variable value,
// return the original input value
return value
}
}
I didn't find a library that takes C:\WINDOWS
and gives %systemroot%
but it can easily be implemented using os.Environ()
.
Imports:
import (
"errors"
"fmt"
"os"
"strings"
)
Hashmap for value -> array of keys:
func createEnvHashMap() map[string][]string {
envMap := make(map[string][]string)
for _, env := range os.Environ() {
pair := strings.SplitN(env, "=", 2)
if len(pair) == 2 {
key := fmt.Sprintf("%%%s%%", strings.ToLower(pair[0]))
value := pair[1]
envMap[value] = append(envMap[value], key)
}
}
return envMap
}
Function to return the list of keys given the value:
func getEnvKeysByValue(envMap map[string][]string, value string) ([]string, error) {
keys, found := envMap[value]
if !found {
return nil, errors.New("no environment variable keys found for the value")
}
return keys, nil
}
Now you can use the getEnvKeysByValue() function in you main function:
func main() {
// Create a map of environment variables and their keys
envMap := createEnvHashMap()
// This value can be replaced with the result variable in your main() function
value := "C:\\WINDOWS"
// Get environment variable keys by value
keys, err := getEnvKeysByValue(envMap, value)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Environment variable keys:")
for _, key := range keys {
fmt.Println(key)
}
}
Output:
Environment variable keys:
%systemroot%
%windir%
This way there won't be a need to write switch case statements manually.
Make sure to call createEnvHashMap()
only once and then call getEnvKeysByValue(envMap, value)
as many times to get list of keys in O(1) time.