GHIDRA, Playstation 1 рдирд┐рд╖реНрдкрд╛рджрдирдпреЛрдЧреНрдп, FLIRT рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдФрд░ PsyQ

рд╕рднреА рдХреЛ рдирдорд╕реНрдХрд╛рд░



рдореБрдЭреЗ рдЖрдкрдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рд╣рдореЗрд╢рд╛ рдкреБрд░рд╛рдиреЗ рдХрдВрд╕реЛрд▓ рдЧреЗрдо рдХреЛ рд░рд┐рд╡рд░реНрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рдЬрд┐рд╕рдореЗрдВ рд╕реНрдЯреЙрдХ рдореЗрдВ рдПрдХ рдбрд┐рдХрдВрдкрд╛рдЗрд▓рд░ рднреА рдерд╛ред рдФрд░ рдЕрдм, рдореЗрд░реЗ рдЬреАрд╡рди рдореЗрдВ рдпрд╣ рдЦреБрд╢реА рдХрд╛ рдХреНрд╖рдг рдЖрдпрд╛ рд╣реИ - GHIDRA рд╕рд╛рдордиреЗ рдЖрдпрд╛ рд╣реИред рдореИрдВрдиреЗ рдпрд╣ рдирд╣реАрдВ рд▓рд┐рдЦрд╛ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рд╣реИ, рдЖрдк рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдЧреВрдЧрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдФрд░, рд╕рдореАрдХреНрд╖рд╛рдПрдВ рдЗрддрдиреА рднрд┐рдиреНрди рд╣реИрдВ (рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдкреНрд░рддрд┐рдЧрд╛рдореА рд╕реЗ) рдХрд┐ рдЗрд╕ рдЪрдорддреНрдХрд╛рд░ рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд░рдирд╛ рдПрдХ рдирд╡рд╛рдЧрдВрддреБрдХ рдХреЗ рд▓рд┐рдП рднреА рдореБрд╢реНрдХрд┐рд▓ рд╣реЛрдЧрд╛ ... рдпрд╣рд╛рдВ рдЖрдкрдХреЗ рд▓рд┐рдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ: " рдореИрдВрдиреЗ 20 рд╡рд░реНрд╖реЛрдВ рддрдХ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛, рдФрд░ рдореИрдВ рдЖрдкрдХреЗ рд╣рд╛рдЗрдбреНрд░рд╛ рдХреЛ рдмрдбрд╝реЗ рдЕрд╡рд┐рд╢реНрд╡рд╛рд╕ рдХреЗ рд╕рд╛рде рджреЗрдЦрддрд╛ рд╣реВрдВ, рдХреНрдпреЛрдВрдХрд┐ рдПрдирдПрд╕рдПред рд▓реЗрдХрд┐рди рдЬрдм- рдореИрдВ рдЗрд╕реЗ рдЪрд▓рд╛рдКрдВрдЧрд╛ рдФрд░ рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рдЗрд╕рдХреА рдЬрд╛рдВрдЪ рдХрд░реВрдВрдЧрд╛ ред "


рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ - рд╣рд╛рдЗрдбреНрд░рд╛ рдХреЛ рдЪрд▓рд╛рдирд╛ рдбрд░рд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИред рдФрд░ рд▓реЙрдиреНрдЪ рдХреЗ рдмрд╛рдж рд╣рдореЗрдВ рдЬреЛ рднреА рдорд┐рд▓реЗрдЧрд╛, рд╡рд╣ рдЖрдкрдХреЗ рд╕рднреА рдбрд░ рдХреЛ рдмреБрдХрдорд╛рд░реНрдХ-рдФрд░-рдмреИрдХрд╕реНрдЯреЗрдб рд╕рд░реНрд╡рд╡реНрдпрд╛рдкреА рдПрдирдПрд╕рдП рд╕реЗ рд░реЛрдХ рджреЗрдЧрд╛ред


рддреЛ, рдореИрдВ рдХрд┐рд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВ ... рдРрд╕рд╛ рдПрдХ рдЙрдкрд╕рд░реНрдЧ рд╣реИ: рд╕реЛрдиреА рдкреНрд▓реЗрд╕реНрдЯреЗрд╢рди 1 ( рдкреАрдПрд╕ 1 , рдкреАрдПрд╕рдПрдХреНрд╕ , рдХрд░реНрд▓рд┐рдВрдЧ рдЖрдпрд░рди )ред рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрдИ рд╢рд╛рдВрдд рдЦреЗрд▓ рдмрдирд╛рдП рдЧрдП рдереЗ, рдлреНрд░реЗрдВрдЪрд╛рдЗрдЬрд┐рдпреЛрдВ рдХрд╛ рдПрдХ рдЭреБрдВрдб рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ рдЬреЛ рдЕрднреА рднреА рд▓реЛрдХрдкреНрд░рд┐рдп рд╣реИрдВред рдФрд░ рдПрдХ рджрд┐рди рдореИрдВ рдпрд╣ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рд╡реЗ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ: рдбреЗрдЯрд╛ рдкреНрд░рд╛рд░реВрдк рдХреНрдпрд╛ рд╣реИрдВ, рдХреНрдпрд╛ рд╕рдВрд╕рд╛рдзрди рд╕рдВрдкреАрдбрд╝рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреБрдЫ рд░реВрд╕реА рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ (рдореИрдВ рддреБрд░рдВрдд рдХрд╣реВрдВрдЧрд╛ рдХрд┐ рдореИрдВрдиреЗ рдЕрднреА рддрдХ рдХрд┐рд╕реА рднреА рдЧреЗрдо рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ)ред


рдореИрдВрдиреЗ Delphi рдкрд░ рдПрдХ рджреЛрд╕реНрдд рдХреЗ рд╕рд╛рде TIM рдкреНрд░рд╛рд░реВрдк рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╢рд╛рдВрдд рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд▓рд┐рдЦрдХрд░ рд╢реБрд░реВ рдХрд┐рдпрд╛ (рдпрд╣ рдкреНрд▓реЗрд╕реНрдЯреЗрд╢рди рд╡рд░реНрд▓реНрдб рд╕реЗ BMP рдЬреИрд╕рд╛ рдХреБрдЫ рд╣реИ): рдЯрд┐рдо 2 рд╡реНрдпреВ ред рдПрдХ рд╕рдордп рдореЗрдВ, рд╕рдлрд▓рддрд╛ рдХрд╛ рдЖрдирдВрдж рд▓рд┐рдпрд╛ (рдФрд░ рд╢рд╛рдпрдж рдЕрдм рдЖрдирдВрдж рдорд┐рд▓рддрд╛ рд╣реИ)ред рддрдм рдореИрдВ рдЧрд╣рд░рд╛рдИ рдореЗрдВ рдЬрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред


рдЫрд╡рд┐


рдФрд░ рдлрд┐рд░ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╢реБрд░реВ рд╣реБрдИрдВред рдореИрдВ рддрдм MIPS рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рдерд╛ред рдкрдврд╝рд╛рдИ рдореЗрдВ рд▓рдЧ рдЧрдПред рдореИрдВ рдпрд╛ рддреЛ IDA Pro рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рдерд╛ (рдореИрдВ Playstation рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╛рдж рдореЗрдВ Sega Mega Drive рдкрд░ рдЧреЗрдо рдХреЛ рд░рд┐рд╡рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдпрд╛ рдерд╛)ред рд▓реЗрдХрд┐рди, рдЗрдВрдЯрд░рдиреЗрдЯ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдореБрдЭреЗ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ IDA Pro PS1 рдбрд╛рдЙрдирд▓реЛрдб рдФрд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ: PS-X EXE рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдлрд╛рдЗрд▓реЗрдВ ред рдореИрдВрдиреЗ рдПрдХ рдЕрдЬреАрдм рдирд╛рдо рдФрд░ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд╕рд╛рде рдПрдХ рдЧреЗрдо рдлрд╝рд╛рдЗрд▓ (рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╡реЗ Lemmings рдереЗ) рдХреЛ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рдЬреИрд╕реЗ рдХрд┐ Ida рдореЗрдВ SLUS_123.45 , рдореБрдЭреЗ рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЛрдб рдХреА рд▓рд╛рдЗрдиреЛрдВ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдорд┐рд▓рд╛ (рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдореБрдЭреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрддрд╛ рдерд╛ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рдерд╛, рд╡рд┐рдВрдбреЛрдЬ рдПрдХреНрд╕-рдбреНрд░рд╛рдЗрд╡рд░реЛрдВ рдХреЗ рддрд╣рдд рдзрдиреНрдпрд╡рд╛рджред x86), рдФрд░ рд╕рдордЭрдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛ред



рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реА рдореБрд╢реНрдХрд┐рд▓ рдЬрдЧрд╣ рд╡рд┐рдзрд╛рдирд╕рднрд╛ рд▓рд╛рдЗрди рдереАред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдк рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рджреЗрдЦрддреЗ рд╣реИрдВ, рдФрд░ рдЗрд╕рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рд▓реЛрдб рд╣реЛ рд░рд╣рд╛ рд╣реИ рдкреИрд░рд╛рдореАрдЯрд░ рдЬрд┐рд╕реЗ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдХрд┐рд╕реА рднреА рдХреВрджрдиреЗ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЬрдВрдк / рдХреЙрд▓ рдХреЗ рдмрд╛рдж рдирд┐рд░реНрджреЗрд╢ рдХреЛ рдкрд╣рд▓реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣реА рдХреЙрд▓ рдпрд╛ рдЬрдВрдк рд╕реНрд╡рдпрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рдореИрдВ рдЬрд┐рди рднреА рдХрдард┐рдирд╛рдЗрдпреЛрдВ рд╕реЗ рдЧреБрдЬрд╝рд░рд╛, рдЙрд╕рдХреЗ рдмрд╛рдж рдореИрдВрдиреЗ рдЦреЗрд▓ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рдХрдИ рдкреИрдХрд░реНрд╕ / рдЕрдирдкреИрдХрд░реНрд╕ рд▓рд┐рдЦрдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдмреА рд╣рд╛рд╕рд┐рд▓ рдХреАред рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдХрднреА рднреА рдХреЛрдб рдХрд╛ рдЕрдзреНрдпрдпрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред рдХреНрдпреЛрдВ? рдареАрдХ рд╣реИ, рд╕рдм рдХреБрдЫ рд╕рд╛рдорд╛рдиреНрдп рд╣реИ: рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХреЛрдб рдереЗ, BIOS рддрдХ рдкрд╣реБрдВрдЪ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдЬреЛ рдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдордЭрдирд╛ рдЕрд╕рдВрднрд╡ рдерд╛ (рд╡реЗ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдереЗ, рдФрд░ рдлрд┐рд░ рдореЗрд░реЗ рдкрд╛рд╕ рдПрд╕рдбреАрдХреЗ рдХреЗ рд▓рд┐рдП рдХрд░реНрд▓рд┐рдВрдЧ рдирд╣реАрдВ рд╣реИ), рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рддреАрди рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдирд┐рд░реНрджреЗрд╢, рдПрдХ рдбрд┐рдХрдореНрдкреЙрдЗрд▓рд░ рдХреА рдХрдореАред


рдФрд░ рдЗрд╕рд▓рд┐рдП, рдХрдИ рд╕рд╛рд▓реЛрдВ рдХреЗ рдмрд╛рдж, GHIDRA рд╕рд╛рдордиреЗ рдЖрддрд╛ GHIDRA ред рдбрд┐рдХрдореНрдкреЙрдЗрд▓рд░ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдкреНрд▓реЗрдЯрдлрд╛рд░реНрдореЛрдВ рдХреЗ рдмреАрдЪ MIPS ред рд╣реЗ рдЖрдирдВрдж! рдЪрд▓реЛ рдХреБрдЫ рдЬрд▓реНрдж рд╣реА рд╡рд┐рдШрдЯрд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ! рд▓реЗрдХрд┐рди ... рдореИрдВ рдПрдХ рдмрдореНрдорд░ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣рд╛ рдерд╛ред PS-X EXE рд╣рд╛рдЗрдбреНрд░рд╛ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ PS-X EXE ред рдХреЛрдИ рдмрд╛рдд рдирд╣реАрдВ, рдЕрдкрдирд╛ рд▓рд┐рдЦреЛ!


рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрдб


рдкрд░реНрдпрд╛рдкреНрдд рдЧреАрддрд╛рддреНрдордХ рд╡рд┐рд╖рдпрд╛рдВрддрд░, рдЪрд▓реЛ рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╣реИрдВред Ghidra рд▓рд┐рдП рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдбрд╛рдЙрдирд▓реЛрдбрд░реНрд╕ рдХреИрд╕реЗ рдмрдирд╛рдПрдВ, рдореБрдЭреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрддрд╛ рдерд╛ рдХрд┐ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдХреНрдпрд╛ рд▓рд┐рдЦрд╛ рдерд╛ ред рдЗрд╕рд▓рд┐рдП, рдпрд╣ рдХреЗрд╡рд▓ рдкрд╣рд▓реЗ рдХрд░реНрд▓рд┐рдВрдЧ рд▓реЛрд╣реЗ рдХреЗ рдореЗрдореЛрд░реА рдореИрдк рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИ, рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЗ рдкрддреЗ рдФрд░, рдЖрдк рдмрд╛рдпрдиреЗрд░рд┐рдЬрд╝ рдХреЛ рдЗрдХрдЯреНрдард╛ рдФрд░ рд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЬрд▓реНрджреА рд╕реЗ рдирд╣реАрдВ рдХрд╣рд╛ред


рдХреЛрдб рддреИрдпрд╛рд░ рдерд╛, рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдФрд░ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдорд╛рдиреНрдпрддрд╛ рджреА рдЧрдИ рдереА, рд▓реЗрдХрд┐рди рдЕрднреА рднреА рдЙрди рдЬрдЧрд╣реЛрдВ рдкрд░ рдПрдХ рдмрдбрд╝рд╛ рдЦрд╛рд▓реА рд╕реНрдерд╛рди рдерд╛ рдЬрд╣рд╛рдВ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛рд░реНрдпреЛрдВ рдФрд░ BIOS рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рдерд╛ред рдФрд░, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рд╣рд╛рдЗрдбреНрд░рд╛ рдХреЗ рдкрд╛рд╕ FLIRT рд╕рдорд░реНрдерди рдирд╣реАрдВ рдерд╛ред рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред


FLIRT рд╣рд╕реНрддрд╛рдХреНрд╖рд░реЛрдВ рдХрд╛ рдкреНрд░рд╛рд░реВрдк pat.txt рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЬрд╛рдирд╛ рдФрд░ рд╡рд░реНрдгрд┐рдд рд╣реИ, рдЬрд┐рд╕реЗ Ida SDK рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрдбрд╛ рдХреЗ рдкрд╛рд╕ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ Playstation рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдлрд╝рд╛рдЗрд▓реЛрдВ рд╕реЗ рдпреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ: ppsx ред рдореИрдВрдиреЗ PsyQ Playstation Development Kit рдирд╛рдордХ PsyQ Playstation Development Kit рд▓рд┐рдП SDK рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛, рд╡рд╣рд╛рдВ рдкрд░ рдХрд╛рдо рдХреА рдлрд╛рдЗрд▓реЗрдВ рдорд┐рд▓реАрдВ рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдХрдо рд╕реЗ рдХрдо рдХреБрдЫ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА - рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХред рдпрд╣ рдПрдХ рдЫреЛрдЯрд╛ рдкрд╛рда рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдкрдВрдХреНрддрд┐ рдХрд╛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рд╛рд░реВрдк рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рдХреЛрдб рд▓рд┐рдЦрдирд╛ рд╢реЗрд╖ рд╣реИ рдЬреЛ рдЗрди рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░реЗрдЧрд╛, рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХреЛрдб рдкрд░ рд▓рд╛рдЧреВ рдХрд░реЗрдЧрд╛ред



PatParser


рдЪреВрдВрдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рд╛рд░реВрдк рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд▓рд┐рдЦрдирд╛ рддрд░реНрдХрд╕рдВрдЧрдд рд╣реЛрдЧрд╛ред рдпрд╣ рдЗрд╕ рддрд░рд╣ рдирд┐рдХрд▓рд╛:


 private static final Pattern linePat = Pattern.compile("^((?:[0-9A-F\\.]{2})+) ([0-9A-F]{2}) ([0-9A-F]{4}) ([0-9A-F]{4}) ((?:[:\\^][0-9A-F]{4}@? [\\.\\w]+ )+)((?:[0-9A-F\\.]{2})+)?$"); 

рдареАрдХ рд╣реИ, рддреЛ рдСрдлрд╕реЗрдЯ, рдкреНрд░рдХрд╛рд░ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдирд╛рдо рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ рд╕реЗ рдореЙрдбреНрдпреВрд▓ рдХреА рд╕реВрдЪреА рдореЗрдВ, рд╣рдо рдПрдХ рдЕрд▓рдЧ regexp рд▓рд┐рдЦрддреЗ рд╣реИрдВ:


 private static final Pattern modulePat = Pattern.compile("([:\\^][0-9A-F]{4}@?) ([\\.\\w]+) "); 

рдЕрдм рдкреНрд░рддреНрдпреЗрдХ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреЗ рдШрдЯрдХреЛрдВ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрд░рддреЗ рд╣реИрдВ:


  1. рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдмрд╛рдЗрдЯреНрд╕ ( 0-9A-F ) рдХрд╛ рд╣реЗрдХреНрд╕ рдЕрдиреБрдХреНрд░рдо рдЖрддрд╛ рд╣реИ, рдЬрд╣рд╛рдБ рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рднреА рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ (рдбреЙрдЯ рдХреИрд░реЗрдХреНрдЯрд░ "ред")ред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдПрдХ рдРрд╕рд╛ рд╡рд░реНрдЧ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬреЛ рдЗрд╕ рддрд░рд╣ рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛ред рдореИрдВрдиреЗ рдЗрд╕реЗ MaskedBytes рдХрд╣рд╛:

MaskedBytes.java
 package pat; public class MaskedBytes { private final byte[] bytes, masks; public final byte[] getBytes() { return bytes; } public final byte[] getMasks() { return masks; } public final int getLength() { return bytes.length; } public MaskedBytes(byte[] bytes, byte[] masks) { this.bytes = bytes; this.masks = masks; } public static MaskedBytes extend(MaskedBytes src, MaskedBytes add) { return extend(src, add.getBytes(), add.getMasks()); } public static MaskedBytes extend(MaskedBytes src, byte[] addBytes, byte[] addMasks) { int length = src.getBytes().length; byte[] tmpBytes = new byte[length + addBytes.length]; byte[] tmpMasks = new byte[length + addMasks.length]; System.arraycopy(src.getBytes(), 0, tmpBytes, 0, length); System.arraycopy(addBytes, 0, tmpBytes, length, addBytes.length); System.arraycopy(src.getMasks(), 0, tmpMasks, 0, length); System.arraycopy(addMasks, 0, tmpMasks, length, addMasks.length); return new MaskedBytes(tmpBytes, tmpMasks); } } 

  1. рдЙрд╕ рдЦрдВрдб рдХреА рд▓рдВрдмрд╛рдИ рдЬрд╣рд╛рдВ рд╕реЗ CRC16 рдХреА рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИред
  2. CRC16 , рдЬреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдмрд╣реБрдкрдж ( 0x8408 ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:

рдЧрд┐рдирддреА рдХреЛрдб CRC16
 public static boolean checkCrc16(byte[] bytes, short resCrc) { if ( bytes.length == 0 ) return true; int crc = 0xFFFF; for (int i = 0; i < bytes.length; ++i) { int a = bytes[i]; for (int x = 0; x < 8; ++x) { if (((crc ^ a) & 1) != 0) { crc = (crc >> 1) ^ 0x8408; } else { crc >>= 1; } a >>= 1; } } crc = ~crc; int x = crc; crc = (crc << 8) | ((x >> 8) & 0xFF); crc &= 0xFFFF; return (short)crc == resCrc; } 

  1. рдмрд╛рдЗрдЯреНрд╕ рдореЗрдВ "рдореЙрдбреНрдпреВрд▓" рдХреА рдХреБрд▓ рд▓рдВрдмрд╛рдИред
  2. рд╡реИрд╢реНрд╡рд┐рдХ рдирд╛рдореЛрдВ рдХреА рд╕реВрдЪреА (рд╣рдореЗрдВ рдХреНрдпрд╛ рдЪрд╛рд╣рд┐рдП)
  3. рдЕрдиреНрдп рдирд╛рдореЛрдВ рдХреЗ рд▓рд┐рдВрдХ рдХреА рд╕реВрдЪреА (рднреА рдЖрд╡рд╢реНрдпрдХ)ред
  4. рдЯреЗрд▓ рдмрд╛рдЗрдЯреНрд╕ред

рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдирд╛рдо рдореЗрдВ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ рд╣реИ рдФрд░ рд╢реБрд░реБрдЖрдд рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ рдСрдлрд╕реЗрдЯ рд╣реИред рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рдВрдХреЗрдд рд╡рд░реНрдгреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ::, ^, @, рдкреНрд░рдХрд╛рд░ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ:


  • " : NAME ": рд╡реИрд╢реНрд╡рд┐рдХ рдирд╛рдоред рдпрд╣ рдРрд╕реЗ рдирд╛рдореЛрдВ рдХреЗ рд▓рд┐рдП рдерд╛ рдХрд┐ рдореИрдВрдиреЗ рд╕рдм рдХреБрдЫ рд╢реБрд░реВ рдХрд┐рдпрд╛;
  • " : NAME @ ": рд╕реНрдерд╛рдиреАрдп рдирд╛рдо / рд▓реЗрдмрд▓ред рдпрд╣ рд╕рдВрдХреЗрдд рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рд░рд╣рдиреЗ рджреЛ;
  • " ^ NAME ": рдирд╛рдо рдХрд╛ рд▓рд┐рдВрдХред

рдПрдХ рддрд░рдл, рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд▓рд┐рдВрдХ рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╕рдВрджрд░реНрдн рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ (рдФрд░, рддрджрдиреБрд╕рд╛рд░, рдХреВрдж рд░рд┐рд╢реНрддреЗрджрд╛рд░ рд╣реЛрдЧрд╛), рд▓реЗрдХрд┐рди рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдХреЗ рд▓рд┐рдПред рдХреНрдпрд╛, рдЖрдк рдХрд╣рддреЗ рд╣реИрдВ, рд╕рдорд╕реНрдпрд╛ рд╣реИ? рдФрд░ рдпрд╣ рд╣реИ рдХрд┐ PSX рдореЗрдВ рдЖрдк рдПрдХ рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд╕рд╛рде рдкреВрд░реЗ DWORD рдХреЛ рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдзрдХреЗрд▓ рдирд╣реАрдВ рд╕рдХрддреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐, MIPS рдЕрдиреБрджреЗрд╢ рдЖрдХрд╛рд░ рдЪрд╛рд░ рдмрд╛рдЗрдЯреНрд╕ рддрдХ рд╕реАрдорд┐рдд рд╣реИред рдФрд░, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ, рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рдПрдХ рдирд┐рд░реНрджреЗрд╢ рд╕реЗ рдПрдХ рдЖрдзрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЕрдЧрд▓реЗ рдХреЛ рдЕрд▓рдЧ рдХрд░реЗрдВ - рдФрд░ рджреВрд╕рд░рд╛ рдЖрдзрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред рд▓реЗрдХрд┐рди рдЗрддрдирд╛ рд╕рд░рд▓ рдирд╣реАрдВ рд╣реИред рдкрд╣рд▓реА рдЫрдорд╛рд╣реА рдХреЛ 5 рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рд▓рд┐рдВрдХ рдЗрд╕рдХреА рджреВрд╕рд░реА рдЫрдорд╛рд╣реА рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╣реА рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдореБрдЭреЗ рдПрдХ рдкрд░рд┐рд╖реНрдХреГрдд рдкрд╛рд░реНрд╕рд░ рд▓рд┐рдЦрдирд╛ рдерд╛ (рд╢рд╛рдпрдж рдЗрд╕реЗ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ)ред


рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдо рддреАрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдирд╛рдореЛрдВ рдХреЗ рд▓рд┐рдП enum рдмрдирд╛рддреЗ рд╣реИрдВ:


ModuleType.java
 package pat; public enum ModuleType { GLOBAL_NAME, LOCAL_NAME, REF_NAME; public boolean isGlobal() { return this == GLOBAL_NAME; } public boolean isLocal() { return this == LOCAL_NAME; } public boolean isReference() { return this == REF_NAME; } @Override public String toString() { if (isGlobal()) { return "Global"; } else if (isLocal()) { return "Local"; } else { return "Reference"; } } } 

рдЖрдЗрдП рдПрдХ рдХреЛрдб рд▓рд┐рдЦреЗрдВ рдЬреЛ рдкрд╛рда рд╣реЗрдХреНрд╕рд╛рдбреЗрд╕рд┐рдорд▓ рдЕрдиреБрдХреНрд░рдо рдФрд░ рдбреЙрдЯреНрд╕ рдХреЛ MaskedBytes рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП MaskedBytes :


hexStringToMaskedBytesArray ()
 private MaskedBytes hexStringToMaskedBytesArray(String s) { MaskedBytes res = null; if (s != null) { int len = s.length(); byte[] bytes = new byte[len / 2]; byte[] masks = new byte[len / 2]; for (int i = 0; i < len; i += 2) { char c1 = s.charAt(i); char c2 = s.charAt(i + 1); masks[i / 2] = (byte) ( (((c1 == '.') ? 0x0 : 0xF) << 4) | (((c2 == '.') ? 0x0 : 0xF) << 0) ); bytes[i / 2] = (byte) ( (((c1 == '.') ? 0x0 : Character.digit(c1, 16)) << 4) | (((c2 == '.') ? 0x0 : Character.digit(c2, 16)) << 0) ); } res = new MaskedBytes(bytes, masks); } return res; } 

рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рд╡рд░реНрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛: рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд╛рдо, рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдСрдлрд╕реЗрдЯ рдФрд░ рдкреНрд░рдХрд╛рд░:


ModuleData.java
 package pat; public class ModuleData { private final long offset; private final String name; private final ModuleType type; public ModuleData(long offset, String name, ModuleType type) { this.offset = offset; this.name = name; this.type = type; } public final long getOffset() { return offset; } public final String getName() { return name; } public final ModuleType getType() { return type; } } 

рдФрд░, рдЕрдВрдд рдореЗрдВ: рдПрдХ рд╡рд░реНрдЧ рдЬреЛ рд╕рдм рдХреБрдЫ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛ рдЬреЛ pat рдлрд╝рд╛рдЗрд▓ рдХреА рдкреНрд░рддреНрдпреЗрдХ рдкрдВрдХреНрддрд┐ рдкрд░ рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╡рд╣ рд╣реИ: рдмрд╛рдЗрдЯреНрд╕, рд╕реАрдЖрд░рд╕реА, рдСрдлрд╕реЗрдЯ рдХреЗ рд╕рд╛рде рдирд╛рдореЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА:


SignatureData.java
 package pat; import java.util.Arrays; import java.util.List; public class SignatureData { private final MaskedBytes templateBytes, tailBytes; private MaskedBytes fullBytes; private final int crc16Length; private final short crc16; private final int moduleLength; private final List<ModuleData> modules; public SignatureData(MaskedBytes templateBytes, int crc16Length, short crc16, int moduleLength, List<ModuleData> modules, MaskedBytes tailBytes) { this.templateBytes = this.fullBytes = templateBytes; this.crc16Length = crc16Length; this.crc16 = crc16; this.moduleLength = moduleLength; this.modules = modules; this.tailBytes = tailBytes; if (this.tailBytes != null) { int addLength = moduleLength - templateBytes.getLength() - tailBytes.getLength(); byte[] addBytes = new byte[addLength]; byte[] addMasks = new byte[addLength]; Arrays.fill(addBytes, (byte)0x00); Arrays.fill(addMasks, (byte)0x00); this.fullBytes = MaskedBytes.extend(this.templateBytes, addBytes, addMasks); this.fullBytes = MaskedBytes.extend(this.fullBytes, tailBytes); } } public MaskedBytes getTemplateBytes() { return templateBytes; } public MaskedBytes getTailBytes() { return tailBytes; } public MaskedBytes getFullBytes() { return fullBytes; } public int getCrc16Length() { return crc16Length; } public short getCrc16() { return crc16; } public int getModuleLength() { return moduleLength; } public List<ModuleData> getModules() { return modules; } } 

рдЕрдм рдореБрдЦреНрдп рдмрд╛рдд: рд╣рдо рдЗрди рд╕рднреА рд╡рд░реНрдЧреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╣реИрдВ:


рдПрдХ рдкреИрдЯ рдлрд╝рд╛рдЗрд▓ рдХреА рдкрд╛рд░реНрд╕рд┐рдВрдЧ рд▓реА рдЧрдИ
 private List<ModuleData> parseModuleData(String s) { List<ModuleData> res = new ArrayList<ModuleData>(); if (s != null) { Matcher m = modulePat.matcher(s); while (m.find()) { String __offset = m.group(1); ModuleType type = __offset.startsWith(":") ? ModuleType.GLOBAL_NAME : ModuleType.REF_NAME; type = (type == ModuleType.GLOBAL_NAME && __offset.endsWith("@")) ? ModuleType.LOCAL_NAME : type; String _offset = __offset.replaceAll("[:^@]", ""); long offset = Integer.parseInt(_offset, 16); String name = m.group(2); res.add(new ModuleData(offset, name, type)); } } return res; } 

рд╕рднреА рдкреИрдЯ рдлрд╝рд╛рдЗрд▓ рд▓рд╛рдЗрдиреЛрдВ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдирд╛
 private void parse(List<String> lines) { modulesCount = 0L; signatures = new ArrayList<SignatureData>(); int linesCount = lines.size(); monitor.initialize(linesCount); monitor.setMessage("Reading signatures..."); for (int i = 0; i < linesCount; ++i) { String line = lines.get(i); Matcher m = linePat.matcher(line); if (m.matches()) { MaskedBytes pp = hexStringToMaskedBytesArray(m.group(1)); int ll = Integer.parseInt(m.group(2), 16); short ssss = (short)Integer.parseInt(m.group(3), 16); int llll = Integer.parseInt(m.group(4), 16); List<ModuleData> modules = parseModuleData(m.group(5)); MaskedBytes tail = null; if (m.group(6) != null) { tail = hexStringToMaskedBytesArray(m.group(6)); } signatures.add(new SignatureData(pp, ll, ssss, llll, modules, tail)); modulesCount += modules.size(); } monitor.incrementProgress(1); } } 

рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдЬрд╣рд╛рдВ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдореЗрдВ рд╕реЗ рдПрдХ рдХреЛ рдорд╛рдиреНрдпрддрд╛ рджреА рдЧрдИ рдереА:


рдлрдВрдХреНрд╢рди рдХреНрд░рд┐рдПрд╢рди
 private static void disasmInstruction(Program program, Address address) { DisassembleCommand cmd = new DisassembleCommand(address, null, true); cmd.applyTo(program, TaskMonitor.DUMMY); } public static void setFunction(Program program, FlatProgramAPI fpa, Address address, String name, boolean isFunction, boolean isEntryPoint, MessageLog log) { try { if (fpa.getInstructionAt(address) == null) disasmInstruction(program, address); if (isFunction) { fpa.createFunction(address, name); } if (isEntryPoint) { fpa.addEntryPoint(address); } if (isFunction && program.getSymbolTable().hasSymbol(address)) { return; } program.getSymbolTable().createLabel(address, name, SourceType.IMPORTED); } catch (InvalidInputException e) { log.appendException(e); } } 

рд╕рдмрд╕реЗ рдХрдард┐рди рдЬрдЧрд╣, рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдХрд┐рд╕реА рдЕрдиреНрдп рдирд╛рдо / рдЪрд░ рдХреЗ рд▓рд┐рдВрдХ рдХреА рдЧрд┐рдирддреА рдХрд░ рд░рд╣рд╛ рд╣реИ (рд╢рд╛рдпрдж рдХреЛрдб рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ):


рд▓рд┐рдВрдХ рдЧрдгрдирд╛
 public static void setInstrRefName(Program program, FlatProgramAPI fpa, PseudoDisassembler ps, Address address, String name, MessageLog log) { ReferenceManager refsMgr = program.getReferenceManager(); Reference[] refs = refsMgr.getReferencesFrom(address); if (refs.length == 0) { disasmInstruction(program, address); refs = refsMgr.getReferencesFrom(address); if (refs.length == 0) { refs = refsMgr.getReferencesFrom(address.add(4)); if (refs.length == 0) { refs = refsMgr.getFlowReferencesFrom(address.add(4)); Instruction instr = program.getListing().getInstructionAt(address.add(4)); if (instr == null) { disasmInstruction(program, address.add(4)); instr = program.getListing().getInstructionAt(address.add(4)); if (instr == null) { return; } } FlowType flowType = instr.getFlowType(); if (refs.length == 0 && !(flowType.isJump() || flowType.isCall() || flowType.isTerminal())) { return; } refs = refsMgr.getReferencesFrom(address.add(8)); if (refs.length == 0) { return; } } } } try { program.getSymbolTable().createLabel(refs[0].getToAddress(), name, SourceType.IMPORTED); } catch (InvalidInputException e) { log.appendException(e); } } 

рдФрд░, рдЕрдВрддрд┐рдо рд╕реНрдкрд░реНрд╢ - рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд▓рд╛рдЧреВ рдХрд░реЗрдВ:


рдЖрд╡реЗрджрди ()
 public void applySignatures(ByteProvider provider, Program program, Address imageBase, Address startAddr, Address endAddr, MessageLog log) throws IOException { BinaryReader reader = new BinaryReader(provider, false); PseudoDisassembler ps = new PseudoDisassembler(program); FlatProgramAPI fpa = new FlatProgramAPI(program); monitor.initialize(getAllModulesCount()); monitor.setMessage("Applying signatures..."); for (SignatureData sig : signatures) { MaskedBytes fullBytes = sig.getFullBytes(); MaskedBytes tmpl = sig.getTemplateBytes(); Address addr = program.getMemory().findBytes(startAddr, endAddr, fullBytes.getBytes(), fullBytes.getMasks(), true, TaskMonitor.DUMMY); if (addr == null) { monitor.incrementProgress(sig.getModules().size()); continue; } addr = addr.subtract(imageBase.getOffset()); byte[] nextBytes = reader.readByteArray(addr.getOffset() + tmpl.getLength(), sig.getCrc16Length()); if (!PatParser.checkCrc16(nextBytes, sig.getCrc16())) { monitor.incrementProgress(sig.getModules().size()); continue; } addr = addr.add(imageBase.getOffset()); List<ModuleData> modules = sig.getModules(); for (ModuleData data : modules) { Address _addr = addr.add(data.getOffset()); if (data.getType().isGlobal()) { setFunction(program, fpa, _addr, data.getName(), data.getType().isGlobal(), false, log); } monitor.setMessage(String.format("%s function %s at 0x%08X", data.getType(), data.getName(), _addr.getOffset())); monitor.incrementProgress(1); } for (ModuleData data : modules) { Address _addr = addr.add(data.getOffset()); if (data.getType().isReference()) { setInstrRefName(program, fpa, ps, _addr, data.getName(), log); } monitor.setMessage(String.format("%s function %s at 0x%08X", data.getType(), data.getName(), _addr.getOffset())); monitor.incrementProgress(1); } } } 

рдпрд╣рд╛рдВ рдЖрдк рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: findBytes() ред рдЗрд╕рдХреЗ рд╕рд╛рде, рдЖрдк рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рджреГрд╢реНрдпреЛрдВ рдХреА рдЦреЛрдЬ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдмрд┐рдЯ рдорд╛рд╕реНрдХ рдХреЗ рд╕рд╛рдеред рд╡рд┐рдзрд┐ рдХреЛ рдЗрд╕ рддрд░рд╣ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ:


 Address addr = program.getMemory().findBytes(startAddr, endAddr, bytes, masks, forward, TaskMonitor.DUMMY); 

рдирддреАрдЬрддрди, рдЬрд┐рд╕ рдкрддреЗ рд╕реЗ рдмрд╛рдЗрдЯреНрд╕ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИрдВ, рд╡рд╣ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╛ null ред


рдПрдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рд▓рд┐рдЦ рд░рд╣рд╛ рд╣реИ


рдЪрд▓реЛ рдЗрд╕реЗ рдЦреВрдмрд╕реВрд░рддреА рд╕реЗ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рд╣рдо рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдпрд╣ рдЪрд░рдг рдЪреБрдирдиреЗ рджреЗрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдХреЛрдб рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ (рдЖрдк рдЗрд╕ рд╕реВрдЪреА рдореЗрдВ рд▓реЛрдЧреЛрдВ рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ - рдпрд╣ рд╕рдм рд╡реЗ рд╣реИрдВ, рд╣рд╛рдБ):



рдЗрд╕рд▓рд┐рдП, рдЗрд╕ рд╕реВрдЪреА рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ AbstractAnalyzer рд╡рд░реНрдЧ рд╕реЗ рд╡рд╛рд░рд┐рд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдХреБрдЫ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдирд╛ рд╣реЛрдЧрд╛:


  1. рдбрд┐рдЬрд╛рдЗрдирд░ред рдЗрд╕реЗ рдЖрдзрд╛рд░ рд╡рд░реНрдЧ рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдирд╛рдо, рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреЗ рд╡рд┐рд╡рд░рдг рдФрд░ рдЗрд╕рдХреЗ рдкреНрд░рдХрд╛рд░ (рдмрд╛рдж рдореЗрдВ рдЙрд╕ рдкрд░ рдЕрдзрд┐рдХ) рдХреЗ рд╕рд╛рде рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рдореБрдЭреЗ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

 public PsxAnalyzer() { super("PSYQ Signatures", "PSX signatures applier", AnalyzerType.INSTRUCTION_ANALYZER); } 

  1. getDefaultEnablement() ред рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╣рдорд╛рд░рд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рд╣рдореЗрд╢рд╛ рдЙрдкрд▓рдмреНрдз рд╣реИ, рдпрд╛ рдХреЗрд╡рд▓ рдЕрдЧрд░ рдХреБрдЫ рд╢рд░реНрддреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╣рдорд╛рд░реЗ рд▓реЛрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред
  2. canAnalyze() ред рдХреНрдпрд╛ рдПрдХ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдмрд╛рдЗрдирд░реА рдлрд╝рд╛рдЗрд▓ рдкрд░ рдЗрд╕ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ?
    рдкреИрд░рд╛рдЧреНрд░рд╛рдл 2 рдФрд░ 3, рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдПрдХ рдПрдХрд▓ рдлрд╝рдВрдХреНрд╢рди рджреНрд╡рд╛рд░рд╛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ:

 public static boolean isPsxLoader(Program program) { return program.getExecutableFormat().equalsIgnoreCase(PsxLoader.PSX_LOADER); } 

рдЬрд╣рд╛рдБ PsxLoader.PSX_LOADER рдмреВрдЯрд▓реЛрдбрд░ рдХрд╛ рдирд╛рдо рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдореЗрдВ рдкрд╣рд▓реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред


рдХреБрд▓, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣реИ:


 @Override public boolean getDefaultEnablement(Program program) { return isPsxLoader(program); } @Override public boolean canAnalyze(Program program) { return isPsxLoader(program); } 

  1. registerOptions() ред рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдХреБрдЫ рдкреВрдЫрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╕реЗ рдкрд╣рд▓реЗ рдкреИрдЯ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдкрде, рддреЛ рдЗрд╕ рд╡рд┐рдзрд┐ рдореЗрдВ рдРрд╕рд╛ рдХрд░рдирд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╣реИред рд╣рдореЗрдВ рдорд┐рд▓рддрд╛ рд╣реИ:

 private static final String OPTION_NAME = "PSYQ PAT-File Path"; private File file = null; @Override public void registerOptions(Options options, Program program) { try { file = Application.getModuleDataFile("psyq4_7.pat").getFile(false); } catch (FileNotFoundException e) { } options.registerOption(OPTION_NAME, OptionType.FILE_TYPE, file, null, "PAT-File (FLAIR) created from PSYQ library files"); } 

рдпрд╣рд╛рдБ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рд╕реНрдереИрддрд┐рдХ рд╡рд┐рдзрд┐ getModuleDataFile() Application рд╡рд░реНрдЧ data рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП рдкреВрд░реНрдг рдкрде рджреЗрддрд╛ рд╣реИ, рдЬреЛ рд╣рдорд╛рд░реЗ рдореЙрдбреНрдпреВрд▓ рдХреЗ рдкреЗрдбрд╝ рдореЗрдВ рд╣реИ, рдФрд░ рд╣рдо рдмрд╛рдж рдореЗрдВ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдЖрд╡рд╢реНрдпрдХ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рдЦреИрд░, OPTION_NAME registerOption() рд╡рд┐рдзрд┐ OPTION_NAME рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╛рдо рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХреЛ registerOption() OPTION_NAME , рдкреНрд░рдХрд╛рд░ File (рдпрд╛рдиреА, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдХ рдирд┐рдпрдорд┐рдд рд╕рдВрд╡рд╛рдж рдмреЙрдХреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛), рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореВрд▓реНрдп рдФрд░ рд╡рд┐рд╡рд░рдгред


рдЕрдЧрд▓рд╛ред рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрдВрдЬреАрдХреГрдд рд╡рд┐рдХрд▓реНрдк рдХреЛ рдмрд╛рдж рдореЗрдВ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЕрд╡рд╕рд░ рдирд╣реАрдВ рд╣реИ, рд╣рдореЗрдВ optionsChanged() рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА: optionsChanged()


 @Override public void optionsChanged(Options options, Program program) { super.optionsChanged(options, program); file = options.getFile(OPTION_NAME, file); } 

рдпрд╣рд╛рдВ рд╣рдо рдирдП рдореВрд▓реНрдп рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдХрд╛ рдЕрджреНрдпрддрди рдХрд░рддреЗ рд╣реИрдВред


added() рд╡рд┐рдзрд┐ред рдЕрдм рдореБрдЦреНрдп рдмрд╛рдд: рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рд╢реБрд░реВ рд╣реЛрдиреЗ рдкрд░ рд╡рд┐рдзрд┐ рдЬрд┐рд╕реЗ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдореЗрдВ рд╣рдо рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рдкрддреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЙрди рд▓реЛрдЧреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрд┐рдирдореЗрдВ рдХреЛрдб рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдЖрдкрдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрдВрддрд┐рдо рдХреЛрдб:


рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ () рд╡рд┐рдзрд┐
 @Override public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) throws CancelledException { if (file == null) { return true; } Memory memory = program.getMemory(); AddressRangeIterator it = memory.getLoadedAndInitializedAddressSet().getAddressRanges(); while (!monitor.isCancelled() && it.hasNext()) { AddressRange range = it.next(); try { MemoryBlock block = program.getMemory().getBlock(range.getMinAddress()); if (block.isInitialized() && block.isExecute() && block.isLoaded()) { PatParser pat = new PatParser(file, monitor); RandomAccessByteProvider provider = new RandomAccessByteProvider(new File(program.getExecutablePath())); pat.applySignatures(provider, program, block.getStart(), block.getStart(), block.getEnd(), log); } } catch (IOException e) { log.appendException(e); return false; } } return true; } 

рдпрд╣рд╛рдВ рд╣рдо рдЙрди рдкрддреЛрдВ рдХреА рд╕реВрдЪреА рд╕реЗ рдЧреБрдЬрд░рддреЗ рд╣реИрдВ рдЬреЛ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рд╣реИрдВ, рдФрд░ рд╡рд╣рд╛рдВ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред



рдирд┐рд╖реНрдХрд░реНрд╖ рдФрд░ рдЕрдВрдд


рд╕рдм рдХреБрдЫ рдкрд╕рдВрдж рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣рд╛рдВ рдХреБрдЫ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИред рдЙрджрд╛рд╣рд░рдг рд╣реИрдВ, рд╕рдореБрджрд╛рдп рдЬреАрд╡рдВрдд рд╣реИ, рдЖрдк рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдкреВрдЫ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╕рдордп рдХреНрдпрд╛ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИред рдирд┐рдЪрд▓рд╛ рд░реЗрдЦрд╛: Playstation 1 рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╛рд░реНрдпрд╢реАрд▓ рдмреВрдЯрд▓реЛрдбрд░ рдФрд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдХред



рд╕рднреА рд╕реНрд░реЛрдд рдХреЛрдб рдпрд╣рд╛рдВ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ: ghidra_psx_ldr
рдпрд╣рд╛рдБ рд╡рд┐рдЬреНрдЮрдкреНрддрд┐: рд╡рд┐рдЬреНрдЮрдкреНрддрд┐

Source: https://habr.com/ru/post/hi448098/


All Articles