Files
gtav-src/tools_ng/script/coding/protection/rpfEncryptionFinder/rpfEncryptionFinder.rb
T
2025-09-29 00:52:08 +02:00

283 lines
7.8 KiB
Ruby
Executable File

require 'getoptlong'
require 'csv'
# Setting up
RAGE_DIR = ENV['RAGE_DIR'].gsub(/\\/, "/")
RS_CODEBRANCH = ENV['RS_CODEBRANCH'].gsub(/\\/, "/")
RS_BUILDBRANCH = ENV['RS_BUILDBRANCH'].gsub(/\\/, "/")
RS_TOOLSROOT = ENV['RS_TOOLSROOT'].gsub(/\\/, "/")
RS_TITLE = ENV['RS_TITLE']
USER_PROFILE = ENV['USERPROFILE']
USER_DESKTOP = USER_PROFILE + "/Desktop"
USERNAME = ENV['USERNAME']
PROTECTION_PATH = RS_TOOLSROOT + "/script/coding/protection"
COMMON_RUBY_PATH = RS_TOOLSROOT + "/script/coding/protection/common/ruby"
TOOL_PATH = PROTECTION_PATH + "/rpfEncryptionFinder"
GENERATED_PATH = PROTECTION_PATH + "/generated"
CURR_TIME = Time.now.strftime("%Y%m%d.%H.%M.%S")
$LOAD_PATH << COMMON_RUBY_PATH
# Creating our logger
require 'RsgLog'
LOG_SEVERITY_LEVEL = Logger::INFO
log = RsgLog::RsgLog.instance()
log.SetParameters(GENERATED_PATH,CURR_TIME, LOG_SEVERITY_LEVEL)
# Alright, lets start the fun
# Do the work for our parameters
class Parameters
attr_reader :path
attr_reader :outdir
def initialize
@outdir = ""
@path = ""
@opts = GetoptLong.new(
[ '--path', '-p', GetoptLong::REQUIRED_ARGUMENT ],
[ '--outdir', '-o', GetoptLong::REQUIRED_ARGUMENT ]
)
end
def PrintHelp()
RsgLog::RsgLog.instance().info("DNE Yet");
end
def ParseArguments()
@opts.each do |opt, arg|
case opt
when '--help'
PrintHelp()
exit
when '--path'
@path = arg
when '--outdir'
@outdir = arg
end
end
end
end
# Define a class for our results
class RpfItem
attr_accessor :file
attr_accessor :directory
attr_accessor :resource
attr_accessor :keyid
attr_accessor :path
@@array = Array.new
@@files = Array.new
@@rpffiles = Array.new
@@resources = Array.new
@@directories = Array.new
def self.all_instances
@@array
end
def self.all_rpffiles
@@rpffiles
end
def self.all_files
@@files
end
def self.all_resources
@@resources
end
def self.all_directories
@@directories
end
def initialize(path="", file=false, directory=false, resource=false, keyid="N/A")
@file = file
@directory = directory
@resource = resource
if resource == true
@keyid = "N/A"
else
@keyid = keyid
end
@path = path
if file == true
@@files << self
elsif directory == true
@@directories << self
elsif resource == true
@@resources << self
end
if File.extname(path) == ".rpf"
@@rpffiles << self
end
@@array << self
end
def to_s
"\nPath:\t#{@path}\nIsFile:\t#{@file}\nIsDir:\t#{@directory}\nIsRes:\t#{@resource}\nKeyId:\t#{@keyid}"
end
def to_array
{"PATH"=> @path, "KEYID"=>@keyid, "IS_FILE"=>@file, "IS_DIRECTORY"=>@directory, "IS_RESOURCE"=>@resource, "IS_RPF"=>(File.extname(path)==".rpf")}
end
end
log.info("Starting the magic...")
log.info("Parsing arguments...")
parameters = Parameters.new
parameters.ParseArguments()
if parameters.path == "" || (File::file?(parameters.path) == 0 && File.directory?(parameters.path) ==0)
parameters.PrintHelp()
log.error("Invalid path [#{parameters.path}] specified")
exit
elsif parameters.outdir == "" || File.directory?(parameters.path) ==0
parameters.PrintHelp()
log.error("Invalid output path [#{parameters.outdir}] specified")
exit
end
# Set whether we're starting from a directory or a file
isInputDirectory = false
isInputFile = false
if File::file?(parameters.path)
log.info("Input parameter is a file.")
isInputFile = true
elsif File::directory?(parameters.path)
log.info("Input parameter is a directory.")
isInputDirectory = true
end
# Declare our input array
inputArray = Array.new
# Now lets build our input set of data
if isInputDirectory == true
# Apparently glob only works when the slashes are set correctly
unixDir = parameters.path.gsub(/\\/, "/")
# Iterate over the dir
Dir.glob("#{unixDir}/*.rpf").each do |f|
inputArray << f
end
else
inputArray << parameters.path
end
# First lets nuke the contents of the directoryu
FileUtils.rm_rf("#{parameters.outdir}")
# Now rebuild it
def IterateRpfs(rpfArray, subdir)
log = RsgLog::RsgLog.instance()
recursiveArray = Array.new
begin
Dir.mkdir(subdir)
rescue Exception =>e
puts e.message
end
# Good, now lets call our extraction script
rpfArray.each { |inputFile|
log.info(inputFile)
# This needs to be looped up
cmd = "#{RS_TOOLSROOT}/ironlib/lib/RSG.Pipeline.RpfExtract.exe --output \"#{subdir}\" --verbose \"#{inputFile}\""
# Capture the output
log.info("Extracting \[#{inputFile}\] to \[#{subdir}\]...")
log.info(cmd)
output = `#{cmd}`
log.info("Completed extraction...")
regexp = Regexp.new('.*\[KEY\]\[(.*)\]\[DIR\]\[(.*)\]\[FILE\]\[(.*)\]\[RES\]\[(.*)\].*Extracting: (.*)\.')
itemCollection = Array.new
output.each do |line|
matchData = regexp.match(line.strip)
if matchData == nil
#log.debug("No bueno RegExp for #{line}")
else
keyid = matchData[1]
dir = false
file = false
res = false
if matchData[2].downcase == "true"
dir = true
end
if matchData[3].downcase == "true"
file = true
end
if matchData[4].downcase == "true"
res = true
end
path = matchData[5]
log.info(line)
if File.extname(path) == ".rpf" && path!=inputFile
outPath = File.dirname(path)
outPath = outPath + "/" + File.basename(path, ".rpf")
IterateRpfs(path, outPath)
else
RpfItem.new(path, file, dir, res, keyid)
end
end
end
}
end
IterateRpfs(inputArray, parameters.outdir)
log.info("Found #{RpfItem.all_instances.length} items in this pass...")
# File Statistics
log.info("\t#{RpfItem.all_files.length} Files found")
numTransformIT = 0
RpfItem.all_files.each do |file|
if file.keyid == "0xFEFFFFF"
numTransformIT = numTransformIT+1
end
end
log.info("\t\t#{numTransformIT} TransformIT Encrypted")
# RPF File Statistics
log.info("\t\t#{RpfItem.all_rpffiles.length} RPF Files ")
numTransformIT = 0
RpfItem.all_rpffiles.each do |file|
if file.keyid == "0xFEFFFFF"
numTransformIT = numTransformIT+1
end
end
log.info("\t\t\t#{numTransformIT} TransformIT Encrypted")
# Directory Statistics
log.info("\t#{RpfItem.all_directories.length} Directories")
# Resource Statistics
log.info("\t#{RpfItem.all_resources.length} Resources")
# Now lets write out a CSV
writeArray = Array.new
RpfItem.all_instances.each do |file |
writeArray << file.to_array
end
if writeArray == nil || writeArray.first == nil
log.error("Something was wrong with the output of the rpfLog file. Exiting out.")
exit
end
writeArrayColumns = writeArray.first.keys
CSV.open("myfile.csv", "w") do |csv|
csv << writeArrayColumns
writeArray.each do |row|
csv << row.values
end
end