这个问题网络上的解决方案都是右键以管理员权限运行
我电脑之前都是可以用这个程序的,但是这些天就是一直报错,如下图:
很无奈,没遇到过这样的问题,网络上找了一遍,没有哪个答案能解决我这个问题的。
.net的程序,也就只有自己动手逆向了。
从上面的报错信息来看,应该是注册表没有访问权
三个比较关键的函数:opensubkey、update、reload
一个比较关键的位置:Shadowsocks.Program.Main
因为这程序是没有混淆的,所以可以直接上dnspy,跟一下报错的位置,看看到底是哪里的问题。
执行到Program._controller.Start();就报错了
跟进Program._controller.Start(); 发现了关键的函数:reload
在跟进reload这个函数看看
protected void Reload()
{
if (this._port_map_listener != null)
{
foreach (Listener current in this._port_map_listener)
{
current.Stop();
}
this._port_map_listener = null;
}
this._config = this.MergeGetConfiguration(this._config);
this._config.FlushPortMapCache();
this.ReloadIPRange();
HostMap hostMap = new HostMap();
hostMap.LoadHostFile();
HostMap.Instance().Clear(hostMap);
if (this.polipoRunner == null)
{
this.polipoRunner = new HttpProxyRunner();
}
if (this._pacServer == null)
{
this._pacServer = new PACServer();
this._pacServer.PACFileChanged += new EventHandler(this.pacServer_PACFileChanged);
}
this._pacServer.UpdateConfiguration(this._config);
if (this.gfwListUpdater == null)
{
this.gfwListUpdater = new GFWListUpdater();
this.gfwListUpdater.UpdateCompleted += new EventHandler<GFWListUpdater.ResultEventArgs>(this.pacServer_PACUpdateCompleted);
this.gfwListUpdater.Error += new ErrorEventHandler(this.pacServer_PACUpdateError);
}
bool flag = this.firstRun;
for (int i = 1; i <= 5; i++)
{
flag = false;
try
{
if (this._listener != null && !this._listener.isConfigChange(this._config))
{
Local value = new Local(this._config, this._transfer, this._rangeSet);
this._listener.GetServices()[0] = value;
if (this.polipoRunner.HasExited())
{
this.polipoRunner.Stop();
this.polipoRunner.Start(this._config);
this._listener.GetServices()[3] = new HttpPortForwarder(this.polipoRunner.RunningPort, this._config);
}
}
else
{
if (this._listener != null)
{
this._listener.Stop();
this._listener = null;
}
this.polipoRunner.Stop();
this.polipoRunner.Start(this._config);
Local item = new Local(this._config, this._transfer, this._rangeSet);
this._listener = new Listener(new List<Listener.Service>
{
item,
this._pacServer,
new APIServer(this, this._config),
new HttpPortForwarder(this.polipoRunner.RunningPort, this._config)
});
this._listener.Start(this._config, 0);
}
break;
}
catch (Exception ex)
{
if (ex is SocketException)
{
SocketException ex2 = (SocketException)ex;
if (ex2.SocketErrorCode == SocketError.AccessDenied)
{
ex = new Exception(I18N.GetString("Port already in use") + string.Format(" {0}", this._config.localPort), ex);
}
}
Logging.LogUsefulException(ex);
if (!flag)
{
this.ReportError(ex);
break;
}
Thread.Sleep(1000 * i * i);
if (this._listener != null)
{
this._listener.Stop();
this._listener = null;
}
}
}
this._port_map_listener = new List<Listener>();
foreach (KeyValuePair<int, PortMapConfigCache> current2 in this._config.GetPortMapCache())
{
try
{
Local item2 = new Local(this._config, this._transfer, this._rangeSet);
Listener listener = new Listener(new List<Listener.Service>
{
item2
});
listener.Start(this._config, current2.Key);
this._port_map_listener.Add(listener);
}
catch (Exception ex3)
{
if (ex3 is SocketException)
{
SocketException ex4 = (SocketException)ex3;
if (ex4.SocketErrorCode == SocketError.AccessDenied)
{
ex3 = new Exception(I18N.GetString("Port already in use") + string.Format(" {0}", current2.Key), ex3);
}
}
Logging.LogUsefulException(ex3);
this.ReportError(ex3);
}
}
EventHandler expr_429 = this.ConfigChanged;
if (expr_429 != null)
{
expr_429(this, new EventArgs());
}
this.UpdateSystemProxy(); //这句报错
Utils.ReleaseMemory();
}
发现报错的问题在this.UpdateSystemProxy(); 这句,再跟进一看,关键的函数:update出现了
跟进update函数看看,看到了打开注册表的函数,OpenUserRegKey 跟进去发现是报错的关键函数:OpenSubKey
public static RegistryKey OpenUserRegKey(string name, bool writable)
{
return RegistryKey.OpenRemoteBaseKey(RegistryHive.CurrentUser, "", Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32).OpenSubKey(name, writable);
}
到这里问题基本上就出现了,程序无权限打开注册表:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
我检查了下我电脑的注册表权限,发现是存在问题
这个程序需要修改注册表的这个位置,但注册表又只有读取权限,导致报错。
把这个完全控制打勾,确定就可以了。