Be a Scout. Always leave the code cleaner than you found it.
Fix the broken windows. All those comments "change in version 2.0" when you're on version 3.0
When there are major hacks, design a better solution as a team and do it. If you can't fix the hack as a team, they you don't understand the system well enough. "Ask an adult for help." The oldest people around might have seen this before.
Try drawing or extracting a diagram of the system.
Try drawing or extracting the use cases that are particularly hacky as interaction diagrams. This doesn't fix it but at least you can see it.
What assumptions are no longer true that pushed the design in a particular direction?
There might be a small refactoring hiding behind some of that mess.
If you explain how the system works (even just one use case) and find yourself having to apologize of a subsystem over and over again, its the problem. What behavoid would make the rest of the system simpler, (No matter how hard it looks to implement compared to what is there) The classic subsystem to rewrite is one that pollutes every other subsystem with it's operating semantics and implementation. "Oh, you have to groz the values before you feed them into the the froo subsystem, then you un-groz them again as you get output from the froo. Maybe all values should be groz'ed when read from the user & storage, and the rest of the system is wrong ? This gets more exciting when there are two or more different grozifications.
Spend a week as a team removing warnings so that real problems are visible.
Reformat all the code to the coding standard.
Ensure your Version control system is tied to your bug tracker. This means future changes are nice and accountable, and you can work out WHY.
Do some archeology. Find the original design documents and review them. They might be on that old PC in the corner of the office, in the abandoned office space or in the filing cabinet nobody ever opens.
Republish the design documents on a wiki. This helps institutionalize knowledge.
Write checklist-like procedures for releases and builds. This stops people having to think so they can concentrate on solving problems. Automate builds wherever possible.
Try continuous integration. The sooner you get a failed build , the less time the project can spend off the rails.
If your team lead does not do these things, well that's bad for the company.
Try to ensure all new code gets proper unit tests with measured coverage. So the problem can't get much worse.
Try to unit test some of the old bits that are not unit tested. This helps cut back the fear of change.
Automate your integration and regression test if you can. At least have a checklist.
Pilots are smart and get paid lots and they use checklists. They also screw up pretty rarely.