本文主要介绍了一个c#编写的rar压缩文件密码恢复工具,该程序通过加载密码字典文件,逐个尝试密码来破解受密码保护的rar文件。
主要功能包括
1.选择rar文件和密码字典
2.显示恢复进度
3.统计尝试密码数量和速度
4.计算剩余时间
本工具采用后台线程运行密码破解过程,可以避免ui冻结,并提供取消操作功能。
效果图

程序代码
using system;
using system.collections.generic;
using system.componentmodel;
using system.diagnostics;
using system.drawing;
using system.io;
using system.linq;
using system.security.cryptography;
using system.windows.forms;
using sharpcompress.archives;
using sharpcompress.archives.rar;
using sharpcompress.common;
using sharpcompress.readers;
namespace rarpasswordrecovery
{
public partial class mainform : form
{
private backgroundworker worker;
private long totalpasswords;
private long testedpasswords;
private stopwatch stopwatch;
private list<string> passwordlist;
private bool passwordfound;
private string foundpassword;
private bool isrunning;
public mainform()
{
initializecomponent();
initializebackgroundworker();
setupui();
}
private void initializebackgroundworker()
{
worker = new backgroundworker
{
workerreportsprogress = true,
workersupportscancellation = true
};
worker.dowork += worker_dowork;
worker.progresschanged += worker_progresschanged;
worker.runworkercompleted += worker_runworkercompleted;
}
private void setupui()
{
// 设置窗体
this.text = "rar密码恢复工具";
this.size = new size(800, 500);
this.minimumsize = new size(600, 400);
this.backcolor = color.fromargb(45, 45, 65);
this.forecolor = color.white;
this.formborderstyle = formborderstyle.fixedsingle;
this.startposition = formstartposition.centerscreen;
// 创建控件
createcontrols();
}
private void createcontrols()
{
// 标题标签
label titlelabel = new label
{
text = "rar压缩文件密码恢复",
font = new font("segoe ui", 16, fontstyle.bold),
autosize = true,
location = new point(20, 15),
forecolor = color.lightskyblue
};
this.controls.add(titlelabel);
// rar文件选择
label lblrarfile = new label
{
text = "rar文件路径:",
location = new point(20, 60),
autosize = true
};
this.controls.add(lblrarfile);
textbox txtrarfilepath = new textbox
{
location = new point(120, 57),
size = new size(500, 25),
name = "txtrarfilepath",
readonly = true
};
this.controls.add(txtrarfilepath);
button btnbrowserar = new button
{
text = "浏览...",
location = new point(630, 55),
size = new size(80, 25),
name = "btnbrowserar",
backcolor = color.fromargb(70, 70, 90),
forecolor = color.white,
flatstyle = flatstyle.flat
};
btnbrowserar.flatappearance.bordersize = 0;
btnbrowserar.click += btnbrowserar_click;
this.controls.add(btnbrowserar);
// 字典文件选择
label lbldictionary = new label
{
text = "密码字典文件:",
location = new point(20, 100),
autosize = true
};
this.controls.add(lbldictionary);
textbox txtdictionarypath = new textbox
{
location = new point(120, 97),
size = new size(500, 25),
name = "txtdictionarypath",
readonly = true
};
this.controls.add(txtdictionarypath);
button btnbrowsedict = new button
{
text = "浏览...",
location = new point(630, 95),
size = new size(80, 25),
name = "btnbrowsedict",
backcolor = color.fromargb(70, 70, 90),
forecolor = color.white,
flatstyle = flatstyle.flat
};
btnbrowsedict.flatappearance.bordersize = 0;
btnbrowsedict.click += btnbrowsedict_click;
this.controls.add(btnbrowsedict);
// 进度条
progressbar progressbar = new progressbar
{
location = new point(20, 150),
size = new size(690, 25),
name = "progressbar",
style = progressbarstyle.continuous
};
this.controls.add(progressbar);
// 状态标签
label lblstatus = new label
{
location = new point(20, 185),
size = new size(690, 20),
name = "lblstatus",
text = "就绪",
textalign = contentalignment.middleleft
};
this.controls.add(lblstatus);
// 统计信息
label lbltotal = new label
{
location = new point(20, 215),
size = new size(200, 20),
name = "lbltotalpasswords",
text = "总密码数: 0"
};
this.controls.add(lbltotal);
label lbltested = new label
{
location = new point(230, 215),
size = new size(200, 20),
name = "lbltested",
text = "已尝试: 0"
};
this.controls.add(lbltested);
label lblspeed = new label
{
location = new point(440, 215),
size = new size(200, 20),
name = "lblspeed",
text = "速度: 0 p/s"
};
this.controls.add(lblspeed);
// 时间信息
label lblelapsed = new label
{
location = new point(20, 245),
size = new size(200, 20),
name = "lblelapsed",
text = "已用时间: 00:00:00"
};
this.controls.add(lblelapsed);
label lblremaining = new label
{
location = new point(230, 245),
size = new size(200, 20),
name = "lblremaining",
text = "剩余时间: --:--:--"
};
this.controls.add(lblremaining);
// 当前尝试密码
label lblcurrent = new label
{
text = "当前尝试密码:",
location = new point(20, 280),
autosize = true
};
this.controls.add(lblcurrent);
textbox txtcurrentpassword = new textbox
{
location = new point(120, 277),
size = new size(500, 25),
name = "txtcurrentpassword",
readonly = true,
font = new font("consolas", 10),
backcolor = color.fromargb(30, 30, 40),
forecolor = color.lightgreen
};
this.controls.add(txtcurrentpassword);
// 按钮
button btnstart = new button
{
text = "开始恢复",
location = new point(200, 320),
size = new size(120, 35),
name = "btnstart",
backcolor = color.seagreen,
flatstyle = flatstyle.flat,
font = new font("segoe ui", 10, fontstyle.bold)
};
btnstart.flatappearance.bordersize = 0;
btnstart.click += btnstart_click;
this.controls.add(btnstart);
button btncancel = new button
{
text = "取消",
location = new point(340, 320),
size = new size(120, 35),
name = "btncancel",
enabled = false,
backcolor = color.indianred,
flatstyle = flatstyle.flat,
font = new font("segoe ui", 10)
};
btncancel.flatappearance.bordersize = 0;
btncancel.click += btncancel_click;
this.controls.add(btncancel);
// 法律声明
linklabel linklegal = new linklabel
{
text = "使用条款和道德声明",
location = new point(20, 370),
autosize = true,
linkcolor = color.lightskyblue,
activelinkcolor = color.cyan
};
linklegal.linkclicked += linklegal_linkclicked;
this.controls.add(linklegal);
// 状态图标
picturebox statusicon = new picturebox
{
location = new point(650, 320),
size = new size(60, 60),
sizemode = pictureboxsizemode.zoom
};
// 注意:在实际项目中,您需要添加自己的图标
statusicon.backcolor = color.transparent;
this.controls.add(statusicon);
}
private void btnbrowserar_click(object sender, eventargs e)
{
using (openfiledialog openfiledialog = new openfiledialog())
{
openfiledialog.filter = "rar files (*.rar)|*.rar|all files (*.*)|*.*";
openfiledialog.title = "选择rar文件";
if (openfiledialog.showdialog() == dialogresult.ok)
{
gettextbox("txtrarfilepath").text = openfiledialog.filename;
}
}
}
private void btnbrowsedict_click(object sender, eventargs e)
{
using (openfiledialog openfiledialog = new openfiledialog())
{
openfiledialog.filter = "text files (*.txt)|*.txt|all files (*.*)|*.*";
openfiledialog.title = "选择密码字典文件";
if (openfiledialog.showdialog() == dialogresult.ok)
{
gettextbox("txtdictionarypath").text = openfiledialog.filename;
}
}
}
private void btnstart_click(object sender, eventargs e)
{
textbox txtrarfilepath = gettextbox("txtrarfilepath");
textbox txtdictionarypath = gettextbox("txtdictionarypath");
if (string.isnullorwhitespace(txtrarfilepath.text))
{
messagebox.show("请选择rar文件", "错误", messageboxbuttons.ok, messageboxicon.error);
return;
}
if (string.isnullorwhitespace(txtdictionarypath.text))
{
messagebox.show("请选择密码字典文件", "错误", messageboxbuttons.ok, messageboxicon.error);
return;
}
if (!file.exists(txtrarfilepath.text))
{
messagebox.show("选择的rar文件不存在", "错误", messageboxbuttons.ok, messageboxicon.error);
return;
}
if (!file.exists(txtdictionarypath.text))
{
messagebox.show("选择的字典文件不存在", "错误", messageboxbuttons.ok, messageboxicon.error);
return;
}
// 重置ui
passwordfound = false;
foundpassword = null;
testedpasswords = 0;
isrunning = true;
getprogressbar().value = 0;
getlabel("lblstatus").text = "加载密码字典...";
getlabel("lbltested").text = "已尝试: 0";
getlabel("lblspeed").text = "速度: 0 p/s";
getlabel("lblelapsed").text = "已用时间: 00:00:00";
getlabel("lblremaining").text = "剩余时间: --:--:--";
gettextbox("txtcurrentpassword").text = "";
getbutton("btnstart").enabled = false;
getbutton("btncancel").enabled = true;
try
{
// 读取字典文件
passwordlist = file.readalllines(txtdictionarypath.text)
.where(p => !string.isnullorwhitespace(p))
.distinct()
.tolist();
totalpasswords = passwordlist.count;
if (totalpasswords == 0)
{
messagebox.show("字典文件为空", "错误", messageboxbuttons.ok, messageboxicon.error);
resetui();
return;
}
getlabel("lbltotalpasswords").text = $"总密码数: {totalpasswords:n0}";
stopwatch = stopwatch.startnew();
worker.runworkerasync();
}
catch (exception ex)
{
messagebox.show($"读取字典文件错误: {ex.message}", "错误", messageboxbuttons.ok, messageboxicon.error);
resetui();
}
}
private void worker_dowork(object sender, doworkeventargs e)
{
backgroundworker worker = sender as backgroundworker;
passwordfound = false;
foundpassword = null;
string rarfilepath = gettextbox("txtrarfilepath").text;
try
{
// 尝试每个密码
for (int i = 0; i < passwordlist.count; i++)
{
if (worker.cancellationpending)
{
e.cancel = true;
return;
}
string password = passwordlist[i];
testedpasswords++;
try
{
// 修复:使用readeroptions传递密码
var options = new readeroptions
{
password = password,
lookforheader = true,
disablecheckincomplete = true
};
// 尝试打开压缩文件
using (var archive = rararchive.open(rarfilepath, options))
{
// 尝试访问第一个文件
var entry = archive.entries.firstordefault();
if (entry != null)
{
// 尝试读取少量数据
using (var stream = entry.openentrystream())
{
byte[] buffer = new byte[10];
stream.read(buffer, 0, buffer.length);
// 如果成功读取数据,密码正确
passwordfound = true;
foundpassword = password;
return;
}
}
}
}
catch (sharpcompress.common.cryptographicexception)
{
// 密码错误,继续尝试
}
catch (invalidformatexception)
{
// 密码错误或文件格式问题
}
catch (exception ex)
{
// 其他错误,记录并继续尝试
worker.reportprogress(0, $"密码 '{password}' 尝试失败: {ex.message}");
}
// 每100次尝试报告一次进度
if (testedpasswords % 100 == 0)
{
int progress = (int)((double)testedpasswords / totalpasswords * 100);
worker.reportprogress(progress, password);
}
}
}
catch (exception ex)
{
worker.reportprogress(0, $"错误: {ex.message}");
}
}
private void worker_progresschanged(object sender, progresschangedeventargs e)
{
if (e.userstate is string currentpassword)
{
gettextbox("txtcurrentpassword").text = currentpassword;
}
getprogressbar().value = e.progresspercentage;
getlabel("lbltested").text = $"已尝试: {testedpasswords:n0} / {totalpasswords:n0}";
// 计算速度
double seconds = stopwatch.elapsed.totalseconds;
double passwordspersecond = seconds > 0 ? testedpasswords / seconds : 0;
getlabel("lblspeed").text = $"速度: {passwordspersecond:n1} p/s";
// 计算剩余时间
if (passwordspersecond > 0)
{
long remaining = totalpasswords - testedpasswords;
timespan remainingtime = timespan.fromseconds(remaining / passwordspersecond);
getlabel("lblremaining").text = $"剩余时间: {remainingtime:hh\\:mm\\:ss}";
}
getlabel("lblelapsed").text = $"已用时间: {stopwatch.elapsed:hh\\:mm\\:ss}";
getlabel("lblstatus").text = "正在尝试恢复密码...";
}
private void worker_runworkercompleted(object sender, runworkercompletedeventargs e)
{
stopwatch.stop();
isrunning = false;
if (e.cancelled)
{
getlabel("lblstatus").text = "操作已取消";
}
else if (e.error != null)
{
getlabel("lblstatus").text = $"错误: {e.error.message}";
}
else if (passwordfound)
{
getlabel("lblstatus").text = "密码已找到!";
gettextbox("txtcurrentpassword").text = foundpassword;
gettextbox("txtcurrentpassword").forecolor = color.lime;
messagebox.show($"密码已找到: {foundpassword}", "成功",
messageboxbuttons.ok, messageboxicon.information);
}
else
{
getlabel("lblstatus").text = "在字典中未找到密码";
gettextbox("txtcurrentpassword").text = "未找到匹配的密码";
}
getbutton("btnstart").enabled = true;
getbutton("btncancel").enabled = false;
}
private void btncancel_click(object sender, eventargs e)
{
if (worker.isbusy)
{
worker.cancelasync();
getbutton("btncancel").enabled = false;
getlabel("lblstatus").text = "正在取消操作...";
}
}
private void linklegal_linkclicked(object sender, linklabellinkclickedeventargs e)
{
messagebox.show("本工具仅供教育目的使用\n\n" +
"仅限您合法拥有的文件使用\n\n" +
"未经授权访问他人文件是违法行为\n\n" +
"使用本工具即表示您同意承担所有责任",
"法律和道德声明",
messageboxbuttons.ok,
messageboxicon.information);
}
private void resetui()
{
getbutton("btnstart").enabled = true;
getbutton("btncancel").enabled = false;
}
// helper methods to get controls by name
private textbox gettextbox(string name) => this.controls.find(name, true).firstordefault() as textbox;
private label getlabel(string name) => this.controls.find(name, true).firstordefault() as label;
private button getbutton(string name) => this.controls.find(name, true).firstordefault() as button;
private progressbar getprogressbar() => this.controls.find("progressbar", true).firstordefault() as progressbar;
}
}以上就是基于c#实现rar文件密码破解工具的详细内容,更多关于c#破解rar文件密码的资料请关注代码网其它相关文章!
发表评论