为方便自己初步学习用gdb调试,在这个专项总结里再开一篇文章专门记录gdb的调试命令。这篇文章应该会在未来不断更新。
Pwn学习总结(2):ELF保护知识篇
在学习下面的内容前,希望你对x86及amd64体系结构的汇编、Linux下的调用约定、ELF文件格式有一定的了解[1][2][3][4][5][7]。
继续阅读
Pwn学习总结(1):工具篇
虽然之前已经了解了一些Pwn。但根据需要,最近需要系统的学习一遍Pwn。经权威人士推荐,选择“Linux下pwn从入门到放弃”进行再次入门。
本学习总结根据该参考资料及个人经验重新总结整理。
需要用到的工具包括:
(1)gdb:GNU gcc调试器
(2)peda/gef/gdbinit:美化gdb命令行界面的脚本,同时可以扩展gdb的命令,可以参考[2]
(3)pwntools: python的一个pwn库,提供了很多封装过的用于pwn的函数
(4)checksec: 查询ELF程序的各类保护措施及程序的运行平台
(5)objdump/readelf: 查询ELF各节的关键信息
(6)IDA Pro: “全世界首屈一指”的反编译工具
(7)ROPgadget: ROP(Return-Oriented Programming)利用工具
(8)one_gadget: 快速寻找libc中的 execve(“/bin/sh”, * 的位置
(9)LibcSearcher: 非常方便的通过libc泄漏函数偏移地址和函数名查询libc版本及其他函数地址的python库
参考资料:
[1] Linux下pwn从入门到放弃 https://blog.csdn.net/niexinming/article/details/78814422
[2] https://github.com/bjrjk/GDBPlugins
黑金 ALinx AX7020使用Petalinux编译从SD卡启动的Linux内核及构建SD卡EXT4 rootfs
本次使用的Vivado, Petalinux版本均为v2021.1。记录下来方便自己和其他人之后参考。
继续阅读
OI/ACM/算法 入门学习指导经验贴
最近有不少人问我OI/ACM/算法到底应当如何入门,为了方便起见,我专门写一篇文章来讲一讲自己的认识。
继续阅读
LeetCode 44 Wildcard Matching
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | class Solution { public: string input, pattern; short arr[2005][2005]; bool isMatch(string s, string p) { input = s; pattern = p; memset(arr, -1, sizeof(arr)); return dfs(0, 0); } bool dfs(int iPos, int pPos){ if(arr[iPos][pPos] != -1) return arr[iPos][pPos]; int inputLen = input.size(), patternLen = pattern.size(); if(iPos == inputLen && pPos == patternLen) return arr[iPos][pPos]=true; if(iPos >= inputLen || pPos >= patternLen){ if(iPos == inputLen && pPos < patternLen){ for(int i=pPos;i<patternLen;i++){ if(pattern[i]!='*') return arr[iPos][pPos]=false; } return arr[iPos][pPos]=true; } return arr[iPos][pPos]=false; } switch(pattern[pPos]){ case '*': return arr[iPos][pPos]=dfs(iPos+1, pPos+1) || dfs(iPos+1, pPos) || dfs(iPos, pPos+1); break; case '?': return arr[iPos][pPos]=dfs(iPos+1, pPos+1); break; default: if(input[iPos] == pattern[pPos]) return arr[iPos][pPos]=dfs(iPos+1, pPos+1); else return arr[iPos][pPos]=false; break; } } }; |
《冰糖炖雪梨》
CSP 201903-3 损坏的RAID5
真是没想到这道题还能被IO卡住。原本的做法是scanf”%8X”读,然后用getchar试探换行符。结果T。再试把试探删了,始终不行。最后放弃直接读Binary的想法,用的时候再做转换,直接读字符串进来。总算过了。
希望明天别遇上这么恶心的IO。今天晚上整理一下cstdio和iostream的格式化相关文档,明天考CSP使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #include <iostream> #include <iomanip> #include <cstdio> #include <vector> #include <string> #include <deque> #include <algorithm> #include <tuple> using namespace std; int n, s, l; vector<string> RAIDArray; int diskBlockCount; char buf[100]; void input(){ ios::sync_with_stdio(false); cin.tie(nullptr); cin>>n>>s>>l; RAIDArray.resize(n); for(int i=0;i<l;i++){ int diskID, data; int bCnt = 0; string s; cin>>diskID>>s; RAIDArray[diskID]=s; diskBlockCount = s.size() / 8; } } int RAID(int diskID, int localBlockID){ int data; sscanf((char *)&RAIDArray[diskID].c_str()[localBlockID*8],"%8X",&data); return data; } inline bool isDiskExists(int diskID){ return !RAIDArray[diskID].empty(); } inline int getGlobalStripeID(int blockID){ return blockID / s; } inline int getLocalStripeID(int globalStripeID){ return globalStripeID / (n-1); } inline int getlocalStripeECCDiskID(int localStripeID){ return n - 1 - localStripeID % n; } inline std::tuple<int, int> getLocalDiskAndBlockID(int blockID){ // Return Disk ID, Local Block ID int globalStripeID = getGlobalStripeID(blockID); int localStripeID = getLocalStripeID(globalStripeID); int localStripeECCDiskID = getlocalStripeECCDiskID(localStripeID); int localStripeDiskID = (localStripeECCDiskID + 1 + globalStripeID % (n-1)) % n; int localBlockID = localStripeID * s + blockID % s; return std::tuple<int, int>(localStripeDiskID, localBlockID); } inline std::tuple<bool, int> recoverDataDirect(int blockID){ int diskID, localBlockID; std::tie(diskID, localBlockID) = getLocalDiskAndBlockID(blockID); if(!isDiskExists(diskID)) return std::tuple<bool, int>(false, -1); else return std::tuple<bool, int>(true, RAID(diskID, localBlockID)); } inline std::tuple<bool, int> recoverDataECC(int blockID){ if(l < n-1) return std::tuple<bool, int>(false, -1); int diskID, localBlockID; int data = 0; std::tie(diskID, localBlockID) = getLocalDiskAndBlockID(blockID); for(int curDisk = 0;curDisk<n;curDisk++){ if(curDisk == diskID)continue; data ^= RAID(curDisk,localBlockID); } return std::tuple<bool, int>(true, data); } inline std::tuple<bool, int> recoverDataMain(int blockID){ int diskID, localBlockID; std::tie(diskID, localBlockID) = getLocalDiskAndBlockID(blockID); if(localBlockID >= diskBlockCount) return std::tuple<bool, int> (false, -1); bool flag; int result; std::tie(flag, result) = recoverDataDirect(blockID); if(flag) return std::tuple<bool, int> (flag, result); std::tie(flag, result) = recoverDataECC(blockID); if(flag) return std::tuple<bool, int> (flag, result); return std::tuple<bool, int> (false, -1); } void solve(){ int m, blockID; cin>>m; while(m--){ cin>>blockID; bool flag; int result; tie(flag, result) = recoverDataMain(blockID); if(!flag) cout<<"-\n"; else cout<<setw(8)<<setfill('0')<<hex<<uppercase<<result<<"\n"; } } int main(){ input(); solve(); } |
CSP 201703-2 学生排队
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #include <iostream> #include <vector> using namespace std; int n, m; vector<int> arr; int arr_find(int value){ for(int i=0;i<n;i++){ if(arr[i]==value) return i; } return -1; } void move(int stuID, int shift){ if(shift==0)return; int pos = arr_find(stuID); if(shift>0){ for(int i=pos;i<pos+shift;i++){ swap(arr[i],arr[i+1]); } }else{ for(int i=pos;i>pos+shift;i--){ swap(arr[i],arr[i-1]); } } } int main(){ ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++){ arr.push_back(i); } cin>>m; for(int i=0;i<m;i++){ int p,q; cin>>p>>q; move(p,q); } for(int i=0;i<n;i++){ cout<<arr[i]<<" "; } } |
CSP 201903-2 二十四点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #include <iostream> #include <cstdio> #include <vector> #include <string> #include <deque> #include <algorithm> using namespace std; int calculate(int n1, int n2, char op) { switch (op) { case '+': return n1 + n2; break; case '-': return n1 - n2; break; case 'x': return n1 * n2; break; case '/': return n1 / n2; break; } return -1; } bool solve(string s) { deque<int> si; deque<char> sop; for (int i = 0; i < 7; i++) { if (i % 2 == 0) { // Inttop int t = s[i] - '0'; si.push_back(t); if (sop.empty()) continue; if (sop.back() == 'x' || sop.back() == '/') { int t2 = si.back(); si.pop_back(); int t1 = si.back(); si.pop_back(); int t = calculate(t1, t2, sop.back()); sop.pop_back(); si.push_back(t); } } else { // Op char op = s[i]; sop.push_back(op); } } while (!sop.empty()) { int t1 = si.front(); si.pop_front(); int t2 = si.front(); si.pop_front(); int t = calculate(t1, t2, sop.front()); sop.pop_front(); si.push_front(t); } return si.front()==24; } int main() { ios::sync_with_stdio(false); int n; string s; cin >> n; while (n--) { cin >> s; if (solve(s)) cout << "Yes\n"; else cout << "No\n"; } } |